UNPKG

@polygonjs/polygonjs

Version:

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

155 lines (154 loc) 5.57 kB
"use strict"; import { TypedSopNode } from "./_Base"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { Attribute } from "../../../core/geometry/Attribute"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { SopType } from "../../poly/registers/nodes/types/Sop"; import { pointsFromObject } from "../../../core/geometry/entities/point/CorePointUtils"; import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory"; class NormalsSopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param toggle on if normals can be updated via expressions */ this.edit = ParamConfig.BOOLEAN(0); /** @param toggle on to update the x component */ this.updateX = ParamConfig.BOOLEAN(0, { visibleIf: { edit: 1 } }); /** @param expression or value for the x component */ this.x = ParamConfig.FLOAT("@N.x", { visibleIf: { updateX: 1, edit: 1 }, expression: { forEntities: true } }); /** @param toggle on to update the y component */ this.updateY = ParamConfig.BOOLEAN(0, { visibleIf: { edit: 1 } }); /** @param expression or value for the y component */ this.y = ParamConfig.FLOAT("@N.y", { visibleIf: { updateY: 1, edit: 1 }, expression: { forEntities: true } }); /** @param toggle on to update the z component */ this.updateZ = ParamConfig.BOOLEAN(0, { visibleIf: { edit: 1 } }); /** @param expression or value for the z component */ this.z = ParamConfig.FLOAT("@N.z", { visibleIf: { updateZ: 1, edit: 1 }, expression: { forEntities: true } }); /** @param recompute the normals based on the position */ this.recompute = ParamConfig.BOOLEAN(1, { visibleIf: { edit: 0 } }); /** @param invert normals */ this.invert = ParamConfig.BOOLEAN(0); } } const ParamsConfig = new NormalsSopParamsConfig(); export class NormalsSopNode extends TypedSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return SopType.NORMALS; } initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE); } async cook(inputCoreGroups) { const coreGroup = inputCoreGroups[0]; if (isBooleanTrue(this.pv.edit)) { await this._evalExpressionsForCoreGroup(coreGroup); } else { if (this.pv.recompute) { const objects = coreGroup.threejsObjectsWithGeo(); for (const object of objects) { object.geometry.computeVertexNormals(); } } } if (isBooleanTrue(this.pv.invert)) { this._invertNormals(coreGroup); } this.setCoreGroup(coreGroup); } async _evalExpressionsForCoreGroup(coreGroup) { const coreObjects = coreGroup.threejsCoreObjects(); for (const coreObject of coreObjects) { await this._evalExpressionsForCoreObject(coreObject); } } async _evalExpressionsForCoreObject(coreObject) { const object = coreObject.object(); const geometry = object.geometry; const points = []; pointsFromObject(object, points); const corePointClass = corePointClassFactory(object); let attrib = geometry.getAttribute(Attribute.NORMAL); if (!attrib) { corePointClass.addNumericAttribute(object, Attribute.NORMAL, 3, 0); attrib = geometry.getAttribute(Attribute.NORMAL); } const array = attrib.array; if (isBooleanTrue(this.pv.updateX)) { const param = this.p.x; if (param.hasExpression() && param.expressionController && param.expressionController.entitiesDependent()) { await param.expressionController.computeExpressionForPoints(points, (point, value) => { array[point.index() * 3 + 0] = value; }); } else { let point; for (let i = 0; i < points.length; i++) { point = points[i]; array[point.index() * 3 + 0] = param.value; } } } if (isBooleanTrue(this.pv.updateY)) { const param = this.p.y; if (param.hasExpression() && param.expressionController && param.expressionController.entitiesDependent()) { await param.expressionController.computeExpressionForPoints(points, (point, value) => { array[point.index() * 3 + 1] = value; }); } else { let point; for (let i = 0; i < points.length; i++) { point = points[i]; array[point.index() * 3 + 1] = param.value; } } } if (isBooleanTrue(this.pv.updateZ)) { const param = this.p.z; if (param.hasExpression() && param.expressionController && param.expressionController.entitiesDependent()) { await param.expressionController.computeExpressionForPoints(points, (point, value) => { array[point.index() * 3 + 2] = value; }); } else { let point; for (let i = 0; i < points.length; i++) { point = points[i]; array[point.index() * 3 + 2] = param.value; } } } } _invertNormals(coreGroup) { const objects = coreGroup.allObjects(); for (const object of objects) { const corePointClass = corePointClassFactory(object); const normalAttrib = corePointClass.attribute(object, Attribute.NORMAL); if (normalAttrib) { const array = normalAttrib.array; for (let i = 0; i < array.length; i++) { array[i] *= -1; } } } } }