Babylon.js icon indicating copy to clipboard operation
Babylon.js copied to clipboard

Add Solid Particle System (SPS) Support to Node Particle Editor

Open Soullnik opened this issue 1 month ago • 90 comments

Overview

This PR integrates Babylon.js Solid Particle System (SPS) into the Node Particle Editor, enabling users to create and manage SPS-based particle systems through a visual node graph interface. This brings the power of SPS (instanced rendering, shape-based particles) to the node-based workflow.

Important Note

This is a proposal for discussion and requires future refactoring. The current implementation is created for community discussion as I don't have sufficient knowledge of the node ecosystem architecture. The goal is to gather feedback on the best approach for integrating SPS into the existing node graph system.

Features Added

1. SPS Node Graph Integration

  • SPSSystemBlock: Main SPS system node for managing particle systems
  • SPSCreateBlock: Node for defining particle shapes and counts
  • SPSInitBlock: Node for particle initialization logic
  • SPSUpdateBlock: Node for particle update logic
  • SPSMeshSourceBlock: Node for mesh shape sources (Box, Sphere, etc.)

Technical Implementation

Core SPS Blocks:

// SPSSystemBlock - Main SPS system
public createSystem(state: NodeParticleBuildState): SolidParticleSystem

// SPSCreateBlock - Particle shape definition
public _build(state: NodeParticleBuildState): ISPSCreateData

// SPSInitBlock - Particle initialization
public _build(state: NodeParticleBuildState): SPSUpdateData

// SPSUpdateBlock - Particle updating
public _build(state: NodeParticleBuildState): SPSUpdateData

// SPSMeshSourceBlock - Mesh shape sources
public _build(state: NodeParticleBuildState): Mesh

Usage Example

// Create SPS system with multiple particle types
const spsSystem = new SPSSystemBlock("SPS System");
const createBox = new SPSCreateBlock("Create Box Particles");
const createSphere = new SPSCreateBlock("Create Sphere Particles");

// Connect multiple particle sources
createBox.solidParticle.connectTo(spsSystem.solidParticle);
createSphere.solidParticle.connectTo(spsSystem.solidParticle);

// Add mesh sources
const boxMesh = new SPSMeshSourceBlock("Box Mesh");
const sphereMesh = new SPSMeshSourceBlock("Sphere Mesh");
boxMesh.mesh.connectTo(createBox.mesh);
sphereMesh.mesh.connectTo(createSphere.mesh);

Current Challenges & Seeking Solutions

1. Multiple Connection Architecture (Incomplete)

Challenge: SPS requires multiple SPSCreateBlock inputs to one SPSSystemBlock. Current Implementation:

  • Added allowMultipleConnections flag
  • Implemented connectedPoints array to store multiple connections
  • Modified NodeParticleBlock.build() to traverse all connected blocks Issues:
  • Visual representation of multiple connections is not fully working
  • Graph editor doesn't properly display all connections Question: What's the best architectural approach for handling multiple input connections in the node graph system?

Questions

  1. Multiple Connections Architecture: What's the best pattern for handling multiple inputs in the node graph system?

  2. SPS Integration: Are there any SPS-specific considerations we should be aware of the implementation?

  3. Future Extensibility: How can we make this system more extensible for other particle system?


The main goal is to bring SPS capabilities to the node-based workflow. Looking forward to feedback on the integration approach and suggestions for better solutions to the identified challenges!

Soullnik avatar Oct 20 '25 21:10 Soullnik

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 20 '25 21:10 bjsplat

  1. Multiple Connections Architecture: Look at what I did for the GradientBlock

  2. Future Extensibility: Not sure to follow. What are the other particle system? Note that NPE is based on the premise that the update loop is CPU side.

deltakosh avatar Oct 20 '25 21:10 deltakosh

Building or testing the sandbox has failed.

If the tests failed, results can be found here: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/SANDBOX/refs/pull/17320/merge/testResults/

bjsplat avatar Oct 20 '25 21:10 bjsplat

Building or testing the playground has failed.

If the tests failed, results can be found here: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/PLAYGROUND/refs/pull/17320/merge/testResults/

bjsplat avatar Oct 20 '25 21:10 bjsplat

Graph tools CI has failed you can find the test results at:

https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/TOOLS/refs/pull/17320/merge/testResults/

bjsplat avatar Oct 20 '25 21:10 bjsplat

Question for you: How does it integrate with current update nodes that take a particle as parameter?

deltakosh avatar Oct 20 '25 21:10 deltakosh

Ok @Soullnik the more I think about it, the more I struggle to see it working. My main problem is that we cannot share anything with the main blocks. Which blocks will work in both mode? I feel like we are stuffing spa in but it makes not a lot of sense.

deltakosh avatar Oct 21 '25 01:10 deltakosh

Lol sorry I'm thinking too much lol. I think all the nodes working on base types will work still. But all nodes working on particles needs to be hidden. Then it means we need to provide an update node for sps. Same way: update position, etc...

deltakosh avatar Oct 21 '25 01:10 deltakosh

  1. Multiple Connections Architecture: Look at what I did for the GradientBlock
  2. Future Extensibility: Not sure to follow. What are the other particle system? Note that NPE is based on the premise that the update loop is CPU side.

i will check gradientBlock

The second question was about architecture - I had to modify NodeParticleSystemSet to support SPS:

private _systemBlocks: (SystemBlock | SPSSystemBlock)[] = [];

This union type works for now, but if we add more particle system types, we'd need:

private _systemBlocks: (SystemBlock | SPSSystemBlock | GPUSystemBlock)[] = [];

Soullnik avatar Oct 21 '25 07:10 Soullnik

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 21 '25 12:10 bjsplat

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 21 '25 12:10 bjsplat

  1. Multiple Connections Architecture: Look at what I did for the GradientBlock
  2. Future Extensibility: Not sure to follow. What are the other particle system? Note that NPE is based on the premise that the update loop is CPU side.

i will check gradientBlock

The second question was about architecture - I had to modify NodeParticleSystemSet to support SPS:

private _systemBlocks: (SystemBlock | SPSSystemBlock)[] = [];

This union type works for now, but if we add more particle system types, we'd need:

private _systemBlocks: (SystemBlock | SPSSystemBlock | GPUSystemBlock)[] = [];

I think that works. Other option will be to have a NodeParticleSystemSet<T>

deltakosh avatar Oct 21 '25 15:10 deltakosh

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 28 '25 10:10 bjsplat

@deltakosh I’m running into an issue disposing previously created SPS instances. I see that _build inside SPSCreateBlock is called twice for different scenes. What’s the correct way to dispose the previouse SPS associated with the scene?

Soullnik avatar Oct 29 '25 07:10 Soullnik

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 29 '25 08:10 bjsplat

Well it should be on the user no? That's what I do for particle. The user will generate a new ps on each build and will be the owner

deltakosh avatar Oct 29 '25 15:10 deltakosh

Well it should be on the user no? That's what I do for particle. The user will generate a new ps on each build and will be the owner

I mean sps is created when build is called and for example when we change position in spsnitblock it will automatically call build in related spscreatblock and I see this method is always called 2 times and with different scenes in state, the problem is I need to delete previous sps so there is no duplication.

Soullnik avatar Oct 29 '25 18:10 Soullnik

I struggle to see what is different from the particle system?

deltakosh avatar Oct 29 '25 19:10 deltakosh

@deltakosh in CreateParticleBlock, I see const system = new ParticleSystem(this.name, state.capacity, state.scene, null, false, undefined, true); This means that a new particle system will be created with each rebuild. But in state.scene.particleSystems, I see the correct number of particles. If I have one CreateParticleBlock, I see one particle system in each build. But in my SPSCreateBlock, each build adds new sps to the scene, and after the third build, I see 3 sps. This means that for regular particles, there's some cleanup happening somewhere before rebuilding, and I can't figure out where.

Soullnik avatar Oct 30 '25 14:10 Soullnik

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Oct 30 '25 14:10 bjsplat

Hey sorry I'm not available to help right now but you can simply drop a breakpoint in the PS.dispose() and see who is calling? (I think it is done by the preview window)

deltakosh avatar Oct 30 '25 16:10 deltakosh

@deltakosh I have finished implementing a basic example based on https://playground.babylonjs.com/#GLZ1PX#7.

To see this example:

  1. Run the Node Particle Editor (NPE)
  2. Select SPS mode image
  3. The example will be displayed, showing a particle system created entirely using node blocks

Note: While this implementation may not be the most optimal approach, it demonstrates the capabilities and opportunities that these SPS blocks provide for creating particle systems through a visual node-based interface.

Soullnik avatar Nov 14 '25 10:11 Soullnik

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Nov 14 '25 15:11 bjsplat

Building or testing the sandbox has failed.

If the tests failed, results can be found here: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/SANDBOX/refs/pull/17320/merge/testResults/

bjsplat avatar Nov 14 '25 16:11 bjsplat

Graph tools CI has failed you can find the test results at:

https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/TOOLS/refs/pull/17320/merge/testResults/

bjsplat avatar Nov 14 '25 16:11 bjsplat

Building or testing the playground has failed.

If the tests failed, results can be found here: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/PLAYGROUND/refs/pull/17320/merge/testResults/

bjsplat avatar Nov 14 '25 16:11 bjsplat

Audio test results:

https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/17320/merge/testResults/audioV2/index.html

bjsplat avatar Nov 14 '25 16:11 bjsplat

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Nov 14 '25 16:11 bjsplat

Nice work mate!! Now we need to make sure you filter the list of the available nodes on the left when in SPS mode (only keep the one working)

We are doing the same in NME. This way there is no need of a special SPS group. When in SPS we only display the SPS + available blocks

deltakosh avatar Nov 14 '25 18:11 deltakosh

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). To prevent this PR from going to the changelog marked it with the "skip changelog" label.

bjsplat avatar Nov 17 '25 07:11 bjsplat