Jump to content

SPS on the go !


Recommended Posts

I added some new features in the SPS useful if you want to optimize a immutable set of 3D objects (buildings in the distance, asteroids, etc) : https://github.com/BabylonJS/Documentation/blob/master/content/tutorials/03_Advanced/Solid_Particle_System.md


You can now rotate/ translate, color, etc the SPS objects not only on update (for classical animated particles) but also on creation (for for ever frozen objects)


Under the hood, I also ported the numeric arrays to typed arrays (float32) so it is better to pass data to WebGL

Link to comment
Share on other sites

De nada


Demos soon  ;) (maybe one for the future "features demo" for the BJS web site ? don't know what to do though)


The SPS needs for more little tweaks and is almost OK.

I think it's already fully functionnal (according to what I expect and I'm quite hard to please) for any immutable mesh.


Just some little (most of them invisible for users) fixes to add or some refactor to do and it will be finished for its first introductionin the BJS core.

You can use it already, of course.  


I would really like to have some parts of the code in asm.js, or even just our great magic ComputeNormals() method, which is a really good candidate for this, in order to check what the gains would be.

However I don't want to recode everything in C, then to compile to asm.js. I would like to write the asm.js directly : iterations and accesses in arrays,  and simple float operations (+, -, *, /) only

If anyone has some experience in coding directly in asm.js, please let me know

Link to comment
Share on other sites

First very basic (and commented) examples that you will find in the documentation (finished soon)


plane particles, billboard mode, no rotation : http://www.babylonjs-playground.com/#WCDZS

same but without billboard mode and with rotation : http://www.babylonjs-playground.com/#WCDZS#1


solid particles : box and tetrahedrons



last news :

you can now modify the SPS mesh, per particle, at creation time. This means you can build a non-updatable mesh but you can still set the particle positions, rotations, scales, colors, uvs, even their vertices, once for all and never call then _setParticles()_.

It is useful for immutable meshes (building in the distance, asteroids, etc) or whatever un-animated because you will have then one draw call and no vertex buffer update (and no need for some behavior logic either, so less CPU consumption). In brief, the more performance possible for immutable customized SPS.


If you take a look at the code from this example (feature not yet in PG) , you'll see there's no SPS behavior and its mesh isn't updatable, so the code is quite short : http://jerome.bousquie.fr/BJS/test/solidparticlesAsteroid.html


Have fun

Link to comment
Share on other sites

Awesome.. good job indeed! Is it already in the current Babylon version? I might give this a try. Got some nice ideas on how to use it :D


By the way: is it already possible to remove single particles? Lets say I want to shoot some of the asteroids and make them disappear. Could I do that (yet)? Or is this a planed feature? Or just not possible?

Link to comment
Share on other sites

thinking about something ...

in this version I added a double-link on each particl to its previous and next neighbour, as I thought it was useful.


But, as the user has access to the global particles array and to each particle index, he can know the next and the previous one

var i = particle.idx;var next = SPS.particles[i - 1];var previous = SPS.particles[i + 1];

So unless someone tells me the need for the double-link, I guess I will remove it from the SPS

Link to comment
Share on other sites



Yesterday night, I was reading some ThreeJS documentation about their feature called BufferGeometry, which is something to optimize the render of massive geometries (ex : many meshes merged into one big that won't evolve after) in one single draw call.


Well, I'm proud to announce to you that the SPS is our BufferGeometry when you use it as an immutable SPS (cf documentation).

The difference is that the SPS has many other features like, not the least, the ability to animate each of its components (what we call the solid particles), even to morph them or to apply them a different texture per component... which aren't avalaible in the ThreeJS BufferGeometry ;) .

Link to comment
Share on other sites

improvment added in setParticles(), validated with the profiler :)

as well as a new SPS property to manage cleanly the memory at SPS level and avoid GC trigerring : SPS.vars


documented here : https://github.com/BabylonJS/Documentation/blob/master/content/tutorials/03_Advanced/Solid_Particle_System.md

in "GC concerns" section

Link to comment
Share on other sites

a last lead to improve again setParticles() and I will have reached everything possible in JS in this algo :P


[EDIT] : done

Now the particle normals aren't recomputed, but rotated within the same loop on positions, each call of setParticles() as long as the particles can't be morphed, it is to say as long as SPS.computeParticleVertex keeps false.

Although ComputeNormals() has been optimized, it is still a big process reiterating on positions, indices and normals arrays... so quite CPU consuming when you have to deal with dozens of thousands of position and normal values.

So now ComputeNormals() is called only when the particle shapes may change.

Link to comment
Share on other sites

Hi Jerome!  Great work, thanks!  The SPS doc is EXCELLENT!  I thought I was a thorough explain-er, but Jerome... you are kicking my butt on that!  :)


Have you ever thought of splitting setParticles into 2-3 more-distinctly-named functions?  For example, setParticles might call setRotation, setPosition, and setScaling?  That way, users could create custom functions for one or more of those.


What I was thinking about... was a custom setPosition which placed all particles in a giant ball around the emitter.  Now, using each particle's scaling as the MASS value, start spinning the emitter... and use centrifugal force (emitter spin rate/particle mass) to determine when each particle flies away-from the emitter crowd.  (essentially, connect emit power to emitter spin rate).


In this case, I ONLY need a custom setPosition, but not custom setRotation or setScaling.


Or should I be dealing-with updateParticle?  Maybe setParticle just does initial placement.  I'm new at this.  :)  And 'setParticle' is not very indicative of what the function does.  (I hear echoes of a long-ago programming mentor of mine, who would OFTEN say to me "If a function is more than 10 lines, it should be sub-functioned.")


Just thinkin'  :)  I realize that particle mass is starting to enter the world of physics, but we are already using one physics property for particles - gravity.  So, I don't think it is too far-fetched to ponder particles having mass (but probably not built-into SPS.  User can add it.) 


The particle mass affects the gravitational pull, too... the fall rate.


What's that?  You say "No"?  Newton claims what? 


Oh, he claims that BB's fall just as fast as bowling balls?  Well I'll be darned.  ;)

Link to comment
Share on other sites

Well, you post is interesting because I understand that everything is not really clear in my documentation.


So I'll try to summarize it here :


The SPS is behavior-agnostic. This means it doesn't know how the particles will move, rotate, if they have a mass, if there are forces, etc. You have to see it like a big mesh that you can create (buildMesh) from many shape models, some BJS existing meshes, (addShape) that will be its solid particles. It provides some methods to access then and to manage these solid particles.

So the initial stuff to do is to create the SPS, then to add as many shapes you need and at last to build the SPS mesh.

var  SPS = new BABYLON.SolidParticleSystem("sps", scene);SPS.addShape(modelMesh1, 100);SPS.addShape(modelMesh2, 200);SPS.addShape(modelMesh3, 150);// etc ...SPS.buildMesh();   // this builds the mesh and displays it at just construction time

Once you've done it, you need to manage your solid particles.

The way to fix the particle status and then to display them at this status is to call SPS.setParticles()

Each time you call setParticles() the particles are rendered at their current status. Easy, isn't it ?

So three steps :

  1. SPS and its mesh creation
  2. compute your particle behavior
  3. call setParticles() to update the mesh and draw it

Just remember that, once the mesh is build, only setParticles() does then the job : updates the mesh VBO and draws it.


To help you to update each particle status, setParticle() will call for each particle SPS.updateParticle(particle).

This function doesn't do anything by default, so it is the place were you can implement your particle behavior, with physics if you want.

It is passed each particle object in turn, which you can set its initial properties (position, rotation, quaternion, scale, color, uvs, velocity) or add and set your own if your logic needs it (age ? mass ? etc).


example :

SPS.updateParticle = function(particle) {  particle.position.x += 0.01;  if (particle.age > 20 ) {    SPS.recycleParticle(particle);}

So updateParticle() just changes the particle data, not the mesh itself. The setParticles() process updates the mesh. Hopefully, setParticles() calls updateParticle(particle) ;)


If you want to set an initial status, different from the live behavior that you would implement in SPS.updateParticle(particle), you can use SPS.initParticles().

This function doesn't do anything, you have to implement it.

It doesn't draw the mesh, it just changes the particle initial status that will be taken in account by the next SPS.setParticle() call.


example :

// declares initParticleSPS.initParticles = function() {  for (var i = 0; i < SPS.nbParticles; i++) {    SPS.particles[i].position.x = Math.random() * 100;    SPS.particles[i].position.y = Math.random() * 100;    SPS.particles[i].position.z = Math.random() * 100;  }}SPS.initParticles();    // calls initParticles : the particle status are now changed, not the SPS meshSPS.setParticles();    // the mesh is now updated from the particle status

Same thing with SPS.recycleParticle(particle) what is not called automatically and that you have to implement by your own and to call when you need (cf the first example about updateParticle) :

SPS.recycleParticle = function(particle) {  particle.position.x = 0;  particle.position.y = 0;  particle.position.z = 0;}

This is the basic principle that will cover most of the cases, I hope.


There are plenty of other advanced features (immutable SPS - 3JS BufferGeometry like -, colors and uvs per particle, particle vertex live update, billboard mode, optimizers, pickable particle -up to come-, etc) that you will discover by reading the doc ;)

The SPS is quite finished (pickable just missing for now) and the documentation is updated everyday according to the latest features.

I will code many PG examples once everything is over.

Link to comment
Share on other sites

Just added the support for pickable particles with the optional pickedParticles array :
SPS.pickedParticles is an array of {idx: particleIndex, faceId: particleFaceId }, with an element per SPS global mesh face.

var SPS = new BABYLON.SolidParticleSystem('SPS', scene, {pickable: true});// add shapes and build SPS mesh as usualSPS.setParticles();scene.onPointerDown = function(evt, pickResult) {   var idx = SPS.pickedParticles[pickResult.faceId].idx;      // get the particle idx from the picked faceId   var p = SPS.particles[idx];                                // get the related particle in the SPS   p.color.r = 1;                                             // change the particle color to red   p.color.b = 0;   p.color.g = 0;   SPS.setParticles();                                        // finally update the SPS};

This array is created and populated only if the SPS is declared explicitly as pickable in order to save memory.

Documentation soon, probably tomorrow ;)

Link to comment
Share on other sites

Sweet! In my maze game I already used SPS for the enemy explosions (wich looks awesome, so thanks for that jerome!)... with pickable particles I want to try making an asteroid field with one SPS and create another SPS when an asteroid has been picked/destroyed and make it explode into little derbies. I imagine that might be pretty cool :D

Link to comment
Share on other sites

Jerome, I didn't read the docs (much).  I just saw how large it was, and how it was sectioned, and the playgrounds (and their code comments).


So, its not that you didn't explain well enough.  You did fine.  I just skimmed (quick scanned) the doc while I finished my coffee before I went fishing.  But I DID see "udpate"  :)


I got skunked!  (no fish).


But hey, thanks for the explanation!  That was nice of you to do that.  I should have told you that I just skimmed them... sorry.


Ok, now, hmm.  It's a single dynamicBuffer mesh, right?  These suffer from the same depth-rendering/alpha issues as the standard particles, correct?  From a single SPS, the particles cannot be BEHIND something and also in-front-of something, right?  errr.


If you place a spacecraft in the center of that asteroid field, all the particles will render BEHIND it or IN-FRONT-OF it (afore it?)... but they can't be both? 


What the heck am I thinking about, here?  :)



Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...