checkpoint mesh split work
This commit is contained in:
parent
b549aad3fe
commit
eac30a458f
4 changed files with 103 additions and 36 deletions
|
|
@ -229,6 +229,13 @@ const selection = {
|
|||
return selection;
|
||||
},
|
||||
|
||||
move_models(dx = 0, dy = 0, dz = 0) {
|
||||
for (let s of selection.models()) {
|
||||
s.move(dx, dy, dz);
|
||||
}
|
||||
return selection;
|
||||
},
|
||||
|
||||
rotate(dx = 0, dy = 0, dz = 0) {
|
||||
for (let s of selection.groups()) {
|
||||
s.rotate(dx, dy, dz);
|
||||
|
|
|
|||
|
|
@ -986,16 +986,19 @@ function ui_build() {
|
|||
e.classList.add('editable');
|
||||
});
|
||||
group_val_X_pos.onclick = field_edit('x position', (group, val) => {
|
||||
let r = group.position();
|
||||
group.position(val, r.y, r.z);
|
||||
// let r = group.position();
|
||||
// group.position(val, r.y, r.z);
|
||||
selection.move_models(val,0,0);
|
||||
}, { floor: false });
|
||||
group_val_Y_pos.onclick = field_edit('y position', (group, val) => {
|
||||
let r = group.position();
|
||||
group.position(r.x, val, r.z);
|
||||
// let r = group.position();
|
||||
// group.position(r.x, val, r.z);
|
||||
selection.move_models(0,val,0);
|
||||
}, { floor: false });
|
||||
group_val_Z_pos.onclick = field_edit('z position', (group, val) => {
|
||||
let r = group.position();
|
||||
group.position(r.x, r.y, val);
|
||||
// let r = group.position();
|
||||
// group.position(r.x, r.y, val);
|
||||
selection.move_models(0,0,val);
|
||||
}, { floor: false });
|
||||
|
||||
// bind scale editable fields
|
||||
|
|
|
|||
|
|
@ -553,14 +553,17 @@ mesh.model = class MeshModel extends mesh.object {
|
|||
return new Promise((resolve,reject) => {
|
||||
worker.model_split({ id: this.id, z }).then(data => {
|
||||
let { o1, o2 } = data;
|
||||
if (!(o1 || o2)) {
|
||||
return resolve(this.group);
|
||||
}
|
||||
if (o1?.length)
|
||||
this.group.add(new mesh.model({
|
||||
file: `${this.file}-top`,
|
||||
file: `${this.file}-bot`,
|
||||
mesh: o1
|
||||
}).reCenter());
|
||||
if (o2?.length)
|
||||
this.group.add(new mesh.model({
|
||||
file: `${this.file}-bot`,
|
||||
file: `${this.file}-top`,
|
||||
mesh: o2
|
||||
}).reCenter());
|
||||
this.remove();
|
||||
|
|
|
|||
110
src/mesh/work.js
110
src/mesh/work.js
|
|
@ -20,7 +20,7 @@
|
|||
// dep: mesh.tool
|
||||
gapp.main("mesh.work", [], (root) => {
|
||||
|
||||
const { Matrix4, Vector3, BufferGeometry, BufferAttribute, computeFaceNormal } = THREE;
|
||||
const { Triangle, Vector3, BufferGeometry, BufferAttribute, computeFaceNormal } = THREE;
|
||||
const { base, mesh, moto } = root;
|
||||
const { client, worker } = moto;
|
||||
const { CSG, newPoint, newPolygon, sliceConnect } = base;
|
||||
|
|
@ -152,6 +152,7 @@ let model = {
|
|||
// return two arrays of vertices for each resulting object
|
||||
split(data) {
|
||||
let { id, z } = data;
|
||||
z = z.round(3);
|
||||
let pos = translate_encode(id);
|
||||
let o1 = []; // new bottom
|
||||
let o2 = []; // new top
|
||||
|
|
@ -169,38 +170,57 @@ let model = {
|
|||
let z1 = Math.abs(v1.z - z);
|
||||
return v1.clone().lerp(v2, z1/zd);
|
||||
}
|
||||
function newV(x,y,z) {
|
||||
return new Vector3(x.round(3), y.round(3), z.round(3));
|
||||
}
|
||||
for (let i=0, l=pos.length; i<l; ) {
|
||||
let v1 = new Vector3(pos[i++], pos[i++], pos[i++]);
|
||||
let v2 = new Vector3(pos[i++], pos[i++], pos[i++]);
|
||||
let v3 = new Vector3(pos[i++], pos[i++], pos[i++]);
|
||||
on.length = over.length = under.length = 0;
|
||||
let v1 = newV(pos[i++], pos[i++], pos[i++]);
|
||||
let v2 = newV(pos[i++], pos[i++], pos[i++]);
|
||||
let v3 = newV(pos[i++], pos[i++], pos[i++]);
|
||||
sort(v1);
|
||||
sort(v2);
|
||||
sort(v3);
|
||||
let onl = on.length;
|
||||
let overl = over.length;
|
||||
let underl = under.length;
|
||||
let isover = (overl === 3 || underl === 0);
|
||||
let isunder = (underl === 3 || overl === 0);
|
||||
let split = !(isover || isunder);
|
||||
let isover = (onl + overl === 3);
|
||||
let isunder = (onl + underl === 3);
|
||||
if (onl === 3) {
|
||||
// co-planar
|
||||
let tri = new Triangle(...on);
|
||||
let norm = tri.getNormal(new Vector3());
|
||||
if (norm.z > 0) {
|
||||
isover = false;
|
||||
isunder = true;
|
||||
} else {
|
||||
isover = true;
|
||||
isunder = false;
|
||||
}
|
||||
}
|
||||
if (isover) {
|
||||
o2.appendAll([...v1, ...v2, ...v3]);
|
||||
}
|
||||
if (isunder) {
|
||||
o1.appendAll([...v1, ...v2, ...v3]);
|
||||
}
|
||||
if (split) {
|
||||
// all points on or over
|
||||
o2.appendAll([ v1, v2, v3 ]);
|
||||
} else if (isunder) {
|
||||
// all points on or under
|
||||
o1.appendAll([ v1, v2, v3 ]);
|
||||
} else {
|
||||
console.log('split');
|
||||
let g1, g2, oa, ua;
|
||||
if (overl === 2) {
|
||||
// two over, one under
|
||||
g1 = o2;
|
||||
g2 = o1;
|
||||
oa = over;
|
||||
ua = under;
|
||||
} else if (underl === 2) {
|
||||
// two under, one over
|
||||
g1 = o1;
|
||||
g2 = o2;
|
||||
oa = under;
|
||||
ua = over;
|
||||
} else if (onl === 1) {
|
||||
// one on, one over, one under
|
||||
let p1 = over[0];
|
||||
let p2 = on[0];
|
||||
let p3 = under[0];
|
||||
|
|
@ -210,32 +230,65 @@ let model = {
|
|||
|| (v1 === p3 && v2 === p1);
|
||||
// clockwise vs counter-clockwise
|
||||
if (cw) {
|
||||
o1.appendAll([ ...p2, ...p3, ...p4 ]);
|
||||
o2.appendAll([ ...p1, ...p2, ...p4 ]);
|
||||
o1.appendAll([ p2, p3, p4 ]);
|
||||
o2.appendAll([ p1, p2, p4 ]);
|
||||
} else {
|
||||
o1.appendAll([ ...p3, ...p2, ...p4 ]);
|
||||
o2.appendAll([ ...p2, ...p1, ...p4 ]);
|
||||
o1.appendAll([ p3, p2, p4 ]);
|
||||
o2.appendAll([ p2, p1, p4 ]);
|
||||
}
|
||||
on.length = over.length = under.length = 0;
|
||||
continue;
|
||||
}
|
||||
let [ p1, p2 ] = oa;
|
||||
let p3 = ua[0] || on[0]; // under or on
|
||||
let p3 = ua[0] || on[0]; // lone point
|
||||
let m1 = lerp(p1, p3);
|
||||
let m2 = lerp(p2, p3);
|
||||
if (v2 === ua[0]) {
|
||||
// reverse when the mid point gap
|
||||
g1.appendAll([ ...m1, ...p2, ...p1 ]);
|
||||
g1.appendAll([ ...m1, ...m2, ...p2 ]);
|
||||
g2.appendAll([ ...p3, ...m2, ...m1 ]);
|
||||
g1.appendAll([ m1, p2, p1 ]);
|
||||
g1.appendAll([ m1, m2, p2 ]);
|
||||
g2.appendAll([ p3, m2, m1 ]);
|
||||
} else {
|
||||
g1.appendAll([ ...p1, ...p2, ...m1 ]);
|
||||
g1.appendAll([ ...p2, ...m2, ...m1 ]);
|
||||
g2.appendAll([ ...m1, ...m2, ...p3 ]);
|
||||
g1.appendAll([ p1, p2, m1 ]);
|
||||
g1.appendAll([ p2, m2, m1 ]);
|
||||
g2.appendAll([ m1, m2, p3 ]);
|
||||
}
|
||||
edges.push({ p1: newPoint().move(m1), p2: newPoint().move(m2) });
|
||||
}
|
||||
on.length = over.length = under.length = 0;
|
||||
}
|
||||
{
|
||||
// find unshared edges on Z plane
|
||||
let faces = o1.group(3);
|
||||
for (let face of faces) {
|
||||
edges.push({ p1: face[0], p2: face[1] });
|
||||
edges.push({ p1: face[1], p2: face[2] });
|
||||
edges.push({ p1: face[2], p2: face[0] });
|
||||
}
|
||||
// eliminate edges that show up twice since it means they're shared
|
||||
outer: for (let i=0, l=edges.length; i<l; i++) {
|
||||
for (let j=i+1; j<l; j++) {
|
||||
let e1 = edges[i];
|
||||
let e2 = edges[j];
|
||||
if (!(e1 && e2)) {
|
||||
continue;
|
||||
}
|
||||
if (e1.p1.equals(e2.p1) && e1.p2.equals(e2.p2)) {
|
||||
edges[i] = edges[j] = undefined;
|
||||
continue outer;
|
||||
}
|
||||
if (e1.p2.equals(e2.p1) && e1.p1.equals(e2.p2)) {
|
||||
edges[i] = edges[j] = undefined;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
// filter and convert Vector3 to Point for sliceConnect()
|
||||
edges = edges.filter(e => e && e.p1.z === z && e.p2.z === z).map(e => {
|
||||
return {
|
||||
p1: newPoint().move(e.p1),
|
||||
p2: newPoint().move(e.p2),
|
||||
}
|
||||
});
|
||||
o1 = o1.map(e => [ ...e ]).flat();
|
||||
o2 = o2.map(e => [ ...e ]).flat();
|
||||
}
|
||||
if (edges.length) {
|
||||
// heal open spaces created by split
|
||||
|
|
@ -244,8 +297,9 @@ let model = {
|
|||
let o2p = heal.map(poly => poly.points.reverse().map(p => [ p.x, p.y, p.z ]));
|
||||
o1.appendAll(o1p.flat().flat());
|
||||
o2.appendAll(o2p.flat().flat());
|
||||
// console.log({ edges, heal, o1, o2 });
|
||||
console.log({ edges, heal, o1, o2 });
|
||||
}
|
||||
// return null;
|
||||
return { o1: o1.toFloat32(), o2: o2.toFloat32() };
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue