@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
113 lines (112 loc) • 4.35 kB
JavaScript
;
import { stringToAttribNames } from "./../../../core/String";
import { BaseSopOperation } from "./_Base";
import { InputCloneMode } from "../../poly/InputCloneMode";
import { BufferGeometry, Float32BufferAttribute } from "three";
import {
SUBTRACTION,
ADDITION,
DIFFERENCE,
INTERSECTION,
Brush,
Evaluator
} from "../../../core/thirdParty/three-bvh-csg";
import { ObjectType } from "../../../core/geometry/Constant";
import { CoreGeometryBuilderMerge } from "../../../core/geometry/modules/three/builders/Merge";
import { arrayPushItems } from "../../../core/ArrayUtils";
export var BooleanOperation = /* @__PURE__ */ ((BooleanOperation2) => {
BooleanOperation2["INTERSECT"] = "intersect";
BooleanOperation2["SUBTRACT"] = "subtract";
BooleanOperation2["ADD"] = "add";
BooleanOperation2["DIFFERENCE"] = "difference";
return BooleanOperation2;
})(BooleanOperation || {});
export const BOOLEAN_OPERATIONS = [
"intersect" /* INTERSECT */,
"subtract" /* SUBTRACT */,
"add" /* ADD */,
"difference" /* DIFFERENCE */
];
const evaluationIdByBooleanOperation = {
["intersect" /* INTERSECT */]: INTERSECTION,
["subtract" /* SUBTRACT */]: SUBTRACTION,
["add" /* ADD */]: ADDITION,
["difference" /* DIFFERENCE */]: DIFFERENCE
};
const _attribNames = [];
export class BooleanSopOperation extends BaseSopOperation {
static type() {
return "boolean";
}
cook(inputCoreGroups, params) {
var _a;
const meshA = inputCoreGroups[0].threejsObjectsWithGeo()[0];
const meshB = inputCoreGroups[1].threejsObjectsWithGeo()[0];
if (!(meshA && meshA.geometry && meshB && meshB.geometry)) {
(_a = this.states) == null ? void 0 : _a.error.set("input objects need to have mesh geometries at the top level");
return this.createCoreGroupFromObjects([]);
}
const csgEvaluator = new Evaluator();
const brush1 = new Brush(meshA.geometry, params.keepMaterials ? meshA.material : void 0);
const brush2 = new Brush(meshB.geometry, params.keepMaterials ? meshB.material : void 0);
const operation = BOOLEAN_OPERATIONS[params.operation];
const operationId = evaluationIdByBooleanOperation[operation];
const attributes = ["position", "normal"];
if (params.keepVertexColor) {
attributes.push("color");
}
if (params.additionalAttributes.trim() != "") {
stringToAttribNames(params.additionalAttributes, _attribNames);
arrayPushItems(_attribNames, attributes);
}
csgEvaluator.attributes = attributes;
csgEvaluator.useGroups = params.keepMaterials || params.useInputGroups;
csgEvaluator.debug.enabled = params.intersectionEdgesOnly;
const output = csgEvaluator.evaluate(brush1, brush2, operationId);
if (params.intersectionEdgesOnly) {
const lines = csgEvaluator.debug.intersectionEdges;
if (lines.length > 0) {
const linesGeometry = _createLinesObject(lines);
if (linesGeometry) {
const object = BaseSopOperation.createObject(linesGeometry, ObjectType.LINE_SEGMENTS);
return this.createCoreGroupFromObjects([object]);
}
}
} else {
output.disposeCacheData();
BaseSopOperation.createIndexIfNone(output.geometry);
if (!params.keepMaterials) {
output.material = meshA.material;
}
return this.createCoreGroupFromObjects([output]);
}
return this.createCoreGroupFromObjects([]);
}
}
BooleanSopOperation.DEFAULT_PARAMS = {
operation: BOOLEAN_OPERATIONS.indexOf("intersect" /* INTERSECT */),
keepVertexColor: false,
additionalAttributes: "",
keepMaterials: true,
useInputGroups: false,
intersectionEdgesOnly: false
};
BooleanSopOperation.INPUT_CLONED_STATE = [InputCloneMode.FROM_NODE, InputCloneMode.NEVER];
function _createLinesObject(lines) {
const geometries = lines.map(_createLineGeometry);
return CoreGeometryBuilderMerge.merge(geometries);
}
function _createLineGeometry(line) {
const pointsCount = 2;
const positions = new Array(pointsCount * 3);
const indices = new Array(pointsCount);
const i = 0;
line.start.toArray(positions, i * 3);
line.end.toArray(positions, (i + 1) * 3);
indices[0] = 0;
indices[1] = 1;
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
geometry.setIndex(indices);
return geometry;
}