update worker/db sync model
This commit is contained in:
parent
0b28616bfd
commit
08f67a0ea6
5 changed files with 68 additions and 67 deletions
|
|
@ -943,9 +943,8 @@ const tool = {
|
||||||
return log('nothing to union');
|
return log('nothing to union');
|
||||||
}
|
}
|
||||||
log(`union ${models.length} models`).pin();
|
log(`union ${models.length} models`).pin();
|
||||||
worker.model_union(models.map(m => {
|
worker
|
||||||
return { id: m.id, matrix: m.matrix }
|
.model_union(models.map(m => m.id))
|
||||||
}))
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
api.selection.visible(false);
|
api.selection.visible(false);
|
||||||
let group = api.group.new([new mesh.model({
|
let group = api.group.new([new mesh.model({
|
||||||
|
|
@ -968,9 +967,7 @@ const tool = {
|
||||||
return log('nothing to diff');
|
return log('nothing to diff');
|
||||||
}
|
}
|
||||||
log(`diff ${models.length} models`).pin();
|
log(`diff ${models.length} models`).pin();
|
||||||
worker.model_difference(models.map(m => {
|
worker.model_difference(models.map(m => m.id))
|
||||||
return { id: m.id, matrix: m.matrix }
|
|
||||||
}))
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
api.selection.visible(false);
|
api.selection.visible(false);
|
||||||
let group = api.group.new([new mesh.model({
|
let group = api.group.new([new mesh.model({
|
||||||
|
|
@ -993,9 +990,7 @@ const tool = {
|
||||||
return log('nothing to intersect');
|
return log('nothing to intersect');
|
||||||
}
|
}
|
||||||
log(`intersect ${models.length} models`).pin();
|
log(`intersect ${models.length} models`).pin();
|
||||||
worker.model_intersect(models.map(m => {
|
worker.model_intersect(models.map(m => m.id))
|
||||||
return { id: m.id, matrix: m.matrix }
|
|
||||||
}))
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let group = api.group.new([new mesh.model({
|
let group = api.group.new([new mesh.model({
|
||||||
file: `intersect`,
|
file: `intersect`,
|
||||||
|
|
@ -1019,7 +1014,7 @@ const tool = {
|
||||||
}
|
}
|
||||||
log(`subtract ${models.length} models`).pin();
|
log(`subtract ${models.length} models`).pin();
|
||||||
worker.model_subtract(models.map(m => {
|
worker.model_subtract(models.map(m => {
|
||||||
return { id: m.id, matrix: m.matrix, tool: m.tool() }
|
return { id: m.id, tool: m.tool() }
|
||||||
}))
|
}))
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let group = api.group.new([new mesh.model({
|
let group = api.group.new([new mesh.model({
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ mesh.group = class MeshGroup extends mesh.object {
|
||||||
}
|
}
|
||||||
|
|
||||||
promote() {
|
promote() {
|
||||||
this.centerModels();
|
|
||||||
let { dim, mid } = this.bounds;
|
let { dim, mid } = this.bounds;
|
||||||
let { x, y, z } = dim;
|
let { x, y, z } = dim;
|
||||||
let max = Math.max(x, y, z);
|
let max = Math.max(x, y, z);
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,10 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
.attributes.position.array;
|
.attributes.position.array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get positions() {
|
||||||
|
return this.geometry.attributes.position.array;
|
||||||
|
}
|
||||||
|
|
||||||
get matrix() {
|
get matrix() {
|
||||||
return this.mesh.matrixWorld.elements;
|
return this.mesh.matrixWorld.elements;
|
||||||
}
|
}
|
||||||
|
|
@ -188,8 +192,6 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
this.log('model-rotate', quaternion.toArray());
|
this.log('model-rotate', quaternion.toArray());
|
||||||
this.geometry.applyQuaternion(quaternion);
|
this.geometry.applyQuaternion(quaternion);
|
||||||
this.updateBounds();
|
this.updateBounds();
|
||||||
this.persist();
|
|
||||||
moto.space.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scale(x = 1, y = 1, z = 1) {
|
scale(x = 1, y = 1, z = 1) {
|
||||||
|
|
@ -197,8 +199,6 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
if (x === 1 && y === 1 && z === 1) return;
|
if (x === 1 && y === 1 && z === 1) return;
|
||||||
this.geometry.scale(x, y, z);
|
this.geometry.scale(x, y, z);
|
||||||
this.updateBounds();
|
this.updateBounds();
|
||||||
this.persist();
|
|
||||||
moto.space.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
translate(x = 0, y = 0, z = 0) {
|
translate(x = 0, y = 0, z = 0) {
|
||||||
|
|
@ -206,7 +206,6 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
if (!(x || y || z)) return;
|
if (!(x || y || z)) return;
|
||||||
this.geometry.translate(x, y, z);
|
this.geometry.translate(x, y, z);
|
||||||
this.updateBounds();
|
this.updateBounds();
|
||||||
this.persist();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
move(x = 0, y = 0, z = 0) {
|
move(x = 0, y = 0, z = 0) {
|
||||||
|
|
@ -222,7 +221,7 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
pos.set(...arguments);
|
pos.set(...arguments);
|
||||||
this.metaChanged();
|
this.metaChanged({ pos: pos.toArray() });
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,6 +263,7 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
this.log('update-bounds', this.geometry.boundingBox);
|
this.log('update-bounds', this.geometry.boundingBox);
|
||||||
this.updateBoundsBox();
|
this.updateBoundsBox();
|
||||||
moto.space.update();
|
moto.space.update();
|
||||||
|
this.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBoundsBox() {
|
updateBoundsBox() {
|
||||||
|
|
@ -315,11 +315,7 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
this.opacity(1);
|
this.opacity(1);
|
||||||
// this ref allows clicks to be traced to models and groups
|
// this ref allows clicks to be traced to models and groups
|
||||||
meh.model = this;
|
meh.model = this;
|
||||||
// persist in db so it can be restored on page load
|
// sync worker, allows raycasting to work
|
||||||
this.persist();
|
|
||||||
// sync data to worker
|
|
||||||
worker.model_load({ id: this.id, name: this.file, vertices });
|
|
||||||
// update bounds
|
|
||||||
this.updateBounds();
|
this.updateBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,29 +327,25 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
// signal util.box3expand that geometry changed
|
// signal util.box3expand that geometry changed
|
||||||
geo._model_invalid = true;
|
geo._model_invalid = true;
|
||||||
geo.computeVertexNormals();
|
geo.computeVertexNormals();
|
||||||
// allows raycasting to work
|
|
||||||
// geo.computeBoundingSphere();
|
|
||||||
// persist in db so it can be restored on page load
|
|
||||||
this.persist();
|
|
||||||
// sync data to worker
|
|
||||||
worker.model_load({id: this.id, name: this.name, vertices });
|
|
||||||
// restore wireframe state
|
// restore wireframe state
|
||||||
this.wireframe(was);
|
this.wireframe(was);
|
||||||
// fixup normals
|
// fixup normals
|
||||||
this.normals({refresh: true});
|
this.normals({refresh: true});
|
||||||
|
// sync worker, allows raycasting to work
|
||||||
|
this.updateBounds();
|
||||||
// re-gen face index in surface mode
|
// re-gen face index in surface mode
|
||||||
mesh.api.mode.check();
|
mesh.api.mode.check();
|
||||||
// allows raycasting to work
|
|
||||||
// update bounds
|
|
||||||
this.updateBounds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rename(file) {
|
rename(file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.persist();
|
this.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
persist() {
|
// sync to worker and indexeddb for page restoration or worker ops
|
||||||
|
sync() {
|
||||||
|
// sync to worker
|
||||||
|
worker.model_load({ id: this.id, name: this.file, vertices: this.positions });
|
||||||
// persist in db so it can be restored on page load
|
// persist in db so it can be restored on page load
|
||||||
mapp.db.space.put(this.id, {
|
mapp.db.space.put(this.id, {
|
||||||
file: this.file,
|
file: this.file,
|
||||||
|
|
@ -556,7 +548,7 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
// extract axes from plane and split when present (only z for now)
|
// extract axes from plane and split when present (only z for now)
|
||||||
let { z } = plane;
|
let { z } = plane;
|
||||||
return new Promise((resolve,reject) => {
|
return new Promise((resolve,reject) => {
|
||||||
worker.model_split({ pos: this.world_positions, z }).then(data => {
|
worker.model_split({ id: this.id, z }).then(data => {
|
||||||
let { o1, o2 } = data;
|
let { o1, o2 } = data;
|
||||||
let model;
|
let model;
|
||||||
if (o1.length)
|
if (o1.length)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ mesh.object = class MeshObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
log() {
|
log() {
|
||||||
console.log(this.id, this.type, ...arguments);
|
// mesh.api.log.emit(this.id, this.type, ...arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
get type() {
|
get type() {
|
||||||
|
|
@ -65,6 +65,7 @@ mesh.object = class MeshObject {
|
||||||
this.log('apply-meta', meta);
|
this.log('apply-meta', meta);
|
||||||
this.applyMatrix(meta.matrix);
|
this.applyMatrix(meta.matrix);
|
||||||
this.visible(meta.visible ?? true);
|
this.visible(meta.visible ?? true);
|
||||||
|
this.metaChanged(meta);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,10 +74,8 @@ mesh.object = class MeshObject {
|
||||||
if (elements) {
|
if (elements) {
|
||||||
this.log('apply-matrix');
|
this.log('apply-matrix');
|
||||||
this.object.applyMatrix4(new Matrix4().fromArray(elements));
|
this.object.applyMatrix4(new Matrix4().fromArray(elements));
|
||||||
return this.metaChanged();
|
|
||||||
} else {
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// used during model splitting
|
// used during model splitting
|
||||||
|
|
@ -195,11 +194,14 @@ mesh.object = class MeshObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metaChanged() {
|
metaChanged(values = {}) {
|
||||||
this.object.updateMatrix();
|
this.object.updateMatrix();
|
||||||
this.updateBoundsBox();
|
this.updateBoundsBox();
|
||||||
space.update();
|
space.update();
|
||||||
this.meta.matrix = this.object.matrix.elements;
|
Object.assign(this.meta, values, {
|
||||||
|
matrix: this.object.matrix.elements
|
||||||
|
});
|
||||||
|
worker.object_meta({ id: this.id, meta: this.meta });
|
||||||
publish.meta({ id: this.id, meta: this.meta });
|
publish.meta({ id: this.id, meta: this.meta });
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
gapp.main("mesh.work", [], (root) => {
|
gapp.main("mesh.work", [], (root) => {
|
||||||
|
|
||||||
const { Matrix4, Vector3, BufferGeometry, BufferAttribute, computeFaceNormal } = THREE;
|
const { Matrix4, Vector3, BufferGeometry, BufferAttribute, computeFaceNormal } = THREE;
|
||||||
const { Quaternion } = THREE;
|
const { Quaternion, } = THREE;
|
||||||
const { base, mesh, moto } = root;
|
const { base, mesh, moto } = root;
|
||||||
const { client, worker } = moto;
|
const { client, worker } = moto;
|
||||||
const { util } = mesh;
|
const { util } = mesh;
|
||||||
|
|
@ -48,13 +48,19 @@ function cacheUpdate(id, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate original mesh vertices into UI world view (PI/2 rotation on X)
|
// translate original mesh vertices into UI world view (PI/2 rotation on X)
|
||||||
function translate_encode(id, matrix) {
|
function translate_encode(id) {
|
||||||
let rec = cache[id];
|
let rec = cache[id];
|
||||||
|
let { pos, matrix } = rec;
|
||||||
let mkey = matrix.map(v => v.round(6)).join('-');
|
let mkey = matrix.map(v => v.round(6)).join('-');
|
||||||
|
// re-translate on missing cache or changed matrix
|
||||||
if (!rec || !rec.trans || rec.mkey !== mkey) {
|
if (!rec || !rec.trans || rec.mkey !== mkey) {
|
||||||
let geo = rec.geo.clone();
|
let geo = rec.geo.clone();
|
||||||
|
if (pos) {
|
||||||
|
geo.translate(new Vector3().fromArray(pos));
|
||||||
|
} else {
|
||||||
let mat = core_matrix.clone().multiply(new Matrix4().fromArray(matrix));
|
let mat = core_matrix.clone().multiply(new Matrix4().fromArray(matrix));
|
||||||
geo.applyMatrix4(mat);
|
geo.applyMatrix4(mat);
|
||||||
|
}
|
||||||
rec.mkey = mkey;
|
rec.mkey = mkey;
|
||||||
rec.trans = geo.attributes.position.array
|
rec.trans = geo.attributes.position.array
|
||||||
}
|
}
|
||||||
|
|
@ -122,22 +128,22 @@ let model = {
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
union(recs) {
|
union(ids) {
|
||||||
let arrays = recs.map(rec => translate_encode(rec.id, rec.matrix));
|
let arrays = ids.map(id => translate_encode(id));
|
||||||
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
||||||
let union = CSG.union(...solids);
|
let union = CSG.union(...solids);
|
||||||
return CSG.toPositionArray(union);
|
return CSG.toPositionArray(union);
|
||||||
},
|
},
|
||||||
|
|
||||||
difference(recs) {
|
difference(ids) {
|
||||||
let arrays = recs.map(rec => translate_encode(rec.id, rec.matrix));
|
let arrays = ids.map(id => translate_encode(id));
|
||||||
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
||||||
let diff = CSG.difference(...solids);
|
let diff = CSG.difference(...solids);
|
||||||
return CSG.toPositionArray(diff);
|
return CSG.toPositionArray(diff);
|
||||||
},
|
},
|
||||||
|
|
||||||
intersect(recs) {
|
intersect(ids) {
|
||||||
let arrays = recs.map(rec => translate_encode(rec.id, rec.matrix));
|
let arrays = ids.map(id => translate_encode(id));
|
||||||
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
let solids = arrays.map(a => CSG.fromPositionArray(a));
|
||||||
let union = CSG.intersect(...solids);
|
let union = CSG.intersect(...solids);
|
||||||
return CSG.toPositionArray(union);
|
return CSG.toPositionArray(union);
|
||||||
|
|
@ -145,10 +151,10 @@ let model = {
|
||||||
|
|
||||||
subtract(recs) {
|
subtract(recs) {
|
||||||
let bases = recs.filter(rec => !rec.tool)
|
let bases = recs.filter(rec => !rec.tool)
|
||||||
.map(rec => translate_encode(rec.id, rec.matrix))
|
.map(rec => translate_encode(rec.id))
|
||||||
.map(a => CSG.fromPositionArray(a));
|
.map(a => CSG.fromPositionArray(a));
|
||||||
let tools = recs.filter(rec => rec.tool)
|
let tools = recs.filter(rec => rec.tool)
|
||||||
.map(rec => translate_encode(rec.id, rec.matrix))
|
.map(rec => translate_encode(rec.id))
|
||||||
.map(a => CSG.fromPositionArray(a));
|
.map(a => CSG.fromPositionArray(a));
|
||||||
let subs = [];
|
let subs = [];
|
||||||
for (let obj of bases) {
|
for (let obj of bases) {
|
||||||
|
|
@ -161,7 +167,8 @@ let model = {
|
||||||
// split a model along an axis at a given point
|
// split a model along an axis at a given point
|
||||||
// return two arrays of vertices for each resulting object
|
// return two arrays of vertices for each resulting object
|
||||||
split(data) {
|
split(data) {
|
||||||
let { pos, z } = data;
|
let { id, z } = data;
|
||||||
|
let pos = translate_encode(id);
|
||||||
let o1 = []; // new bottom
|
let o1 = []; // new bottom
|
||||||
let o2 = []; // new top
|
let o2 = []; // new top
|
||||||
let on = [];
|
let on = [];
|
||||||
|
|
@ -372,6 +379,12 @@ let group = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = {
|
let object = {
|
||||||
|
meta(data) {
|
||||||
|
let { id, meta } = data;
|
||||||
|
cacheUpdate(id, meta);
|
||||||
|
console.log('object_meta', data);
|
||||||
|
},
|
||||||
|
|
||||||
create(data) {
|
create(data) {
|
||||||
let { id, type } = data;
|
let { id, type } = data;
|
||||||
cache[id] = { id, type };
|
cache[id] = { id, type };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue