add mesh patterning
This commit is contained in:
parent
17581dbe7e
commit
8aae9885e8
4 changed files with 79 additions and 15 deletions
|
|
@ -12,7 +12,7 @@
|
|||
gapp.register("mesh.api", [], (root, exports) => {
|
||||
|
||||
const { Matrix4, Vector3 } = THREE;
|
||||
const { mesh, moto } = root;
|
||||
const { base, mesh, moto } = root;
|
||||
const { space } = moto;
|
||||
const { util } = mesh;
|
||||
|
||||
|
|
@ -229,6 +229,58 @@ const selection = {
|
|||
}
|
||||
};
|
||||
|
||||
const pattern = {
|
||||
/**
|
||||
* @param {int} count number of entities
|
||||
* @param {float[]} center [x,y,z]
|
||||
*/
|
||||
circle(count, center) {
|
||||
async function doit(count, center = [0,0,0]) {
|
||||
api.modal.hide();
|
||||
let models = selection.models();
|
||||
let [ cx, cy, cz ] = center;
|
||||
for (let model of models) {
|
||||
await api.tool.regroup([ model ]);
|
||||
let pos = model.group.position().clone();
|
||||
let stepr = (Math.PI * 2) / count;
|
||||
let modnu = [ model ];
|
||||
for (let i=1; i<count; i++) {
|
||||
let clone = await model.duplicate();
|
||||
let [x, y] = base.util.rotate(pos.x - cx, pos.y - cy, stepr * i);
|
||||
clone.group.rotate(0, 0, stepr * i);
|
||||
clone.group.position(x + cx, y + cy, pos.z);
|
||||
modnu.push(clone);
|
||||
}
|
||||
await api.tool.regroup(modnu);
|
||||
}
|
||||
}
|
||||
if (!count) {
|
||||
api.modal.dialog({
|
||||
title: "object pattern",
|
||||
body: [ h.div({ class: "addgear" }, [
|
||||
h.label('total count'),
|
||||
h.input({ value: 3, size: 5, id: "_count" }),
|
||||
h.label('center x,y,z'),
|
||||
h.input({ value: "0,0,0", size: 5, id: "_center" }),
|
||||
h.button({ _: "create", onclick() {
|
||||
doit(
|
||||
parseInt(api.modal.bound._count.value) || 3,
|
||||
api.modal.bound._center.value.split(',').map(v => parseFloat(v))
|
||||
);
|
||||
} })
|
||||
]) ]
|
||||
});
|
||||
api.modal.bound._count.focus();
|
||||
} else {
|
||||
doit(count, origin);
|
||||
}
|
||||
},
|
||||
|
||||
grid() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const group = {
|
||||
// @returns {MeshGroup[]}
|
||||
list() {
|
||||
|
|
@ -565,8 +617,8 @@ const tool = {
|
|||
api.log.emit(`regrouping ${models.length} model(s)`);
|
||||
let bounds = util.bounds(models);
|
||||
let { mid } = bounds;
|
||||
Promise.all(models.map(m => m.ungroup())).then(() => {
|
||||
mesh.api.group.new(models)
|
||||
return Promise.all(models.map(m => m.ungroup())).then(() => {
|
||||
return mesh.api.group.new(models)
|
||||
.centerModels()
|
||||
.position(mid.x, mid.y, mid.z)
|
||||
.setSelected();
|
||||
|
|
@ -592,7 +644,7 @@ const tool = {
|
|||
});
|
||||
promises.push(p);
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
return Promise.all(promises).then(() => {
|
||||
api.log.emit('analysis complete').unpin();
|
||||
});
|
||||
},
|
||||
|
|
@ -613,7 +665,7 @@ const tool = {
|
|||
});
|
||||
promises.push(p);
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
return Promise.all(promises).then(() => {
|
||||
api.log.emit('isolation complete').unpin();
|
||||
// api.log.emit(`... isolate time = ${Date.now() - mark}`);
|
||||
});
|
||||
|
|
@ -902,6 +954,8 @@ const api = exports({
|
|||
|
||||
selection,
|
||||
|
||||
pattern,
|
||||
|
||||
group,
|
||||
|
||||
model,
|
||||
|
|
|
|||
|
|
@ -398,6 +398,14 @@ function ui_build() {
|
|||
h.button({ _: 'intersect', onclick: tool.intersect }),
|
||||
])
|
||||
]),
|
||||
h.div([
|
||||
h.div({ _: "pattern", class: "head" }),
|
||||
h.div({ class: "back"}),
|
||||
h.div({ class: "pop"}, [
|
||||
h.button({ _: 'circular', onclick() { api.pattern.circle() } }),
|
||||
h.button({ _: 'grid', onclick() { api.pattern.grid } }),
|
||||
])
|
||||
]),
|
||||
h.div([
|
||||
h.div({ _: "models", class: "head" }),
|
||||
h.div({ class: "back"}),
|
||||
|
|
|
|||
|
|
@ -155,18 +155,19 @@ mesh.model = class MeshModel extends mesh.object {
|
|||
|
||||
// return new group containing just this model in world coordinates
|
||||
duplicate(opt = {}) {
|
||||
worker.model_duplicate({
|
||||
return worker.model_duplicate({
|
||||
matrix: this.matrix,
|
||||
id: this.id,
|
||||
opt
|
||||
opt: { mirror: opt.mirror}
|
||||
}).then(data => {
|
||||
let group = mesh.api.group.new([new mesh.model({
|
||||
file: `${this.file}`,
|
||||
mesh: data
|
||||
})]).setSelected();
|
||||
let model = new mesh.model({ file: `${this.file}`, mesh: data });
|
||||
let group = opt.group || mesh.api.group.new();
|
||||
group.add(model);
|
||||
group.setSelected();
|
||||
if (opt.mirror) {
|
||||
group.move(0, 0, group.bounds.dim.z);
|
||||
}
|
||||
return model;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -460,9 +461,10 @@ mesh.model = class MeshModel extends mesh.object {
|
|||
// release from a group but remain in memory and storage
|
||||
// so it can be re-assigned to another group
|
||||
ungroup() {
|
||||
this.group.remove(this, { free: false });
|
||||
this.group = undefined;
|
||||
|
||||
if (this.group) {
|
||||
this.group.remove(this, { free: false });
|
||||
this.group = undefined;
|
||||
}
|
||||
return worker.model_duplicate({
|
||||
matrix: this.matrix,
|
||||
id: this.id,
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ button:hover {
|
|||
}
|
||||
|
||||
.addgear {
|
||||
gap: 5px;
|
||||
gap: 5px 10px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 50px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue