add mirroring, exclude normals from bounds, fix paint selection update
This commit is contained in:
parent
e682881374
commit
5d2f4ac02e
7 changed files with 88 additions and 7 deletions
|
|
@ -276,6 +276,7 @@ function space_init(data) {
|
||||||
case 'KeyF':
|
case 'KeyF':
|
||||||
return selection.floor().focus();
|
return selection.floor().focus();
|
||||||
case 'KeyM':
|
case 'KeyM':
|
||||||
|
if (shiftKey) return api.tool.mirror();
|
||||||
return api.tool.merge();
|
return api.tool.merge();
|
||||||
case 'KeyA':
|
case 'KeyA':
|
||||||
return api.tool.analyze();
|
return api.tool.analyze();
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,8 @@ let selection = {
|
||||||
}
|
}
|
||||||
// update saved selection id list
|
// update saved selection id list
|
||||||
prefs.save( prefs.map.space.select = selected.map(s => s.id) );
|
prefs.save( prefs.map.space.select = selected.map(s => s.id) );
|
||||||
|
// force repaint in case of idle
|
||||||
|
space.update();
|
||||||
return selection;
|
return selection;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -293,6 +295,9 @@ function fallback(models, strict) {
|
||||||
let tool = {
|
let tool = {
|
||||||
merge(models) {
|
merge(models) {
|
||||||
models = fallback(models);
|
models = fallback(models);
|
||||||
|
if (models.length <= 1) {
|
||||||
|
return api.log.emit('nothing to merge');
|
||||||
|
}
|
||||||
api.log.emit(`merging ${models.length} models`).pin();
|
api.log.emit(`merging ${models.length} models`).pin();
|
||||||
worker.model_merge(models.map(m => {
|
worker.model_merge(models.map(m => {
|
||||||
return { id: m.id, matrix: m.matrix }
|
return { id: m.id, matrix: m.matrix }
|
||||||
|
|
@ -313,6 +318,12 @@ let tool = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mirror() {
|
||||||
|
for (let m of selection.models()) {
|
||||||
|
m.mirror();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
invert() {
|
invert() {
|
||||||
for (let m of selection.models()) {
|
for (let m of selection.models()) {
|
||||||
m.invert(api.mode.get());
|
m.invert(api.mode.get());
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,7 @@ function ui_build() {
|
||||||
// h.div({ class: "vsep" }),
|
// h.div({ class: "vsep" }),
|
||||||
h.button({ _: 'duplicate', onclick: tool.duplicate }),
|
h.button({ _: 'duplicate', onclick: tool.duplicate }),
|
||||||
h.button({ _: 'merge', onclick: tool.merge }),
|
h.button({ _: 'merge', onclick: tool.merge }),
|
||||||
|
h.button({ _: 'mirror', onclick: tool.mirror }),
|
||||||
h.button({ _: 'split', onclick: call.edit_split }),
|
h.button({ _: 'split', onclick: call.edit_split }),
|
||||||
h.button({ _: 'invert', onclick: tool.invert }),
|
h.button({ _: 'invert', onclick: tool.invert }),
|
||||||
]),
|
]),
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,13 @@ mesh.group = class MeshGroup extends mesh.object {
|
||||||
return this.centerXY().floor();
|
return this.centerXY().floor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scale(x = 1, y = 1, z = 1) {
|
||||||
|
for (let m of this.models) {
|
||||||
|
m.scale(x, y, z);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// center objects to group bounds
|
// center objects to group bounds
|
||||||
// dependent on first being added to world/scene
|
// dependent on first being added to world/scene
|
||||||
centerModels() {
|
centerModels() {
|
||||||
|
|
@ -141,6 +148,11 @@ mesh.group = class MeshGroup extends mesh.object {
|
||||||
model.select(...arguments);
|
model.select(...arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ok, this is confusing, but necessary for now :/
|
||||||
|
setSelected() {
|
||||||
|
super.select();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -108,16 +108,45 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
return this.mesh.matrixWorld.elements;
|
return this.mesh.matrixWorld.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override and translate mesh
|
||||||
|
move(x = 0, y = 0, z = 0) {
|
||||||
|
let arr = this.attributes.position.array;
|
||||||
|
for (let i=0, l=arr.length; i<l; ) {
|
||||||
|
arr[i] = arr[i++] + x;
|
||||||
|
arr[i] = arr[i++] + y;
|
||||||
|
arr[i] = arr[i++] + z;
|
||||||
|
}
|
||||||
|
this.reload(arr);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// override and translate mesh
|
||||||
|
scale(x = 1, y = 1, z = 1) {
|
||||||
|
let arr = this.attributes.position.array;
|
||||||
|
for (let i=0, l=arr.length; i<l; ) {
|
||||||
|
arr[i] = arr[i++] *= x;
|
||||||
|
arr[i] = arr[i++] *= y;
|
||||||
|
arr[i] = arr[i++] *= z;
|
||||||
|
}
|
||||||
|
this.reload(arr);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
mirror() {
|
||||||
|
return this.duplicate({ mirror: true });
|
||||||
|
}
|
||||||
|
|
||||||
// return new group containing just this model in world coordinates
|
// return new group containing just this model in world coordinates
|
||||||
duplicate() {
|
duplicate(opt = {}) {
|
||||||
worker.model_duplicate({
|
worker.model_duplicate({
|
||||||
matrix: this.matrix,
|
matrix: this.matrix,
|
||||||
id: this.id
|
id: this.id,
|
||||||
|
opt
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
mesh.api.group.new([new mesh.model({
|
mesh.api.group.new([new mesh.model({
|
||||||
file: `${this.file}-dup`,
|
file: `${this.file}`,
|
||||||
mesh: data
|
mesh: data
|
||||||
})]).select();
|
})]).setSelected();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -357,7 +386,7 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
this.group.add(model = new mesh.model({
|
this.group.add(model = new mesh.model({
|
||||||
file: `${this.file}`,
|
file: `${this.file}`,
|
||||||
mesh: o2
|
mesh: o2
|
||||||
}).applyMatrix4(m4)).select();
|
}).applyMatrix4(m4)).setSelected();
|
||||||
if (o1.length) {
|
if (o1.length) {
|
||||||
// this becomes bottom
|
// this becomes bottom
|
||||||
this.reload(o1);
|
this.reload(o1);
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,10 @@ let util = mesh.util = {
|
||||||
// https://discourse.threejs.org/t/bounding-box-bigger-than-concave-object-extrudegeometry/26073/2
|
// https://discourse.threejs.org/t/bounding-box-bigger-than-concave-object-extrudegeometry/26073/2
|
||||||
// https://discourse.threejs.org/t/invalid-bounds-generated-for-some-orientations/33205
|
// https://discourse.threejs.org/t/invalid-bounds-generated-for-some-orientations/33205
|
||||||
box3expand(box3, object) {
|
box3expand(box3, object) {
|
||||||
|
if (object._no_bounds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let geometry = object.geometry;
|
let geometry = object.geometry;
|
||||||
object.updateWorldMatrix(geometry ? true : false, false);
|
object.updateWorldMatrix(geometry ? true : false, false);
|
||||||
|
|
||||||
|
|
@ -183,6 +187,7 @@ let util = mesh.util = {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.type = 'FaceNormalsHelper';
|
this.type = 'FaceNormalsHelper';
|
||||||
this.matrixAutoUpdate = false;
|
this.matrixAutoUpdate = false;
|
||||||
|
this._no_bounds = true;
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,30 @@ let model = {
|
||||||
|
|
||||||
// return new vertices in world coordinates
|
// return new vertices in world coordinates
|
||||||
duplicate(data) {
|
duplicate(data) {
|
||||||
let { id, matrix } = data;
|
let { id, matrix, opt } = data;
|
||||||
return translate_encode(id, matrix);
|
let array = translate_encode(id, matrix);
|
||||||
|
if (opt.mirror) {
|
||||||
|
// find max z and invert z
|
||||||
|
let maxz = -Infinity;
|
||||||
|
for (let i=2, l=array.length; i<l; i += 3) {
|
||||||
|
maxz = Math.max(maxz, array[i]);
|
||||||
|
array[i] = -array[i];
|
||||||
|
}
|
||||||
|
maxz *= 2;
|
||||||
|
for (let i=0, l=array.length; i<l; i += 9) {
|
||||||
|
// swap first two vertices in face to invert normals
|
||||||
|
let v1 = array.slice(i, i+3);
|
||||||
|
for (let j=0; j<3; j++) {
|
||||||
|
array[i+j] = array[i+j+3];
|
||||||
|
array[i+j+3] = v1[j];
|
||||||
|
}
|
||||||
|
// move part up in Z
|
||||||
|
array[i+2] += maxz;
|
||||||
|
array[i+5] += maxz;
|
||||||
|
array[i+8] += maxz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
},
|
},
|
||||||
|
|
||||||
// merge several model vertices into a single array
|
// merge several model vertices into a single array
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue