Particle Length By Velocity

Particle Flow has the ability to display particles in the viewports in multiple ways, including lines representing the velocity vector.
There is no comparable built-in mode to render geometry particles for the final animation though.
The following tutorial assigns a box to the particle shape and changes its height based on the particle's speed to achieve a similar effect.

Particle View Setup

Natural Language - Script

 

Final Result

Complete Script

on ChannelsUsed pCont do
(
  pCont.useSpeed = true
  pCont.useShape = true
)

on Init pCont do
(
  global VelocityParticle_170268 = $VelocityParticle_170268
  if VelocityParticle_170268 == undefined then
  (
    VelocityParticle_170268 = cylinder height:1 radius:1 sides:3 smooth:false name:"VelocityParticle_170268"
    hide VelocityParticle_170268
  )
)

on Proceed pCont do
(
  count = pCont.NumParticles()
  for i in 1 to count do
  (
    pCont.particleIndex = i
    VelocityParticle_170268.height = length pCont.particleSpeed *200.0
    pCont.particleShape = VelocityParticle_170268.mesh
  )
)

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.useSpeed = true

Since we want to read the speed of the particles in order to calculate the length of the particle mesh, we will need access to the Speed channel.

pCont.useShape = true

We will also replace the mesh of all particles with a custom one, so we need access to the Shape channel, too.

)

on Init pCont do
(

The Init handler is called on initialization. 
We will use it to define the custom particle shape (a Box).


global VelocityParticle_170268 = $VelocityParticle_170268

We will define a custom global variable with a unique name.
The Box object in the scene should also have a unique name.
If you want to use the script multiple times with different objects, you will have to change both to other unique names.


if VelocityParticle_170268 == undefined then
(

In case the object does not exist in the scene (leading to an undefined value),
we will have to define a new one ourselves.

VelocityParticle_170268 = cylinder height:1 radius:1 sides:3 smooth:false name:"VelocityParticle_170268"

Here we define a new box, set all parameters as needed, and also assign the unique name to it.

hide VelocityParticle_170268

Then we hide the box to free up the viewports.

)
)

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!


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!


VelocityParticle_170268.height = length pCont.particleSpeed *TicksPerFrame

Here we do the actual work - we take the particle speed which is in units per tick, multiply by the TicksPerFrame variable containing the number of ticks in a frame and assign the result to the height of the box. (TickPerFrame will be 192 on PAL systems with 25 fps, or 160 on NTSC systems at 30 fps). 
This results in a box which is exactly as long as the speed in units/frame. 


pCont.particleShape = VelocityParticle_170268.mesh

Finally, we get the mesh of the box and assign to the current particle's Shape.

)
)

on Release pCont do
(
)

Copyright 2003 by Borislav 'Bobo' Petrov.