From d42db44009e02dd58996cd9cb67ed7d572158636 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sat, 1 Jan 2022 00:04:35 -0500 Subject: [PATCH] add drag/move, quaternion rotation, lay flat, work mesh matrix debug --- src/main/mesh.js | 40 ++++++++++++++++++++++++++++++++++++++++ src/mesh/api.js | 11 ++++++++++- src/mesh/model.js | 27 +++++++++++++++++++++------ src/mesh/object.js | 4 ++++ src/mesh/work.js | 4 +++- 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/main/mesh.js b/src/main/mesh.js index 5e165398..aa6939c1 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -8,6 +8,7 @@ let broker = gapp.broker; function init() { let moto = self.moto, + api = mesh.api, sky = false, dark = false, ortho = false, @@ -22,6 +23,9 @@ function init() { color: dark ? 0 : 0xffffff }); space.init($('container'), delta => { }, ortho); + platform.onClick(click => { + api.selection.clear(); + }); platform.onMove(delta => { }); platform.set({ volume: false, @@ -55,6 +59,7 @@ broker.subscribe('space_init', data => { let { space, platform } = data; let platcolor = 0x00ff00; let api = mesh.api; + // add file drop handler space.event.addHandlers(self, [ 'drop', (evt) => { @@ -105,6 +110,41 @@ broker.subscribe('space_init', data => { } } ]); + + // mouse hover/click handlers + space.mouse.downSelect((int, event) => { + // mesh array including platform + return api.objects(); + }); + + space.mouse.upSelect((int, event) => { + if (event && event.target.nodeName === "CANVAS") { + let model = int && int.object.model ? int.object.model : undefined; + if (model) { + let group = model.group; + // lay flat with meta or ctrl clicking a selected face + if ((event.ctrlKey || event.metaKey)) { + let q = new THREE.Quaternion(); + // find intersecting point, look "up" on Z and rotate to face that + q.setFromUnitVectors(int.face.normal, new THREE.Vector3(0,0,-1)); + group.qrotate(q); + } else { + api.selection.toggle(model.group); + } + } + } else { + return api.objects(); + } + }); + + space.mouse.onDrag((delta, offset, up = false) => { + if (delta) { + api.selection.move(delta.x, delta.y, 0); + } else { + return api.objects().length > 0; + } + }); + }); // add object loader diff --git a/src/mesh/api.js b/src/mesh/api.js index c37bcd7b..71a8fd1d 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -24,7 +24,7 @@ let selected = []; let selection = { // @returns {MeshObject[]} list() { - return selected.slice() + return selected.slice(); }, // @param group {MeshObject[]} @@ -39,6 +39,11 @@ let selection = { this.update(); }, + toggle(object) { + selected.remove(object) || selected.addOnce(object); + this.update(); + }, + // @param group {MeshObject} remove(object) { selected.remove(object); @@ -172,6 +177,10 @@ let api = mesh.api = { remove: (model) => { model.group.remove(model); } + }, + + objects: () => { + return group.list().map(o => o.models).flat().map(o => o.object()); } }; diff --git a/src/mesh/model.js b/src/mesh/model.js index f8a10adc..c82efaf1 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -57,12 +57,12 @@ mesh.model = class MeshModel extends mesh.object { vertices: this.mesh.geometry.attributes.position.array, matrix: this.mesh.matrixWorld.elements }).then(data => { - console.log({data: data[0]}); - // mesh.api.group.new([new mesh.model({ - // file: "synth", - // mesh: data[0] - // })]); - this.load(data[0]); + if (data && data.length) + // for debugging matrix ops + return mesh.api.group.new([new mesh.model({ + file: "synth", + mesh: data[0] + })]); }); } @@ -78,9 +78,24 @@ mesh.model = class MeshModel extends mesh.object { meh.receiveShadow = true; meh.castShadow = true; meh.renderOrder = 1; + // this ref allows clicks to be traced to models and groups + meh.model = this; return meh; } + reload(vertices, indices) { + let geo = this.mesh.geometry; + geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); + geo.setAttribute('normal', undefined); + if (indices) { + geo.setIndex(new THREE.BufferAttribute(indices, 1)); + geo.attributes.index.needsUpdate = true; + } + geo.attributes.position.needsUpdate = true; + geo.computeFaceNormals(); + geo.computeVertexNormals(); + } + get group() { return this._group; } diff --git a/src/mesh/object.js b/src/mesh/object.js index d210fee5..29d113d5 100644 --- a/src/mesh/object.js +++ b/src/mesh/object.js @@ -77,6 +77,10 @@ mesh.object = class MeshObject { if (z) this.object().rotateOnWorldAxis(new THREE.Vector3(0,0,1), z); } + qrotate(quaternion) { + this.object().setRotationFromQuaternion(quaternion); + } + position() { let pos = this.object().position; if (arguments.length === 0) { diff --git a/src/mesh/work.js b/src/mesh/work.js index 9c0e968d..e510ea1a 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -22,7 +22,7 @@ let space_rotation = new THREE.Matrix4().makeRotationX(Math.PI / 2); moto.worker.bind("model_sync", (data, send) => { let { vertices, matrix } = data; - console.log('model_sync', {vertices, matrix, send}); + // return send.done(vertices); let geo = new THREE.BufferGeometry(); geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); geo.setAttribute('normal', undefined); @@ -30,6 +30,8 @@ moto.worker.bind("model_sync", (data, send) => { geo.computeVertexNormals(); let m4 = space_rotation.clone().multiply( new THREE.Matrix4().fromArray(matrix) ); geo.applyMatrix4(m4); + return send.done(); + // for debugging matrix ops send.done(geo.attributes.position.array); });