UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

187 lines (186 loc) 7.43 kB
"use strict"; 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; }