Expanding Solid Particle Systems
Create an expandable SPS
Until now, the SPS you created has had a fixed number of particles once and for all because that is the most performant way to use it.
In some cases, it may be useful to add or remove particles from the SPS after it is created, because they are newly needed or no longer needed.
In this case, you can create an expandable SPS with the optional parameter expandable: true (default false).
import { SolidParticleSystem } from "@babylonjs/core/Particles/solidParticleSystem";var sps = new SolidParticleSystem("sps", scene, { expandable: true });Adding particles
If you want to add more particles to the existing ones, just use the addShape() method again as many times as necessary. Then call buildMesh() to rebuild the SPS geometry with the newly added particles.
import { SolidParticleSystem } from "@babylonjs/core/Particles/solidParticleSystem";var sps = new SolidParticleSystem("sps", scene, { expandable: true });sps.addShape(model1, 100); // adds 100 particles from model1sps.buildMesh();// ... further in the code, when neededsps.addShape(model2, 100); // adds 100 new particles from model2sps.addShape(model3, 200); // and 200 particles from model3sps.buildMesh(); // update the SPS mesh geometry from the last particle additionssps.setParticles();Example: Adding Particles To A Solid Particle System Each mouse click adds 20 new depth sorted particles.
Removing particles
If you want to remove particles from the SPS, use the method removeParticles(start, end), where start and end are the starting and ending indexes of the particles.
This method returns an array populated with the removed particles.
import { SolidParticleSystem } from "@babylonjs/core/Particles/solidParticleSystem";var sps = new SolidParticleSystem("sps", scene, { expandable: true });sps.addShape(model1, 1000); // adds 1000 particles from model1sps.buildMesh();// ... further in the code, when neededvar removed1 = sps.removeParticles(700, 999); // removes the last 300 particlesvar removed2 = sps.removeParticles(0, 9); // removes the first 10sps.buildMesh(); // updates the SPS mesh geometry from the last particle additionssps.setParticles();Example: Removing Particles From A Solid Particle System
Each click removes the first 2 particles and the last 100 particles.
Important note: The SPS must contain at least one particle to work, so never empty it completely!
Storable particles
You may want to create new particles without inserting them into the SPS at creation time, but later. You may also want to keep removed particles aside so you can put them back in the system later.
So when creating new particles, you can specify that they should be stored aside from the SPS with the optional parameter storage: [] of the method addShape().
import { SolidParticleSystem } from "@babylonjs/core/Particles/solidParticleSystem";var stock = []; // the array to store the particlesvar sps = new SolidParticleSystem("sps", scene, { expandable: true });sps.addShape(model1, 1); // the SPS needs at least one particlesps.addShape(model1, 100, { storage: stock }); // stores 100 particles from model1 in the stock arraysps.buildMesh();This SPS contains only one particle. The 100 others are stored in an external array.
If you want now to restore these particles, or some previously removed ones, just use the method insertParticlesFromArray(array).
import { SolidParticleSystem } from "@babylonjs/core/Particles/solidParticleSystem";var stock = []; // the array to store the particles invar sps = new SolidParticleSystem("sps", scene, { expandable: true });sps.addShape(model1, 1000); // the SPS contains 1000 particlessps.addShape(model1, 100, { storage: stock }); // 100 others are stored asidesps.buildMesh();// ... later in the codevar removed = sps.removeParticles(0, 99); // the 100 first particles are removed and stored in another arraysps.buildMesh();// ... later again in the code : let's restore the misssing particlessps.insertParticlesFromArray(removed); // restores the previously removed particlessps.insertParticlesFromArray(stock); // restores the previously created particlessps.buildMesh();sps.setParticles();Each time you call insertParticlesFromArray(), the stored particle objects are not just referenced in the SPS; they are cloned, and the clones are reindexed and given a new identifier.
This means that you can modify or get rid of the storage array or its contained particle objects with no effect on the SPS.
Example: Storable Particles Example
Each click removes 100 particles of a given shape and restores 100 particles of another shape in turn.
100 particles are stored aside at the SPS creation.
Notes:
-
When you remove particles, the remaining ones are reindexed, meaning that their
particle.idxvalue can change. The particle identifierparticle.idkeeps unchanged. If a particle is given a parent and if this parent is removed, then the particleparentproperty value is set tonull. -
Adding or removing particles will create a new VertexData object, and therefore a new VBO buffer, each time
buildMesh()is called.
This can trigger Garbage Collector activity at an unwanted moment, so it is not a good idea to add or remove particles on each frame.
Moreover, an expandable SPS uses more memory than a fixed one because all the dynamic extensible arrays are kept under the hood throughout the SPS lifecycle.In a standard SPS, the particle index
particle.idxand the particle identifierparticle.idhave the same value.
In an expandable SPS (see below), when particles are removed, only the particle identifierparticle.idremains unchanged, whereas the particle index may change.
So, when using an expandable SPS, make sure to set a particle parent with the parent identifier and make sure that this parent still exists.
if (otherParticle) { particle.parentId = otherParticle.id; // not otherParticle.idx}