reorganize and rename driver files for consistency and clarity
This commit is contained in:
parent
7f50bafe9e
commit
67f405fd7b
74 changed files with 283 additions and 283 deletions
103
src/kiri/mode/cam/work/op-shadow.js
Normal file
103
src/kiri/mode/cam/work/op-shadow.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { CamOp } from '../core/op.js';
|
||||
import { newSlice } from '../../../core/slice.js';
|
||||
import { newPolygon } from '../../../../geo/polygon.js';
|
||||
|
||||
/**
|
||||
* Computes the Part "shadow" and attaches relevant data to the "state" object
|
||||
*
|
||||
* The part shadow consists of top-cown layers at which the polygon shadow changes
|
||||
* shape. For curved or sloped surfaces, this is approximated and paths that clip
|
||||
* to it should use the next lower layer from current Z to ensure no part collisions.
|
||||
*
|
||||
* The shadow at each layer is computed by top-down unioning the part outline with
|
||||
* the shadow from the layer above.
|
||||
*
|
||||
* This operation is injected at the start of the operation chain before processing.
|
||||
*/
|
||||
class OpShadow extends CamOp {
|
||||
constructor(state, op) {
|
||||
super(state, op);
|
||||
}
|
||||
|
||||
async slice(progress) {
|
||||
let state = this.state;
|
||||
|
||||
let { addSlices, settings, shadowAt, unsafe, widget, workarea } = state;
|
||||
let { devel } = settings.controller;
|
||||
|
||||
let bounds = widget.getBoundingBox();
|
||||
let slices = [];
|
||||
let shadowBase;
|
||||
let skipTerrain = unsafe;
|
||||
let terrain = [];
|
||||
let tzindex = [];
|
||||
|
||||
let minZ = Math.floor(bounds.min.z);
|
||||
let maxZ = Math.floor(bounds.max.z);
|
||||
for (let z = maxZ; z >= minZ; z--) {
|
||||
tzindex.push(z);
|
||||
}
|
||||
|
||||
if (skipTerrain) {
|
||||
let { stock } = settings;
|
||||
let { center } = stock;
|
||||
|
||||
console.log("skipping terrain generation");
|
||||
shadowBase = [ newPolygon().centerRectangle(center, stock.x, stock.y) ];
|
||||
tzindex = [ ];
|
||||
|
||||
state.shadow = {
|
||||
base: shadowBase, // computed shadow union at base of part
|
||||
holes: [],
|
||||
skip: skipTerrain,
|
||||
slices: [], // legacy / transitional
|
||||
stack: [], // stack of shadow slices
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// distributed pre-fill shadow layer cache
|
||||
await widget.computeShadowStack(tzindex, prog => progress(prog / 2, 'shadow'));
|
||||
|
||||
// terrain is the "shadow stack" where index 0 = top of part
|
||||
// thus array.length -1 = bottom of part
|
||||
for (let i=0; i<tzindex.length; i++) {
|
||||
let z = tzindex[i];
|
||||
let shadow = shadowBase = await shadowAt(z);
|
||||
let slice = newSlice(z);
|
||||
slice.shadow = shadow;
|
||||
slice.addTops(shadow);
|
||||
slices.push(slice);
|
||||
terrain.push({ slice, tops: shadow });
|
||||
if (devel) {
|
||||
slice.output()
|
||||
.setLayer("shadow", {line: 0x888800, thin: true })
|
||||
.addPolys(shadow, { thin: true });
|
||||
}
|
||||
progress(0.5 + (i / tzindex.length) * 0.5, 'shadow');
|
||||
}
|
||||
|
||||
if (devel && slices.length) {
|
||||
addSlices(slices);
|
||||
}
|
||||
|
||||
if (terrain.length === 0) {
|
||||
throw `invalid widget shadow`;
|
||||
}
|
||||
|
||||
// TODO: refactor ops to use a unified shadow object
|
||||
state.shadow = {
|
||||
base: shadowBase, // computed shadow union at base of part
|
||||
holes: shadowBase.map(p => p.inner || []).flat(),
|
||||
skip: skipTerrain,
|
||||
slices: slices, // legacy / transitional
|
||||
stack: terrain, // stack of shadow slices
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export { OpShadow };
|
||||
Loading…
Reference in a new issue