checkpoint

This commit is contained in:
Stewart Allen 2024-08-09 21:53:33 -04:00
commit 7ff172f5f3
7 changed files with 234 additions and 199 deletions

View file

@ -126,12 +126,10 @@ async function restore_space() {
return { id, md: cached[id] } return { id, md: cached[id] }
}) })
.filter(r => r.md) // filter cache misses .filter(r => r.md) // filter cache misses
.map(r => new mesh.model(r.md, r.id) .map(r => new mesh.model(r.md, r.id).applyMeta(mcache[r.id]))
.applyMatrix(mcache[r.id]?.matrix)
.visible(mcache[r.id]?.visible ?? true));
if (models.length) { if (models.length) {
log(`restored ${models.length} model(s)`); log(`restored ${models.length} model(s)`);
mesh.api.group.new(models, id).applyMatrix(mcache[id]?.matrix) mesh.api.group.new(models, id).applyMeta(mcache[id])
} else { } else {
log(`removed empty group ${id}`); log(`removed empty group ${id}`);
db_space.remove(id); db_space.remove(id);
@ -237,15 +235,12 @@ function space_init(data) {
case 'KeyA': case 'KeyA':
if (api.mode.is([ api.modes.edge ])) return mesh.edges.add(); if (api.mode.is([ api.modes.edge ])) return mesh.edges.add();
return shiftKey && api.tool.analyze(); return shiftKey && api.tool.analyze();
// case 'KeyR':
// return shiftKey ? api.tool.rebuild() : api.tool.repair();
case 'KeyE': case 'KeyE':
if (api.mode.is([ api.modes.sketch ])) { if (api.mode.is([ api.modes.sketch ])) {
estop(evt); estop(evt);
return api.sketch.extrude(); return api.sketch.extrude();
} }
return; return;
// return api.tool.clean();
case 'KeyV': case 'KeyV':
return shiftKey ? selection.show() : selection.focus(); return shiftKey ? selection.show() : selection.focus();
case 'KeyN': case 'KeyN':
@ -335,8 +330,7 @@ function space_init(data) {
break; break;
} }
if (rot && floor) { if (rot && floor) {
// todo future pref to auto-floor or not rot.floor();
rot.floor(mesh.group);
} }
} }
]); ]);
@ -396,7 +390,7 @@ function space_init(data) {
} }
} else if (ctrlKey) { } else if (ctrlKey) {
// rotate selected face towawrd z "floor" // rotate selected face towawrd z "floor"
group.faceDown(int.face.normal); group.rotateTowardZ(int.face.normal);
selection.update(); selection.update();
} else { } else {
const { modes } = api; const { modes } = api;
@ -610,9 +604,9 @@ function object_visible(data) {
} }
// cache model matrices for page restores // cache model matrices for page restores
function object_matrix(data) { function object_meta(data) {
let { id, matrix } = data; let { id, meta } = data;
update_meta(id, { matrix: matrix.elements }); update_meta(id, meta);
} }
function object_destroy(id) { function object_destroy(id) {
@ -706,7 +700,7 @@ function set_snap_value(snap) {
// bind functions to topics // bind functions to topics
broker.listeners({ broker.listeners({
load_files, load_files,
object_matrix, object_meta,
object_destroy, object_destroy,
object_visible, object_visible,
space_init, space_init,

View file

@ -253,14 +253,14 @@ const selection = {
floor() { floor() {
for (let s of selection.groups()) { for (let s of selection.groups()) {
s.floor(...arguments); s.floor();
} }
return selection; return selection;
}, },
centerXY() { centerXY() {
for (let s of [...selection.groups(), ...selection.sketches()]) { for (let s of [...selection.groups(), ...selection.sketches()]) {
s.centerXY(...arguments); s.centerXY();
} }
return selection; return selection;
}, },
@ -1096,17 +1096,10 @@ const tool = {
regroup(models) { regroup(models) {
models = fallback(models, true); models = fallback(models, true);
if (models.length === 0) { if (models.length) {
return; log(`regrouping ${models.length} model(s)`);
return mesh.api.group.new(models.map(m => m.ungroup()));
} }
log(`regrouping ${models.length} model(s)`);
let bounds = util.bounds(models);
let { mid } = bounds;
return Promise.all(models.map(m => m.ungroup())).then(() => {
return mesh.api.group.new(models)
.centerModels()
.position(mid.x, mid.y, mid.z);;
});
}, },
analyze(models, opt = { compound: true }) { analyze(models, opt = { compound: true }) {
@ -1410,8 +1403,8 @@ const api = exports({
let left, up; let left, up;
if (normal) { if (normal) {
let { x, y, z } = normal; let { x, y, z } = normal;
left = new Vector3(x,y,z).angleTo(new Vector3(0,-1,0)); left = new Vector3(x,y,0).angleTo(new Vector3(0,-1,0));
up = new Vector3(x,y,z).angleTo(new Vector3(0,0,1)); up = new Vector3(0,y,z).angleTo(new Vector3(0,0,1));
if (x < 0) left = -left; if (x < 0) left = -left;
} }
// sets "home" views (front, back, home, reset) // sets "home" views (front, back, home, reset)

View file

@ -13,13 +13,12 @@
gapp.register("mesh.group", [], (root, exports) => { gapp.register("mesh.group", [], (root, exports) => {
const { mesh, moto } = root; const { mesh, moto } = root;
const { Quaternion, Group, Vector3 } = THREE; const { Group, Box3 } = THREE;
const { broker } = gapp; const { broker } = gapp;
const { space } = moto; const { space } = moto;
const call = broker.send; const call = broker.send;
const worker = moto.client.fn; const worker = moto.client.fn;
const lookUp = new Vector3(0,0,-1);
mesh.group = class MeshGroup extends mesh.object { mesh.group = class MeshGroup extends mesh.object {
@ -42,6 +41,14 @@ mesh.group = class MeshGroup extends mesh.object {
return this.group3; return this.group3;
} }
get bounds() {
let box3 = new Box3();
for (let model of this.models) {
box3.union(model.bounds.translate(model.position()));
}
return box3;
}
// @param model {MeshModel} // @param model {MeshModel}
add(model) { add(model) {
model.group = this; model.group = this;
@ -58,7 +65,6 @@ mesh.group = class MeshGroup extends mesh.object {
// @param model {MeshModel} // @param model {MeshModel}
// @param free {boolean} prevent cleanup of model so it can be re-used // @param free {boolean} prevent cleanup of model so it can be re-used
remove(model, opt = { free: true }) { remove(model, opt = { free: true }) {
// console.log('group',this,'remove',model);
// remove all models and group // remove all models and group
if (arguments.length === 0) { if (arguments.length === 0) {
for (let m of this.models.slice()) { for (let m of this.models.slice()) {
@ -87,13 +93,6 @@ mesh.group = class MeshGroup extends mesh.object {
return this; return this;
} }
// rotate model so face normal points toward floor
faceDown(normal) {
let q = new Quaternion().setFromUnitVectors(normal, lookUp);
this.qrotation(q);
this.floor();
}
promote() { promote() {
this.centerModels(); this.centerModels();
let { dim, mid } = this.bounds; let { dim, mid } = this.bounds;
@ -110,34 +109,48 @@ mesh.group = class MeshGroup extends mesh.object {
} }
rotate(x = 0, y = 0, z = 0) { rotate(x = 0, y = 0, z = 0) {
console.log('group rotate', ...arguments); this.log('group-rotate', ...arguments);
for (let model of this.models) { for (let model of this.models) {
model.rotate(...arguments); model.rotate(...arguments);
} }
return this;
}
qrotate(quaternion) {
this.log('group-rotate', quaternion.toArray());
for (let model of this.models) {
model.qrotate(quaternion);
}
return this;
} }
scale(x = 1, y = 1, z = 1) { scale(x = 1, y = 1, z = 1) {
this.log('group-scale', ...arguments);
for (let m of this.models) { for (let m of this.models) {
m.scale(x, y, z); m.scale(x, y, z);
} }
return this; return this;
} }
// center objects to group bounds move(x = 0, y = 0, z = 0) {
// dependent on first being added to world/scene this.log('group-move', ...arguments);
centerModels() { if (!(x || y || z)) return;
let bounds = this.bounds;
for (let model of this.models) { for (let model of this.models) {
model.center(bounds); model.move(x, y, z);
}
let { center } = mesh.api.prefs.map.space;
if (center === false) {
let { mid } = bounds;
this.move(mid.x, mid.y, mid.z);
} }
return this; return this;
} }
center() {
let b = this.bounds;
return this.move(-b.mid.x, -b.mid.y, -b.mid.z);
}
centerXY() {
let b = this.bounds;
return this.move(-b.mid.x, -b.mid.y, 0);
}
opacity() { opacity() {
for (let model of this.models) { for (let model of this.models) {
model.opacity(...arguments); model.opacity(...arguments);

View file

@ -13,13 +13,15 @@
gapp.register("mesh.model", [], (root, exports) => { gapp.register("mesh.model", [], (root, exports) => {
const { MeshPhongMaterial, MeshBasicMaterial, LineBasicMaterial } = THREE; const { MeshPhongMaterial, MeshBasicMaterial, LineBasicMaterial } = THREE;
const { BufferGeometry, BufferAttribute, DoubleSide, Mesh } = THREE; const { BufferGeometry, BufferAttribute, DoubleSide, Mesh} = THREE;
const { Quaternion, Box3, Vector3 } = THREE;
const { mesh, moto } = root; const { mesh, moto } = root;
const { space } = moto; const { space } = moto;
const { api } = mesh; const { api } = mesh;
const mapp = mesh; const mapp = mesh;
const worker = moto.client.fn; const worker = moto.client.fn;
const zero = new Vector3(0,0,0);
/** default materials **/ /** default materials **/
let materials = mesh.material = { let materials = mesh.material = {
@ -122,6 +124,10 @@ mesh.model = class MeshModel extends mesh.object {
return this.mesh; return this.mesh;
} }
get bounds() {
return this.geometry.boundingBox.clone();
}
get matrix() { get matrix() {
return this.mesh.matrixWorld.elements; return this.mesh.matrixWorld.elements;
} }
@ -166,40 +172,82 @@ mesh.model = class MeshModel extends mesh.object {
} }
} }
rotate(x = 0, y = 0, z = 0) { qrotate(quaternion) {
console.log('model rotate', ...arguments); this.log('model-rotate', quaternion.toArray());
worker.model_rotate({ id: this.id, x, y, z }).then(() => { this.geometry.applyQuaternion(quaternion);
this.attributes.position.needsUpdate = true; this.updateBounds();
moto.space.update(); this.persist();
}); moto.space.update();
} }
// override and translate mesh scale(x = 1, y = 1, z = 1) {
xmove(x = 0, y = 0, z = 0) { this.log('model-scale', ...arguments, this.bounds);
let attr = this.attributes; if (x === 1 && y === 1 && z === 1) return;
let arr = attr.position.array; this.geometry.scale(x, y, z);
for (let i=0, l=arr.length; i<l; ) { this.updateBounds();
arr[i] = arr[i++] + x; this.persist();
arr[i] = arr[i++] + y; moto.space.update();
arr[i] = arr[i++] + z; }
translate(x = 0, y = 0, z = 0) {
this.log('model-translate', ...arguments);
if (!(x || y || z)) return;
this.geometry.translate(x, y, z);
this.updateBounds();
this.persist();
}
move(x = 0, y = 0, z = 0) {
this.log('model-move', ...arguments);
if (!(x || y || z)) return;
let pos = this.position();
return this.position(pos.x + x, pos.y + y, pos.z + z);
}
position() {
let pos = this.object.position;
if (arguments.length === 0) {
return pos;
} }
this.reload(arr, attr.index ? attr.index.array : undefined); pos.set(...arguments);
this.metaChanged();
return this; return this;
} }
// override and translate mesh // preserves world location while updating mesh for rotation and scaling
xscale(x = 1, y = 1, z = 1) { // moves mesh center to 0,0,0 via translation then
let attr = this.attributes; // moves mesh object to former bounds center
let arr = attr.position.array; reCenter() {
for (let i=0, l=arr.length; i<l; ) { this.log('model-center');
arr[i] = arr[i++] *= x; let pos = this.position();
arr[i] = arr[i++] *= y; let { mid } = this.bounds;
arr[i] = arr[i++] *= z; let moveTo = mid.clone().add(pos);
} this.translate(-mid.x, -mid.y, -mid.z);
this.reload(arr, attr.index ? attr.index.array : undefined); this.position(moveTo.x, moveTo.y, moveTo.z);
return this; return this;
} }
// preserves world location while updating mesh for rotation and scaling
// moves mesh center to x,y,z via translation then
// moves mesh object to former bounds center
centerTo(pos) {
}
updateBounds() {
if (this._wire)
this._wire.geometry.attributes.position.needsUpdate = true;
this.attributes.position.needsUpdate = true;
this.geometry.computeBoundingBox();
this.geometry.computeBoundingSphere();
this.log('update-bounds', this.geometry.boundingBox);
this.updateBoundsBox();
moto.space.update();
}
updateBoundsBox() {
this.group?.updateBoundsBox();
}
mirror() { mirror() {
return this.duplicate({ mirror: true }); return this.duplicate({ mirror: true });
} }
@ -209,27 +257,24 @@ mesh.model = class MeshModel extends mesh.object {
// defaults to returning a new model in a new group // defaults to returning a new model in a new group
// options to mirror, re-use a group, or update model in-place // options to mirror, re-use a group, or update model in-place
duplicate(opt = { select: true }) { duplicate(opt = { select: true }) {
return worker.model_duplicate({ let pos = this.position();
matrix: this.matrix, let data = this.attributes.position.clone().array;
id: this.id, if (opt.append) data = [...data, ...opt.append].toFloat32();
opt: { mirror: opt.mirror } if (opt.x) return this.reload(data);
}).then(data => { let model = new mesh.model({ file: `${this.file}`, mesh: data });
if (opt.append) data = [...data, ...opt.append].toFloat32(); let group = opt.group || mesh.api.group.new();
if (opt.x) return this.reload(data); group.add(model);
let model = new mesh.model({ file: `${this.file}`, mesh: data }); model.position(pos.x, pos.y, pos.z);
let group = opt.group || mesh.api.group.new(); model.wireframe(this.wireframe());
group.add(model); if (opt.select) {
model.wireframe(this.wireframe()); api.selection.add(model);
if (opt.select) { }
api.selection.add(model); if (opt.mirror) {
} group.move(0, 0, group.bounds.dim.z);
if (opt.mirror) { } else if (opt.shift) {
group.move(0, 0, group.bounds.dim.z); group.move(group.bounds.dim.x, 0, 0);
} else if (opt.shift) { }
group.move(group.bounds.dim.x, 0, 0); return model;
}
return model;
});
} }
rebuild(opt = {}) { rebuild(opt = {}) {
@ -259,11 +304,9 @@ mesh.model = class MeshModel extends mesh.object {
} }
load(vertices) { load(vertices) {
let shared = mesh.util.toSharedF32(vertices); this.log('load');
let local = mesh.util.toLocal32(vertices);
console.log('load', { vertices, local, shared });
let geo = new BufferGeometry(); let geo = new BufferGeometry();
geo.setAttribute('position', new BufferAttribute(shared, 3)); geo.setAttribute('position', new BufferAttribute(vertices, 3));
let meh = this.mesh = new Mesh(geo, [ let meh = this.mesh = new Mesh(geo, [
this.mats.normal, this.mats.normal,
this.mats.face this.mats.face
@ -277,39 +320,49 @@ mesh.model = class MeshModel extends mesh.object {
// 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 // persist in db so it can be restored on page load
mapp.db.space.put(this.id, { file: this.file, mesh: local }); this.persist();
// sync data to worker // sync data to worker
worker.model_load({ id: this.id, name: this.file, vertices: shared }); worker.model_load({ id: this.id, name: this.file, vertices });
// update bounds
this.updateBounds();
} }
reload(vertices) { reload(vertices) {
let local = mesh.util.toLocal32(vertices); this.log('reload');
let shared = mesh.util.toSharedF32(vertices);
console.trace('reload', { vertices, local, shared });
let was = this.wireframe(false); let was = this.wireframe(false);
let geo = this.mesh.geometry; let geo = this.mesh.geometry;
geo.setAttribute('position', new BufferAttribute(shared, 3)); geo.setAttribute('position', new BufferAttribute(vertices, 3));
// 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 // allows raycasting to work
geo.computeBoundingSphere(); // geo.computeBoundingSphere();
// 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, { file: this.file, mesh: local }); this.persist();
// sync data to worker // sync data to worker
worker.model_load({id: this.id, name: this.name, vertices: shared }); 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});
// 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();
}
persist() {
// 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, { file, mesh: this.attributes.position.array }); mapp.db.space.put(this.id, {
file: this.file,
mesh: this.attributes.position.array
});
} }
get group() { get group() {
@ -323,8 +376,12 @@ mesh.model = class MeshModel extends mesh.object {
this._group = gv; this._group = gv;
} }
get geometry() {
return this.mesh.geometry;
}
get attributes() { get attributes() {
return this.mesh.geometry.attributes; return this.geometry.attributes;
} }
get vertices() { get vertices() {
@ -460,6 +517,10 @@ mesh.model = class MeshModel extends mesh.object {
} }
} }
render() {
// TODO
}
// invert normals for entire mesh or selected faces depending on mod // invert normals for entire mesh or selected faces depending on mod
invert(mode) { invert(mode) {
let { modes } = mesh.api; let { modes } = mesh.api;
@ -529,13 +590,7 @@ mesh.model = class MeshModel extends mesh.object {
this.group.remove(this, { free: false }); this.group.remove(this, { free: false });
this.group = undefined; this.group = undefined;
} }
return worker.model_duplicate({ return this;
matrix: this.matrix,
id: this.id,
opt: {}
}).then(data => {
this.reload(data);
});
} }
// remove model from group and space // remove model from group and space
@ -553,12 +608,6 @@ mesh.model = class MeshModel extends mesh.object {
} }
} }
updateBoundsBox() {
if (this.group) {
mesh.util.defer(this.group.deferUBB);
}
}
clearSelections() { clearSelections() {
// clear face selections (since they've been deleted); // clear face selections (since they've been deleted);
this.sel.faces = []; this.sel.faces = [];
@ -597,13 +646,6 @@ mesh.model = class MeshModel extends mesh.object {
// clear face selections (since they've been deleted); // clear face selections (since they've been deleted);
this.sel.faces = []; this.sel.faces = [];
this.updateSelections(); this.updateSelections();
// let { modes } = mesh.api;
// switch (mode) {
// case modes.face:
// console.log('delete selected faces');
// break;
// }
} }
updateSelections() { updateSelections() {

View file

@ -14,10 +14,11 @@ const { mesh, moto } = root;
const { space } = moto; const { space } = moto;
const worker = moto.client.fn; const worker = moto.client.fn;
const lookUp = new Vector3(0,0,-1);
// broker updates generated by objects // broker updates generated by objects
let publish = { let publish = {
matrix: gapp.broker.bind("object_matrix"), meta: gapp.broker.bind("object_meta"),
destroy: gapp.broker.bind("object_destroy"), destroy: gapp.broker.bind("object_destroy"),
visible: gapp.broker.bind("object_visible"), visible: gapp.broker.bind("object_visible"),
}; };
@ -26,8 +27,14 @@ mesh.object = class MeshObject {
constructor(id) { constructor(id) {
this.id = id || mesh.util.uuid(); this.id = id || mesh.util.uuid();
this.deferUBB = () => { this.updateBoundsBox() };
worker.object_create({id: this.id, type: this.type}); worker.object_create({id: this.id, type: this.type});
this.log('NEW');
// storage location for meta data like position, scale, rotation
this.meta = {};
}
log() {
console.log(this.id, this.type, ...arguments);
} }
get type() { get type() {
@ -40,7 +47,7 @@ mesh.object = class MeshObject {
} }
get bounds() { get bounds() {
return mesh.util.bounds(this.object); throw "bounds() requires implementation";
} }
// manage lifecycle with worker, mesh app caches, etc // manage lifecycle with worker, mesh app caches, etc
@ -53,16 +60,26 @@ mesh.object = class MeshObject {
publish.destroy(this.id); publish.destroy(this.id);
} }
// used during state restoration
applyMeta(meta = {}) {
this.log('apply-meta', meta);
this.applyMatrix(meta.matrix);
this.visible(meta.visible ?? true);
return this;
}
// used during state restoration
applyMatrix(elements) { applyMatrix(elements) {
if (elements) { if (elements) {
console.log('matrix', this.type, this.id); this.log('apply-matrix');
this.object.applyMatrix4(new Matrix4().fromArray(elements)); this.object.applyMatrix4(new Matrix4().fromArray(elements));
return this.matrixChanged(); return this.metaChanged();
} else { } else {
return this; return this;
} }
} }
// used during model splitting
applyMatrix4(matrix) { applyMatrix4(matrix) {
return this.applyMatrix(matrix.elements); return this.applyMatrix(matrix.elements);
} }
@ -93,73 +110,58 @@ mesh.object = class MeshObject {
return this; return this;
} }
floor(clazz) { floor() {
if (!clazz || this instanceof clazz) { let b = this.bounds;
let b = this.bounds; return this.move(0, 0, -b.min.z);
this.move(0, 0, -b.min.z);
}
return this;
} }
center(bounds) { center() {
let b = bounds || this.bounds; throw "center() requires implementation";
this.move(-b.mid.x, -b.mid.y, -b.mid.z); let b = this.bounds;
return this; return this.move(-b.mid.x, -b.mid.y, -b.mid.z);
} }
centerXY(bounds) { centerXY() {
let b = bounds || this.bounds; throw "centerXY() requires implementation";
this.move(-b.mid.x, -b.mid.y, 0); let b = this.bounds;
return this; return this.move(-b.mid.x, -b.mid.y, 0);
} }
move(x = 0, y = 0, z = 0) { move() {
let pos = this.position(); throw "move() requires implementation";
return this.position(pos.x + x, pos.y + y, pos.z + z);
} }
scale() { scale() {
let scale = this.object.scale; throw "scale() requires implementation";
if (arguments.length === 0) { }
return scale;
} qrotate(quaternion) {
scale.set(...arguments); throw "qrotate() requires implementation";
this.matrixChanged();
} }
rotate(x = 0, y = 0, z = 0) { rotate(x = 0, y = 0, z = 0) {
throw "rotate() requires implementation"; this.log('object-rotate', ...arguments);
console.log('object rotate', ...arguments); let m = new Matrix4();
if (x) this.object.rotateOnWorldAxis(new Vector3(1,0,0), x); if (x) m.multiply(new Matrix4().makeRotationX(x));
if (y) this.object.rotateOnWorldAxis(new Vector3(0,1,0), y); if (y) m.multiply(new Matrix4().makeRotationY(y));
if (z) this.object.rotateOnWorldAxis(new Vector3(0,0,1), z); if (z) m.multiply(new Matrix4().makeRotationZ(z));
this.matrixChanged(); this.qrotate(new Quaternion().setFromRotationMatrix(m));
return this; return this;
} }
rotation() { rotation() {
throw "rotate() requires implementation"; throw "rotation() requires implementation";
let rotation = this.object.rotation;
if (arguments.length === 0) {
return rotation;
}
return this.qrotation(new Quaternion().setFromEuler(new Euler(...arguments)));
} }
qrotation(quaternion) { // rotate object in the directon of normal (place face on Z plane)
this.object.setRotationFromQuaternion(quaternion); rotateTowardZ(normal) {
this.matrixChanged(); let q = new Quaternion().setFromUnitVectors(normal, lookUp);
return this; this.qrotate(q);
this.floor();
} }
position() { position() {
let pos = this.object.position; throw "position() requires implementation";
if (arguments.length === 0) {
return pos;
}
pos.set(...arguments);
this.matrixChanged();
return this;
} }
showBounds(bool) { showBounds(bool) {
@ -175,6 +177,7 @@ mesh.object = class MeshObject {
} }
updateBoundsBox() { updateBoundsBox() {
this.log('update-bounds-box', this._showBounds);
let helper = this._boundsBox; let helper = this._boundsBox;
let world = space.world; let world = space.world;
if (helper) { if (helper) {
@ -192,12 +195,12 @@ mesh.object = class MeshObject {
} }
} }
matrixChanged() { metaChanged() {
if (!this.updateBoundsBox()) { this.object.updateMatrix();
this.object.updateMatrix(); this.updateBoundsBox();
}
space.update(); space.update();
publish.matrix({ id: this.id, matrix: this.object.matrix }); this.meta.matrix = this.object.matrix.elements;
publish.meta({ id: this.id, meta: this.meta });
return this; return this;
} }
}; };

View file

@ -549,7 +549,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
const euler = this.group.rotation; const euler = this.group.rotation;
const quaternion = new THREE.Quaternion(); const quaternion = new THREE.Quaternion();
quaternion.setFromEuler(euler); quaternion.setFromEuler(euler);
ngrp.qrotation(quaternion); ngrp.qrotate(quaternion);
} }
} }
} }

View file

@ -44,7 +44,7 @@ function log(msg) {
mesh.log = log; mesh.log = log;
function cacheUpdate(id, data) { function cacheUpdate(id, data) {
Object.assign(cache[id], data); return Object.assign(cache[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)
@ -98,15 +98,6 @@ function indexFaces(id) {
} }
let model = { 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));
},
load(data) { load(data) {
let { vertices, name, id } = data; let { vertices, name, id } = data;
let geo = new BufferGeometry(); let geo = new BufferGeometry();
@ -114,7 +105,6 @@ let model = {
cacheUpdate(id, { cacheUpdate(id, {
name, name,
geo, geo,
xmatrix: core_matrix.clone(),
trans: undefined, trans: undefined,
tool: undefined tool: undefined
}); });