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 |
Create a default Particle Flow Source, rotate to emit particles up.
Edit the Rotation Operator to Speed Follow, X:0, Y:90, Z:0 to orient the Z axis of the particles to the velocity vector.
Add a Force to assign Gravity to the particles.
Add a Script Operator to define the Particle Shape using a scene object's mesh (see code below)
Add a Collision Operator, add the Deflector to get collision effects slowing down the particles (optional)
Natural Language - Script |
Enable the Speed and the Shape channels
In the Init handler, get the Box from the scene by its unique name
If the Box does not exist, create a new one, assign a unique name
In the Proceed handler, loop through all particles
Get the Speed of the current particle in units/tick
Multiply by the TicksPerFrame
Assign to the Height property of the Box
Get the mesh of the Box and assign to the Shape of the Particle
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. |