UNPKG

@polygonjs/polygonjs

Version:

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

176 lines (175 loc) 6.02 kB
"use strict"; import { TypedSopNode } from "./_Base"; import { InputCloneMode } from "../../poly/InputCloneMode"; const POSITION_ATTRIB_NAME = "position"; 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"; class PointSopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param toggle on to update the x component */ this.updateX = ParamConfig.BOOLEAN(0); /** @param expression the x component */ this.x = ParamConfig.FLOAT("@P.x", { visibleIf: { updateX: 1 }, expression: { forEntities: true } }); /** @param toggle on to update the y component */ this.updateY = ParamConfig.BOOLEAN(0); /** @param expression the y component */ this.y = ParamConfig.FLOAT("@P.y", { visibleIf: { updateY: 1 }, expression: { forEntities: true } }); /** @param toggle on to update the z component */ this.updateZ = ParamConfig.BOOLEAN(0); /** @param expression the z component */ this.z = ParamConfig.FLOAT("@P.z", { visibleIf: { updateZ: 1 }, expression: { forEntities: true } }); /** @param toggle on to update the normals */ this.updateNormals = ParamConfig.BOOLEAN(1); } } const ParamsConfig = new PointSopParamsConfig(); export class PointSopNode extends TypedSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._x_arrays_by_geometry_uuid = /* @__PURE__ */ new Map(); this._y_arrays_by_geometry_uuid = /* @__PURE__ */ new Map(); this._z_arrays_by_geometry_uuid = /* @__PURE__ */ new Map(); } static type() { return SopType.POINT; } initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE); } async cook(inputCoreGroups) { const coreGroup = inputCoreGroups[0]; await this._evalExpressionsForCoreGroup(coreGroup); } async _evalExpressionsForCoreGroup(coreGroup) { const coreObjects = coreGroup.threejsCoreObjects(); for (let i = 0; i < coreObjects.length; i++) { await this._evalExpressionsForCoreObject(coreObjects[i]); } if (isBooleanTrue(this.pv.updateNormals)) { const objects = coreGroup.threejsObjectsWithGeo(); for (const object of objects) { if (object.isMesh) { object.geometry.computeVertexNormals(); } } } const geometries = coreGroup.geometries(); for (const geometry of geometries) { geometry.computeBoundingBox(); } if (!this.io.inputs.cloneRequired(0)) { const geometries2 = coreGroup.geometries(); for (const geometry of geometries2) { const attrib = geometry.getAttribute(POSITION_ATTRIB_NAME); attrib.needsUpdate = true; } } this.setCoreGroup(coreGroup); } async _evalExpressionsForCoreObject(coreObject) { const object = coreObject.object(); const geometry = object.geometry; const points = []; pointsFromObject(object, points); const array = geometry.getAttribute(POSITION_ATTRIB_NAME).array; const tmp_array_x = await this._updateFromParam( geometry, points, this.p.updateX, this.p.x, this.pv.x, this._x_arrays_by_geometry_uuid, 0 ); const tmp_array_y = await this._updateFromParam( geometry, points, this.p.updateY, this.p.y, this.pv.y, this._y_arrays_by_geometry_uuid, 1 ); const tmp_array_z = await this._updateFromParam( geometry, points, this.p.updateZ, this.p.z, this.pv.z, this._z_arrays_by_geometry_uuid, 2 ); if (tmp_array_x) { this._commitTmpValues(tmp_array_x, array, 0); } if (tmp_array_y) { this._commitTmpValues(tmp_array_y, array, 1); } if (tmp_array_z) { this._commitTmpValues(tmp_array_z, array, 2); } } async _updateFromParam(geometry, points, do_update_param, value_param, param_value, arrays_by_geometry_uuid, offset) { const do_update = do_update_param; const param = value_param; let tmpArray = this._initArrayIfRequired(geometry, arrays_by_geometry_uuid, points.length, offset); if (do_update.value) { if (param.hasExpression() && param.expressionController && param.expressionController.entitiesDependent()) { await param.expressionController.computeExpressionForPoints(points, (point, value) => { tmpArray[point.index()] = value; }); } else { let point; for (let i = 0; i < points.length; i++) { point = points[i]; tmpArray[point.index()] = param_value; } } } return tmpArray; } _initArrayIfRequired(geometry, arrays_by_geometry_uuid, points_count, offset) { const uuid = geometry.uuid; const current_array = arrays_by_geometry_uuid.get(uuid); if (current_array) { if (current_array.length < points_count) { const new_array = this._array_for_component(geometry, points_count, offset); arrays_by_geometry_uuid.set(uuid, new_array); return new_array; } else { return current_array; } } else { const new_array = this._array_for_component(geometry, points_count, offset); arrays_by_geometry_uuid.set(uuid, new_array); return new_array; } } _array_for_component(geometry, pointsCount, offset) { const new_array = new Array(pointsCount); const src_array = geometry.getAttribute(POSITION_ATTRIB_NAME).array; for (let i = 0; i < new_array.length; i++) { new_array[i] = src_array[i * 3 + offset]; } return new_array; } _commitTmpValues(tmp_array, targetArray, offset) { for (let i = 0; i < tmp_array.length; i++) { targetArray[i * 3 + offset] = tmp_array[i]; } } }