From f500ee0f5c926dbfc6e808838055425b2814a6d7 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 11 Jan 2022 16:29:54 -0500 Subject: [PATCH] add duplication and merging --- src/main/mesh.js | 6 +++--- src/mesh/api.js | 44 +++++++++++++++++++++++++++++++++++++++----- src/mesh/build.js | 5 ++++- src/mesh/work.js | 18 ++++++++++++------ 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/main/mesh.js b/src/main/mesh.js index c55767f5..68760c87 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -157,15 +157,15 @@ function space_init(data) { switch (code) { case 'KeyD': if (shiftKey) { - for (let m of selection.models()) { - m.duplicate(); - } + return selection.duplicate(); } break; case 'KeyC': return selection.centerXY().focus(); case 'KeyF': return selection.floor().focus(); + case 'KeyM': + return selection.merge(); case 'KeyI': return api.file.import(); case 'KeyX': diff --git a/src/mesh/api.js b/src/mesh/api.js index 7ce3611f..b1feee5a 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -103,6 +103,17 @@ let selection = { } }, + duplicate() { + for (let m of selection.models()) { + m.duplicate(); + } + }, + + merge() { + tool.merge(selection.models()); + }, + + // update material selections update() { for (let group of groups) { group.material(mesh.material.unselected); @@ -257,20 +268,40 @@ let file = { }; let tool = { + merge(models) { + api.log.emit(`merging ${models.length} models`).pin(); + worker.model_merge(models.map(m => { + return { id: m.id, matrix: m.matrix } + })) + .then(data => { + let group = api.group.new([new mesh.model({ + file: `merged`, + mesh: data + })]).centerModels(); + api.selection.set([group]); + api.log.emit('merge complete').unpin(); + }); + }, + analyze() { + let promises = []; api.log.emit('analyzing mesh(es)...').pin(); for (let m of selection.models()) { - worker.model_analyze(m.id).then(data => { - console.log({data}); - api.log.emit('analysis complete').unpin(); + let p = worker.model_analyze(m.id).then(data => { + // console.log({data}); }); + promises.push(p); } + Promise.all(promises).then(() => { + api.log.emit('analysis complete').unpin(); + }); }, repair() { + let promises = []; api.log.emit('repairing mesh(es)...').pin(); for (let m of selection.models()) { - worker.model_heal(m.id).then(data => { + let p = worker.model_heal(m.id).then(data => { if (data) { m.reload( data.vertices, @@ -278,9 +309,12 @@ let tool = { data.normals ); } - api.log.emit('repair complete').unpin(); }); + promises.push(p); } + Promise.all(promises).then(() => { + api.log.emit('repair complete').unpin(); + }); } }; diff --git a/src/mesh/build.js b/src/mesh/build.js index 9f1aa415..3dd83c16 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -225,7 +225,10 @@ function ui_build() { h.button({ _: 'gridlines', onclick() { api.grid() } }), h.button({ _: 'wireframe', onclick() { api.wireframe() } }), h.div({ class: "vsep" }), - h.button({ _: 'analyze', disabled: true }), + h.button({ _: 'duplicate', onclick: api.selection.duplicate }), + h.button({ _: 'merge', onclick: api.selection.merge }), + h.div({ class: "vsep" }), + h.button({ _: 'analyze', onclick: api.tool.analyze }), h.button({ _: 'repair', onclick: api.tool.repair }), ]), ]); diff --git a/src/mesh/work.js b/src/mesh/work.js index 7d31fc84..9de37325 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -65,12 +65,18 @@ let model = { duplicate(data) { let { id, matrix } = data; return translate_encode(id, matrix); - throw "should not here"; - let rec = cache[id]; - let geo = rec.geo.clone(); - let m4 = core_matrix.clone().multiply( new THREE.Matrix4().fromArray(matrix) ); - geo.applyMatrix4(m4); - return geo.attributes.position.array; + }, + + // merge several model vertices into a single array + merge(recs) { + let arrays = recs.map(rec => translate_encode(rec.id, rec.matrix)); + let length = arrays.map(a => a.length).reduce((v,a) => v + a); + let data = new Float32Array(length); + for (let i=0, l=arrays.length, p=0; i