@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
109 lines (108 loc) • 4.35 kB
JavaScript
;
import { TypedSopNode } from "./_Base";
import { CoreInterpolate } from "../../../core/math/Interpolate";
import { CoreOctree } from "../../../core/math/octree/Octree";
import { CoreIterator } from "../../../core/Iterator";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { InputCloneMode } from "../../poly/InputCloneMode";
import { Box3, Vector3 } from "three";
import { SopType } from "../../poly/registers/nodes/types/Sop";
import { corePointClassFactory } from "../../../core/geometry/CoreObjectFactory";
import { pointsFromObjectFromGroup } from "../../../core/geometry/entities/point/CorePointUtils";
const _tmpBox = new Box3();
const _position = new Vector3();
const _nearestPoints = [];
const _pointsSrc = [];
class AttribTransferSopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
/** @param source group to transfer from (right input, or input 1) */
this.srcGroup = ParamConfig.STRING();
/** @param dest group to transfer to (left input, or input 0) */
this.destGroup = ParamConfig.STRING();
/** @param name of the attribute to transfer */
this.name = ParamConfig.STRING();
/** @param max number of samples to use */
this.maxSamplesCount = ParamConfig.INTEGER(1, {
range: [1, 10],
rangeLocked: [true, false]
});
/** @param max distance to search points to transfer from */
this.distanceThreshold = ParamConfig.FLOAT(1);
/** @param blend width */
this.blendWidth = ParamConfig.FLOAT(0);
}
}
const ParamsConfig = new AttribTransferSopParamsConfig();
export class AttribTransferSopNode extends TypedSopNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
}
static type() {
return SopType.ATTRIB_TRANSFER;
}
initializeNode() {
this.io.inputs.setCount(2);
this.io.inputs.initInputsClonedState([InputCloneMode.FROM_NODE, InputCloneMode.NEVER]);
}
async cook(inputCoreGroups) {
const coreGroupDest = inputCoreGroups[0];
const coreGroupSrc = inputCoreGroups[1];
coreGroupSrc.pointsFromGroup(this.pv.srcGroup, _pointsSrc);
coreGroupSrc.boundingBox(_tmpBox);
const octree = new CoreOctree(_tmpBox);
octree.setPoints(_pointsSrc);
const destObjects = coreGroupDest.allObjects();
const srcObjects = coreGroupSrc.allObjects();
let i = 0;
for (const destObject of destObjects) {
const srcObject = srcObjects[i];
const corePointClass = corePointClassFactory(destObject);
const attributeNames = corePointClass.attributeNamesMatchingMask(srcObject, this.pv.name);
this._addAttributeIfRequired(destObject, srcObject, attributeNames);
await this._transferAttributes(destObject, octree, attributeNames);
i++;
}
this.setCoreGroup(coreGroupDest);
}
async _transferAttributes(object, octree, attribNames) {
const callback = (destPoint) => {
this._transferAttributesForPoint(destPoint, octree, attribNames);
};
const destPoints = [];
pointsFromObjectFromGroup(object, this.pv.destGroup, destPoints);
const _iterator = new CoreIterator();
await _iterator.startWithArray(destPoints, callback);
}
_addAttributeIfRequired(destObject, srcObject, attribNames) {
for (const attribName of attribNames) {
const corePointClass = corePointClassFactory(destObject);
const hasAttrib = corePointClass.hasAttribute(destObject, attribName);
if (!hasAttrib) {
const attribSize = corePointClass.attribSize(srcObject, attribName);
corePointClass.addNumericAttribute(destObject, attribName, attribSize, 0);
}
}
}
_transferAttributesForPoint(destPoint, octree, attribNames) {
const totalDist = this.pv.distanceThreshold + this.pv.blendWidth;
destPoint.position(_position);
octree.findPoints(_position, totalDist, this.pv.maxSamplesCount, _nearestPoints);
for (const attribName of attribNames) {
this._interpolatePoints(destPoint, _nearestPoints, attribName);
}
}
_interpolatePoints(pointDest, srcPoints, attribName) {
const newValue = CoreInterpolate.perform(
pointDest,
srcPoints,
attribName,
this.pv.distanceThreshold,
this.pv.blendWidth
);
if (newValue != null) {
pointDest.setAttribValue(attribName, newValue);
}
}
}