Particle Speed By Age

The following tutorial shows how to speed up and slow down particles based on their Age and LifeSpan.

Particle View Setup

Natural Language - Script
Final Result

Watch the Preview AVI ( 310K, DivX 5.2)

Download the demo scene (14KB ZIP)

Complete Script

on ChannelsUsed pCont do
(
  pCont.useAge = true 
  pCont.useSpeed = true 
  pCont.useLifespan = true 
  pCont.useVector = true 
)

on Init pCont do
(
)

on Proceed pCont do
(
  count = pCont.NumParticles() 
  maxSpeed = 0.1
  pSystemTM = (pCont.getParticleSystemNode()).transform 

  pSystemTM.row4 = [0,0,0]
  for i in 1 to count do 
  (

    pCont.particleIndex = i 
    if pCont.particleAge.frame == 0.0 then pCont.particleVector = ([0.0,0.0,-1.0] * pSystemTM)
    life = pCont.particleLifespan.frame 
    vel = maxSpeed * (1.0 - Abs (2* (Mod pCont.particleAge.frame life)/life - 1.0))
    pCont.particleSpeed = vel * pCont.particleVector 
  )
)

on Release pCont do
(
)

Step-By-Step Comments

on ChannelsUsed pCont do
(

The ChannelsUsed handler defines the channels to be used by the Script Operator - you cannot get or set particle related values from the particle container without specifying which properties you need access to. This way, Particle Flow does not have to provide the Script Operator with all possible channels (and there can be an arbitrary number of channels in Particle Flow) but only with those that are actually needed. This conserves memory!
The parameter pCont contains  the Particle Container.


pCont.useAge = true 
pCont.useSpeed = true 
pCont.useLifespan = true 

As we want to change the speed based on the Age and Lifespan of the particles, we need to activate the respective channels. .

pCont.useVector = true 

We will also need the particleVector channel which can be used to store user values. We will store the initial orientation of the particles there.

)

on Init pCont do
(

The Init handler is called on initialization. Not used this time though.

)

on Proceed pCont do
(

The Proceed  handler is called every time the Script Operator is evaluated by Particle Flow. 
It contains the actual body of the script.
The parameter pCont contains  the Particle Container which contains all particles the Operator is applied to.


count = pCont.NumParticles()

Here we read the current number of particles in the particle container. 
We will access every one of them in the following loop. 
The reason we assign the value to a variable is that in the for loop that follows, the to limit is evaluated after each cycle of the loop to decide whether the i variable is greater than the limit. 
Using the pCont.NumParticles() method call inside the for loop would call the method n times where n is the number of particles. 
With the current code though, the method will be called just once and this will make the script faster!

maxSpeed = 0.1

This variable contains the max.  speed in units per tick a particle can reach. Change this to get faster or slower top velocity at age of 50%

pSystemTM = (pCont.getParticleSystemNode()).transform 

In order to respect the orientation of the Source icon, we need to get the transformation matrix of the Source. We call the .getParticleSystemNode() method to access the actual scene particle system node and assign its matrix to the user variable.

pSystemTM.row4 = [0,0,0]

We only need the rotation part of the transformation matrix. This will zero out the position information...

for i in 1 to count do
(

Now we repeat the following code block for every single particle by using a for loop which counts from 1 to the number of particles. 
The variable i will contain the current particle index.

pCont.particleIndex = i

In order to work with multiple particles, we have to specify the current particle to access. 
Setting the .particleIndex property of the Particle Container to the i variable will make the i-th particle the current one. 
Any subsequent particle property access calls will be directed to that particle!

if pCont.particleAge.frame == 0.0 then pCont.particleVector = ([0.0,0.0,-1.0] * pSystemTM)

When a particle is first born in the scene, (its Age is 0.0), we will get the actual transformation matrix of the source at that time, multiply a -Z vector by this matrix and store the value in the particleVector channel for later access. 

life = pCont.particleLifespan.frame 

Now we take the lifespan of the the particle as a Float value (by default it returns a time value like 10f, .frame returns 10.0 in that case) and assign to a variable.

vel = maxSpeed * (1.0 - Abs (2* (Mod pCont.particleAge.frame life)/life - 1.0))

Now we multiply the max. speed value defined in a user variable by a Triangle function  which starts at 0.0, goes up to 1.0 in half the life time value and then falls down to 0.0 again. The resulting variable vel contains the velocity factor of the current particle based on its age relatively to its life span...

pCont.particleSpeed = vel * pCont.particleVector 

Finally, we multiply the velocity factor by the direction vector stored in the particleVector channel and assign to the particleSpeed channel of the current particle.

)
)

on Release pCont do
(
)

Copyright © 2003 by Borislav 'Bobo' Petrov.