[Closed] Fixing particle Index
Hi all,
I’m trying to do an explosion scene where an object is fragmented and the fragments are all individual mesh objects with animation baked in.
What I’ve so far is that with Bobo’s “Scripting Custom Chunks” birthscript, I replace the mesh fragments with pflow particles to animate them and now I need to put the animation of the particles back into the fragment objects.
I’ve tried to modify another one of bobo’s script , to bake the animation and shape of the particles into new box objects
theSystem = $PF_Source_01
theArray = $Box* as array
for t = animationRange.start to animationRange.end do
(
sliderTime = t --set the slider time to the time value
theCount = theSystem.numParticles()
for p = 1 to theCount do
(
theSystem.particleIndex = p
if p <= theArray.count do
theArray[p].mesh = theSystem.particleShape -- turn box into fragment shapes
with animate on theArray[p].transform = theSystem.particleTM
)
)
It all work out fine until I place in a collision test in the Pflow system. The animation is still baked into the box objects but the shape and orientation are messed up. I figured that when the particles pass through the collision test, their particle Index might have change. So is there anyway to fixed the particle index?
This is correct, particle index is morphing based on the content of the event. Each particle container numbers the particles from 1 to the last particle without gaps, so if you have 10 particles and index 5 leaves the event, 6,7,8,9 and 10 become 5,6,7,8 and 9 respectively.
When running on top of the PF_Source, the source might change the numbering as it represents all particles in all events connected to it, but the particles are moving between these events.
The way to avoid this is to track the ParticleID instead – it is given to each particle at birth and is thus non-changing and unique. There are methods to get the ID from Index and the other way round and lots of methods to read particle channels by ID. So you should collect the IDs of the particles in the beginning of the animation and then bake based on them. So your arrays will be indexed by ID and you will have to count from 1 to the number of particles, get the ID of each indexed particle and then grab the data by ID.
Thanks for the reply Bobo : )
Althought I’m still a noob at Maxscript (currently only capable of understanding and mixing lines from different scripts written by others), I shall give it a try.
Hope I can figure it out : D
It worked! All I need to do is to change theSystem.particleIndex into theSystem.particleId.
theSystem = $PF_Source_01
theArray = $Box* as array
for t = animationRange.start to animationRange.end do
(
sliderTime = t --set the slider time to the time value
theCount = theSystem.numParticles()
for p = 1 to theCount do
(
theSystem.particleId = p -- Use .ID instead of .particleIndex
if p <= theArray.count do
theArray[p].mesh = theSystem.particleShape
with animate on theArray[p].transform = theSystem.particleTM
)
)
Thanks again for the explaination , Bobo : D
This is not safe. If you have to do this in a PFLow that contains Delete operators, some IDs might be lost in the process and your code would stop working.
The way to do is:
*Loop as before
*Set theSystem.particleIndex = p as before
*Now get the ID of the current particle using theID = theSystem.getParticleID p
*Then you can get the TM of the current particle as before but assign to the array element with index theID instead of p.
This ensures that the array elements will always be affected by the SAME ID no matter what the index is. Normally, if you create 100 particles, they will have IDs from 1 to 100 and indices from 1 to 100. But if you send random 50 particles out to another event, the first event will contain indices 1 to 50 and the second event also indices from 1 to 50. The system might see these particles rather scrambled (so counting the index from 1 to 100 does not go through the same order as when getting from a single event). If you delete 10 particles now, the indices in the system will go down to 1 to 90, but the IDs will still go from 1 to 100 with ten gaps somewhere in between. Thus, only array elements that have “alive” IDs will be keyframed. Even if you would delete 99 particles, the one left (with index 1) will have some ID (not necessarily 1) which will move its corresponding piece from the array.
For your current purposes though, you code will do nicely. I am talking about a more general situation with changing particle counts.
I did a simple test scene and I got what you mean. Thanks for the help, I shall take note of it for future reference.