synching animation timing of individual particles?


I’ve looked through this forum but cant seem to find a solution to the following problem:
I have a deforming mesh and I want to grow new animated geometry from a selected number of vertices over time. Lets say a sphere moves from left to right and moves through a volume/reference point in space. As the sphere’s verts enter this volume I would like to ‘grow’ particle geometry on them creating a kind of wave pattern. I’ve tried using a Magma InVolume script to select the verts and I can use Frost to place the animated particle mesh on them. But the problem is that there is no age I can convert to Geomtime to offset the animation so they all grow at the same time. I would of course like to synchronize the particle mesh animation with the time when the they enter the volume.
So the question is, how do I create particles on the sphere verts and then synch the animation of the particle meshes to start from that time? Any solution using Frost, Stoke or Pflow would be very welcome.


The main problem with this is that most of the Magma implementations (Krakatoa MX, Genome, Stoke Field Magma) are history-independent. This means that the calculations on each frame are totally independent from any other frames, and you cannot store info about what happened earlier (as this is not really a simulation).

The Stoke Field Simulator CAN store history information, but it would be normally locked spatially to the world space cells where the data is stored. We are interested in storing data in the actual vertices, since they are the ones that would drive the Frost animation…
It might be doable, but it is tricky.

There is of course a procedural way to do something like that if the motion of the object is relatively constant, because then the Velocity is constant, and the Position would be equivalent to the Time passing. In other words, if your sphere is entering a volume at a constant rate and does not stop inside or move faster while exiting, you could equate the position change (in this case the distance to the closest point of the volume’s surface, for example) to the passing of time. I set up such a simple example where a GeoSphere is entering a Box volume, and the GeomTime of the Frost particles is driven by the absolute distance of each vertex to the closest point on the Box’ surface when inside (and 0 when outside, so it does not grow). It produces a neat effect, but it might not be exactly what you are after… (see attachment). (25.1 KB)


There is also a “recursive saving” workaround that could be performed which I have shown in the past using Genome and XMesh, and also Krakatoa MX. Basically you would create a PRT Source from the vertices of the GeoSphere and save that to a PRT file sequence with GeomTime set to 0.0 for all vertices on all frames. Then you create a PRT Loader with this sequence, set it to custom range, and set the offset to load the previous frame (Offset -1). You hide the first PRT Source and make a new PRT Source from the PRT Loader. On the new PRT Source, you add the Magma which has GeomTime as input and output, and the InVolume logic which increments the GeomTime by 1 when inside the volume, and decrements it when outside the volume, but clamps between 0 and the last frame of the geometry animation to avoid excessive “growth”. You then resave the PRT Source alone (PRT Loader saving should be disabled) OVER THE SAME PRT sequence being loaded by the PRT Loader. Since the PRT Loader reads a frame back, it will load frame 0, perform the Magma on the PRT Source and save over frame 0. Then on frame 1 it will load again frame 0, with the changes from the previous iteration, make new changes, and save frame 1. On frame 2 it will load frame 1, make increments/decrements as needed, and save frame 2, and so on. Since the PRT Loader is not being saved directly, its PRT sequence it fair game for overwriting by Krakatoa.

Once the sequence is resaved, you will have a History-Dependent version of the simulation where the particles increment and decrement their GeomTime depending on how long they have been inside the volume.

However, this approach requires saving of files, while the other approaches are pretty much interactive, so… let’s see what PFlow can do for us.

Using Particle Flow, this would also be rather easy to implement since all channels in Particle Flow are history-dependent. You would need a Data Operator which checks if a particle is inside the volume, and incements, say, the MXSFloat channel, or a component of a Mapping channel. Then you can save that PFlow to PRT, or convert it on the fly to PRT Source in Krakatoa MX 2.5 and higher, add a Magma to copy the data from the PFlow channel to the GeomTime channel, and off you go. See the attached scene: (35.6 KB)

Note that other than in the first example, the shrinking does not happen inside the box, but once the vertices are outside, even if the GeoSphere does not move anymore… I also used 2.0 increment for growth and 1.0 decrement for shrinking, so the “tentacles” appear faster than they disappear!

Hope this helps!


Thank you very much for the quick and helpful reply! Unfortunately my company hasn’t upgraded yet and I’m still stuck on 3ds max 2014 so I cant open your sample files.
The velocity will not be constant so your Pflow example seems like the way to go. I tried reconstructing the Pflow example from your description. I can select verts that are inside the volume using the Geometry-inObjects operator but cant find a way to create/increment an MSXfloat channel using Pflow’s data operators. I dont mean to impose but if you could reup max 2014 compatible samples or perhaps post some screenshots of the data operator and Magma flows I would very greatful.


No problem, here you go… (35.5 KB)

In the DataOp, I did the following:

  • We input the Script Float channel.

  • We need to clamp it between a min. and max. value:
    [*]If it is less than 0, we output 0.0 (to prevent it from getting negative while outside the volume), otherwise we pass it through the Pipe op.

  • If it is greater than 40 (which is the last frame of my animated shape), we output 40.0, otherwise we pass the original value through the Pipe op.
    ]We increment the clamped value by adding 2.0 to it, and outputting it to Script Float again. This operation is conditional, controlled by a boolean result of an Inside Objects test.

  • For the test, we take the Box001 object and check if the current particle is inside it.

  • We connect the boolean output to the control socket of the R1+R2 operator mentioned above.

  • We invert the boolean value to NOT B1 so when the particle is outside (Inside Objects = FALSE), the result becomes TRUE, and connect this to the control socket of a R1-R2 operator that decrements by 1.0 and outputs to Script Float, too.

As result, the Script Float channel is clamped, and incremented or decremented depending on whether the particle is inside or outside.


Works like a charm. Thanks a lot for your help.