UNPKG

@polygonjs/polygonjs

Version:

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

109 lines (108 loc) 4.35 kB
"use strict"; 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); } } }