@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
183 lines (182 loc) • 7.13 kB
JavaScript
"use strict";
import { Mesh, BufferAttribute, Vector3 } from "three";
import { TypedSopNode } from "./_Base";
import { CoreFace } from "../../../core/geometry/modules/three/CoreFace";
import { InputCloneMode } from "../../poly/InputCloneMode";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { arrayChunk, rangeWithEnd } from "../../../core/ArrayUtils";
import { isBooleanTrue } from "../../../core/BooleanValue";
import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory";
import { ThreejsPoint } from "../../../core/geometry/modules/three/ThreejsPoint";
import { ThreejsPrimitiveTriangle } from "../../../core/geometry/modules/three/ThreejsPrimitiveTriangle";
const dummyMesh = new Mesh();
var FaceAttribName = /* @__PURE__ */ ((FaceAttribName2) => {
FaceAttribName2["CENTER"] = "faceCenter";
FaceAttribName2["ID"] = "faceId";
FaceAttribName2["POSITION"] = "position";
return FaceAttribName2;
})(FaceAttribName || {});
const _faceCenter = new Vector3();
const _position = new Vector3();
const _newPosition = new Vector3();
class FaceSopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
/** @param makes faces unique */
this.makeFacesUnique = ParamConfig.BOOLEAN(0);
/** @param adds a vector3 attribute that represents the center of a face */
this.addFaceCenterAttribute = ParamConfig.BOOLEAN(0, {
visibleIf: { makeFacesUnique: 1 }
});
/** @param add an id attribute for each face */
this.addFaceId = ParamConfig.BOOLEAN(0, {
visibleIf: { makeFacesUnique: 1 }
});
/** @param allows to transform each face */
this.transform = ParamConfig.BOOLEAN(0, {
visibleIf: { makeFacesUnique: 1 }
});
/** @param scales the faces indepedently */
this.scale = ParamConfig.FLOAT(1, {
visibleIf: { makeFacesUnique: 1, transform: 1 }
});
}
}
const ParamsConfig = new FaceSopParamsConfig();
export class FaceSopNode extends TypedSopNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
this._face = new CoreFace();
this._points = [
new ThreejsPoint(dummyMesh, 0),
new ThreejsPoint(dummyMesh, 0),
new ThreejsPoint(dummyMesh, 0)
];
}
static type() {
return "face";
}
initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE);
}
cook(input_contents) {
const core_group = input_contents[0];
if (isBooleanTrue(this.pv.makeFacesUnique)) {
this._makeFacesUnique(core_group);
if (isBooleanTrue(this.pv.addFaceCenterAttribute)) {
this._addFaceCenterAttribute(core_group);
}
if (isBooleanTrue(this.pv.addFaceId)) {
this._addFaceId(core_group);
}
if (isBooleanTrue(this.pv.transform)) {
this._transformFaces(core_group);
}
}
this.setCoreGroup(core_group);
}
_makeFacesUnique(core_group) {
var _a;
const objects = core_group.threejsObjects();
for (const object of objects) {
if (object.isMesh) {
const geometry = object.geometry;
const index = (_a = geometry.index) == null ? void 0 : _a.array;
if (index) {
const faces = arrayChunk([...index], 3);
const pointsCount = faces.length * 3;
for (const attrib_name of Object.keys(geometry.attributes)) {
const attrib = geometry.attributes[attrib_name];
const attrib_size = attrib.itemSize;
const new_values = new Float32Array(pointsCount * attrib_size);
let new_value_index = 0;
faces.forEach((face) => {
face.forEach((index2) => {
for (let i = 0; i < attrib_size; i++) {
const current_value = attrib.array[index2 * attrib_size + i];
new_values[new_value_index] = current_value;
new_value_index += 1;
}
});
});
geometry.setAttribute(attrib_name, new BufferAttribute(new_values, attrib_size));
}
const newIndices = rangeWithEnd(pointsCount);
geometry.setIndex(newIndices);
}
}
}
}
_addFaceCenterAttribute(coreGroup) {
const coreObjects = coreGroup.threejsCoreObjects();
for (const coreObject of coreObjects) {
const object = coreObject.object();
const corePointClass = corePointClassFactory(object);
if (object.isMesh) {
if (!corePointClass.hasAttribute(object, "faceCenter" /* CENTER */)) {
corePointClass.addNumericAttribute(object, "faceCenter" /* CENTER */, 3, -1);
}
const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object);
this._face.setGeometry(object.geometry);
for (let fi = 0; fi < facesCount; fi++) {
this._face.setIndex(fi);
this._face.center(_faceCenter);
this._face.points(this._points);
for (const point of this._points) {
point.setAttribValue("faceCenter" /* CENTER */, _faceCenter);
}
}
}
}
}
_addFaceId(coreGroup) {
const coreObjects = coreGroup.threejsCoreObjects();
for (const coreObject of coreObjects) {
const object = coreObject.object();
const corePointClass = corePointClassFactory(object);
if (object.isMesh) {
if (!corePointClass.hasAttribute(object, "faceId" /* ID */)) {
corePointClass.addNumericAttribute(object, "faceId" /* ID */, 1, -1);
}
const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object);
this._face.setGeometry(object.geometry);
for (let i = 0; i < facesCount; i++) {
this._face.setIndex(i);
this._face.points(this._points);
for (const point of this._points) {
point.setAttribValue("faceId" /* ID */, i);
}
}
}
}
}
_transformFaces(coreGroup) {
const scale = this.pv.scale;
const coreObjects = coreGroup.threejsCoreObjects();
for (const coreObject of coreObjects) {
const object = coreObject.object();
const corePointClass = corePointClassFactory(object);
if (object.isMesh) {
if (!corePointClass.hasAttribute(object, "position" /* POSITION */)) {
corePointClass.addNumericAttribute(object, "position" /* POSITION */, 3, -1);
}
const facesCount = ThreejsPrimitiveTriangle.entitiesCount(object);
this._face.setGeometry(object.geometry);
for (let fi = 0; fi < facesCount; fi++) {
this._face.setIndex(fi);
this._face.center(_faceCenter);
this._face.points(this._points);
for (const point of this._points) {
point.position(_position);
_newPosition.x = _position.x * scale + _faceCenter.x * (1 - scale);
_newPosition.y = _position.y * scale + _faceCenter.y * (1 - scale);
_newPosition.z = _position.z * scale + _faceCenter.z * (1 - scale);
point.setAttribValue("position" /* POSITION */, _newPosition);
}
}
}
}
}
}