UNPKG

@polygonjs/polygonjs

Version:

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

94 lines (87 loc) 3.2 kB
import {BaseSopOperation} from './_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {InputCloneMode} from '../../../engine/poly/InputCloneMode'; import {MarchingCubes} from '../../../modules/core/objects/MarchingCubes'; import {Vector3} from 'three'; import {isNumber} from '../../../core/Type'; import {isBooleanTrue} from '../../../core/BooleanValue'; import {BufferGeometry} from 'three'; import {DefaultOperationParams} from '../../../core/operations/_Base'; import {CorePoint} from '../../../core/geometry/entities/point/CorePoint'; import {CoreObjectType} from '../../../core/geometry/ObjectContent'; interface MetaballSopParams extends DefaultOperationParams { resolution: number; isolation: number; useMetaStrengthAttrib: boolean; metaStrength: number; useMetaSubtractAttrib: boolean; metaSubtract: number; enableUVs: boolean; enableColors: boolean; } const pos = new Vector3(); const _points: CorePoint<CoreObjectType>[] = []; export class MetaballSopOperation extends BaseSopOperation { static override readonly DEFAULT_PARAMS: MetaballSopParams = { resolution: 40, isolation: 30, useMetaStrengthAttrib: false, metaStrength: 0.1, useMetaSubtractAttrib: false, metaSubtract: 1, enableUVs: false, enableColors: false, }; static override readonly INPUT_CLONED_STATE = InputCloneMode.NEVER; static override type(): Readonly<'metaball'> { return 'metaball'; } override cook(inputContents: CoreGroup[], params: MetaballSopParams) { const inputCoreGroup = inputContents[0]; try { const geometry = this._createMetaballsGeometry(inputCoreGroup, params); return this.createCoreGroupFromGeometry(geometry); } catch (err) { this.states?.error.set(`failed to create metaballs, possibly a memory issue`); console.error('metaballs failed'); return this.createCoreGroupFromObjects([]); } } private _createMetaballsGeometry(inputCoreGroup: CoreGroup, params: MetaballSopParams) { const metaballs = new MarchingCubes( params.resolution, // CoreConstant.MATERIALS[ObjectType.MESH], params.enableUVs, params.enableColors ); metaballs.isolation = params.isolation; inputCoreGroup.points(_points); for (const point of _points) { point.position(pos); pos.multiplyScalar(0.5).addScalar(0.5); let metaStrength = params.metaStrength; if (isBooleanTrue(params.useMetaStrengthAttrib)) { let metaStrengthAttrib = point.attribValue('metaStrength') as number; if (isNumber(metaStrengthAttrib)) { metaStrength *= metaStrengthAttrib; } } let metaSubtract = params.metaSubtract; if (isBooleanTrue(params.useMetaSubtractAttrib)) { let metaSubtractAttrib = point.attribValue('metaSubtract') as number; if (isNumber(metaSubtractAttrib)) { metaSubtract *= metaSubtractAttrib; } } metaballs.addBall(pos.x, pos.y, pos.z, metaStrength, metaSubtract, undefined); } metaballs.createPolygons(); const geometry = new BufferGeometry(); const attribNames = Object.keys(metaballs.attributes); for (let attribName of attribNames) { const attrib = metaballs.attributes[attribName]; geometry.setAttribute(attribName, attrib); } return geometry; } }