PhysX particle emitter and destroyer

Hi there.

I’m looking to create a water simulation where Physx particles are continuously emitted and destroyed, creating an endless water flowing animation.

I looked up the “Paint Ball Emitter” demo in the Physics Demo Scenes and replicated the emitter function using Action Graph script node.

Now I’m at the destroy particle part and I don’t know where to start.
I’d like to create a prim that can delete any colliding Physx particles. So I can imagine there are probably two scripts to write.
-A collision event that triggers the destroy function, along with the identifier for the colliding particles
-And the script that destroys the particle in question

Looking at script used for emitting particles, spawning a particle seems to be as simple as adding an extra element to an array, so I suppose deleting a particle would be of similar concept, but I wouldn’t know how to find the index of a specific particle.

The emitter script based on the sample script is in enabled “single particle set” and disabled “use instancer” configuration so as to contain all the particles within one prim.

Any insight would be appreciated. Many Thanks.

Thanks for your post. Let me ask the physics team how to do this. Thank you.

Hi @luijoevin ,
Since we don’t support contact reports for particles, you will have to implement the intersection logic in your script to identify the particle indices that you want to remove. Then I think you should be able to just do a replace with last operation on the UsdGeom.Points point array attributes. I think that should work but I haven’t tried it myself.

Thanks @SimonPhysX

A very crude script written to sequentially check if each point of the particle is below a certain Z-value, and by popping the particle elements out of the array, I managed to destroy the particle.

But this detection and popping operation has slowed down performance for quite a significant amount.

I also looked into the PhysX overlap nodes in the Action Graph, specifically “Overlap, Prim, All”, but apparently this and other similar nodes can only detect prims with collider components, it can’t detect Physx particles, nor can it output which indices of the particle is in collision with the input prim.

Is there another method of calculating particle intersection? Is there a function to determine whether a coordinate/point is within a geometry?

Yes this is expected. You are running now two complex physics commands and it will be cpu bound. Normally people would run the first particle emitter and not worry about destroying them at the other end. Is this for a specific use case? Some kind of effect you need rendering? What is the final output for this?

I’m creating a simulation of water running through a funnel.

The simulation would be running for a long time, which means Omniverse would be calculating particles running through the funnel, as well as the particles on top either waiting to flow through or waiting at the bottom. So I’m looking for methods to improve the framerate by creating particles at run time (which I can also control its spawn rate and initial velocity) and deleting particles that has passed through the funnel.

Other than deleting intersecting particles, I’d also like to use the collision/overlap detection for counting particles passing through certain area.

See if PhysX and Omniverse can do these kinds of things while keeping up the performance.

Whilst what you are doing is very impressive and looks really amazing, be aware that running this kind of high-density particle simulation “for a long time”, could be very very demanding on your system and on omniverse. I would have thought it better to dump a finite amount of particles into the system, let them funnel through and then end the simulation. The longer you run it, the more the load. So set your particle emitter to say 100,000 particles and let it run until conclusion.

If you send me the file, I can see how stable it is here on my powerful system and see how well it runs.

EmitterExport.zip (1.3 MB)

Run using 2.4GHz 24-Core Intel Xeon Silver 4214R and RTX4070. With the exception of stuttering when creating and destroying particles, the simulation would run at 20-30fps. Destroying particles, depending on the amount of particles deleted, can freeze the simulation for up to 20 seconds.

I was wondering if the checking/appending/popping can be optimized, perhaps using warp in script node can speed things up while keeping use of the PhysX particle system. Otherwise, destroying the particles using script node would be too resource demanding and I’ll choose to limit the simulation time.

Within the action graph are the two script nodes responsible for creating and destroying the particles, you can unlink the second script node to disable the particle destruction function.

Also, because I don’t know how to execute the script’s cleanup and setup after running the first time, you may have to reload the scene if you wish to play the simulation the second time.

One more thing, I’d like to know what Simon refers to when he mentioned intersection logic. Is he referring to overlaps? If collision detection doesn’t include for particles, is there a function to determine whether a coordinate/point is within a geometry?

I need a function that can calculate the flow rate of particles.

Many thanks

I cannot get this scene to play any particles in either the old 2023.2.5 which you are using and the new kit 107

Sorry, I forgot to mention I’m currently using 2023.2.2. I’ll try to install the latest version and update the scene.

Checked with updated version, the simulation seems fine. This might be because the script node extension isn’t enabled at your end.

Yes please make sure it works in the very latest version of kit, which is kit 107.03 available from GITHUB at GitHub - NVIDIA-Omniverse/kit-app-template: Omniverse Kit App Template

EmitterExportNew.zip (356.4 KB)

Updated to work in Kit 107.03, you will have to enable script node extension and physics bundle extension for the emission and funnel collider to work.

Although some of the features seem to be broken after the upgrade. I made a new warp script to change the color of each particle based on their individual speed, and after the upgrade they keep flashing grey because the
particle primvar interpolation mode keeps switching from HdInterpolationVertex to HdInterpolationConstant due to “not enough data size”. But other than that everything else should work fine.

@luijoevin ,

I don’t have a good recipe for you for really good performance. We don’t have draining nor overlap, nor contact report support for particles unfortunately. We also don’t support Fabric at the moment, which would have been a good option together with warp code on the GPU as you mention.
I can only suggest some workaround which might be good enough:

I suggest you use Gf.Range3d.IsInside(…) to check overlaps. To make this a bit faster, you don’t have to do the intersection test every simulation update. You can just test a small portion of all active particles per simulation update, and always consider another small set per update. I don’t think you need to be very exact when it comes to particle removal. For particle counting something similar might work too, but it’s a bit more tricky.

Once again by writing a crude Warp script to check and mark the number of particles passing through a set X-axis position at each set time interval I managed to calculate the flow rate. While I couldn’t find a function called IsInside() in the Gf.Range3d class (at least on pxr-usd-api Gf docs anyway), I did see an other function called Contains(), which I believe would serve similar purpose. I’ll try to get it running to see if it runs smoother than warp, or with warp function.

Particle removal at this point becomes too resource intensive to be kept as a feature, and so I’ll limit the simulation time to about 30 seconds.

The particle interpolation jumping between vertex and constant (flashing between my intended color and grey color) is still an issue, but I’ll consider opening a new topic.

One thing does spike my interest though.

Does this mean there is a function I can use to select a range of particles based on user conditions? Or is it just something similar to what I wrote in the Warp script (X-axis position check)?

@wp.kernel
def WarpCheckSetParticle(	InputPos: wp.array(dtype=wp.vec3),
							InputXValue: wp.float32,
							OutputBool: wp.array(dtype=bool)
):
	tid = wp.tid()

	OutputBool[tid] = (InputPos[tid][0] < InputXValue)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.