UNPKG

@polygonjs/polygonjs

Version:

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

302 lines (301 loc) 10.2 kB
"use strict"; import { CoreMath } from "./../../../core/math/_Module"; import { TypeAssert } from "./../../poly/Assert"; import { AttribClass } from "./../../../core/geometry/Constant"; import { BaseSopOperation } from "./_Base"; import { InputCloneMode } from "../../../engine/poly/InputCloneMode"; import { Vector3 } from "three"; import { pushOnArrayAtEntry } from "../../../core/MapUtils"; import { isBooleanTrue } from "../../../core/Type"; import { setToArray } from "../../../core/SetUtils"; import { isNumber } from "../../../core/Type"; import { pointsFromObject } from "../../../core/geometry/entities/point/CorePointUtils"; import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory"; const tmpPos = new Vector3(); export var SortMode = /* @__PURE__ */ ((SortMode2) => { SortMode2["RANDOM"] = "random"; SortMode2["AXIS"] = "axis"; SortMode2["ATTRIBUTE"] = "attribute"; return SortMode2; })(SortMode || {}); export const SORT_MODES = ["axis" /* AXIS */, "random" /* RANDOM */, "attribute" /* ATTRIBUTE */]; export const SORT_TARGET_TYPES = [AttribClass.POINT, AttribClass.OBJECT]; export var Axis = /* @__PURE__ */ ((Axis2) => { Axis2["X"] = "x"; Axis2["Y"] = "y"; Axis2["Z"] = "z"; return Axis2; })(Axis || {}); export const AXISES = ["x" /* X */, "y" /* Y */, "z" /* Z */]; const _points = []; export class SortSopOperation extends BaseSopOperation { constructor() { super(...arguments); this._pointPos = new Vector3(); this._positions = []; this._indicesByPos = /* @__PURE__ */ new Map(); this._indexDest = /* @__PURE__ */ new Map(); this._debugActive = false; } static type() { return "sort"; } cook(inputCoreGroups, params) { const coreGroup = inputCoreGroups[0]; this._sort(coreGroup, params); return coreGroup; } _sort(coreGroup, params) { const targetType = SORT_TARGET_TYPES[params.targetType]; switch (targetType) { case AttribClass.POINT: return this._sortPoints(coreGroup, params); case AttribClass.OBJECT: return this._sortObjects(coreGroup, params); } } _sortObjects(coreGroup, params) { const sortMode = SORT_MODES[params.mode]; switch (sortMode) { case "axis" /* AXIS */: return this._sortObjectsByAxis(coreGroup, params); case "random" /* RANDOM */: return this._sortObjectsByRandom(coreGroup, params); case "attribute" /* ATTRIBUTE */: return this._sortObjectsByAttribute(coreGroup, params); } TypeAssert.unreachable(sortMode); } _sortObjectsByAxis(coreGroup, params) { const coreObjects = coreGroup.allCoreObjects(); const objectsByPos = /* @__PURE__ */ new Map(); const positions = /* @__PURE__ */ new Set(); const axis = AXISES[params.axis]; let axisValue = 0; for (let coreObject of coreObjects) { coreObject.position(tmpPos); switch (axis) { case "x" /* X */: { axisValue = tmpPos.x; break; } case "y" /* Y */: { axisValue = tmpPos.y; break; } case "z" /* Z */: { axisValue = tmpPos.z; break; } } positions.add(axisValue); pushOnArrayAtEntry(objectsByPos, axisValue, coreObject); } let sortedPositions = setToArray(positions, []).sort((a, b) => a - b); if (isBooleanTrue(params.invert)) { sortedPositions.reverse(); } const sortedObjects = []; for (let position of sortedPositions) { const coreObjectsForPosition = objectsByPos.get(position); if (coreObjectsForPosition) { for (let coreObjectForPosition of coreObjectsForPosition) { const object = coreObjectForPosition.object(); if (object) { sortedObjects.push(object); } } } } coreGroup.setAllObjects(sortedObjects); } _sortObjectsByRandom(coreGroup, params) { const coreObjects = coreGroup.allCoreObjects(); const objectsByPos = /* @__PURE__ */ new Map(); const positions = []; let sortValue = 0; let i = 0; for (let coreObject of coreObjects) { sortValue = CoreMath.randFloat(params.seed, i); positions[i] = sortValue; pushOnArrayAtEntry(objectsByPos, sortValue, coreObject); i++; } let sortedPositions = positions.sort((a, b) => a - b); if (params.invert) { sortedPositions.reverse(); } const sortedObjects = []; for (let position of sortedPositions) { const coreObjectsForPosition = objectsByPos.get(position); if (coreObjectsForPosition) { for (let coreObjectForPosition of coreObjectsForPosition) { const object = coreObjectForPosition.object(); if (object) { sortedObjects.push(object); } } } } coreGroup.setAllObjects(sortedObjects); } _sortObjectsByAttribute(coreGroup, params) { const coreObjects = coreGroup.allCoreObjects(); const objectsByAttribValue = /* @__PURE__ */ new Map(); const attribValues = []; let i = 0; for (let coreObject of coreObjects) { const attribValue = coreObject.attribValue(params.attribute); const sortValue = isNumber(attribValue) ? attribValue : 0; attribValues[i] = sortValue; pushOnArrayAtEntry(objectsByAttribValue, sortValue, coreObject); i++; } let sortedValues = attribValues.sort((a, b) => a - b); if (params.invert) { sortedValues.reverse(); } const sortedObjects = []; for (let sortedValue of sortedValues) { const coreObjectsForPosition = objectsByAttribValue.get(sortedValue); if (coreObjectsForPosition) { for (let coreObjectForPosition of coreObjectsForPosition) { const object = coreObjectForPosition.object(); if (object) { sortedObjects.push(object); } } } } coreGroup.setAllObjects(sortedObjects); } _sortPoints(coreGroup, params) { const sortMode = SORT_MODES[params.mode]; switch (sortMode) { case "axis" /* AXIS */: return this._sortPointsByAxis(coreGroup, params); case "random" /* RANDOM */: return this._sortPointsByRandom(coreGroup, params); case "attribute" /* ATTRIBUTE */: return this._sortPointsByAttribute(coreGroup, params); } TypeAssert.unreachable(sortMode); } _sortPointsByAxis(coreGroup, params) { const objects = coreGroup.threejsObjectsWithGeo(); for (let object of objects) { this._sortPointsForObject(object, params); } } _sortPointsByRandom(coreGroup, params) { var _a; (_a = this.states) == null ? void 0 : _a.error.set("sorting points in random mode is not yet implemented"); } _sortPointsByAttribute(coreGroup, params) { var _a; (_a = this.states) == null ? void 0 : _a.error.set("sorting points by attribute is not yet implemented"); } _debug(a) { if (!this._debugActive) { return; } } _sortPointsForObject(object, params) { pointsFromObject(object, _points); const oldIndexAttribute = object.geometry.getIndex(); if (!oldIndexAttribute) { console.warn("geometry cannot be sorted since it has no index"); return; } const oldIndices = oldIndexAttribute.array; this._positions = new Array(_points.length); this._indicesByPos.clear(); this._indexDest.clear(); const axis = AXISES[params.axis]; let axisValue = 0; let i = 0; for (let point of _points) { point.position(this._pointPos); switch (axis) { case "x" /* X */: { axisValue = this._pointPos.x; break; } case "y" /* Y */: { axisValue = this._pointPos.y; break; } case "z" /* Z */: { axisValue = this._pointPos.z; break; } } this._positions[i] = axisValue; pushOnArrayAtEntry(this._indicesByPos, axisValue, point.index()); i++; } let sortedPositions = this._positions.sort((a, b) => a - b); if (params.invert) { sortedPositions.reverse(); } const newIndices = new Array(_points.length); i = 0; for (let position of sortedPositions) { const indices = this._indicesByPos.get(position); if (indices) { this._indicesByPos.delete(position); for (let index of indices) { newIndices[i] = index; this._indexDest.set(index, i); i++; } } } const newIndexAttrib = new Array(oldIndices.length); for (let i2 = 0; i2 < oldIndices.length; i2++) { const oldIndex = oldIndices[i2]; const newI = this._indexDest.get(oldIndex); newIndexAttrib[i2] = newI; } object.geometry.setIndex(newIndexAttrib); const corePointClass = corePointClassFactory(object); const attributeNames = corePointClass.attributeNames(object); for (let attributeName of attributeNames) { if (attributeName == "id") { this._debugActive = true; } const attribute = object.geometry.getAttribute(attributeName); this._updateAttribute(attribute, newIndices); this._debugActive = false; } } _updateAttribute(attribute, newIndices) { const clonedAttribute = attribute.clone(); const srcArray = attribute.array; const clonedArray = clonedAttribute.array; const itemSize = clonedAttribute.itemSize; this._debug(newIndices); for (let newIndex of newIndices) { const oldIndex = this._indexDest.get(newIndex); this._debug(`${newIndex} -> ${oldIndex}`); if (oldIndex != null) { for (let i = 0; i < itemSize; i++) { clonedArray[oldIndex * itemSize + i] = srcArray[newIndex * itemSize + i]; } } else { console.warn("no old index found"); } } attribute.array = clonedArray; attribute.needsUpdate = true; } } SortSopOperation.DEFAULT_PARAMS = { mode: SORT_MODES.indexOf("axis" /* AXIS */), targetType: SORT_TARGET_TYPES.indexOf(AttribClass.POINT), seed: 0, axis: AXISES.indexOf("x" /* X */), attribute: "", invert: false }; SortSopOperation.INPUT_CLONED_STATE = InputCloneMode.FROM_NODE;