2020-11-24 00:11:49 -05:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
2020-11-24 17:01:58 -05:00
|
|
|
self.kiri.loader.push(function() {
|
2020-11-24 00:11:49 -05:00
|
|
|
|
|
|
|
|
let KIRI = self.kiri,
|
|
|
|
|
CAM = KIRI.driver.CAM,
|
2020-11-24 14:03:45 -05:00
|
|
|
API, WORLD, SPACE,
|
2020-11-24 19:21:30 -05:00
|
|
|
meshes = {},
|
2020-11-30 11:30:02 -05:00
|
|
|
unitScale = 1,
|
2020-11-30 10:59:24 -05:00
|
|
|
toolPosX, toolPosY, toolPosZ,
|
2020-11-29 10:04:13 -05:00
|
|
|
speedValues = [ 25, 12, 6, 3 ],
|
|
|
|
|
speedNames = [ "1x", "2x", "4x", "8x" ],
|
|
|
|
|
speedIndex = 0,
|
|
|
|
|
speedLabel,
|
2020-11-24 19:21:30 -05:00
|
|
|
speed;
|
2020-11-24 00:11:49 -05:00
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
// ---( CLIENT FUNCTIONS )---
|
|
|
|
|
|
2020-11-24 00:37:44 -05:00
|
|
|
if (KIRI.client)
|
2020-11-24 11:01:29 -05:00
|
|
|
CAM.animate_clear = function(api) {
|
2020-11-24 14:35:08 -05:00
|
|
|
KIRI.client.animate_cleanup();
|
2020-11-24 14:03:45 -05:00
|
|
|
SPACE = (API = api).const.SPACE;
|
|
|
|
|
WORLD = SPACE.platform.world;
|
2020-11-24 11:01:29 -05:00
|
|
|
$('layer-animate').innerHTML = '';
|
2020-11-30 10:59:24 -05:00
|
|
|
$('layer-toolpos').innerHTML = '';
|
2020-11-24 11:01:29 -05:00
|
|
|
Object.keys(meshes).forEach(id => deleteMesh(id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (KIRI.client)
|
2020-11-24 19:21:30 -05:00
|
|
|
CAM.animate = function(api, delay) {
|
2020-11-24 14:03:45 -05:00
|
|
|
SPACE = (API = api).const.SPACE;
|
|
|
|
|
WORLD = SPACE.platform.world;
|
2020-11-24 11:01:29 -05:00
|
|
|
KIRI.client.animate_setup(API.conf.get(), data => {
|
|
|
|
|
checkMeshCommands(data);
|
2020-11-25 12:51:18 -05:00
|
|
|
if (!(data && data.mesh_add)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-11-24 11:01:29 -05:00
|
|
|
const UC = API.uc;
|
|
|
|
|
const layer = $('layer-animate');
|
|
|
|
|
layer.innerHTML = '';
|
|
|
|
|
UC.setGroup(layer);
|
|
|
|
|
UC.newRow([
|
2020-11-29 10:04:13 -05:00
|
|
|
UC.newButton(null,replay,{icon:'<i class="fas fa-fast-backward"></i>'}),
|
2020-11-24 14:03:45 -05:00
|
|
|
UC.newButton(null,play,{icon:'<i class="fas fa-play"></i>'}),
|
|
|
|
|
UC.newButton(null,step,{icon:'<i class="fas fa-step-forward"></i>'}),
|
2020-11-29 10:04:13 -05:00
|
|
|
UC.newButton(null,fast,{icon:'<i class="fas fa-fast-forward"></i>'}),
|
|
|
|
|
UC.newButton(null,pause,{icon:'<i class="fas fa-pause"></i>'}),
|
|
|
|
|
speedLabel = UC.newLabel("speed")
|
2020-11-24 11:01:29 -05:00
|
|
|
]);
|
2020-11-29 10:04:13 -05:00
|
|
|
updateSpeed();
|
2020-11-24 19:21:30 -05:00
|
|
|
setTimeout(() => {
|
|
|
|
|
play({steps: 1});
|
|
|
|
|
}, delay || 0);
|
2020-11-30 10:59:24 -05:00
|
|
|
const toolpos = $('layer-toolpos');
|
|
|
|
|
toolpos.innerHTML = '';
|
|
|
|
|
UC.setGroup(toolpos);
|
|
|
|
|
toolPosX = UC.newInput('x', {disabled: true, size: 7});
|
|
|
|
|
toolPosY = UC.newInput('y', {disabled: true, size: 7});
|
|
|
|
|
toolPosZ = UC.newInput('z', {disabled: true, size: 7});
|
2020-11-24 00:48:45 -05:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-29 10:04:13 -05:00
|
|
|
function updateSpeed(inc = 0) {
|
|
|
|
|
if (inc > 0) {
|
|
|
|
|
speedIndex = (speedIndex + inc) % speedValues.length;
|
|
|
|
|
}
|
|
|
|
|
speed = speedValues[speedIndex];
|
|
|
|
|
speedLabel.innerText = speedNames[speedIndex];
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 19:21:30 -05:00
|
|
|
function replay() {
|
|
|
|
|
CAM.animate_clear(API);
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
CAM.animate(API, 50);
|
|
|
|
|
}, 250);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 11:01:29 -05:00
|
|
|
function checkMeshCommands(data) {
|
|
|
|
|
if (!data) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (data.mesh_add) {
|
|
|
|
|
const { id, ind, pos } = data.mesh_add;
|
2020-11-24 12:27:55 -05:00
|
|
|
meshAdd(id, ind, pos);
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
if (data.mesh_del) {
|
|
|
|
|
deleteMesh(data.mesh_del);
|
|
|
|
|
}
|
|
|
|
|
if (data.mesh_move) {
|
|
|
|
|
const { id, pos } = data.mesh_move;
|
|
|
|
|
const mesh = meshes[id];
|
2020-11-24 19:21:30 -05:00
|
|
|
if (mesh) {
|
|
|
|
|
mesh.position.x = pos.x;
|
|
|
|
|
mesh.position.y = pos.y;
|
|
|
|
|
mesh.position.z = pos.z;
|
2020-11-25 12:51:18 -05:00
|
|
|
SPACE.update();
|
2020-11-30 10:59:24 -05:00
|
|
|
if (id !== 0) {
|
2020-11-30 11:30:02 -05:00
|
|
|
toolPosX.value = (pos.x * unitScale).toFixed(2);
|
|
|
|
|
toolPosY.value = (pos.y * unitScale).toFixed(2);
|
|
|
|
|
toolPosZ.value = (pos.z * unitScale).toFixed(2);
|
2020-11-30 10:59:24 -05:00
|
|
|
}
|
2020-11-24 19:21:30 -05:00
|
|
|
}
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
2020-11-24 12:27:55 -05:00
|
|
|
if (data.mesh_update) {
|
|
|
|
|
meshUpdates(data.id, data.mesh_update);
|
|
|
|
|
}
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-24 12:27:55 -05:00
|
|
|
function meshAdd(id, ind, pos) {
|
2020-11-24 11:01:29 -05:00
|
|
|
const geo = new THREE.BufferGeometry();
|
|
|
|
|
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
|
2020-11-24 14:35:08 -05:00
|
|
|
geo.setIndex(new THREE.BufferAttribute(new Uint32Array(ind), 1));
|
2020-11-24 11:01:29 -05:00
|
|
|
const mat = new THREE.LineBasicMaterial({
|
|
|
|
|
transparent: true,
|
|
|
|
|
opacity: 0.75,
|
|
|
|
|
color: 0
|
2020-11-24 00:48:45 -05:00
|
|
|
});
|
2020-11-24 11:01:29 -05:00
|
|
|
const mesh = new THREE.LineSegments(geo, mat);
|
|
|
|
|
WORLD.add(mesh);
|
|
|
|
|
meshes[id] = mesh;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 12:27:55 -05:00
|
|
|
function meshUpdates(id, updates) {
|
|
|
|
|
const mesh = meshes[id];
|
2020-11-24 19:21:30 -05:00
|
|
|
if (!mesh) {
|
|
|
|
|
return; // animate cancelled
|
|
|
|
|
}
|
2020-11-24 12:27:55 -05:00
|
|
|
const mpos = mesh.geometry.attributes.position;
|
|
|
|
|
for (let i=0, il=updates.length; i<il; ) {
|
|
|
|
|
const pos = updates[i++];
|
|
|
|
|
const val = updates[i++];
|
|
|
|
|
mpos.array[pos] = val;
|
|
|
|
|
}
|
|
|
|
|
mpos.needsUpdate = true;
|
2020-11-24 14:03:45 -05:00
|
|
|
SPACE.update();
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deleteMesh(id) {
|
|
|
|
|
WORLD.remove(meshes[id]);
|
|
|
|
|
delete meshes[id];
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
function step(opts) {
|
2020-11-24 19:21:30 -05:00
|
|
|
const { steps } = opts;
|
2020-11-29 10:04:13 -05:00
|
|
|
updateSpeed();
|
2020-11-24 19:21:30 -05:00
|
|
|
KIRI.client.animate({speed, steps: 1}, handleGridUpdate);
|
2020-11-24 14:03:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function play(opts) {
|
2020-11-24 19:21:30 -05:00
|
|
|
const { steps } = opts;
|
2020-11-29 10:04:13 -05:00
|
|
|
updateSpeed();
|
2020-11-24 19:21:30 -05:00
|
|
|
KIRI.client.animate({speed, steps: steps || Infinity}, handleGridUpdate);
|
2020-11-24 14:03:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fast(opts) {
|
2020-11-24 19:21:30 -05:00
|
|
|
const { steps } = opts;
|
2020-11-29 10:04:13 -05:00
|
|
|
updateSpeed(1);
|
2020-11-24 19:21:30 -05:00
|
|
|
KIRI.client.animate({speed, steps: steps || Infinity}, handleGridUpdate);
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pause() {
|
|
|
|
|
KIRI.client.animate({speed: 0}, handleGridUpdate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleGridUpdate(data) {
|
|
|
|
|
checkMeshCommands(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (KIRI.client)
|
|
|
|
|
KIRI.client.animate_setup = function(settings, ondone) {
|
2020-11-30 11:30:02 -05:00
|
|
|
unitScale = settings.controller.units === 'in' ? 1/25.4 : 1;
|
2020-11-24 11:01:29 -05:00
|
|
|
send("animate_setup", {settings}, ondone);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (KIRI.client)
|
|
|
|
|
KIRI.client.animate = function(data, ondone) {
|
|
|
|
|
send("animate", data, ondone);
|
2020-11-24 00:48:45 -05:00
|
|
|
};
|
|
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
if (KIRI.client)
|
|
|
|
|
KIRI.client.animate_cleanup = function(data, ondone) {
|
|
|
|
|
send("animate_cleanup", data, ondone);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ---( WORKER FUNCTIONS )---
|
|
|
|
|
|
2020-11-25 13:09:01 -05:00
|
|
|
let stock, center, grid, gridX, gridY, rez;
|
|
|
|
|
let path, pathIndex, tool, tools, last, toolID = 1;
|
2020-11-24 11:01:29 -05:00
|
|
|
|
2020-11-24 00:48:45 -05:00
|
|
|
if (KIRI.worker)
|
2020-11-24 11:01:29 -05:00
|
|
|
KIRI.worker.animate_setup = function(data, send) {
|
2020-11-24 00:48:45 -05:00
|
|
|
const { settings } = data;
|
2020-11-25 12:51:18 -05:00
|
|
|
const print = current.print;
|
2020-11-24 19:46:15 -05:00
|
|
|
const density = parseInt(settings.controller.animesh) * 1000;
|
2020-11-24 11:01:29 -05:00
|
|
|
|
2020-11-24 19:21:30 -05:00
|
|
|
pathIndex = 0;
|
2020-11-25 12:51:18 -05:00
|
|
|
path = print.output.flat();
|
2020-11-24 11:01:29 -05:00
|
|
|
tools = settings.tools;
|
2020-11-24 12:27:55 -05:00
|
|
|
stock = settings.stock;
|
2020-11-25 12:51:18 -05:00
|
|
|
|
2020-11-24 19:46:15 -05:00
|
|
|
rez = 1/Math.sqrt(density/(stock.x * stock.y));
|
2020-11-24 11:01:29 -05:00
|
|
|
|
|
|
|
|
const step = rez;
|
2020-11-24 19:21:30 -05:00
|
|
|
const stepsX = Math.floor(stock.x / step);
|
|
|
|
|
const stepsY = Math.floor(stock.y / step);
|
2020-11-24 11:01:29 -05:00
|
|
|
const { pos, ind } = createGrid(stepsX, stepsY, stock, step);
|
|
|
|
|
|
2020-11-24 12:27:55 -05:00
|
|
|
grid = pos;
|
|
|
|
|
gridX = stepsX;
|
|
|
|
|
gridY = stepsY;
|
|
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
tool = null;
|
|
|
|
|
last = null;
|
|
|
|
|
animating = false;
|
|
|
|
|
animateClear = false;
|
2020-11-24 14:35:08 -05:00
|
|
|
|
2020-11-25 13:09:01 -05:00
|
|
|
center = Object.assign({}, stock.center);
|
2020-11-25 12:51:18 -05:00
|
|
|
center.z -= stock.z / 2;
|
|
|
|
|
|
|
|
|
|
send.data({ mesh_add: { id: 0, pos, ind } });
|
|
|
|
|
send.data({ mesh_move: { id: 0, pos: center } });
|
|
|
|
|
send.done();
|
2020-11-24 11:01:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function createGrid(stepsX, stepsY, size, step) {
|
2020-11-24 00:11:49 -05:00
|
|
|
const gridPoints = stepsX * stepsY;
|
2020-11-24 12:27:55 -05:00
|
|
|
const pos = new Float32Array(gridPoints * 3);
|
2020-11-24 00:37:44 -05:00
|
|
|
const ind = [];
|
2020-11-24 11:01:29 -05:00
|
|
|
const ox = size.x / 2;
|
|
|
|
|
const oy = size.y / 2;
|
2020-11-24 00:11:49 -05:00
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
const b = { mx: 0, my: 0, Mx: 0, My: 0};
|
|
|
|
|
|
2020-11-24 00:11:49 -05:00
|
|
|
// initialize grid points
|
|
|
|
|
for (let x=0, ai=0; x<stepsX; x++) {
|
|
|
|
|
for (let y=0; y<stepsY; y++) {
|
2020-11-24 19:21:30 -05:00
|
|
|
let px = pos[ai++] = x * step - ox + step / 2;
|
|
|
|
|
let py = pos[ai++] = y * step - oy + step / 2;
|
2020-11-24 11:01:29 -05:00
|
|
|
pos[ai++] = size.z;
|
2020-11-24 00:11:49 -05:00
|
|
|
if (y > 0) ind.appendAll([
|
|
|
|
|
(stepsY * x) + (y - 1),
|
|
|
|
|
(stepsY * x) + (y )
|
|
|
|
|
]);
|
|
|
|
|
if (x > 0) ind.appendAll([
|
|
|
|
|
(stepsY * (x - 1)) + y,
|
|
|
|
|
(stepsY * (x )) + y
|
|
|
|
|
]);
|
2020-11-24 14:03:45 -05:00
|
|
|
b.mx = Math.min(b.mx, px);
|
|
|
|
|
b.my = Math.min(b.my, py);
|
|
|
|
|
b.Mx = Math.max(b.Mx, px);
|
|
|
|
|
b.My = Math.max(b.My, py);
|
2020-11-24 00:11:49 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 11:01:29 -05:00
|
|
|
return { pos, ind };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (KIRI.worker)
|
|
|
|
|
KIRI.worker.animate = function(data, send) {
|
2020-11-24 14:03:45 -05:00
|
|
|
if (data.speed >= 0) {
|
|
|
|
|
renderSpeed = data.speed;
|
|
|
|
|
}
|
|
|
|
|
if (data.steps > 0) {
|
|
|
|
|
stepsRemain = data.steps;
|
|
|
|
|
}
|
|
|
|
|
if (animating) {
|
|
|
|
|
return send.done();
|
|
|
|
|
}
|
|
|
|
|
renderPath(send);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (KIRI.worker)
|
|
|
|
|
KIRI.worker.animate_cleanup = function(data, send) {
|
|
|
|
|
if (animating) {
|
|
|
|
|
animateClear = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let animateClear = false;
|
|
|
|
|
let animating = false;
|
|
|
|
|
let renderSpeed = 25;
|
|
|
|
|
let stepsRemain = 0;
|
|
|
|
|
|
|
|
|
|
function renderPath(send) {
|
|
|
|
|
if (animateClear) {
|
|
|
|
|
animateClear = false;
|
|
|
|
|
animating = false;
|
|
|
|
|
send.done();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (stepsRemain <= 0 || renderSpeed === 0) {
|
|
|
|
|
animating = false;
|
|
|
|
|
send.done();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const next = path[pathIndex++];
|
|
|
|
|
if (!next) {
|
|
|
|
|
animating = false;
|
|
|
|
|
stepsRemain = 0;
|
|
|
|
|
send.done();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
animating = true;
|
|
|
|
|
stepsRemain--;
|
2020-11-25 12:51:18 -05:00
|
|
|
if (next.tool >= 0 && (!tool || tool.getNumber() !== next.tool)) {
|
2020-12-01 19:54:54 -05:00
|
|
|
// on real tool change, go to safe Z first
|
|
|
|
|
if (tool) {
|
|
|
|
|
let pos = last.point = {
|
|
|
|
|
x: last.point.x,
|
|
|
|
|
y: last.point.y,
|
|
|
|
|
z: stock.z
|
|
|
|
|
};
|
|
|
|
|
send.data({ mesh_move: { toolID, pos }});
|
|
|
|
|
}
|
2020-11-24 14:03:45 -05:00
|
|
|
updateTool(next.tool, send);
|
|
|
|
|
}
|
2020-11-25 12:51:18 -05:00
|
|
|
const id = toolID;
|
2020-11-24 14:03:45 -05:00
|
|
|
if (last) {
|
|
|
|
|
const lp = last.point, np = next.point;
|
|
|
|
|
const dx = np.x - lp.x, dy = np.y - lp.y, dz = np.z - lp.z;
|
2020-11-24 19:21:30 -05:00
|
|
|
// skip moves that are closer than resolution
|
|
|
|
|
if (Math.sqrt(dx*dx +dy*dy + dz*dz) < rez) {
|
2020-11-25 12:51:18 -05:00
|
|
|
setTimeout(() => { renderPath(send) }, 0);
|
2020-11-24 19:21:30 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 14:03:45 -05:00
|
|
|
const md = Math.max(Math.abs(dx), Math.abs(dy), Math.abs(dz));
|
|
|
|
|
const st = Math.ceil(md / rez);
|
|
|
|
|
const mx = dx / st, my = dy / st, mz = dz / st;
|
|
|
|
|
const moves = [];
|
|
|
|
|
for (let i=0, x=lp.x, y=lp.y, z=lp.z; i<st; i++) {
|
|
|
|
|
moves.push({x,y,z});
|
|
|
|
|
x += mx;
|
|
|
|
|
y += my;
|
|
|
|
|
z += mz;
|
2020-11-24 12:27:55 -05:00
|
|
|
}
|
2020-11-24 14:03:45 -05:00
|
|
|
moves.push(next.point);
|
|
|
|
|
renderMoves(id, moves, send);
|
2020-11-24 12:27:55 -05:00
|
|
|
} else {
|
2020-11-24 14:03:45 -05:00
|
|
|
tool.pos = next.point;
|
|
|
|
|
send.data({ mesh_move: { id, pos: next.point }});
|
|
|
|
|
setTimeout(() => { renderPath(send) }, 0);
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
2020-11-24 14:03:45 -05:00
|
|
|
last = next;
|
|
|
|
|
}
|
2020-11-24 00:11:49 -05:00
|
|
|
|
2020-11-24 12:27:55 -05:00
|
|
|
function renderMoves(id, moves, send) {
|
|
|
|
|
let index = 0;
|
|
|
|
|
function update() {
|
2020-11-24 14:03:45 -05:00
|
|
|
if (animateClear) {
|
|
|
|
|
return renderPath(send);
|
|
|
|
|
}
|
|
|
|
|
if (renderSpeed > 0 && index < moves.length) {
|
|
|
|
|
const pos = moves[index++];
|
|
|
|
|
if (!pos) throw `no pos @ ${index} of ${moves.length}`;
|
|
|
|
|
tool.pos = pos;
|
|
|
|
|
updateMesh(pos, send);
|
|
|
|
|
send.data({ mesh_move: { id, pos }});
|
|
|
|
|
}
|
2020-11-24 12:27:55 -05:00
|
|
|
if (index < moves.length) {
|
2020-11-24 14:03:45 -05:00
|
|
|
setTimeout(update, renderSpeed);
|
2020-11-24 12:27:55 -05:00
|
|
|
} else {
|
2020-11-24 14:03:45 -05:00
|
|
|
setTimeout(() => { renderPath(send) }, renderSpeed);
|
2020-11-24 12:27:55 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
update(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateMesh(pos, send) {
|
|
|
|
|
const prof = tool.profile;
|
|
|
|
|
const { size, pix } = tool.profileDim;
|
|
|
|
|
const mid = Math.floor(pix/2);
|
2020-11-24 19:21:30 -05:00
|
|
|
const update = new Float32Array(Math.round(prof.length * 0.8));
|
2020-11-25 13:09:01 -05:00
|
|
|
const rx = Math.floor((pos.x + stock.x / 2 - size / 2 - center.x) / rez);
|
|
|
|
|
const ry = Math.floor((pos.y + stock.y / 2 - size / 2 - center.y) / rez);
|
2020-11-24 19:21:30 -05:00
|
|
|
let upos = 0;
|
2020-11-24 12:27:55 -05:00
|
|
|
// deform mesh to lowest point on tool profile
|
|
|
|
|
for (let i=0, il=prof.length; i < il; ) {
|
|
|
|
|
const dx = mid + prof[i++];
|
|
|
|
|
const dy = mid + prof[i++];
|
|
|
|
|
const dz = prof[i++];
|
|
|
|
|
|
|
|
|
|
const gx = rx + dx;
|
|
|
|
|
const gy = ry + dy;
|
2020-11-24 14:03:45 -05:00
|
|
|
|
|
|
|
|
if (gx < 0|| gy < 0 || gx > gridX-1 || gy > gridY-1) continue;
|
|
|
|
|
|
2020-11-24 12:27:55 -05:00
|
|
|
const gi = gx * gridY + gy;
|
|
|
|
|
const iz = gi * 3 + 2;
|
|
|
|
|
|
|
|
|
|
const cz = grid[iz];
|
|
|
|
|
const tz = tool.pos.z - dz;
|
|
|
|
|
if (tz < cz) {
|
2020-11-24 19:21:30 -05:00
|
|
|
update[upos++] = iz;
|
|
|
|
|
update[upos++] = tz;
|
2020-11-24 12:27:55 -05:00
|
|
|
grid[iz] = tz;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-24 19:21:30 -05:00
|
|
|
if (upos > 0) {
|
|
|
|
|
const mesh_update = update.slice(0,upos);
|
|
|
|
|
send.data({ id: 0, mesh_update }, [ mesh_update.buffer ]);
|
2020-11-24 12:27:55 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 11:01:29 -05:00
|
|
|
function updateTool(toolnum, send) {
|
|
|
|
|
if (tool) {
|
2020-11-25 12:51:18 -05:00
|
|
|
send.data({ mesh_del: toolID });
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
tool = new CAM.Tool({ tools }, undefined, toolnum);
|
|
|
|
|
tool.generateProfile(rez);
|
2020-11-24 20:18:02 -05:00
|
|
|
const flen = tool.fluteLength() || 15;
|
|
|
|
|
const slen = tool.shaftLength() || 15;
|
2020-11-24 11:01:29 -05:00
|
|
|
// const frad = tool.fluteDiameter() / 2;
|
|
|
|
|
const prof = tool.profile;
|
|
|
|
|
const { size, pix } = tool.profileDim;
|
2020-11-24 20:18:02 -05:00
|
|
|
const { pos, ind } = createGrid(pix, pix, {x:size, y:size, z:flen+slen}, rez);
|
2020-11-24 11:01:29 -05:00
|
|
|
const mid = Math.floor(pix/2);
|
|
|
|
|
// deform mesh to fit tool profile
|
|
|
|
|
for (let i=0, il=prof.length; i < il; ) {
|
|
|
|
|
const dx = mid + prof[i++];
|
|
|
|
|
const dy = mid + prof[i++];
|
|
|
|
|
const dz = prof[i++];
|
|
|
|
|
pos[(dx * pix + dy) * 3 + 2] = -dz;
|
|
|
|
|
}
|
2020-11-25 12:51:18 -05:00
|
|
|
send.data({ mesh_add: { id:++toolID, pos, ind }});
|
2020-11-24 11:01:29 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-24 00:37:44 -05:00
|
|
|
});
|