@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
187 lines (186 loc) • 7.43 kB
JavaScript
;
import { Vector3, Plane, BoxGeometry } from "three";
import { QuadSopNode } from "./_BaseQuad";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { SopType } from "../../poly/registers/nodes/types/Sop";
import { QuadPrimitive } from "../../../core/geometry/modules/quad/QuadPrimitive";
import { InputCloneMode } from "../../poly/InputCloneMode";
import { quadGraphFromQuadObject } from "../../../core/geometry/modules/quad/graph/QuadGraphUtils";
import { QuadPoint } from "../../../core/geometry/modules/quad/QuadPoint";
import { quadPrimitiveOppositePoints } from "../../../core/geometry/modules/quad/QuadPrimitiveUtils";
import { ConvexGeometry } from "three/examples/jsm/geometries/ConvexGeometry";
import { ObjectType } from "../../../core/geometry/Constant";
import { ThreejsCoreObject } from "../../../core/geometry/modules/three/ThreejsCoreObject";
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils";
const _currentPointPosition = new Vector3();
const _neighbourPosition = new Vector3();
const _neighbourPositionOnPlane = new Vector3();
const _delta = new Vector3();
const _tmp = new Vector3();
const _normal = new Vector3();
const _plane = new Plane();
const _positions = [];
const quadOppositePoints = {
p0: -1,
p1: -1
};
const _pointIdsSet = /* @__PURE__ */ new Set();
const BOX_DIVISIONS = 1;
const _newObjectsForPoint = [];
var StarMode = /* @__PURE__ */ ((StarMode2) => {
StarMode2["ALONG_EDGES"] = "along edges";
StarMode2["TO_CENTER"] = "to center";
return StarMode2;
})(StarMode || {});
const STAR_MODES = ["along edges" /* ALONG_EDGES */, "to center" /* TO_CENTER */];
class QuadCornersSopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
this.center = ParamConfig.BOOLEAN(1);
this.star = ParamConfig.BOOLEAN(1);
this.height = ParamConfig.FLOAT(0.1, {
range: [0, 1],
rangeLocked: [false, false]
});
this.centerSize = ParamConfig.FLOAT(0.1, {
range: [0, 1],
rangeLocked: [false, false],
visibleIf: { center: 1 }
});
this.starSize = ParamConfig.VECTOR2([0.05, 0.3], {
visibleIf: { star: 1 }
});
this.starMode = ParamConfig.INTEGER(STAR_MODES.indexOf("along edges" /* ALONG_EDGES */), {
visibleIf: { star: 1 },
menu: {
entries: STAR_MODES.map((name, value) => ({ name, value }))
}
});
this.cornersAttribName = ParamConfig.STRING("cornersCount");
this.quadsAttribName = ParamConfig.STRING("quadsCount");
}
}
const ParamsConfig = new QuadCornersSopParamsConfig();
export class QuadCornersSopNode extends QuadSopNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
}
static type() {
return SopType.QUAD_CORNERS;
}
initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE);
}
cook(inputCoreGroups) {
const coreGroup = inputCoreGroups[0];
const objects = coreGroup.quadObjects();
if (!objects) {
this.states.error.set(`no quad objects found`);
return;
}
const newObjects = [];
for (const object of objects) {
this._processObject(object, newObjects);
}
this.setObjects(newObjects);
}
_processObject(quadObject, newObjects) {
const { center, star, centerSize, starSize, height, cornersAttribName, quadsAttribName } = this.pv;
const graph = quadGraphFromQuadObject(quadObject);
const pointsCount = QuadPoint.entitiesCount(quadObject);
const starMode = STAR_MODES[this.pv.starMode];
for (let i = 0; i < pointsCount; i++) {
_newObjectsForPoint.length = 0;
QuadPoint.position(quadObject, i, _currentPointPosition);
_plane.normal;
_pointIdsSet.clear();
const quadIds = graph.quadIdsByPointIndex(i);
if (!quadIds) {
continue;
}
_plane.normal.set(0, 0, 0);
quadIds.forEach((quadId) => {
QuadPrimitive.normal(quadObject, quadId, _tmp);
_plane.normal.add(_tmp);
quadPrimitiveOppositePoints(quadObject, quadId, i, quadOppositePoints);
_pointIdsSet.add(quadOppositePoints.p0);
_pointIdsSet.add(quadOppositePoints.p1);
});
if (_pointIdsSet.size <= 2) {
continue;
}
_plane.normal.divideScalar(quadIds.size).normalize();
_plane.constant = _plane.distanceToPoint(_currentPointPosition);
if (center) {
_normal.copy(_plane.normal).multiplyScalar(height / 2);
_positions.length = 0;
_pointIdsSet.forEach((pointId, neighbourPointIndex) => {
QuadPoint.position(quadObject, pointId, _neighbourPosition);
_plane.projectPoint(_neighbourPosition, _neighbourPositionOnPlane);
_delta.copy(_neighbourPositionOnPlane).sub(_currentPointPosition);
_delta.normalize().multiplyScalar(centerSize);
_neighbourPositionOnPlane.copy(_delta);
_tmp.copy(_neighbourPositionOnPlane).add(_normal);
_positions.push(_tmp.clone());
_tmp.copy(_neighbourPositionOnPlane).sub(_normal);
_positions.push(_tmp.clone());
});
const newGeo = new ConvexGeometry(_positions);
const object = this.createObject(newGeo, ObjectType.MESH);
object.position.copy(_currentPointPosition);
_newObjectsForPoint.push(object);
}
if (star) {
const boxGeometry = new BoxGeometry(
starSize.x,
height,
starSize.y,
BOX_DIVISIONS,
BOX_DIVISIONS,
BOX_DIVISIONS
);
const geometries = [];
this._applyStarMode(starMode, quadObject, boxGeometry, starSize, geometries, _pointIdsSet, quadIds);
const mergedGeometry = mergeGeometries(geometries);
const object = this.createObject(mergedGeometry, ObjectType.MESH);
object.position.copy(_currentPointPosition);
_newObjectsForPoint.push(object);
}
for (const object of _newObjectsForPoint) {
ThreejsCoreObject.addAttribute(object, cornersAttribName, _pointIdsSet.size);
ThreejsCoreObject.addAttribute(object, quadsAttribName, quadIds.size);
newObjects.push(object);
}
}
}
_applyStarMode(starMode, quadObject, boxGeometry, starSize, geometries, pointIdsSet, quadIdsSet) {
switch (starMode) {
case "along edges" /* ALONG_EDGES */: {
pointIdsSet.forEach((pointId) => {
QuadPoint.position(quadObject, pointId, _neighbourPosition);
const currentBoxGeometry = _createBoxTowardPoint(boxGeometry, _neighbourPosition, starSize);
geometries.push(currentBoxGeometry);
});
return;
}
case "to center" /* TO_CENTER */: {
quadIdsSet.forEach((quadId) => {
QuadPrimitive.position(quadObject, quadId, _neighbourPosition);
const currentBoxGeometry = _createBoxTowardPoint(boxGeometry, _neighbourPosition, starSize);
geometries.push(currentBoxGeometry);
});
return;
}
}
}
}
function _createBoxTowardPoint(boxGeometry, target, starSize) {
_plane.projectPoint(target, _neighbourPositionOnPlane);
_delta.copy(_neighbourPositionOnPlane).sub(_currentPointPosition);
const currentBoxGeometry = boxGeometry.clone();
currentBoxGeometry.translate(0, 0, starSize.y * 0.5);
currentBoxGeometry.lookAt(_delta);
return currentBoxGeometry;
}