UNPKG

@polygonjs/polygonjs

Version:

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

113 lines (105 loc) 4.16 kB
/** * Prepares a geometry for cloth simulation. * * */ import {CoreGroup} from '../../../core/geometry/Group'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {InputCloneMode} from '../../poly/InputCloneMode'; import {SopType} from '../../poly/registers/nodes/types/Sop'; import {ClothGeometryAttributeName} from '../../../core/cloth/ClothAttribute'; import {TypedSopNode} from './_Base'; import {mergeFaces} from '../../../core/geometry/operation/Fuse'; import {BufferAttribute, Mesh} from 'three'; import {FloatParam} from '../../params/Float'; import {Attribute} from '../../../core/geometry/Attribute'; import {populateAdjacency3, POPULATE_ADJACENCY_DEFAULT} from '../../../core/geometry/operation/Adjacency'; import {corePointClassFactory} from '../../../core/geometry/CoreObjectFactory'; import {pointsFromObject} from '../../../core/geometry/entities/point/CorePointUtils'; import {CorePoint} from '../../../core/geometry/entities/point/CorePoint'; import {CoreObjectType} from '../../../core/geometry/ObjectContent'; class ClothPrepareSopParamsConfig extends NodeParamsConfig { fuseDist = ParamConfig.FLOAT(0.001); viscosity = ParamConfig.FLOAT(0.1, { range: [0, 1], rangeLocked: [true, false], expression: {forEntities: true}, }); spring = ParamConfig.FLOAT(2, { range: [0, 5], rangeLocked: [true, false], expression: {forEntities: true}, }); } const ParamsConfig = new ClothPrepareSopParamsConfig(); export class ClothPrepareSopNode extends TypedSopNode<ClothPrepareSopParamsConfig> { override readonly paramsConfig = ParamsConfig; static override type(): SopType.CLOTH_PREPARE { return SopType.CLOTH_PREPARE; } protected override initializeNode() { this.io.inputs.setCount(1); this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE); } override async cook(inputCoreGroups: CoreGroup[]) { const coreGroup = inputCoreGroups[0]; const inputMeshes = coreGroup.threejsObjectsWithGeo() as Mesh[]; for (const inputMesh of inputMeshes) { const geometry = inputMesh.geometry; if (!geometry) { return; } this._applyFuse(inputMesh); this._addIdAttribute(inputMesh); this._addViscosityAttribute(inputMesh); this._addSpringAttribute(inputMesh); this._addAdjacencyAttributes(inputMesh); } this.setCoreGroup(coreGroup); } private _applyFuse(mesh: Mesh) { mergeFaces(mesh.geometry, this.pv.fuseDist); } private async _addIdAttribute(mesh: Mesh) { const geometry = mesh.geometry; const positionAttrib = geometry.getAttribute(Attribute.POSITION); if (!positionAttrib) { return; } const pointsCount = positionAttrib.count; const idValues = new Array(pointsCount); for (let i = 0; i < pointsCount; i++) { idValues[i] = i; } const idArray = new Float32Array(idValues); geometry.setAttribute(Attribute.ID, new BufferAttribute(idArray, 1)); } private async _addViscosityAttribute(mesh: Mesh) { await this._addFloatAttribute(mesh, this.p.viscosity, ClothGeometryAttributeName.VISCOSITY); } private async _addSpringAttribute(mesh: Mesh) { await this._addFloatAttribute(mesh, this.p.spring, ClothGeometryAttributeName.SPRING); } private async _addFloatAttribute(mesh: Mesh, param: FloatParam, attribName: ClothGeometryAttributeName) { const corePointClass = corePointClassFactory(mesh); // const coreGeometry = new CoreGeometry(mesh.geometry); if (param.hasExpression() && param.expressionController) { if (!corePointClass.hasAttribute(mesh, attribName)) { corePointClass.addNumericAttribute(mesh, attribName, 1, param.value); } const attrib = corePointClass.attribute(mesh, attribName) as BufferAttribute; attrib.needsUpdate = true; const array = attrib.array; const points: CorePoint<CoreObjectType>[] = []; pointsFromObject(mesh, points); await param.expressionController.computeExpressionForPoints(points, (point, value: number) => { array[point.index()] = value; }); } else { corePointClass.addNumericAttribute(mesh, attribName, 1, param.value); } } private _addAdjacencyAttributes(mesh: Mesh) { populateAdjacency3(mesh, POPULATE_ADJACENCY_DEFAULT); } }