diff --git a/release.md b/release.md index 1da419f1..9dce24f1 100644 --- a/release.md +++ b/release.md @@ -14,6 +14,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto ## Mesh:Tool +* `C` multi-body identification and isolation * `-` parameterize svg and image import diff --git a/src/mesh/api.js b/src/mesh/api.js index 9073c6ac..6cc3a27e 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -400,6 +400,26 @@ const tool = { }); }, + isolate(models) { + models = fallback(models); + api.log.emit('isolating bodies').pin(); + let promises = []; + let mcore = new Matrix4().makeRotationX(Math.PI / 2); + for (let m of models) { + let p = worker.model_isolate({ id: m.id }).then(bodies => { + bodies = bodies.map(vert => new mesh.model({ + file: m.file, + mesh: vert.toFloat32() + })).map( nm => nm.applyMatrix4(mcore.clone().multiply(m.mesh.matrixWorld)) ); + mesh.api.group.new(bodies, undefined, "isolate").setSelected(); + }); + promises.push(p); + } + Promise.all(promises).then(() => { + api.log.emit('isolation complete').unpin(); + }); + }, + mapFaces(models) { models = fallback(models); api.log.emit('mapping faces').pin(); diff --git a/src/mesh/build.js b/src/mesh/build.js index b20b9564..c05a0f6c 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -377,6 +377,7 @@ function ui_build() { h.div({ _: "repair", class: "head" }), // h.div({ class: "vsep" }), h.button({ _: 'analyze', onclick: tool.analyze }), + h.button({ _: 'isolate', onclick: tool.isolate }), h.button({ _: 'patch', onclick: tool.repair }), // h.button({ _: 'rebuild', onclick: tool.rebuild }), h.button({ _: 'clean', onclick: tool.clean }), diff --git a/src/mesh/tool.js b/src/mesh/tool.js index 8324616d..5fe8a615 100644 --- a/src/mesh/tool.js +++ b/src/mesh/tool.js @@ -101,7 +101,7 @@ mesh.tool = class MeshTool { } generateFaceMap(vertices) { - this.checkVertices(vertices, 3); + this.vertices = this.checkVertices(vertices, 3); const normals = this.normals = []; const sides = this.sides = []; const _va = new THREE.Vector3(); @@ -158,12 +158,13 @@ mesh.tool = class MeshTool { return sides.map(side => this.side2face[side].filter(v => v != face)).flat(); } - findConnectedSurface(faces, radians, filterZ) { - const found = {}; + // depends on generateFaceMap() being run first + findConnectedSurface(faces, radians, filterZ, found = {}) { const norms = this.normals; if (filterZ) { faces = faces.filter(f => norms[f][2] >= filterZ); } + const checked = {}; const check = faces.slice(); for (let face of faces) { found[face] = 1; @@ -173,11 +174,17 @@ mesh.tool = class MeshTool { while (check.length) { const face = check.shift(); const norm = norms[face]; + // if (!norm || norm.length < 3) { + // throw `invalid face ${face}`; + // } if (filterZ !== undefined && norm[2] < filterZ) { continue; } - const fadj = this.getAdjacentFaces(face).filter(f => !found[f]); + const fadj = this.getAdjacentFaces(face); for (let f of fadj) { + if (found[f] || checked[f]) { + continue; + } // #1 most accurate // const nf = this.normals[f]; // _v1.set(nf[0], nf[1], nf[2]); @@ -195,6 +202,7 @@ mesh.tool = class MeshTool { if (fn <= radians) { faces.push(f); check.push(f) + checked[f] = 1; found[f] = 1; } } @@ -202,6 +210,29 @@ mesh.tool = class MeshTool { return faces; } + // depends on generateFaceMap() being run first + isolateBodies() { + const verts = this.checkVertices(this.vertices); + const bodies = []; + const used = {}; + for (let i=0, l=this.normals.length-1; i