UNPKG

@polygonjs/polygonjs

Version:

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

134 lines (133 loc) 4.73 kB
"use strict"; import { BaseSopOperation } from "./_Base"; import { BufferGeometry, CatmullRomCurve3, Float32BufferAttribute, Vector3, Vector2 } from "three"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { ObjectType } from "../../../core/geometry/Constant"; import { SPLINE_CURVE_TYPES } from "../../../core/geometry/Curve"; import { ObjectUserData } from "../../../core/UserData"; import { pointsFromObject } from "../../../core/geometry/entities/point/CorePointUtils"; import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory"; const tmpV2 = new Vector2(); const current = new Vector3(); const next = new Vector3(); const _points = []; export class CurveFromPointsSopOperation extends BaseSopOperation { static type() { return "curveFromPoint"; } cook(inputCoreGroups, params) { const inputCoreGroup = inputCoreGroups[0]; const objects = inputCoreGroup.allObjects(); const newObjects = []; for (let object of objects) { const newObject = this._createCurveFromCoreObject(object, params); if (newObject) { newObjects.push(newObject); } } return this.createCoreGroupFromObjects(newObjects); } _createCurveFromCoreObject(object, params) { const { pointsCount, closed, curveType, tension, tTangent } = params; const corePointClass = corePointClassFactory(object); pointsFromObject(object, _points); const pointPositions = _points.map((p) => p.position(new Vector3())); if (pointPositions.length < 2) { return; } const curveTypeName = SPLINE_CURVE_TYPES[curveType]; const curve = new CatmullRomCurve3(pointPositions, closed, curveTypeName, tension); const indices = new Array(pointsCount); for (let i = 0; i < pointsCount; i++) { if (i > 0) { indices[(i - 1) * 2] = i - 1; indices[(i - 1) * 2 + 1] = i; } } const geometry = new BufferGeometry(); geometry.setIndex(indices); const attribNamesToInterpolate = ["position"]; for (const attribName of attribNamesToInterpolate) { const attribSize = corePointClass.attribSize(object, attribName); let attribPositions = []; switch (attribSize) { case 1: { attribPositions = _points.map((p) => new Vector3(p.attribValue(attribName), 0, 0)); break; } case 2: { attribPositions = _points.map((p) => { p.attribValue(attribName, tmpV2); return new Vector3(tmpV2.x, tmpV2.y, 0); }); break; } case 3: { attribPositions = _points.map((p) => { p.attribValue(attribName, current); return current.clone(); }); break; } } const curveTypeName2 = SPLINE_CURVE_TYPES[curveType]; const curve2 = new CatmullRomCurve3(attribPositions, closed, curveTypeName2, tension); const attribValues = new Array(pointsCount * attribSize); for (let i = 0; i < pointsCount; i++) { const t = i / (pointsCount - 1); curve2.getPoint(t, current); switch (attribSize) { case 1: { attribValues[i] = current.x; break; } case 2: { attribValues[2 * i] = current.x; attribValues[2 * i + 1] = current.y; break; } case 3: { current.toArray(attribValues, i * 3); break; } } } geometry.setAttribute(attribName, new Float32BufferAttribute(attribValues, attribSize)); } if (tTangent) { const positions = geometry.getAttribute("position").array; const tangentName = params.tangentName; const tangents = new Array(pointsCount * 3); for (let i = 0; i < pointsCount - 1; i++) { current.fromArray(positions, i * 3); next.fromArray(positions, (i + 1) * 3); next.sub(current).normalize(); next.toArray(tangents, i * 3); } current.fromArray(positions, (pointsCount - 1) * 3); next.fromArray(positions, (pointsCount - 2) * 3); current.sub(next).normalize(); next.toArray(tangents, (pointsCount - 1) * 3); geometry.setAttribute(tangentName, new Float32BufferAttribute(tangents, 3)); } const newObject = BaseSopOperation.createObject(geometry, ObjectType.LINE_SEGMENTS); newObject.userData[ObjectUserData.PATH] = curve; return newObject; } } CurveFromPointsSopOperation.DEFAULT_PARAMS = { pointsCount: 100, closed: false, curveType: 0, tension: 0.5, tTangent: false, tangentName: "tangent" // attributesToInterpolate: '', }; CurveFromPointsSopOperation.INPUT_CLONED_STATE = InputCloneMode.NEVER;