@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
105 lines (104 loc) • 4.01 kB
JavaScript
;
import { QuadSopNode } from "./_BaseQuad";
import { Vector3, Matrix4, BufferAttribute } from "three";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { SopType } from "../../poly/registers/nodes/types/Sop";
import { QuadGeometry } from "../../../core/geometry/modules/quad/QuadGeometry";
import { Attribute } from "../../../core/geometry/Attribute";
import { rotationMatrix } from "../../../core/Transform";
import { QuadObject } from "../../../core/geometry/modules/quad/QuadObject";
const _v3 = new Vector3();
const _m4R = new Matrix4();
const _m4T = new Matrix4();
const _m4 = new Matrix4();
const _dirOrigin = new Vector3(0, 1, 0);
class QuadPlaneSopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
/** @param sizes */
this.size = ParamConfig.VECTOR2([1, 1]);
/** @param defines if the plane resolution is sets via the number of segments or via the step size */
this.useSegmentsCount = ParamConfig.BOOLEAN(0);
/** @param step size */
this.stepSize = ParamConfig.FLOAT(1, {
range: [1e-3, 2],
rangeLocked: [false, false],
visibleIf: { useSegmentsCount: 0 }
});
/** @param segments count */
this.segments = ParamConfig.VECTOR2([1, 1], { visibleIf: { useSegmentsCount: 1 } });
/** @param axis perpendicular to the plane */
this.direction = ParamConfig.VECTOR3([0, 1, 0]);
/** @param center of the plane */
this.center = ParamConfig.VECTOR3([0, 0, 0]);
}
}
const ParamsConfig = new QuadPlaneSopParamsConfig();
export class QuadPlaneSopNode extends QuadSopNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
}
static type() {
return SopType.QUAD_PLANE;
}
cook(inputCoreGroups) {
const geometry = this.pv.useSegmentsCount ? this._createWithSegmentsCount() : this._createWithStepSize();
const center = this.pv.center;
rotationMatrix(_dirOrigin, this.pv.direction, _m4R);
_m4T.makeTranslation(center.x, center.y, center.z);
_m4.multiplyMatrices(_m4T, _m4R);
geometry.applyMatrix(_m4);
const object = new QuadObject(geometry);
object.name = this.name();
this.setQuadObject(object);
}
_createWithStepSize() {
const { size, stepSize } = this.pv;
const segmentsX = Math.round(size.x / stepSize);
const segmentsY = Math.round(size.y / stepSize);
return this._createQuadPlane(segmentsX, segmentsY);
}
_createWithSegmentsCount() {
const { segments } = this.pv;
const segmentsX = Math.round(segments.x);
const segmentsY = Math.round(segments.y);
return this._createQuadPlane(segmentsX, segmentsY);
}
_createQuadPlane(segmentsX, segmentsY) {
const { size } = this.pv;
const geometry = new QuadGeometry();
const quadsCountX = segmentsX;
const quadsCountY = segmentsY;
const pointsCountX = quadsCountX + 1;
const pointsCountY = quadsCountY + 1;
const quadsCount = quadsCountX * quadsCountY;
const positionsCount = pointsCountX * pointsCountY;
const positions = new Array(positionsCount * 3);
const indices = new Array(4);
for (let x = 0; x < pointsCountX; x++) {
for (let y = 0; y < pointsCountY; y++) {
const i = x * pointsCountY + y;
_v3.set((x / segmentsX - 0.5) * size.x, 0, (y / segmentsY - 0.5) * size.y);
_v3.toArray(positions, i * 3);
}
}
for (let i = 0; i < quadsCount; i++) {
const x = i % quadsCountX;
const y = Math.floor(i / quadsCountX);
const i0 = x * pointsCountY + y;
const i1 = i0 + 1;
const i2 = i0 + pointsCountY;
const i3 = i2 + 1;
const quadIndex = i * 4;
indices[quadIndex] = i0;
indices[quadIndex + 1] = i1;
indices[quadIndex + 2] = i3;
indices[quadIndex + 3] = i2;
}
const position = new BufferAttribute(new Float32Array(positions), 3);
geometry.setAttribute(Attribute.POSITION, position);
geometry.setIndex(indices);
return geometry;
}
}