UNPKG

@polygonjs/polygonjs

Version:

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

93 lines (79 loc) 3.37 kB
import {BaseSopOperation} from './_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {TypedNodePathParamValue} from '../../../core/Walker'; import {NodeContext} from '../../../engine/poly/NodeContext'; import {applyRenderHook, applyCustomMaterials} from '../../../core/geometry/Material'; import {Group, Material, Object3D, Mesh} from 'three'; import {InputCloneMode} from '../../../engine/poly/InputCloneMode'; import {DefaultOperationParams} from '../../../core/operations/_Base'; import {CoreMask} from '../../../core/geometry/Mask'; import {SopType} from '../../poly/registers/nodes/types/Sop'; import {CoreParticlesAttribute} from '../../../core/particles/CoreParticlesAttribute'; import {BaseMatNodeType} from '../../nodes/mat/_Base'; interface MaterialAndNode { material: Material; materialNode: BaseMatNodeType; } interface ParticlesSystemGpuMaterialSopParams extends DefaultOperationParams { group: string; material: TypedNodePathParamValue; } // type TraverseCallback = (coreObject: CoreObject) => void; export class ParticlesSystemGpuMaterialSopOperation extends BaseSopOperation { static override readonly DEFAULT_PARAMS: ParticlesSystemGpuMaterialSopParams = { group: '', material: new TypedNodePathParamValue(''), }; static override readonly INPUT_CLONED_STATE = InputCloneMode.FROM_NODE; static override type(): Readonly<SopType.PARTICLES_SYSTEM_GPU_MATERIAL> { return SopType.PARTICLES_SYSTEM_GPU_MATERIAL; } override async cook(inputCoreGroups: CoreGroup[], params: ParticlesSystemGpuMaterialSopParams) { const coreGroup = inputCoreGroups[0]; await this._applyMaterials(coreGroup, params); return coreGroup; } private async _getMaterial(params: ParticlesSystemGpuMaterialSopParams): Promise<MaterialAndNode | undefined> { const materialNode = params.material.nodeWithContext(NodeContext.MAT, this.states?.error); if (materialNode) { const material = await materialNode.material(); if (!material) { this.states?.error.set(`material invalid. (error: '${materialNode.states.error.message()}')`); return; } return {material, materialNode}; } else { this.states?.error.set(`no material node found`); } } private async _applyMaterials(coreGroup: CoreGroup, params: ParticlesSystemGpuMaterialSopParams) { const materialData = await this._getMaterial(params); if (!materialData) { return; } const selectedObjects = CoreMask.filterThreejsObjects(coreGroup, params); for (let selectedObject of selectedObjects) { this._applyMaterial(selectedObject, materialData, params); } return coreGroup; } private _applyMaterial( object: Object3D, materialData: MaterialAndNode, params: ParticlesSystemGpuMaterialSopParams ) { if ((object as Group).isGroup) { // do not assign material to a group, as this could cause render errors return; } const objectWithmaterial = object as Mesh; // const current_mat = object_with_material.material as Material | undefined; // if (current_mat && params.swapCurrentTex) { // this._swap_texture(used_material, current_mat, params); // } objectWithmaterial.material = materialData.material; CoreParticlesAttribute.setMaterialNodeId(object, materialData.materialNode.graphNodeId()); applyRenderHook(object, materialData.material); applyCustomMaterials(object, materialData.material); } }