diff --git a/src/mesh/group.js b/src/mesh/group.js index 33d50d40..7ab4cc2e 100644 --- a/src/mesh/group.js +++ b/src/mesh/group.js @@ -109,6 +109,19 @@ mesh.group = class MeshGroup extends mesh.object { return this; } + xrotate(x = 0, y = 0, z = 0) { + console.log('group rotate', ...arguments); + // super.rotate(...arguments); + for (let model of this.models) { + worker.model_rotate({ id: model.id, x, y, z }); + } + setTimeout(() => { + for (let model of this.models) { + model.attributes.position.needsUpdate = true; + } + }, 250); + } + scale(x = 1, y = 1, z = 1) { for (let m of this.models) { m.scale(x, y, z); diff --git a/src/mesh/model.js b/src/mesh/model.js index 02441261..f1d4b0d0 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -166,6 +166,11 @@ mesh.model = class MeshModel extends mesh.object { } } + rotate(x = 0, y = 0, z = 0) { + console.log('model rotate', ...arguments); + super.rotate(...arguments); + } + // override and translate mesh move(x = 0, y = 0, z = 0) { let attr = this.attributes; @@ -207,7 +212,7 @@ mesh.model = class MeshModel extends mesh.object { opt: { mirror: opt.mirror } }).then(data => { if (opt.append) data = [...data, ...opt.append].toFloat32(); - if (opt.reload) return this.reload(data); + if (opt.x) return this.reload(data); let model = new mesh.model({ file: `${this.file}`, mesh: data }); let group = opt.group || mesh.api.group.new(); group.add(model); @@ -251,8 +256,11 @@ mesh.model = class MeshModel extends mesh.object { } load(vertices) { + let shared = mesh.util.toSharedF32(vertices); + let local = mesh.util.toLocal32(vertices); + console.log('load', { vertices, local, shared }); let geo = new BufferGeometry(); - geo.setAttribute('position', new BufferAttribute(vertices, 3)); + geo.setAttribute('position', new BufferAttribute(shared, 3)); let meh = this.mesh = new Mesh(geo, [ this.mats.normal, this.mats.face @@ -266,24 +274,27 @@ mesh.model = class MeshModel extends mesh.object { // this ref allows clicks to be traced to models and groups meh.model = this; // persist in db so it can be restored on page load - mapp.db.space.put(this.id, { file: this.file, mesh: vertices }); + mapp.db.space.put(this.id, { file: this.file, mesh: local }); // sync data to worker - worker.model_load({id: this.id, name: this.file, vertices}); + worker.model_load({ id: this.id, name: this.file, vertices: shared }); } reload(vertices) { + let local = mesh.util.toLocal32(vertices); + let shared = mesh.util.toSharedF32(vertices); + console.log('reload', { vertices, local, shared }); let was = this.wireframe(false); let geo = this.mesh.geometry; - geo.setAttribute('position', new BufferAttribute(vertices, 3)); + geo.setAttribute('position', new BufferAttribute(shared, 3)); // signal util.box3expand that geometry changed geo._model_invalid = true; geo.computeVertexNormals(); // allows raycasting to work geo.computeBoundingSphere(); // persist in db so it can be restored on page load - mapp.db.space.put(this.id, { file: this.file, mesh: vertices }); + mapp.db.space.put(this.id, { file: this.file, mesh: local }); // sync data to worker - worker.model_load({id: this.id, name: this.name, vertices}); + worker.model_load({id: this.id, name: this.name, vertices: shared }); // restore wireframe state this.wireframe(was); // fixup normals diff --git a/src/mesh/object.js b/src/mesh/object.js index f7b73602..4f7258d7 100644 --- a/src/mesh/object.js +++ b/src/mesh/object.js @@ -128,6 +128,7 @@ mesh.object = class MeshObject { } rotate(x = 0, y = 0, z = 0) { + console.log('rotate', ...arguments); if (x) this.object.rotateOnWorldAxis(new Vector3(1,0,0), x); if (y) this.object.rotateOnWorldAxis(new Vector3(0,1,0), y); if (z) this.object.rotateOnWorldAxis(new Vector3(0,0,1), z); diff --git a/src/mesh/util.js b/src/mesh/util.js index 67322776..0dbffa39 100644 --- a/src/mesh/util.js +++ b/src/mesh/util.js @@ -300,6 +300,25 @@ const util = exports({ groups.push({ start: 0, count: Infinity }); } return groups; + }, + + toSharedF32(float32) { + if (float32.buffer instanceof SharedArrayBuffer) { + return float32; + } + let { buffer } = float32; + let shared = new Float32Array(new SharedArrayBuffer(buffer.byteLength)); + shared.set(float32); + return shared; + }, + + toLocal32(shared32) { + if (!(shared32.buffer instanceof SharedArrayBuffer)) { + return shared32; + } + let local = new Float32Array(shared32.length); + local.set(shared32); + return local; } }); diff --git a/src/mesh/work.js b/src/mesh/work.js index 39558b36..dc9a4d8e 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -21,6 +21,7 @@ gapp.main("mesh.work", [], (root) => { const { Matrix4, Vector3, BufferGeometry, BufferAttribute, computeFaceNormal } = THREE; +const { Quaternion } = THREE; const { base, mesh, moto } = root; const { client, worker } = moto; const { util } = mesh; @@ -97,6 +98,16 @@ function indexFaces(id) { } let model = { + rotate(data) { + let { id, x, y, z } = data; + let rec = cache[id]; + let { geo } = rec; + if (x) geo.applyQuaternion(new Quaternion().setFromAxisAngle(new Vector3(1,0,0), x)); + if (y) geo.applyQuaternion(new Quaternion().setFromAxisAngle(new Vector3(0,1,0), y)); + if (z) geo.applyQuaternion(new Quaternion().setFromAxisAngle(new Vector3(0,0,1), z)); + console.log({ rec, data, geo: geo.attributes.position.array }); + }, + load(data) { let { vertices, name, id } = data; let geo = new BufferGeometry();