UNPKG

@polygonjs/polygonjs

Version:

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

189 lines (188 loc) 7.63 kB
"use strict"; import { BaseSopOperation } from "./_Base"; import { Float32BufferAttribute } from "three"; import { InputCloneMode } from "../../../engine/poly/InputCloneMode"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { stringToAttribNames } from "../../../core/String"; import { ATTRIBUTE_CLASSES, AttribClass } from "../../../core/geometry/Constant"; import { TypeAssert } from "../../../engine/poly/Assert"; import { coreObjectClassFactory } from "../../../core/geometry/CoreObjectFactory"; const _newNames = []; const _attribNames = []; export class AttribCopySopOperation extends BaseSopOperation { static type() { return "attribCopy"; } cook(inputCoreGroups, params) { var _a; const coreGroupDest = inputCoreGroups[0]; const coreGroupSrc = inputCoreGroups[1] || coreGroupDest; const attribClass = ATTRIBUTE_CLASSES[params.class]; stringToAttribNames(params.newName, _newNames); if (attribClass == AttribClass.POINT) { const srcAttribNames = coreGroupSrc.pointAttribNamesMatchingMask(params.name); for (let i = 0; i < srcAttribNames.length; i++) { const srcAttribName = srcAttribNames[i]; let destAttribName = isBooleanTrue(params.tnewName) ? _newNames[i] : srcAttribName; if (!destAttribName) { (_a = this.states) == null ? void 0 : _a.error.set(`no matching new attribute name of ${srcAttribName}`); return coreGroupDest; } this._copyAttributeBetweenCoreGroups(attribClass, { attribName: { src: srcAttribName, dest: destAttribName }, params, coreGroup: { src: coreGroupSrc, dest: coreGroupDest } }); } } else { stringToAttribNames(params.name, _attribNames); for (let i = 0; i < _attribNames.length; i++) { const destAttribName = isBooleanTrue(params.tnewName) ? _newNames[i] : _attribNames[i]; this._copyAttributeBetweenCoreGroups(attribClass, { attribName: { src: _attribNames[i], dest: destAttribName }, params, coreGroup: { src: coreGroupSrc, dest: coreGroupDest } }); } } return coreGroupDest; } _copyAttributeBetweenCoreGroups(attribClass, copyArgs) { var _a, _b; switch (attribClass) { case AttribClass.POINT: this._copyAttributesBetweenGeometries(copyArgs); return; case AttribClass.VERTEX: (_a = this.states) == null ? void 0 : _a.error.set("vertex attributes are not supported yet"); return; case AttribClass.PRIMITIVE: (_b = this.states) == null ? void 0 : _b.error.set("primitive attributes are not supported yet"); return; case AttribClass.OBJECT: this._copyAttributesBetweenObjects(copyArgs); return; case AttribClass.CORE_GROUP: this._copyAttributesBetweenCoreGroups(copyArgs); return; } TypeAssert.unreachable(attribClass); } _copyAttributesBetweenGeometries(copyArgs) { var _a; const { coreGroup, attribName, params } = copyArgs; const srcObjects = coreGroup.src.threejsObjectsWithGeo(); const destObjects = coreGroup.dest.threejsObjectsWithGeo(); if (destObjects.length > srcObjects.length) { (_a = this.states) == null ? void 0 : _a.error.set("second input does not have enough objects to copy attributes from"); } else { for (let i = 0; i < destObjects.length; i++) { const destGeometry = destObjects[i].geometry; const srcGeometry = srcObjects[i].geometry; this._copyPointAttributesBetweenGeometries({ geo: { src: srcGeometry, dest: destGeometry }, attribName, params }); } } } _copyAttributesBetweenObjects(copyArgs) { var _a; const { coreGroup, attribName } = copyArgs; const srcObjects = coreGroup.src.allObjects(); const destObjects = coreGroup.dest.allObjects(); if (destObjects.length > srcObjects.length) { (_a = this.states) == null ? void 0 : _a.error.set("second input does not have enough objects to copy attributes from"); } else { for (let i = 0; i < destObjects.length; i++) { const destObject = destObjects[i]; const srcObject = srcObjects[i]; const srcAttribValue = coreObjectClassFactory(srcObject).attribValue(srcObject, attribName.src); if (srcAttribValue != null) { coreObjectClassFactory(destObject).setAttribute(destObject, attribName.dest, srcAttribValue); } } } } _copyAttributesBetweenCoreGroups(copyArgs) { const { coreGroup, attribName } = copyArgs; const srcCoreGroup = coreGroup.src; const destCoreGroup = coreGroup.dest; const srcAttribValue = srcCoreGroup.attribValue(attribName.src); if (srcAttribValue != null) { destCoreGroup.setAttribValue(attribName.dest, srcAttribValue); } } _copyPointAttributesBetweenGeometries(copyArgs) { var _a, _b; const { geo, attribName, params } = copyArgs; const srcAttrib = geo.src.getAttribute(attribName.src); if (srcAttrib) { const size = srcAttrib.itemSize; const destAttrib = geo.dest.getAttribute(attribName.dest); const srcPointsCount = srcAttrib.array.length / srcAttrib.itemSize; if (destAttrib) { const destPointsCount = destAttrib.array.length / destAttrib.itemSize; if (destPointsCount > srcPointsCount) { (_a = this.states) == null ? void 0 : _a.error.set(`not enough points in second input`); } else { this._fillDestArray(destAttrib, srcAttrib, params); destAttrib.needsUpdate = true; } } else { const src_array = srcAttrib.array; const destPointsCount = geo.dest.getAttribute("position").array.length / 3; const dest_array = src_array.slice(0, destPointsCount * size); geo.dest.setAttribute(attribName.dest, new Float32BufferAttribute(dest_array, size)); } } else { (_b = this.states) == null ? void 0 : _b.error.set(`attribute '${attribName}' does not exist on second input`); } } _fillDestArray(dest_attribute, src_attribute, params) { const dest_array = dest_attribute.array; const src_array = src_attribute.array; const dest_array_size = dest_array.length; const dest_item_size = dest_attribute.itemSize; const src_item_size = src_attribute.itemSize; const srcOffset = params.srcOffset; const destOffset = params.destOffset; if (dest_attribute.itemSize == src_attribute.itemSize) { dest_attribute.copyArray(src_attribute.array); for (let i = 0; i < dest_array_size; i++) { dest_array[i] = src_array[i]; } } else { const pointsCount = dest_array.length / dest_item_size; if (dest_item_size < src_item_size) { for (let i = 0; i < pointsCount; i++) { for (let j = 0; j < dest_item_size; j++) { dest_array[i * dest_item_size + j + destOffset] = src_array[i * src_item_size + j + srcOffset]; } } } else { for (let i = 0; i < pointsCount; i++) { for (let j = 0; j < src_item_size; j++) { dest_array[i * dest_item_size + j + destOffset] = src_array[i * src_item_size + j + srcOffset]; } } } } } } AttribCopySopOperation.DEFAULT_PARAMS = { class: ATTRIBUTE_CLASSES.indexOf(AttribClass.POINT), name: "", tnewName: false, newName: "", srcOffset: 0, destOffset: 0 }; AttribCopySopOperation.INPUT_CLONED_STATE = [InputCloneMode.FROM_NODE, InputCloneMode.NEVER];