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