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