From eac30a458f897f8e61495120d0edbf7a78f77d13 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sat, 10 Aug 2024 21:59:02 -0400 Subject: [PATCH] checkpoint mesh split work --- src/mesh/api.js | 7 +++ src/mesh/build.js | 15 ++++--- src/mesh/model.js | 7 ++- src/mesh/work.js | 110 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 103 insertions(+), 36 deletions(-) diff --git a/src/mesh/api.js b/src/mesh/api.js index 30ae8621..6a6f099d 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -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); diff --git a/src/mesh/build.js b/src/mesh/build.js index ce8cc928..7e8d8a70 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -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 diff --git a/src/mesh/model.js b/src/mesh/model.js index dd400af7..004ae6ee 100644 --- a/src/mesh/model.js +++ b/src/mesh/model.js @@ -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(); diff --git a/src/mesh/work.js b/src/mesh/work.js index 10ddad10..d950944a 100644 --- a/src/mesh/work.js +++ b/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 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 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() }; },