UNPKG

@polygonjs/polygonjs

Version:

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

102 lines (101 loc) 3.79 kB
"use strict"; import { BaseSopOperation } from "./_Base"; import { Float32BufferAttribute, Vector3 } from "three"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { SopType } from "../../poly/registers/nodes/types/Sop"; import { Attribute } from "../../../core/geometry/Attribute"; import { CoreAttribute } from "../../../core/geometry/Attribute"; import { filterThreejsObjectsWithGroup } from "../../../core/geometry/Mask"; export var TangentMode = /* @__PURE__ */ ((TangentMode2) => { TangentMode2["MESH"] = "Normal Maps"; TangentMode2["CURVE"] = "Curve"; return TangentMode2; })(TangentMode || {}); export const TANGENT_MODES = ["Normal Maps" /* MESH */, "Curve" /* CURVE */]; const tangent = new Vector3(); const currentPosition = new Vector3(); const nextPosition = new Vector3(); const STRIDE = 3; export class TangentSopOperation extends BaseSopOperation { static type() { return SopType.TANGENT; } cook(inputCoreGroups, params) { const inputCoreGroup = inputCoreGroups[0]; const objects = filterThreejsObjectsWithGroup(inputCoreGroup, params); return this._process(objects, params); } _process(objects, params) { const mode = TANGENT_MODES[params.mode]; switch (mode) { case "Normal Maps" /* MESH */: return this._processForMesh(objects, params); case "Curve" /* CURVE */: return this._processForCurve(objects, params); } } _processForMesh(objects, params) { for (const object of objects) { const geometry = object.geometry; if (geometry) { geometry.computeTangents(); } } return this.createCoreGroupFromObjects(objects); } _processForCurve(objects, params) { const newObjects = []; for (const object of objects) { const objectWithTangent = this._createTangentForCurve(object, params); if (objectWithTangent) { newObjects.push(objectWithTangent); } } return this.createCoreGroupFromObjects(newObjects); } _createTangentForCurve(object, params) { const { closed } = params; const tangentName = CoreAttribute.remapName(params.tangentName); const geometry = object.geometry; if (!geometry) { return; } const positionAttribute = geometry.getAttribute(Attribute.POSITION); if (!positionAttribute) { return; } const positionArray = positionAttribute.array; const pointsCount = positionArray.length / STRIDE; let tangentAttribute = geometry.getAttribute(tangentName); if (!tangentAttribute) { const values = new Array(pointsCount * STRIDE).fill(1); geometry.setAttribute(tangentName, new Float32BufferAttribute(values, STRIDE)); tangentAttribute = geometry.getAttribute(tangentName); } const tangentArray = tangentAttribute.array; for (let i = 0; i < pointsCount - 1; i++) { currentPosition.fromArray(positionArray, i * STRIDE); nextPosition.fromArray(positionArray, (i + 1) * STRIDE); tangent.copy(nextPosition).sub(currentPosition).normalize(); tangent.toArray(tangentArray, i * STRIDE); } const lastIndex = pointsCount - 1; currentPosition.fromArray(positionArray, lastIndex * STRIDE); if (closed) { nextPosition.fromArray(positionArray, 0); tangent.copy(nextPosition).sub(currentPosition).normalize(); } else { nextPosition.fromArray(positionArray, (lastIndex - 1) * STRIDE); tangent.copy(currentPosition).sub(nextPosition).normalize(); } tangent.toArray(tangentArray, lastIndex * STRIDE); return object; } } TangentSopOperation.DEFAULT_PARAMS = { group: "*", mode: TANGENT_MODES.indexOf("Normal Maps" /* MESH */), closed: false, tangentName: "tangent" }; TangentSopOperation.INPUT_CLONED_STATE = InputCloneMode.FROM_NODE;