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) => {
|
gapp.register("mesh.api", [], (root, exports) => {
|
||||||
|
|
||||||
const { Matrix4, Vector3 } = THREE;
|
const { Matrix4, Vector3 } = THREE;
|
||||||
const { mesh, moto } = root;
|
const { base, mesh, moto } = root;
|
||||||
const { space } = moto;
|
const { space } = moto;
|
||||||
const { util } = mesh;
|
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 = {
|
const group = {
|
||||||
// @returns {MeshGroup[]}
|
// @returns {MeshGroup[]}
|
||||||
list() {
|
list() {
|
||||||
|
|
@ -565,8 +617,8 @@ const tool = {
|
||||||
api.log.emit(`regrouping ${models.length} model(s)`);
|
api.log.emit(`regrouping ${models.length} model(s)`);
|
||||||
let bounds = util.bounds(models);
|
let bounds = util.bounds(models);
|
||||||
let { mid } = bounds;
|
let { mid } = bounds;
|
||||||
Promise.all(models.map(m => m.ungroup())).then(() => {
|
return Promise.all(models.map(m => m.ungroup())).then(() => {
|
||||||
mesh.api.group.new(models)
|
return mesh.api.group.new(models)
|
||||||
.centerModels()
|
.centerModels()
|
||||||
.position(mid.x, mid.y, mid.z)
|
.position(mid.x, mid.y, mid.z)
|
||||||
.setSelected();
|
.setSelected();
|
||||||
|
|
@ -592,7 +644,7 @@ const tool = {
|
||||||
});
|
});
|
||||||
promises.push(p);
|
promises.push(p);
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
api.log.emit('analysis complete').unpin();
|
api.log.emit('analysis complete').unpin();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -613,7 +665,7 @@ const tool = {
|
||||||
});
|
});
|
||||||
promises.push(p);
|
promises.push(p);
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
api.log.emit('isolation complete').unpin();
|
api.log.emit('isolation complete').unpin();
|
||||||
// api.log.emit(`... isolate time = ${Date.now() - mark}`);
|
// api.log.emit(`... isolate time = ${Date.now() - mark}`);
|
||||||
});
|
});
|
||||||
|
|
@ -902,6 +954,8 @@ const api = exports({
|
||||||
|
|
||||||
selection,
|
selection,
|
||||||
|
|
||||||
|
pattern,
|
||||||
|
|
||||||
group,
|
group,
|
||||||
|
|
||||||
model,
|
model,
|
||||||
|
|
|
||||||
|
|
@ -398,6 +398,14 @@ function ui_build() {
|
||||||
h.button({ _: 'intersect', onclick: tool.intersect }),
|
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([
|
||||||
h.div({ _: "models", class: "head" }),
|
h.div({ _: "models", class: "head" }),
|
||||||
h.div({ class: "back"}),
|
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
|
// return new group containing just this model in world coordinates
|
||||||
duplicate(opt = {}) {
|
duplicate(opt = {}) {
|
||||||
worker.model_duplicate({
|
return worker.model_duplicate({
|
||||||
matrix: this.matrix,
|
matrix: this.matrix,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
opt
|
opt: { mirror: opt.mirror}
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
let group = mesh.api.group.new([new mesh.model({
|
let model = new mesh.model({ file: `${this.file}`, mesh: data });
|
||||||
file: `${this.file}`,
|
let group = opt.group || mesh.api.group.new();
|
||||||
mesh: data
|
group.add(model);
|
||||||
})]).setSelected();
|
group.setSelected();
|
||||||
if (opt.mirror) {
|
if (opt.mirror) {
|
||||||
group.move(0, 0, group.bounds.dim.z);
|
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
|
// release from a group but remain in memory and storage
|
||||||
// so it can be re-assigned to another group
|
// so it can be re-assigned to another group
|
||||||
ungroup() {
|
ungroup() {
|
||||||
|
if (this.group) {
|
||||||
this.group.remove(this, { free: false });
|
this.group.remove(this, { free: false });
|
||||||
this.group = undefined;
|
this.group = undefined;
|
||||||
|
}
|
||||||
return worker.model_duplicate({
|
return worker.model_duplicate({
|
||||||
matrix: this.matrix,
|
matrix: this.matrix,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ button:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.addgear {
|
.addgear {
|
||||||
gap: 5px;
|
gap: 5px 10px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 50px;
|
grid-template-columns: 1fr 50px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue