@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
110 lines (109 loc) • 4.18 kB
JavaScript
;
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);
}
}