Control Particle Emissions
Blender's particle system is really a great invention. You can do a lot with it.
But there is a big problem with particles: You can only control the emission of particles using frame start and frame end. That means, you need to find out the frame in your animation where particles should start and stop to emit manually.
Strange idea, especially because you can even not animate the number of keyframes so it would be possible to simply set a keyframe with number=0 and another with number=10000 (or whatever). You would be able to interpolate the number of particles, that would be great - but it's simply not possible. So sad.
I thought I need to find a solution, but Blender makes it really hard to find one.
I tried to use Geometry Nodes (GNs) to simply switch the geometry off at a certain point in time, so: no faces, no emission. But: Blender doesn't feel stopping emission would be good then... Instead, it emits the particles completely on the origin of the object!! So strange...
There's no way around that, I've experimented with a lot different settings. Particles comes, no matter what comes out of Group Output.
Then I thought, let's make the spark (my spark object, an icosphere, which is used as particle) switch itself to a transparent material and switch it to it's illuminated material when the particles should be visible. In theory an idea - but as Blender still emits and emits, there are already a lot of (invisible) particles in the scene and when I switch back to visible, you guess what happens... Particles gets visible wherever they currently are. No solution.
Another problem is (see my spark thread), only the part of the cutter object which is inside the blank object should emit particles, not the whole cutter. In my other thread I simply created another cone, made it smaller and positioned it in the reight Z height. That works of course - but only for linear cuts.
If I rotate my blank for example, the cut area changes constantly so that is also no solution.
So to solve the problem with the emitter cut depth I created a similar GN setting of the real cutter GN setup which simulates a real cut and changes the blank cube object.
Instead of a cut simulation like there I created a new emitter object which also creates a Bool object using Intersect. This is the opposite of the cut: The result is the partial object showing the geometry of the part of the cutter which is currently inside the blank - no matter which rotation etc.
This object is then used as an emitter. That works...partially.
Blender would not be Blender if that would be a solution...
New problem: The emitter object is so near to the cut blank surface that a lot of the particles shoots through the blank object, because of collision settings they do not come out (if the inner wall width is set to a high enough value, in the collision settings).
OK, I could live with that by increasing the number of particles... nooo... 90% of the particles are inside the blank and nearly no one emits outside...
So I thought, OK, if they emit forward in normals direction why not simply flip their faces so the normals of the emitter going outside of the cut (there is a flip faces GN)? Nope. No solution. Didn't change the behaviour.
OK, after a lot experiments I came up with this solution:
As the emitter is the intersection object, I added two Transform nodes to the GN setup. One returns the original intersection object and one returns the same object, turned by 180° in Z direction. As additional tweak I added a bit scale correction: making the emitter object a bit smaller in X/Y direction and a bit bigger in Z direction. On that way the emitter doesn't touch the cut surface of the blank and more particles comes out, also a bit higher than the cut so they are also landing on the blank surface.
These two are joined together and that's it! Particles emits as they should.
But it doesn't solve the problem with the start/end of emitting.
Here I found a funny idea how to control the number of particles using a kind of mask with a windowed object. Nice trick:
Unfortunately not a solution for me as my emitter has not a really closed surface.
Then my last idea (which finally works) is: If Blender wants to emit from the origin of the object if no geometry is returned from the GNs, the simplest way is to move the origin to where it cannot be seen!
As the emitter should rotate around Z axis (better effect) the X/Y-position of the origin needs to be at the same X/Y coordinates as the cutter object. The Z coordinate I set to -10, so it's under the plane which I used as ground.
Now whenever particles should not emit they emit under the ground, when the should emit, they start wherever I want at the faces of the the emitter object.
In the picture below you can see the tricky GN setup assigned to the emitter object.
This makes it possible to start emission whenever the cutter object touches the blank in any way. And it stops when the cutter moves out or have not begun touching the blank.
How does it work?
Group Input comes from the emitter. That's the cone object. This is simply a copy of the cutter object, same size and position. The emitter object is set as child to the cutter object so they move together.
With Object Info I get the blank object (it's geometry). As the blank object has it's simulation GN setup for the cut I'm not sure which geometry it gets here - but I think it's the geometry of the blank without cut. I don't know.
So then the same Intersection is done with the Boolean Mesh node. The result geometry is then the part of the cutter object which is inside the blank object.
Next one is a bit tricky, maybe there are better solutions but it works.
"Intersecting Edges" gives a list of edges which intersecting between the two bool objects. You can see that if you add a "Viewer" node and open the Spreadsheet window, then use the "Intersecting Edges" as input for the Viewer and also the geometry. You'll find out that if no intersection happens, the list is empty. If an intersection happens, you get a list of values which gets longer the more faces intersecting.
I would like to count these simply but whoever made the "Attribute Statistic" node forgot this important aggregate function every database programmer knows. So the only thing is "Sum".
But it can happen that you get a long list of edges, but all with the value "0". So Sum would also be 0. This is why the "Add" node exists:
It adds simply 1 to each value "Intersecting Edges" returns and so all have a value which gets in result a sum > 0. Now it can be tested with "Greater Than 0" Compare Node - and this is the collision detection which always works and don't need raycasts.
So at the other side "Switch" is used with the result of the comparison. It gets the Intersection object geometry from the Bool operation if it is True and if False, no geometry, so an empty object (but not empty enough for Blender's particle emitting.....).
After that the two Transform nodes and the Join node, like described above.
So what it does: It makes sure that the emitter object only exists if the collision between cutter and blank happens. It's origin outside the visible view makes sure, no particles are visible outside of the collision.
To create a Python script out of that, you should really install the extension "Node To Python". It will create a Python script from every node setup and copies it to the clipboard. It's really exact as the coordinates for the nodes are with a lot of digits after the dot... :)
You can of course remove that to integer values.
I have attached the Blender file which the script returns.
It took me a lot of experiments as it is of course not so easy with Blender to find the right way.
Problem here: I duplicate the cutter object using Python. The cutter has already the linear movement animation so the new emitter object has it also. If you move that as child to the cutter object, the animation is still there and it doesn't replace what happens with the cutter during animation, it is additionally calculated. So that means, the emitter moves twice as fast with a bigger distance...
OK, and if you made the error to set the origin lower than the ground before, the animation copy will move it back also. So the animation must be deleted first.
I've also attached the Blend file for anyone who wants to experiment with it.
Also the Python file which creates the basic setup (but the complete setup plus some tweaks are already in the Blend file).
Why did I not simply used start and end frame? The reason is: I want to animate more than one cut and it would no solution to set start and end because it would continue to emit between the cuts.
Yes, I could render that in separated cuts but with the risk that it would not look continously.
Made a short test video (need to set the motion blur higher, but you can see how it works starting and ending the particle animation).
Hope it saves someone headaches and hours of hours experimenting. This works of course with any kind of object collisions and particle emissions, not only for sparks.. ;)
3
7 comments
Christian Coppes
5
Control Particle Emissions
CG Python Academy (Free)
skool.com/cgpython
3D artists learning Blender Python.
Leaderboard (30-day)
Powered by