@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
102 lines (101 loc) • 3.79 kB
JavaScript
;
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;