UNPKG

@polygonjs/polygonjs

Version:

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

110 lines (109 loc) 4.18 kB
"use strict"; import { TypedSopNode } from "./_Base"; import { NodeParamsConfig } from "../utils/params/ParamsConfig"; import { SopType } from "../../poly/registers/nodes/types/Sop"; import { InputCloneMode } from "../../poly/InputCloneMode"; import { Quaternion } from "three"; import { rotatedSide, tileSideUnrotated, neighbourTileSideUnrotated } from "../../../core/wfc/WFCCommon"; import { CoreWFCTileAttribute } from "../../../core/wfc/WFCAttributes"; import { createRuleObject } from "../../../core/wfc/WFCRule"; const identityQuaternion = new Quaternion(); const _q = new Quaternion(); function _angleIncrement(object) { if (Math.abs(object.rotation.y) > 0.1) { return object.rotation.y / (Math.PI / 2); } _q.setFromRotationMatrix(object.matrix); return _q.angleTo(identityQuaternion) / (Math.PI / 2); } class WFCRuleFromProximitySopParamsConfig extends NodeParamsConfig { } const ParamsConfig = new WFCRuleFromProximitySopParamsConfig(); export class WFCRuleFromProximitySopNode extends TypedSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return SopType.WFC_RULE_FROM_PROXIMITY; } initializeNode() { this.io.inputs.setCount(2); this.io.inputs.initInputsClonedState([InputCloneMode.NEVER]); } async cook(inputCoreGroups) { const coreGroup0 = inputCoreGroups[0]; const coreGroup1 = inputCoreGroups[1]; const inputObjects = coreGroup0.threejsObjects(); const tileObjects = coreGroup1.threejsObjects(); const outputObjects = [...inputObjects]; const tileObjectsInGrid = []; const _addTileObject = (tileObject) => { const x = Math.round(tileObject.position.x); const y = Math.round(tileObject.position.y); const z = Math.round(tileObject.position.z); tileObjectsInGrid[x] = tileObjectsInGrid[x] || []; tileObjectsInGrid[x][y] = tileObjectsInGrid[x][y] || []; tileObjectsInGrid[x][y][z] = tileObject; }; const _getTileObject = (x, y, z) => { x = Math.round(x); y = Math.round(y); z = Math.round(z); const xs = tileObjectsInGrid[x]; if (!xs) { return; } const yz = tileObjectsInGrid[x][y]; if (!yz) { return; } return tileObjectsInGrid[x][y][z]; }; const _addConnectionIfNeighbourFound = (currentObject, xOffset, yOffset, zOffset) => { const x = Math.round(currentObject.position.x); const y = Math.round(currentObject.position.y); const z = Math.round(currentObject.position.z); const neighbour = _getTileObject(x + xOffset, y + yOffset, z + zOffset); if (!neighbour) { return; } const id0 = CoreWFCTileAttribute.getTileId(currentObject); const id1 = CoreWFCTileAttribute.getTileId(neighbour); const currentObjectSideUnrotated = tileSideUnrotated(xOffset, yOffset, zOffset); const currentObjectSide = rotatedSide( currentObjectSideUnrotated, Math.round(_angleIncrement(currentObject)) ); const neighbourSideUnrotated = neighbourTileSideUnrotated(xOffset, yOffset, zOffset); const neighbourSide = rotatedSide(neighbourSideUnrotated, Math.round(_angleIncrement(neighbour))); const ruleObject = createRuleObject({ id0, id1, side0: currentObjectSide, side1: neighbourSide }); outputObjects.push(ruleObject); }; for (const tileObject of tileObjects) { const isTile = CoreWFCTileAttribute.getIsTile(tileObject); if (!isTile) { continue; } _addTileObject(tileObject); } for (const tileObject of tileObjects) { const isTile = CoreWFCTileAttribute.getIsTile(tileObject); if (!isTile) { continue; } _addConnectionIfNeighbourFound(tileObject, -1, 0, 0); _addConnectionIfNeighbourFound(tileObject, 1, 0, 0); _addConnectionIfNeighbourFound(tileObject, 0, -1, 0); _addConnectionIfNeighbourFound(tileObject, 0, 1, 0); _addConnectionIfNeighbourFound(tileObject, 0, 0, -1); _addConnectionIfNeighbourFound(tileObject, 0, 0, 1); } this.setObjects(outputObjects); } }