polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
157 lines (156 loc) • 5.67 kB
JavaScript
import {Vector3 as Vector32} from "three/src/math/Vector3";
import {BufferAttribute as BufferAttribute2} from "three/src/core/BufferAttribute";
import {TypedSopNode} from "./_Base";
import {InputCloneMode as InputCloneMode2} from "../../poly/InputCloneMode";
import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig";
import {ArrayUtils as ArrayUtils2} from "../../../core/ArrayUtils";
class FaceSopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
this.makeFacesUnique = ParamConfig.BOOLEAN(0);
this.addFaceCenterAttribute = ParamConfig.BOOLEAN(0, {
visibleIf: {makeFacesUnique: 1}
});
this.addFaceId = ParamConfig.BOOLEAN(0, {
visibleIf: {makeFacesUnique: 1}
});
this.transform = ParamConfig.BOOLEAN(0, {
visibleIf: {makeFacesUnique: 1}
});
this.scale = ParamConfig.FLOAT(1, {
visibleIf: {makeFacesUnique: 1, transform: 1}
});
}
}
const ParamsConfig2 = new FaceSopParamsConfig();
export class FaceSopNode extends TypedSopNode {
constructor() {
super(...arguments);
this.params_config = ParamsConfig2;
}
static type() {
return "face";
}
initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(InputCloneMode2.FROM_NODE);
}
cook(input_contents) {
const core_group = input_contents[0];
if (this.pv.makeFacesUnique) {
this._makeFacesUnique(core_group);
if (this.pv.addFaceCenterAttribute) {
this._addFaceCenterAttribute(core_group);
}
if (this.pv.addFaceId) {
this._addFaceId(core_group);
}
if (this.pv.transform) {
this._transform_faces(core_group);
}
}
this.setCoreGroup(core_group);
}
_makeFacesUnique(core_group) {
for (let object of core_group.objects()) {
if (object.isMesh) {
const geometry = object.geometry;
const faces = ArrayUtils2.chunk(geometry.index?.array || [], 3);
const points_count = faces.length * 3;
for (let attrib_name of Object.keys(geometry.attributes)) {
const attrib = geometry.attributes[attrib_name];
const attrib_size = attrib.itemSize;
const new_values = new Float32Array(points_count * attrib_size);
let new_value_index = 0;
faces.forEach((face) => {
face.forEach((index) => {
for (let i = 0; i < attrib_size; i++) {
const current_value = attrib.array[index * attrib_size + i];
new_values[new_value_index] = current_value;
new_value_index += 1;
}
});
});
geometry.setAttribute(attrib_name, new BufferAttribute2(new_values, attrib_size));
}
const new_indices = ArrayUtils2.range(points_count);
geometry.setIndex(new_indices);
}
}
}
_addFaceCenterAttribute(core_group) {
const attrib_name = "face_center";
const face_center = new Vector32();
let faces, face, points, point;
core_group.coreObjects().forEach((core_object) => {
const object = core_object.object();
const core_geometry = core_object.coreGeometry();
if (object.isMesh && core_geometry) {
faces = core_geometry.faces();
if (!core_geometry.hasAttrib(attrib_name)) {
core_geometry.addNumericAttrib(attrib_name, 3, -1);
}
for (let fi = 0; fi < faces.length; fi++) {
face = faces[fi];
face.center(face_center);
points = face.points();
for (let pi = 0; pi < points.length; pi++) {
point = points[pi];
point.setAttribValue(attrib_name, face_center);
}
}
}
});
}
_addFaceId(core_group) {
const attrib_name = "face_id";
core_group.coreObjects().forEach((core_object) => {
const object = core_object.object();
const core_geometry = core_object.coreGeometry();
if (object.isMesh && core_geometry) {
const faces = core_geometry.faces();
if (!core_geometry.hasAttrib(attrib_name)) {
core_geometry.addNumericAttrib(attrib_name, 1, -1);
}
for (let i = 0; i < faces.length; i++) {
const face = faces[i];
const points = face.points();
for (let j = 0; j < points.length; j++) {
const point = points[j];
point.setAttribValue(attrib_name, i);
}
}
}
});
}
_transform_faces(core_group) {
const attrib_name = "position";
const face_center = new Vector32();
const new_position = new Vector32();
const scale = this.pv.scale;
let faces, face, points, point;
core_group.coreObjects().forEach((core_object) => {
const object = core_object.object();
const core_geometry = core_object.coreGeometry();
if (object.isMesh && core_geometry) {
faces = core_geometry.faces();
if (!core_geometry.hasAttrib(attrib_name)) {
core_geometry.addNumericAttrib(attrib_name, 3, -1);
}
for (let fi = 0; fi < faces.length; fi++) {
face = faces[fi];
face.center(face_center);
points = face.points();
for (let pi = 0; pi < points.length; pi++) {
point = points[pi];
const position = point.position();
new_position.x = position.x * scale + face_center.x * (1 - scale);
new_position.y = position.y * scale + face_center.y * (1 - scale);
new_position.z = position.z * scale + face_center.z * (1 - scale);
point.setAttribValue(attrib_name, new_position);
}
}
}
});
}
}