update to latest manifold api
This commit is contained in:
parent
bb7c232a3b
commit
0983acd50b
4 changed files with 40 additions and 153 deletions
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
Full docs @ https://docs.grid.space/projects/kiri-moto
|
Full docs @ https://docs.grid.space/projects/kiri-moto
|
||||||
|
|
||||||
# Release 3.7
|
# Release 3.7 (2022-11-12)
|
||||||
|
|
||||||
* add CAM axes scaling gcode header directive
|
* add CAM axes scaling gcode header directive
|
||||||
* add CAM 4th axis indexing support, timeline op, updated visuals
|
* add CAM 4th axis indexing support, timeline op, updated visuals
|
||||||
|
* update most CAM ops to work in 4th axis indexing mode
|
||||||
* align FDM top/bottom layer options with convention
|
* align FDM top/bottom layer options with convention
|
||||||
|
* change Kiri:Moto SVG import to default to boolean repair
|
||||||
* add Mesh:Tool SVG import options for extrusion depth and boolean repair
|
* add Mesh:Tool SVG import options for extrusion depth and boolean repair
|
||||||
* replace jscad/modeling with Manifold project for faster mesh boolean
|
* replace jscad/modeling with Manifold project for faster mesh boolean
|
||||||
* various CAM gcode, preview, animation fixes (3 axis)
|
* various CAM gcode, preview, animation fixes (3 axis)
|
||||||
|
|
|
||||||
153
src/geo/csg.js
153
src/geo/csg.js
|
|
@ -29,12 +29,12 @@ const CSG = {
|
||||||
|
|
||||||
moduleOp(name, op) {
|
moduleOp(name, op) {
|
||||||
mesh.log(`${name} ${arguments.length} meshes`);
|
mesh.log(`${name} ${arguments.length} meshes`);
|
||||||
const args = [...arguments].slice(2).map(a => new Module.Manifold(a));
|
const args = [...arguments].slice(2).map(a => new Instance.Manifold(a));
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
throw "missing one or more meshes";
|
throw "missing one or more meshes";
|
||||||
}
|
}
|
||||||
const result = Module[op](...args);
|
const result = Instance[op](...args);
|
||||||
const output = result.getMesh({ normal: () => undefined });
|
const output = result.getMesh();
|
||||||
const errors = [ ...args, result ].map(m => m.status().value);
|
const errors = [ ...args, result ].map(m => m.status().value);
|
||||||
for (let m of [ ...args, result ]) {
|
for (let m of [ ...args, result ]) {
|
||||||
m.delete();
|
m.delete();
|
||||||
|
|
@ -46,33 +46,14 @@ const CSG = {
|
||||||
},
|
},
|
||||||
|
|
||||||
toPositionArray(mesh) {
|
toPositionArray(mesh) {
|
||||||
const { vertPos, triVerts, vertex, index } = mesh;
|
let { vertPos, triVerts } = mesh;
|
||||||
if (vertex && index) {
|
|
||||||
const vertices = new Float32Array(index.length * 3);
|
|
||||||
for (let p=0, i=0, l=index.length; i<l; i++) {
|
|
||||||
let vi = index[i] * 3;
|
|
||||||
vertices[p++] = vertex[vi++];
|
|
||||||
vertices[p++] = vertex[vi++];
|
|
||||||
vertices[p++] = vertex[vi++];
|
|
||||||
}
|
|
||||||
return vertices;
|
|
||||||
}
|
|
||||||
if (vertPos && triVerts) {
|
if (vertPos && triVerts) {
|
||||||
const vertices = new Float32Array(triVerts.length * 9);
|
const vertices = new Float32Array(triVerts.length * 3);
|
||||||
for (let i = 0, t = 0, l = triVerts.length; t < l; t++) {
|
for (let p=0, i=0, l=triVerts.length; i<l; i++) {
|
||||||
let tri = triVerts[t];
|
let vi = triVerts[i] * 3;
|
||||||
let vert = vertPos[tri[0]]; // X
|
vertices[p++] = vertPos[vi++];
|
||||||
vertices[i++] = vert[0];
|
vertices[p++] = vertPos[vi++];
|
||||||
vertices[i++] = vert[1];
|
vertices[p++] = vertPos[vi++];
|
||||||
vertices[i++] = vert[2];
|
|
||||||
vert = vertPos[tri[1]]; // Y
|
|
||||||
vertices[i++] = vert[0];
|
|
||||||
vertices[i++] = vert[1];
|
|
||||||
vertices[i++] = vert[2];
|
|
||||||
vert = vertPos[tri[2]]; // Z
|
|
||||||
vertices[i++] = vert[0];
|
|
||||||
vertices[i++] = vert[1];
|
|
||||||
vertices[i++] = vert[2];
|
|
||||||
}
|
}
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
@ -81,22 +62,10 @@ const CSG = {
|
||||||
|
|
||||||
fromPositionArray(pos) {
|
fromPositionArray(pos) {
|
||||||
const { index, vertices } = indexVertices(pos);
|
const { index, vertices } = indexVertices(pos);
|
||||||
const mesh = {
|
let mesh = new Instance.Mesh({
|
||||||
vertPos: new Module.Vector_vec3(),
|
vertPos: vertices.toFloat32(),
|
||||||
triVerts: new Module.Vector_ivec3(),
|
triVerts: index.toUint32()
|
||||||
vertNormal: new Module.Vector_vec3(),
|
|
||||||
halfedgeTangent: new Module.Vector_vec4()
|
|
||||||
};
|
|
||||||
for (let i = 0, l = vertices.length; i < l; ) {
|
|
||||||
mesh.vertPos.push_back({
|
|
||||||
x: vertices[i++],
|
|
||||||
y: vertices[i++],
|
|
||||||
z: vertices[i++]
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
for (let i = 0, l = index.length; i < l; ) {
|
|
||||||
mesh.triVerts.push_back([ index[i++], index[i++], index[i++] ]);
|
|
||||||
}
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,98 +99,12 @@ function indexVertices(pos) {
|
||||||
return { index, vertices };
|
return { index, vertices };
|
||||||
}
|
}
|
||||||
|
|
||||||
function pos2mesh(pos) {
|
let Instance;
|
||||||
|
Module().then(Module => {
|
||||||
}
|
|
||||||
|
|
||||||
Module.onRuntimeInitialized = () => {
|
|
||||||
Module.setup();
|
Module.setup();
|
||||||
|
Instance = Module;
|
||||||
const tests = false;
|
CSG.Instance = () => { return Instance };
|
||||||
const mesh_perf = false;
|
});
|
||||||
const ball_torture = false;
|
|
||||||
|
|
||||||
if (tests) {
|
|
||||||
console.log('running Manifold tests');
|
|
||||||
|
|
||||||
let c = Module.cube([1,1,1], true);
|
|
||||||
console.log({
|
|
||||||
c,
|
|
||||||
cm: c.getMesh(),
|
|
||||||
cmd: c.getMesh({ normal: () => undefined }),
|
|
||||||
cmdn: c.getMesh({})
|
|
||||||
});
|
|
||||||
|
|
||||||
if (mesh_perf) {
|
|
||||||
console.log('running Manifold getMesh() benchmark');
|
|
||||||
|
|
||||||
let l = 1000;
|
|
||||||
let s = Module.sphere(10, 100);
|
|
||||||
let sm = s.getMesh();
|
|
||||||
let smd = s.getMesh({});
|
|
||||||
console.log({
|
|
||||||
s,
|
|
||||||
sm,
|
|
||||||
smd,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.time('getMesh');
|
|
||||||
for (let i=0; i<l; i++) s.getMesh();
|
|
||||||
console.timeEnd('getMesh');
|
|
||||||
|
|
||||||
console.time(`getMeshDirect`);
|
|
||||||
for (let i=0; i<l; i++) s.getMesh({ normal: () => undefined });
|
|
||||||
console.timeEnd(`getMeshDirect`);
|
|
||||||
|
|
||||||
console.time(`getMeshDirect`);
|
|
||||||
for (let i=0; i<l; i++) s.getMesh({});
|
|
||||||
console.timeEnd(`getMeshDirect`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ball_torture) {
|
|
||||||
console.log('running Manifold ball torture test');
|
|
||||||
|
|
||||||
console.time('ball test');
|
|
||||||
let iter = 1; // increases final complexity (cpu + mem)
|
|
||||||
let maxBatch = 10; // increases memory pressure
|
|
||||||
let sphereDetail = 64; // higher # speeds up progression of complexity
|
|
||||||
let ball = Module.sphere(24, sphereDetail);
|
|
||||||
let box = Module.cube([500, 500, 100], true);
|
|
||||||
let deg2rad = Math.PI / 180;
|
|
||||||
let z = 50;
|
|
||||||
let rad = 250;
|
|
||||||
let last = Date.now();
|
|
||||||
let batch = 0;
|
|
||||||
for (let i=0; i<360*iter; i++) {
|
|
||||||
let x = Math.cos(deg2rad * i) * rad;
|
|
||||||
let y = Math.sin(deg2rad * i) * rad;
|
|
||||||
let ball2 = ball.translate(x, y, z);
|
|
||||||
let box2 = box.subtract(ball2);
|
|
||||||
ball2.delete();
|
|
||||||
box.delete();
|
|
||||||
box = box2;
|
|
||||||
if (batch++ > maxBatch) {
|
|
||||||
batch = 0;
|
|
||||||
let nv = box.numVert();
|
|
||||||
let now = Date.now();
|
|
||||||
console.log(
|
|
||||||
(i / (iter * 360)).toFixed(2), // % complete
|
|
||||||
nv, // num vertices in target block
|
|
||||||
now - last, // elapsed time for maxBatch boolean ops
|
|
||||||
((now - last) / maxBatch).toFixed(4) // time per boolean op
|
|
||||||
);
|
|
||||||
last = now;
|
|
||||||
}
|
|
||||||
rad -= 0.04;
|
|
||||||
z -= 0.08;
|
|
||||||
}
|
|
||||||
console.log(box.getMesh());
|
|
||||||
ball.delete();
|
|
||||||
box.delete();
|
|
||||||
console.timeEnd('ball test');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gapp.overlay(base, {
|
gapp.overlay(base, {
|
||||||
CSG
|
CSG
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ kiri.load(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---( WORKER FUNCTIONS )---
|
// ---( WORKER FUNCTIONS )---
|
||||||
|
const { CSG } = root.base;
|
||||||
|
|
||||||
let nextMeshID = 1;
|
let nextMeshID = 1;
|
||||||
|
|
||||||
|
|
@ -245,8 +246,7 @@ class Stock {
|
||||||
this.sends = 0;
|
this.sends = 0;
|
||||||
this.newbuf = true;
|
this.newbuf = true;
|
||||||
this.subtracts = 0;
|
this.subtracts = 0;
|
||||||
this.mesh = Module.cube([x, y, z], true);
|
this.mesh = CSG.Instance().cube([x, y, z], true);
|
||||||
// console.log({ new_stock: this.id, x, y, z });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
send(send) {
|
send(send) {
|
||||||
|
|
@ -279,11 +279,11 @@ class Stock {
|
||||||
const subs = this.subtracts;
|
const subs = this.subtracts;
|
||||||
this.subtracts = 0;
|
this.subtracts = 0;
|
||||||
let start = Date.now();
|
let start = Date.now();
|
||||||
this.mesh.getMesh({
|
let mesh = this.mesh.getMesh();
|
||||||
normal: () => undefined,
|
this.sharedVertexBuffer(mesh.numVert * 3);
|
||||||
index: this.sharedIndexBuffer.bind(this),
|
this.sharedIndexBuffer(mesh.numTri * 3);
|
||||||
vertex: this.sharedVertexBuffer.bind(this)
|
this.vbuf.set(mesh.vertPos);
|
||||||
});
|
this.ibuf.set(mesh.triVerts);
|
||||||
let sub = Date.now();
|
let sub = Date.now();
|
||||||
updates.push(this);
|
updates.push(this);
|
||||||
if (false) console.log({
|
if (false) console.log({
|
||||||
|
|
@ -360,7 +360,6 @@ kiri.load(() => {
|
||||||
let indexCount = 0;
|
let indexCount = 0;
|
||||||
let updates = 0;
|
let updates = 0;
|
||||||
|
|
||||||
|
|
||||||
kiri.worker.animate_setup2 = function(data, send) {
|
kiri.worker.animate_setup2 = function(data, send) {
|
||||||
const { settings } = data;
|
const { settings } = data;
|
||||||
const { process } = settings;
|
const { process } = settings;
|
||||||
|
|
@ -386,7 +385,7 @@ kiri.load(() => {
|
||||||
|
|
||||||
stockSlices = [];
|
stockSlices = [];
|
||||||
const { x, y, z } = stock;
|
const { x, y, z } = stock;
|
||||||
const sliceCount = 10;
|
const sliceCount = 20;
|
||||||
const sliceWidth = stock.x / sliceCount;
|
const sliceWidth = stock.x / sliceCount;
|
||||||
for (let i=0; i<sliceCount; i++) {
|
for (let i=0; i<sliceCount; i++) {
|
||||||
let xmin = -(x/2) + (i * sliceWidth) + sliceWidth / 2;
|
let xmin = -(x/2) + (i * sliceWidth) + sliceWidth / 2;
|
||||||
|
|
@ -591,23 +590,26 @@ kiri.load(() => {
|
||||||
send.data({ mesh_del: toolID });
|
send.data({ mesh_del: toolID });
|
||||||
}
|
}
|
||||||
tool = new CAM.Tool({ tools }, undefined, toolnum);
|
tool = new CAM.Tool({ tools }, undefined, toolnum);
|
||||||
|
const Instance = CSG.Instance();
|
||||||
const slen = tool.shaftLength() || 15;
|
const slen = tool.shaftLength() || 15;
|
||||||
const srad = tool.shaftDiameter() / 2;
|
const srad = tool.shaftDiameter() / 2;
|
||||||
const flen = tool.fluteLength() || 15;
|
const flen = tool.fluteLength() || 15;
|
||||||
const frad = toolRadius = tool.fluteDiameter() / 2;
|
const frad = toolRadius = tool.fluteDiameter() / 2;
|
||||||
let mesh;
|
let mesh;
|
||||||
if (tool.isBallMill()) {
|
if (tool.isBallMill()) {
|
||||||
mesh = Module.cylinder(flen + slen - frad, frad, frad, 20, true)
|
mesh = Instance.cylinder(flen + slen - frad, frad, frad, 20, true)
|
||||||
.add(Module.sphere(frad, 20).translate(0, 0, -(flen + slen - frad)/2));
|
.add(Instance.sphere(frad, 20).translate(0, 0, -(flen + slen - frad)/2));
|
||||||
} else if (tool.isTaperMill()) {
|
} else if (tool.isTaperMill()) {
|
||||||
const trad = Math.max(tool.tipDiameter() / 2, 0.001);
|
const trad = Math.max(tool.tipDiameter() / 2, 0.001);
|
||||||
mesh = Module.cylinder(slen, srad, srad, 20, true).translate(0, 0, slen/2)
|
mesh = Instance.cylinder(slen, srad, srad, 20, true).translate(0, 0, slen/2)
|
||||||
.add(Module.cylinder(flen, trad, frad, 20, true).translate(0, 0, -flen/2));
|
.add(Instance.cylinder(flen, trad, frad, 20, true).translate(0, 0, -flen/2));
|
||||||
} else {
|
} else {
|
||||||
mesh = Module.cylinder(flen + slen, frad, frad, 20, true);
|
mesh = Instance.cylinder(flen + slen, frad, frad, 20, true);
|
||||||
}
|
}
|
||||||
mesh = mesh.translate(0, 0, (flen + slen - stockZ) / 2);
|
mesh = mesh.translate(0, 0, (flen + slen - stockZ) / 2);
|
||||||
const { vertex, index } = mesh.getMesh({ normal: () => undefined });
|
const raw = mesh.getMesh();
|
||||||
|
const vertex = raw.vertPos;
|
||||||
|
const index = raw.triVerts;
|
||||||
toolMesh = { root: mesh, index, vertex };
|
toolMesh = { root: mesh, index, vertex };
|
||||||
send.data({ mesh_add: { id:--toolID, ind: index, pos: vertex }});
|
send.data({ mesh_add: { id:--toolID, ind: index, pos: vertex }});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const { broker } = gapp;
|
||||||
const { moto } = root;
|
const { moto } = root;
|
||||||
const { space } = moto;
|
const { space } = moto;
|
||||||
|
|
||||||
const version = '1.2.0';
|
const version = '1.3.0';
|
||||||
const call = broker.send;
|
const call = broker.send;
|
||||||
const dbindex = [ "admin", "space" ];
|
const dbindex = [ "admin", "space" ];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue