add codec factory option, improve geo vertex caching, fix surface find in indexed mode
This commit is contained in:
parent
341c971146
commit
d73f72586a
9 changed files with 71 additions and 23 deletions
|
|
@ -518,6 +518,7 @@ export const conf = {
|
||||||
camLatheAngle: 1,
|
camLatheAngle: 1,
|
||||||
camLatheLinear: true,
|
camLatheLinear: true,
|
||||||
camLatheOver: 0.1,
|
camLatheOver: 0.1,
|
||||||
|
camLatheDown: 0,
|
||||||
camLatheSpeed: 500,
|
camLatheSpeed: 500,
|
||||||
camLatheSpindle: 1000,
|
camLatheSpindle: 1000,
|
||||||
camLatheTool: 1000,
|
camLatheTool: 1000,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { codec } from '../../core/codec.js';
|
||||||
import { consts } from '../../core/consts.js';
|
import { consts } from '../../core/consts.js';
|
||||||
import { space } from '../../../moto/space.js';
|
import { space } from '../../../moto/space.js';
|
||||||
import { local } from '../../../data/local.js';
|
import { local } from '../../../data/local.js';
|
||||||
|
import { newWidget } from '../widget.js';
|
||||||
import { utils } from '../../core/utils.js';
|
import { utils } from '../../core/utils.js';
|
||||||
import { version } from '../../../moto/license.js';
|
import { version } from '../../../moto/license.js';
|
||||||
import { JSZip } from '../../../ext/jszip-esm.js';
|
import { JSZip } from '../../../ext/jszip-esm.js';
|
||||||
|
|
@ -608,6 +609,7 @@ function settingsImport(data, ask) {
|
||||||
work.type = 100;
|
work.type = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
codec.setFactory(codec.TYPE.WIDGET, newWidget);
|
||||||
codec.decode(data.work).forEach(widget => {
|
codec.decode(data.work).forEach(widget => {
|
||||||
api.platform.add(widget, 0, true, true);
|
api.platform.add(widget, 0, true, true);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { Slice, newSlice, Top, newTop } from './slice.js';
|
||||||
import { Widget, newWidget } from './widget.js';
|
import { Widget, newWidget } from './widget.js';
|
||||||
|
|
||||||
const decoders = {};
|
const decoders = {};
|
||||||
|
const factories = {};
|
||||||
const freeMem = true;
|
const freeMem = true;
|
||||||
|
|
||||||
const TYPE = {
|
const TYPE = {
|
||||||
|
|
@ -213,6 +214,11 @@ function decodePointArray2D(array, z, fn) {
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFactory(type, factory) {
|
||||||
|
factories[type] = factory;
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
|
||||||
// ----- Widget Codec -----
|
// ----- Widget Codec -----
|
||||||
|
|
||||||
Widget.prototype.encode = function(state) {
|
Widget.prototype.encode = function(state) {
|
||||||
|
|
@ -236,7 +242,8 @@ registerDecoder(TYPE.WIDGET, function(v, state) {
|
||||||
const id = v.id,
|
const id = v.id,
|
||||||
group = v.group || id,
|
group = v.group || id,
|
||||||
track = v.track || undefined,
|
track = v.track || undefined,
|
||||||
widget = newWidget(id, Widget.Groups.forid(group)),
|
factory = factories[TYPE.WIDGET] ?? newWidget,
|
||||||
|
widget = factory(id, Widget.Groups.forid(group)),
|
||||||
meta= v.meta || widget.meta,
|
meta= v.meta || widget.meta,
|
||||||
anno = v.anno || widget.anno;
|
anno = v.anno || widget.anno;
|
||||||
|
|
||||||
|
|
@ -480,6 +487,7 @@ registerDecoder(TYPE.LAYERS, function(v, state) {
|
||||||
});
|
});
|
||||||
|
|
||||||
export const codec = {
|
export const codec = {
|
||||||
|
TYPE,
|
||||||
encode,
|
encode,
|
||||||
decode,
|
decode,
|
||||||
registerDecoder,
|
registerDecoder,
|
||||||
|
|
@ -488,10 +496,12 @@ export const codec = {
|
||||||
decodePointArray,
|
decodePointArray,
|
||||||
encodePointArray2D,
|
encodePointArray2D,
|
||||||
decodePointArray2D,
|
decodePointArray2D,
|
||||||
|
setFactory,
|
||||||
toCodable
|
toCodable
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
TYPE,
|
||||||
encode,
|
encode,
|
||||||
decode,
|
decode,
|
||||||
registerDecoder,
|
registerDecoder,
|
||||||
|
|
@ -500,6 +510,7 @@ export {
|
||||||
decodePointArray,
|
decodePointArray,
|
||||||
encodePointArray2D,
|
encodePointArray2D,
|
||||||
decodePointArray2D,
|
decodePointArray2D,
|
||||||
|
setFactory,
|
||||||
toCodable
|
toCodable
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,9 +181,13 @@ class Widget {
|
||||||
return this.loadVertices(...arguments);
|
return this.loadVertices(...arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
setModified() {
|
setModified(reason) {
|
||||||
this.modified = true;
|
this.modified = true;
|
||||||
this.boundingBoxNeedsUpdate = true;
|
this.boundingBoxNeedsUpdate = true;
|
||||||
|
this.clearShadows();
|
||||||
|
if (reason !== 'axis') {
|
||||||
|
this.cache.geo = undefined;
|
||||||
|
}
|
||||||
if (this.mesh && this.mesh.geometry) {
|
if (this.mesh && this.mesh.geometry) {
|
||||||
// this fixes ray intersections after the mesh is modified
|
// this fixes ray intersections after the mesh is modified
|
||||||
this.mesh.geometry.boundingSphere = null;
|
this.mesh.geometry.boundingSphere = null;
|
||||||
|
|
@ -355,7 +359,7 @@ class Widget {
|
||||||
// invalidate cached points
|
// invalidate cached points
|
||||||
if (x || y || z) {
|
if (x || y || z) {
|
||||||
this.points = null;
|
this.points = null;
|
||||||
this.setModified();
|
this.setModified('moveMesh');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,11 +376,11 @@ class Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
setAxisIndex(deg) {
|
setAxisIndex(deg) {
|
||||||
|
// console.trace(deg);
|
||||||
let rad = deg * (Math.PI / 180);
|
let rad = deg * (Math.PI / 180);
|
||||||
if (rad !== this.track.indexRad) {
|
if (rad !== this.track.indexRad) {
|
||||||
this.track.indexRad = rad;
|
this.track.indexRad = rad;
|
||||||
this.clearShadows();
|
this.setModified('axis');
|
||||||
this.setModified();
|
|
||||||
this._updateMeshPosition();
|
this._updateMeshPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -429,7 +433,7 @@ class Widget {
|
||||||
pos.z += (z || 0);
|
pos.z += (z || 0);
|
||||||
}
|
}
|
||||||
if (x || y || z) {
|
if (x || y || z) {
|
||||||
this.setModified();
|
this.setModified('_move');
|
||||||
this._updateMeshPosition();
|
this._updateMeshPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +479,7 @@ class Widget {
|
||||||
scale.x *= (x || 1.0);
|
scale.x *= (x || 1.0);
|
||||||
scale.y *= (y || 1.0);
|
scale.y *= (y || 1.0);
|
||||||
scale.z *= (z || 1.0);
|
scale.z *= (z || 1.0);
|
||||||
this.setModified();
|
this.setModified('_scale');
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate(x, y, z, temp, center = true) {
|
rotate(x, y, z, temp, center = true) {
|
||||||
|
|
@ -514,7 +518,7 @@ class Widget {
|
||||||
rot.y += (y || 0);
|
rot.y += (y || 0);
|
||||||
rot.z += (z || 0);
|
rot.z += (z || 0);
|
||||||
}
|
}
|
||||||
this.setModified();
|
this.setModified('_rotate');
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo all accumulated rotations
|
// undo all accumulated rotations
|
||||||
|
|
@ -524,7 +528,7 @@ class Widget {
|
||||||
});
|
});
|
||||||
this.roto = [];
|
this.roto = [];
|
||||||
this.center();
|
this.center();
|
||||||
this.setModified();
|
this.setModified('unrotate');
|
||||||
if (this.refreshVisualState) this.refreshVisualState();
|
if (this.refreshVisualState) this.refreshVisualState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,7 +567,7 @@ class Widget {
|
||||||
}
|
}
|
||||||
pos.needsUpdate = true;
|
pos.needsUpdate = true;
|
||||||
ot.mirror = !ot.mirror;
|
ot.mirror = !ot.mirror;
|
||||||
this.setModified();
|
this.setModified('_mirror');
|
||||||
this.points = null;
|
this.points = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -586,6 +590,17 @@ class Widget {
|
||||||
|
|
||||||
getGeoVertices(opt = {}) {
|
getGeoVertices(opt = {}) {
|
||||||
const { unroll, translate } = opt;
|
const { unroll, translate } = opt;
|
||||||
|
let cacheKey = [
|
||||||
|
unroll ? 1 : 0,
|
||||||
|
translate ? 1 : 0,
|
||||||
|
((this.track.indexRad ?? 0) * 100000) | 0
|
||||||
|
].join(',');
|
||||||
|
let marked = Date.now();
|
||||||
|
let geoCache = this.cache.geo = (this.cache.geo || {});
|
||||||
|
let cached = geoCache[cacheKey];
|
||||||
|
if (cached) {
|
||||||
|
return cached.pos;
|
||||||
|
}
|
||||||
let geo = this.mesh.geometry;
|
let geo = this.mesh.geometry;
|
||||||
let pos = geo.getAttribute('position');
|
let pos = geo.getAttribute('position');
|
||||||
// if indexed, return points rotated about X and then offset
|
// if indexed, return points rotated about X and then offset
|
||||||
|
|
@ -595,6 +610,7 @@ class Widget {
|
||||||
.applyMatrix4( new THREE.Matrix4().makeRotationX(-track.indexRad) );
|
.applyMatrix4( new THREE.Matrix4().makeRotationX(-track.indexRad) );
|
||||||
}
|
}
|
||||||
pos = pos.array;
|
pos = pos.array;
|
||||||
|
// unroll indexed geometry
|
||||||
if (geo.index && unroll !== false) {
|
if (geo.index && unroll !== false) {
|
||||||
let idx = geo.index.array;
|
let idx = geo.index.array;
|
||||||
let len = idx.length;
|
let len = idx.length;
|
||||||
|
|
@ -608,12 +624,8 @@ class Widget {
|
||||||
pp2[inc++] = pos[ip];
|
pp2[inc++] = pos[ip];
|
||||||
}
|
}
|
||||||
pos = pp2;
|
pos = pp2;
|
||||||
} else if (translate) {
|
|
||||||
pos = pos.slice();
|
|
||||||
}
|
}
|
||||||
// used by CAM.shadowAt()
|
geoCache[cacheKey] = { pos, marked };
|
||||||
this.cache.geo = pos;
|
|
||||||
delete this.cache.shadow;
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -631,7 +643,7 @@ class Widget {
|
||||||
if (!this.bounds || refresh || this.boundingBoxNeedsUpdate) {
|
if (!this.bounds || refresh || this.boundingBoxNeedsUpdate) {
|
||||||
this.bounds = new THREE.Box3().setFromArray(this.getGeoVertices({
|
this.bounds = new THREE.Box3().setFromArray(this.getGeoVertices({
|
||||||
translate: true,
|
translate: true,
|
||||||
unroll: false
|
unroll: true
|
||||||
}));
|
}));
|
||||||
this.boundingBoxNeedsUpdate = false;
|
this.boundingBoxNeedsUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
@ -701,6 +713,7 @@ class Widget {
|
||||||
// find closest shadow above and use to speed up delta shadow gen
|
// find closest shadow above and use to speed up delta shadow gen
|
||||||
let zover = Object.keys(shadows).map(v => parseFloat(v)).filter(v => v > z);
|
let zover = Object.keys(shadows).map(v => parseFloat(v)).filter(v => v > z);
|
||||||
let minZabove = Math.min(Infinity, ...zover);
|
let minZabove = Math.min(Infinity, ...zover);
|
||||||
|
// shift shadow probeline down a fraction to capture z flats with FP noise
|
||||||
let shadow = this.#computeShadowAt(z - 0.005, minZabove);
|
let shadow = this.#computeShadowAt(z - 0.005, minZabove);
|
||||||
if (minZabove < Infinity) {
|
if (minZabove < Infinity) {
|
||||||
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0, true, { wasm: false });
|
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0, true, { wasm: false });
|
||||||
|
|
@ -725,7 +738,7 @@ class Widget {
|
||||||
if (this.cache.shadow) {
|
if (this.cache.shadow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const geo = this.cache.geo;
|
const geo = this.getGeoVertices({ unroll: true, translate: true });
|
||||||
const length = geo.length;
|
const length = geo.length;
|
||||||
const bounds = this.getBoundingBox();
|
const bounds = this.getBoundingBox();
|
||||||
const stack = {};
|
const stack = {};
|
||||||
|
|
|
||||||
|
|
@ -350,8 +350,9 @@ export function createPopOps() {
|
||||||
createPopOp('lathe', {
|
createPopOp('lathe', {
|
||||||
tool: 'camLatheTool',
|
tool: 'camLatheTool',
|
||||||
spindle: 'camLatheSpindle',
|
spindle: 'camLatheSpindle',
|
||||||
step: 'camLatheOver',
|
|
||||||
angle: 'camLatheAngle',
|
angle: 'camLatheAngle',
|
||||||
|
step: 'camLatheOver',
|
||||||
|
down: 'camLatheDown',
|
||||||
rate: 'camLatheSpeed',
|
rate: 'camLatheSpeed',
|
||||||
tolerance: 'camTolerance',
|
tolerance: 'camTolerance',
|
||||||
filter: 'camContourFilter',
|
filter: 'camContourFilter',
|
||||||
|
|
@ -365,8 +366,9 @@ export function createPopOps() {
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: toInt, units }),
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 100.0) }),
|
|
||||||
angle: UC.newInput(LANG.cc_sang_s, { title: LANG.cc_sang_l, convert: toFloat, bound: UC.bound(0.01, 180.0) }),
|
angle: UC.newInput(LANG.cc_sang_s, { title: LANG.cc_sang_l, convert: toFloat, bound: UC.bound(0.01, 180.0) }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 100.0) }),
|
||||||
|
// down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
offStart: UC.newInput(LANG.ci_laso_s, { title: LANG.ci_laso_l, convert: toFloat}),
|
offStart: UC.newInput(LANG.ci_laso_s, { title: LANG.ci_laso_l, convert: toFloat}),
|
||||||
offEnd: UC.newInput(LANG.ci_laeo_s, { title: LANG.ci_laeo_l, convert: toFloat}),
|
offEnd: UC.newInput(LANG.ci_laeo_s, { title: LANG.ci_laeo_l, convert: toFloat}),
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ function surface_prep(widget, index) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function surface_find(widget, faces, radians) {
|
function surface_find(widget, faces, radians, filterZ) {
|
||||||
surface_prep(widget);
|
surface_prep(widget);
|
||||||
return widget.tool.findConnectedSurface(faces, radians || 0, 0.0);
|
return widget.tool.findConnectedSurface(faces, radians, filterZ);
|
||||||
};
|
};
|
||||||
|
|
||||||
function init(worker) {
|
function init(worker) {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,10 @@ export function menu() {
|
||||||
camStockOffset: newBoolean(LANG.cs_offs_s, onBooleanClick, {title:LANG.cs_offs_l}),
|
camStockOffset: newBoolean(LANG.cs_offs_s, onBooleanClick, {title:LANG.cs_offs_l}),
|
||||||
camStockIndexed: newBoolean(LANG.cs_indx_s, onBooleanClick, {title:LANG.cs_indx_l}),
|
camStockIndexed: newBoolean(LANG.cs_indx_s, onBooleanClick, {title:LANG.cs_indx_l}),
|
||||||
camStockIndexGrid: newBoolean(LANG.cs_ishg_s, onBooleanClick, {title:LANG.cs_ishg_l, show:() => ui.camStockIndexed.checked}),
|
camStockIndexGrid: newBoolean(LANG.cs_ishg_s, onBooleanClick, {title:LANG.cs_ishg_l, show:() => ui.camStockIndexed.checked}),
|
||||||
|
// separator: newBlank({ class:"set-sep", driven }),
|
||||||
|
// camStockManual: newRow([
|
||||||
|
// (ui.stockPlace = newButton('position', onButtonClick, { })),
|
||||||
|
// ], {class:"ext-buttons f-row"}),
|
||||||
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
||||||
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
||||||
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units}),
|
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units}),
|
||||||
|
|
|
||||||
|
|
@ -792,8 +792,24 @@ export function init() {
|
||||||
|
|
||||||
// TAB/TRACE BUTTON HANDLERS
|
// TAB/TRACE BUTTON HANDLERS
|
||||||
api.event.on("button.click", target => {
|
api.event.on("button.click", target => {
|
||||||
let process = api.conf.get().process;
|
let { process, stock } = api.conf.get();
|
||||||
switch (target) {
|
switch (target) {
|
||||||
|
case api.ui.stockPlace:
|
||||||
|
api.uc.prompt("stock x,y,z position", "").then(csv => {
|
||||||
|
if (csv) {
|
||||||
|
let [x,y,z] = csv.split(',').map(v => parseInt(v) || 0);
|
||||||
|
let center = {
|
||||||
|
x: x ?? 0,
|
||||||
|
y: y ?? 0,
|
||||||
|
z: z ?? 0
|
||||||
|
}
|
||||||
|
// move widgets based on postion
|
||||||
|
// more complex than just moving stock
|
||||||
|
// because stock is based on contents, not the other way
|
||||||
|
console.log({ x,y,z });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
case api.ui.tabAdd:
|
case api.ui.tabAdd:
|
||||||
return tabAdd();
|
return tabAdd();
|
||||||
case api.ui.tabDun:
|
case api.ui.tabDun:
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,6 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function computeShadows() {
|
async function computeShadows() {
|
||||||
// console.log('(re)compute shadows');
|
|
||||||
await new OPS.shadow(state, { type: "shadow", silent: true }).slice(progress => {
|
await new OPS.shadow(state, { type: "shadow", silent: true }).slice(progress => {
|
||||||
// console.log('reshadowing', progress.round(3));
|
// console.log('reshadowing', progress.round(3));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue