add z split snapping and work translation caching

This commit is contained in:
Stewart Allen 2022-01-15 23:17:53 -05:00
commit 72d9469699
3 changed files with 66 additions and 16 deletions

View file

@ -145,30 +145,52 @@ let split = {
geo = new PlaneGeometry(1,1),
mat = new MeshPhongMaterial({
side: DoubleSide,
color: 0x999999,
color: 0x5555aa,
transparent: false,
opacity: 0.1
opacity: 0.5
})
);
space.scene.add(obj);
// hide until first hover
obj.visible = false;
// enable temp mode
let state = split.state = { button, obj };
let state = split.state = { button, obj, zlist:[] };
let models = state.models = api.selection.models();
let meshes = models.map(m => m.mesh);
// get z list for snapping
Promise.all(models.map(m => m.zlist(3))).then(zs => {
for (let z of zs.flat()) {
state.zlist.addOnce(z);
}
});
// for split and lay flat modes
space.mouse.onHover((int, event, ints) => {
let models = state.models = api.selection.models();
let meshes = models.map(m => m.mesh);
if (!event) {
return meshes;
}
obj.visible = false;
let { button, buttons } = event;
if (buttons) {
return;
}
let { dim, mid } = util.bounds(meshes);
let { x, y, z } = int.point;
// snap to zlist when shift pressed
let { zlist } = state;
mat.color.set(0x5555aa);
obj.visible = true;
if (event.shiftKey && zlist.length) {
for (let v of zlist) {
if (Math.abs(v - y) < 0.1) {
mat.color.set(0xaa5555);
y = v;
break;
}
}
}
// y is z in model space for the purposes of a split
state.plane = { z: y };
obj.scale.set(dim.x, dim.y, 1);
obj.scale.set(dim.x + 2, dim.y + 2, 1);
obj.position.set(mid.x, y, -mid.y);
});
temp_mode = split;
@ -176,9 +198,9 @@ let split = {
select() {
let { log } = mesh.api;
let { models, plane } = split.state;
let { models, plane, zlist } = split.state;
log.emit(`splitting ${models.length} model(s) at ${plane.z.round(3)}`).pin();
Promise.all(models.map(m => m.split(plane))).then(() => {
Promise.all(models.map(m => m.split(plane))).then(models => {
log.emit('split complete').unpin();
split.end();
});

View file

@ -350,9 +350,10 @@ mesh.model = class MeshModel extends mesh.object {
let { id, matrix } = this;
worker.model_split({id, matrix, z}).then(data => {
let { o1, o2 } = data;
let model;
// new model becomes top
if (o2.length)
this.group.add(new mesh.model({
this.group.add(model = new mesh.model({
file: `${this.file}`,
mesh: o2
}).applyMatrix4(m4)).select();
@ -362,8 +363,17 @@ mesh.model = class MeshModel extends mesh.object {
} else {
this.remove();
}
// and we're done
resolve();
// return the split model
resolve(model);
});
});
}
zlist(round = 2) {
return new Promise((resolve,reject) => {
let { id, matrix } = this;
worker.model_zlist({id, matrix, round}).then(data => {
resolve(data);
});
});
}

View file

@ -36,10 +36,15 @@ function cacheUpdate(id, data) {
// translate original mesh vertices into UI world view (PI/2 rotation on X)
function translate_encode(id, matrix) {
let rec = cache[id];
let geo = rec.geo.clone();
let mat = core_matrix.clone().multiply(new Matrix4().fromArray(matrix));
geo.applyMatrix4(mat);
return geo.attributes.position.array;
let mkey = matrix.map(v => v.round(6)).join('-');
if (!rec || !rec.trans || rec.mkey !== mkey) {
let geo = rec.geo.clone();
let mat = core_matrix.clone().multiply(new Matrix4().fromArray(matrix));
geo.applyMatrix4(mat);
rec.mkey = mkey;
rec.trans = geo.attributes.position.array
}
return rec.trans;
}
function analyze(id, opt = {}) {
@ -62,7 +67,7 @@ let model = {
let geo = new BufferGeometry();
geo.setAttribute('position', new BufferAttribute(vertices, 3));
if (indices) geo.setIndex(new BufferAttribute(indices, 1));
cacheUpdate(id, { name, geo, matrix: core_matrix.clone() });
cacheUpdate(id, { name, geo, xmatrix: core_matrix.clone(), trans: undefined });
},
// return new vertices in world coordinates
@ -83,6 +88,19 @@ let model = {
return data;
},
// used to generate a list for split snapping
zlist(data) {
let { id, matrix, round } = data;
let zlist = {};
let pos = translate_encode(id, matrix);
for (let i=0, l=pos.length; i<l; ) {
let v1 = new Vector3(pos[i++], pos[i++], pos[i++]);
let z = v1.z.round(round || 2);
zlist[z] = '';
}
return Object.keys(zlist);
},
// split a model along an axis at a given point
// return two arrays of vertices for each resulting object
split(data) {