UNPKG

@polygonjs/polygonjs

Version:

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

183 lines (182 loc) 7.13 kB
"use strict"; import { Mesh, BufferAttribute, Vector3 } from "three"; import { TypedSopNode } from "./_Base"; import { CoreFace } from "../../../core/geometry/modules/three/CoreFace"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { arrayChunk, rangeWithEnd } from "../../../core/ArrayUtils"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory"; import { ThreejsPoint } from "../../../core/geometry/modules/three/ThreejsPoint"; import { ThreejsPrimitiveTriangle } from "../../../core/geometry/modules/three/ThreejsPrimitiveTriangle"; const dummyMesh = new Mesh(); var FaceAttribName = /* @__PURE__ */ ((FaceAttribName2) => { FaceAttribName2["CENTER"] = "faceCenter"; FaceAttribName2["ID"] = "faceId"; FaceAttribName2["POSITION"] = "position"; return FaceAttribName2; })(FaceAttribName || {}); const _faceCenter = new Vector3(); const _position = new Vector3(); const _newPosition = new Vector3(); class FaceSopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param makes faces unique */ this.makeFacesUnique = ParamConfig.BOOLEAN(0); /** @param adds a vector3 attribute that represents the center of a face */ this.addFaceCenterAttribute = ParamConfig.BOOLEAN(0, { visibleIf: { makeFacesUnique: 1 } }); /** @param add an id attribute for each face */ this.addFaceId = ParamConfig.BOOLEAN(0, { visibleIf: { makeFacesUnique: 1 } }); /** @param allows to transform each face */ this.transform = ParamConfig.BOOLEAN(0, { visibleIf: { makeFacesUnique: 1 } }); /** @param scales the faces indepedently */ this.scale = ParamConfig.FLOAT(1, { visibleIf: { makeFacesUnique: 1, transform: 1 } }); } } const ParamsConfig = new FaceSopParamsConfig(); export class FaceSopNode extends TypedSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._face = new CoreFace(); this._points = [ new ThreejsPoint(dummyMesh, 0), new ThreejsPoint(dummyMesh, 0), new ThreejsPoint(dummyMesh, 0) ]; } static type() { return "face"; } initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE); } cook(input_contents) { const core_group = input_contents[0]; if (isBooleanTrue(this.pv.makeFacesUnique)) { this._makeFacesUnique(core_group); if (isBooleanTrue(this.pv.addFaceCenterAttribute)) { this._addFaceCenterAttribute(core_group); } if (isBooleanTrue(this.pv.addFaceId)) { this._addFaceId(core_group); } if (isBooleanTrue(this.pv.transform)) { this._transformFaces(core_group); } } this.setCoreGroup(core_group); } _makeFacesUnique(core_group) { var _a; const objects = core_group.threejsObjects(); for (const object of objects) { if (object.isMesh) { const geometry = object.geometry; const index = (_a = geometry.index) == null ? void 0 : _a.array; if (index) { const faces = arrayChunk([...index], 3); const pointsCount = faces.length * 3; for (const attrib_name of Object.keys(geometry.attributes)) { const attrib = geometry.attributes[attrib_name]; const attrib_size = attrib.itemSize; const new_values = new Float32Array(pointsCount * attrib_size); let new_value_index = 0; faces.forEach((face) => { face.forEach((index2) => { for (let i = 0; i < attrib_size; i++) { const current_value = attrib.array[index2 * attrib_size + i]; new_values[new_value_index] = current_value; new_value_index += 1; } }); }); geometry.setAttribute(attrib_name, new BufferAttribute(new_values, attrib_size)); } const newIndices = rangeWithEnd(pointsCount); geometry.setIndex(newIndices); } } } } _addFaceCenterAttribute(coreGroup) { const coreObjects = coreGroup.threejsCoreObjects(); for (const coreObject of coreObjects) { const object = coreObject.object(); const corePointClass = corePointClassFactory(object); if (object.isMesh) { if (!corePointClass.hasAttribute(object, "faceCenter" /* CENTER */)) { corePointClass.addNumericAttribute(object, "faceCenter" /* CENTER */, 3, -1); } const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object); this._face.setGeometry(object.geometry); for (let fi = 0; fi < facesCount; fi++) { this._face.setIndex(fi); this._face.center(_faceCenter); this._face.points(this._points); for (const point of this._points) { point.setAttribValue("faceCenter" /* CENTER */, _faceCenter); } } } } } _addFaceId(coreGroup) { const coreObjects = coreGroup.threejsCoreObjects(); for (const coreObject of coreObjects) { const object = coreObject.object(); const corePointClass = corePointClassFactory(object); if (object.isMesh) { if (!corePointClass.hasAttribute(object, "faceId" /* ID */)) { corePointClass.addNumericAttribute(object, "faceId" /* ID */, 1, -1); } const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object); this._face.setGeometry(object.geometry); for (let i = 0; i < facesCount; i++) { this._face.setIndex(i); this._face.points(this._points); for (const point of this._points) { point.setAttribValue("faceId" /* ID */, i); } } } } } _transformFaces(coreGroup) { const scale = this.pv.scale; const coreObjects = coreGroup.threejsCoreObjects(); for (const coreObject of coreObjects) { const object = coreObject.object(); const corePointClass = corePointClassFactory(object); if (object.isMesh) { if (!corePointClass.hasAttribute(object, "position" /* POSITION */)) { corePointClass.addNumericAttribute(object, "position" /* POSITION */, 3, -1); } const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object); this._face.setGeometry(object.geometry); for (let fi = 0; fi < facesCount; fi++) { this._face.setIndex(fi); this._face.center(_faceCenter); this._face.points(this._points); for (const point of this._points) { point.position(_position); _newPosition.x = _position.x * scale + _faceCenter.x * (1 - scale); _newPosition.y = _position.y * scale + _faceCenter.y * (1 - scale); _newPosition.z = _position.z * scale + _faceCenter.z * (1 - scale); point.setAttribValue("position" /* POSITION */, _newPosition); } } } } } }