@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
185 lines (172 loc) • 5.84 kB
text/typescript
/**
* Adds properties for WFC tiles
*
*
*/
import {TypedSopNode} from './_Base';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {CoreGroup} from '../../../core/geometry/Group';
import {SopType} from '../../poly/registers/nodes/types/Sop';
import {InputCloneMode} from '../../poly/InputCloneMode';
import {CoreWFCTileAttribute} from '../../../core/wfc/WFCAttributes';
import {filterObjectsFromCoreGroup} from '../../../core/geometry/Mask';
import {BufferGeometry, Vector3, Float32BufferAttribute} from 'three';
import {CoreGeometryBuilderMerge} from '../../../core/geometry/modules/three/builders/Merge';
import {ObjectType} from '../../../core/geometry/Constant';
import {BaseSopOperation} from '../../operations/sop/_Base';
import {rotateGeometry} from '../../../core/Transform';
import {Attribute} from '../../../core/geometry/Attribute';
const DEFAULT_UP = new Vector3(0, 1, 0);
const SOUTH_DIR = new Vector3(-1, 0, 0);
const NORTH_DIR = new Vector3(+1, 0, 0);
const WEST_DIR = new Vector3(0, 0, -1);
const EAST_DIR = new Vector3(0, 0, +1);
const BOTTOM_DIR = new Vector3(0, -1, 0);
const TOP_DIR = new Vector3(0, +1, 0);
const _tmp = new Vector3();
class WFCTileSideNameSopParamsConfig extends NodeParamsConfig {
/** @param group to assign the material to */
group = ParamConfig.STRING('', {
objectMask: true,
});
sameNameForSelectedSides = ParamConfig.BOOLEAN(1);
/** @param south side */
south = ParamConfig.BOOLEAN(0);
southName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, south: 1},
});
/** @param north side */
north = ParamConfig.BOOLEAN(0);
northName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, north: 1},
});
/** @param west side */
west = ParamConfig.BOOLEAN(0);
westName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, west: 1},
});
/** @param east side */
east = ParamConfig.BOOLEAN(0);
eastName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, east: 1},
});
/** @param bottom side */
bottom = ParamConfig.BOOLEAN(0);
bottomName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, bottom: 1},
});
/** @param top side */
top = ParamConfig.BOOLEAN(0);
topName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 0, top: 1},
});
/** @param allowedRotationY */
sideName = ParamConfig.STRING('', {
visibleIf: {sameNameForSelectedSides: 1},
});
/** @param highlight */
highlight = ParamConfig.BOOLEAN(false);
}
const ParamsConfig = new WFCTileSideNameSopParamsConfig();
export class WFCTileSideNameSopNode extends TypedSopNode<WFCTileSideNameSopParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return SopType.WFC_TILE_SIDE_NAME;
}
override initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE);
}
override async cook(inputCoreGroups: CoreGroup[]) {
const coreGroup = inputCoreGroups[0];
const objects = filterObjectsFromCoreGroup(coreGroup, this.pv);
const {sameNameForSelectedSides, south, north, west, east, bottom, top} = this.pv;
if (sameNameForSelectedSides == true) {
const sideName = this.pv.sideName;
for (const object of objects) {
if (south) {
CoreWFCTileAttribute.setSideName(object, 's', sideName);
}
if (north) {
CoreWFCTileAttribute.setSideName(object, 'n', sideName);
}
if (west) {
CoreWFCTileAttribute.setSideName(object, 'w', sideName);
}
if (east) {
CoreWFCTileAttribute.setSideName(object, 'e', sideName);
}
if (bottom) {
CoreWFCTileAttribute.setSideName(object, 'b', sideName);
}
if (top) {
CoreWFCTileAttribute.setSideName(object, 't', sideName);
}
}
} else {
for (const object of objects) {
if (south) {
CoreWFCTileAttribute.setSideName(object, 's', this.pv.southName);
}
if (north) {
CoreWFCTileAttribute.setSideName(object, 'n', this.pv.northName);
}
if (west) {
CoreWFCTileAttribute.setSideName(object, 'w', this.pv.westName);
}
if (east) {
CoreWFCTileAttribute.setSideName(object, 'e', this.pv.eastName);
}
if (bottom) {
CoreWFCTileAttribute.setSideName(object, 'b', this.pv.bottomName);
}
if (top) {
CoreWFCTileAttribute.setSideName(object, 't', this.pv.topName);
}
}
}
if (this.pv.highlight) {
const geometries: BufferGeometry[] = [];
if (south) {
geometries.push(this._createHighlightPlane(SOUTH_DIR));
}
if (north) {
geometries.push(this._createHighlightPlane(NORTH_DIR));
}
if (west) {
geometries.push(this._createHighlightPlane(WEST_DIR));
}
if (east) {
geometries.push(this._createHighlightPlane(EAST_DIR));
}
if (bottom) {
geometries.push(this._createHighlightPlane(BOTTOM_DIR));
}
if (top) {
geometries.push(this._createHighlightPlane(TOP_DIR));
}
const mergedGeometry = CoreGeometryBuilderMerge.merge(geometries);
if (mergedGeometry) {
const mergedObject = BaseSopOperation.createObject(mergedGeometry, ObjectType.LINE_SEGMENTS);
objects.push(mergedObject);
}
}
this.setObjects(objects);
}
private _createHighlightPlane(dir: Vector3): BufferGeometry {
const geometry = new BufferGeometry();
const positions: number[] = [];
positions.push(-0.45, 0, -0.45);
positions.push(0.45, 0, -0.45);
positions.push(0.45, 0, 0.45);
positions.push(-0.45, 0, 0.45);
const indices: number[] = [];
indices.push(0, 1, 1, 2, 2, 3, 3, 0);
geometry.setAttribute(Attribute.POSITION, new Float32BufferAttribute(positions, 3));
geometry.setIndex(indices);
rotateGeometry(geometry, DEFAULT_UP, dir);
_tmp.copy(dir).multiplyScalar(0.55);
geometry.translate(_tmp.x, _tmp.y, _tmp.z);
return geometry;
}
}