UNPKG

@polygonjs/polygonjs

Version:

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

140 lines (139 loc) 5.41 kB
"use strict"; import { BaseSopOperation } from "./_Base"; import { Vector3, Matrix4, BufferGeometry } from "three"; import { ObjectType } from "../../../core/geometry/Constant"; import { CoreGeometryUtilCircle } from "../../../core/geometry/util/Circle"; import { CoreGeometryUtilCurve } from "../../../core/geometry/util/Curve"; import { CoreGeometryOperationSkin } from "../../../core/geometry/operation/Skin"; import { isBooleanTrue } from "../../../core/Type"; import { CoreGeometryBuilderMerge } from "../../../core/geometry/modules/three/builders/Merge"; import { addAttributesFromPoint } from "../../../core/geometry/util/addAttributesFromPoint"; import { pointsFromObject } from "../../../core/geometry/entities/point/CorePointUtils"; import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory"; import { copyObject3DProperties } from "../../../core/geometry/modules/three/ThreejsObjectUtils"; import { SopType } from "../../poly/registers/nodes/types/Sop"; const ORIGIN = new Vector3(0, 0, 0); const UP = new Vector3(0, 1, 0); const lookAtMat = new Matrix4(); const translateMat = new Matrix4(); const currentPos = new Vector3(); const prevPos = new Vector3(); const nextPos = new Vector3(); const delta = new Vector3(); const deltaNext = new Vector3(); const deltaPrev = new Vector3(); const _points = []; export class PolywireSopOperation extends BaseSopOperation { static type() { return SopType.POLYWIRE; } cook(inputCoreGroups, params) { const coreGroup = inputCoreGroups[0]; const inputObjects = coreGroup.threejsObjects(); const newObjects = []; for (const inputObject of inputObjects) { const geometries = []; if (inputObject.isLineSegments) { this._createTube(inputObject, params, geometries); } const mergedGeometry = CoreGeometryBuilderMerge.merge(geometries); if (mergedGeometry) { const newObject = this.createObject(mergedGeometry, ObjectType.MESH); copyObject3DProperties(inputObject, newObject); newObjects.push(newObject); } } return this.createCoreGroupFromObjects(newObjects); } _createTube(lineSegment, params, geometries) { var _a; const geometry = lineSegment.geometry; const corePointClass = corePointClassFactory(lineSegment); const attributeNames = corePointClass.attributeNamesMatchingMask(lineSegment, params.attributesToCopy); pointsFromObject(lineSegment, _points); const indices = (_a = geometry.getIndex()) == null ? void 0 : _a.array; if (!indices) { return; } const accumulatedCurvePointIndices = CoreGeometryUtilCurve.accumulatedCurvePointIndices(indices); for (let curvePointIndices of accumulatedCurvePointIndices) { const currentPoints = curvePointIndices.map((index) => _points[index]); this._createTubeFromPoints(currentPoints, attributeNames, params, geometries); } } _createTubeFromPoints(points, attributeNames, params, geometries) { if (points.length <= 1) { return; } const options = { radius: params.radius, segments: params.segmentsRadial, arcAngle: 360, connectLastPoint: true }; const circleTemplate = CoreGeometryUtilCircle.create(options); const circles = []; let i = 0; for (let point of points) { point.position(currentPos); let prevPoint = points[i - 1]; let nextPoint = points[i + 1]; if (prevPoint && nextPoint) { nextPoint.position(nextPos); deltaNext.copy(nextPos).sub(currentPos); prevPoint.position(prevPos); deltaPrev.copy(prevPos).sub(currentPos).multiplyScalar(-1); delta.lerpVectors(deltaNext, deltaPrev, 0.5); } else { if (nextPoint) { nextPoint.position(nextPos); delta.copy(nextPos).sub(currentPos); } else { nextPoint = points[i - 1]; nextPoint.position(nextPos); delta.copy(nextPos).sub(currentPos).multiplyScalar(-1); } } lookAtMat.identity(); lookAtMat.lookAt(ORIGIN, delta.multiplyScalar(-1), UP); translateMat.identity(); translateMat.makeTranslation(currentPos.x, currentPos.y, currentPos.z); const newCircle = circleTemplate.clone(); newCircle.applyMatrix4(lookAtMat); newCircle.applyMatrix4(translateMat); const positionIndex = attributeNames.indexOf("position"); if (positionIndex >= 0) { attributeNames.splice(positionIndex, 1); } addAttributesFromPoint(newCircle, point, attributeNames); circles.push(newCircle); i++; } for (let i2 = 0; i2 < circles.length; i2++) { if (i2 > 0) { const circle = circles[i2]; const prevCircle = circles[i2 - 1]; const geometry = this._skin(prevCircle, circle); geometries.push(geometry); } } if (isBooleanTrue(params.closed)) { const circle = circles[0]; const prevCircle = circles[circles.length - 1]; const geometry = this._skin(prevCircle, circle); geometries.push(geometry); } } _skin(geometry1, geometry0) { const geometry = new BufferGeometry(); const operation = new CoreGeometryOperationSkin(geometry, geometry1, geometry0); operation.process(); return geometry; } } PolywireSopOperation.DEFAULT_PARAMS = { radius: 1, segmentsRadial: 8, closed: true, attributesToCopy: "*" };