@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
176 lines (175 loc) • 6.02 kB
JavaScript
"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];
}
}
}