@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
95 lines (86 loc) • 3.13 kB
text/typescript
/**
* Boolean Intersect Operation
*
*
*/
import {CSGSopNode} from './_BaseCSG';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {CoreGroup} from '../../../core/geometry/Group';
import {CsgGeometryType, CsgGeometry} from '../../../core/geometry/modules/csg/CsgCommon';
import {csgIsGeom2, csgIsGeom3} from '../../../core/geometry/modules/csg/CsgCoreType';
import {SopType} from '../../poly/registers/nodes/types/Sop';
import {csgApplyTransform} from '../../../core/geometry/modules/csg/math/CsgMat4';
import {booleans} from '@jscad/modeling';
import {CsgObject} from '../../../core/geometry/modules/csg/CsgObject';
const {intersect, union, subtract} = booleans;
export enum BooleanCsgOperationType {
INTERSECT = 'intersect',
SUBTRACT = 'subtract',
UNION = 'union',
}
export const BOOLEAN_CSG_OPERATION_TYPES: BooleanCsgOperationType[] = [
BooleanCsgOperationType.INTERSECT,
BooleanCsgOperationType.SUBTRACT,
BooleanCsgOperationType.UNION,
];
class CSGBooleanSopParamsConfig extends NodeParamsConfig {
/** @param operation */
operation = ParamConfig.INTEGER(BOOLEAN_CSG_OPERATION_TYPES.indexOf(BooleanCsgOperationType.INTERSECT), {
menu: {entries: BOOLEAN_CSG_OPERATION_TYPES.map((name, value) => ({name, value}))},
});
}
const ParamsConfig = new CSGBooleanSopParamsConfig();
export class CSGBooleanSopNode extends CSGSopNode<CSGBooleanSopParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return SopType.CSG_BOOLEAN;
}
protected override initializeNode() {
this.io.inputs.setCount(2);
}
setOperation(operation: BooleanCsgOperationType) {
this.p.operation.set(BOOLEAN_CSG_OPERATION_TYPES.indexOf(operation));
}
override cook(inputCoreGroups: CoreGroup[]) {
const objects: CsgObject<CsgGeometryType>[] = [];
const objects0 = inputCoreGroups[0].csgObjects();
const objects1 = inputCoreGroups[1].csgObjects();
if (objects0 && objects1) {
const count = Math.min(objects0.length, objects1.length);
for (let i = 0; i < count; i++) {
const object0 = objects0[i];
const object1 = objects1[i];
const result = this._applyOperation(object0.csgGeometry(), object1.csgGeometry());
if (result) {
objects.push(new CsgObject(result));
}
}
}
this.setCSGObjects(objects);
}
private _applyOperation(object0: CsgGeometry, object1: CsgGeometry) {
const method = this._method();
const bothAreGeom3 = csgIsGeom3(object0) && csgIsGeom3(object1);
if (bothAreGeom3) {
return method(object0, object1);
}
const bothAreGeom2 = csgIsGeom2(object0) && csgIsGeom2(object1);
if (bothAreGeom2) {
// the transforms are applied for geom2, as otherwise the matrix is not taken into account
csgApplyTransform(object0);
csgApplyTransform(object1);
return method(object0, object1);
}
}
private _method() {
const operation = BOOLEAN_CSG_OPERATION_TYPES[this.pv.operation];
switch (operation) {
case BooleanCsgOperationType.INTERSECT:
return intersect;
case BooleanCsgOperationType.SUBTRACT:
return subtract;
case BooleanCsgOperationType.UNION:
return union;
}
}
}