UNPKG

@polygonjs/polygonjs

Version:

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

169 lines (168 loc) 6.97 kB
"use strict"; import { TypeAssert } from "./../../poly/Assert"; import { BaseSopOperation } from "./_Base"; import { InputCloneMode } from "../../../engine/poly/InputCloneMode"; import { AttribClass, ATTRIBUTE_CLASSES } from "../../../core/geometry/Constant"; import { coreObjectClassFactory, coreObjectInstanceFactory } from "../../../core/geometry/CoreObjectFactory"; import { filterObjectsFromCoreGroup } from "../../../core/geometry/Mask"; import { ENTITY_CLASS_FACTORY } from "../../../core/geometry/CoreObjectFactory"; import { arrayMin, arrayMax } from "../../../core/ArrayUtils"; import { isNumber, isString, isBoolean } from "../../../core/Type"; import { Vector2, Vector3, Vector4, Color } from "three"; import { pushOnArrayAtEntry } from "../../../core/MapUtils"; const _v2 = new Vector2(); const _v3 = new Vector3(); const _v4 = new Vector4(); const _c = new Color(); export var AttribPromoteMode = /* @__PURE__ */ ((AttribPromoteMode2) => { AttribPromoteMode2["MIN"] = "min"; AttribPromoteMode2["MAX"] = "max"; AttribPromoteMode2["FIRST_FOUND"] = "first found"; return AttribPromoteMode2; })(AttribPromoteMode || {}); export const ATTRIB_PROMOTE_MODES = [ "min" /* MIN */, "max" /* MAX */, "first found" /* FIRST_FOUND */ ]; export class AttribPromoteSopOperation extends BaseSopOperation { static type() { return "attribPromote"; } cook(inputCoreGroups, params) { const coreGroup = inputCoreGroups[0]; const classFrom = ATTRIBUTE_CLASSES[params.classFrom]; const classTo = ATTRIBUTE_CLASSES[params.classTo]; const mode = ATTRIB_PROMOTE_MODES[params.mode]; const objects = filterObjectsFromCoreGroup(coreGroup, params); for (const object of objects) { const factoryFrom = ENTITY_CLASS_FACTORY[classFrom]; const factoryTo = ENTITY_CLASS_FACTORY[classTo]; const attribNames = factoryFrom ? factoryFrom(object).attributeNamesMatchingMask(object, params.name) : coreGroup.attributeNamesMatchingMask(params.name); for (const attribName of attribNames) { const hasAttribute = factoryTo ? factoryTo(object).hasAttribute(object, attribName) : coreGroup.hasAttribute(attribName); if (!hasAttribute) { const srcAttribSize = factoryFrom ? factoryFrom(object).attribSize(object, attribName) : coreGroup.attribSize(attribName); if (srcAttribSize != null) { if (factoryTo) { factoryTo(object).addNumericAttribute(object, attribName, srcAttribSize); } else { coreGroup.addNumericAttribute(attribName, srcAttribSize); } } } } const destEntities = []; const srcEntities = []; const traversedRelatedEntityData = { [AttribClass.CORE_GROUP]: { ids: [] }, [AttribClass.OBJECT]: { ids: [] }, [AttribClass.POINT]: { ids: [] }, [AttribClass.PRIMITIVE]: { ids: [] }, [AttribClass.VERTEX]: { ids: [] } }; const coreObjectClass = coreObjectClassFactory(object); coreObjectInstanceFactory(object).relatedEntities( classTo, coreGroup, destEntities, traversedRelatedEntityData ); const traversedClassFromEntityIds = traversedRelatedEntityData[classFrom].ids; const classFromEntitiesByClassToEntitytIndex = /* @__PURE__ */ new Map(); if (traversedClassFromEntityIds.length > 0 && classFrom != AttribClass.CORE_GROUP) { const entityClassFrom = coreObjectClass.relatedEntityClass(object, classFrom); for (const classFromEntityId of traversedClassFromEntityIds) { const classToEntities = []; const classFromEntity = new entityClassFrom(object, classFromEntityId); classFromEntity.relatedEntities(classTo, coreGroup, classToEntities); for (const classToEntity of classToEntities) { const index = classToEntity.index(); pushOnArrayAtEntry(classFromEntitiesByClassToEntitytIndex, index, classFromEntity); } } } for (const destEntity of destEntities) { const cachedEntities = classFromEntitiesByClassToEntitytIndex.get(destEntity.index()); if (cachedEntities) { for (const attribName of attribNames) { this._promoteAttribute(attribName, cachedEntities, destEntity, mode); } } else { destEntity.relatedEntities(classFrom, coreGroup, srcEntities); for (const attribName of attribNames) { this._promoteAttribute(attribName, srcEntities, destEntity, mode); } } } } return coreGroup; } _promoteAttribute(attribName, srcEntities, destEntity, mode) { const srcValues = srcEntities.map((entity) => entity.attribValue(attribName)); const destValue = this._convertSrcValues(srcValues, mode); destEntity.setAttribValue(attribName, destValue); } _convertSrcValues(srcValues, mode) { switch (mode) { case "min" /* MIN */: { return this._convertValuesMin(srcValues); } case "max" /* MAX */: { return this._convertValuesMax(srcValues); } case "first found" /* FIRST_FOUND */: { return this._convertValuesFirstFound(srcValues); } } TypeAssert.unreachable(mode); } _convertValuesMin(srcValues) { return this._convertValuesMinMax(srcValues, arrayMin); } _convertValuesMax(srcValues) { return this._convertValuesMinMax(srcValues, arrayMax); } _convertValuesMinMax(srcValues, arrayFunc) { const firstValue = srcValues[0]; if (isNumber(firstValue) || isString(firstValue) || isBoolean(firstValue)) { return arrayFunc(srcValues); } if (firstValue instanceof Vector2) { _v2.x = arrayFunc(srcValues.map((v) => v.x)); _v2.y = arrayFunc(srcValues.map((v) => v.y)); return _v2; } if (firstValue instanceof Vector3) { _v3.x = arrayFunc(srcValues.map((v) => v.x)); _v3.y = arrayFunc(srcValues.map((v) => v.y)); _v3.z = arrayFunc(srcValues.map((v) => v.z)); return _v3; } if (firstValue instanceof Color) { _c.r = arrayFunc(srcValues.map((c) => c.r)); _c.g = arrayFunc(srcValues.map((c) => c.g)); _c.b = arrayFunc(srcValues.map((c) => c.b)); return _c; } if (firstValue instanceof Vector4) { _v4.x = arrayFunc(srcValues.map((v) => v.x)); _v4.y = arrayFunc(srcValues.map((v) => v.y)); _v4.z = arrayFunc(srcValues.map((v) => v.z)); _v4.w = arrayFunc(srcValues.map((v) => v.w)); return _v4; } return 0; } _convertValuesFirstFound(srcValues) { return srcValues[0]; } } AttribPromoteSopOperation.DEFAULT_PARAMS = { group: "", classFrom: ATTRIBUTE_CLASSES.indexOf(AttribClass.POINT), classTo: ATTRIBUTE_CLASSES.indexOf(AttribClass.OBJECT), mode: ATTRIB_PROMOTE_MODES.indexOf("first found" /* FIRST_FOUND */), name: "" }; AttribPromoteSopOperation.INPUT_CLONED_STATE = InputCloneMode.FROM_NODE;