UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

113 lines (112 loc) 4.35 kB
"use strict"; 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; }