Rocket Club:
Home PageCommunity:
Bulletin Board
Developer Pages:
Overview
Texture Assets
Animation
Developers:
Development_Notes
Synthetic Reality
|
So,
What's a Particle System? Rocket Club has its own
idea as to what a particle system is, so my
apologies to any particle system purists in the
audience.
First, a
picture:
This picture has
a single particle system in it, one which is
bound to an object (the fire is rising up out of
the wooden disk below it). While not obvious from
this still image, there is a constant stream of
random fire boiling up and out. It's real pretty.
In this particular image there are 40 'particles'
at any given time. Each particle is born at the
bottom, and rise upwards and enlargens and fades.
In Rocket Club,
a particle system is defined by a special INI
file in your "Particle" asset folder.
For example:
rocket
club/assets/00000001/Particle/00000001.campfire.ini
Where 00000001
is *my* developer serNum and you would add yours
to your own folder. Feel free to rummage through
my particle systems for ideas and possibly
additional documentation.
But remember,
the INI file defines a 'type of' particle system
(fire, smoke, snow, etc) but it is your dna plan
file which calls out which type of particle
system (if any) which is to be used with that
object.
|
Particles,
Emitters, and Stages A particle system is
invisible until it has emitted some particles.
Generally particles are emitted at some rate
(which might vary over time) with some initial
velocity and appearance. Particles then move
according to some form of physics and evolve
through different stages (the fire puff becomes
smoke, the rain drop becomes a splash..)
A particle
system has one or more emitters which define how
new particles are generated.
When you hold a
fourth of july sparkler, the hot end of the wire
is the emitter, and the sparks are the particles.
Gravity and thermodynamics provide the physics,
and the particles go through the stages of
'glowing on wire', 'leaping as sparks', 'being
pulled to the ground', 'becoming glowing embers',
and 'fading out'
A campfire
particle system might have one emitter for the
flame, and another emitter for background smoke,
and perhaps a third for the occasional popping
ember. Individual particles may stay as fire and
fade, or evolve into smoke. The physics might
change with each stage, with fire rising quickly,
embers affected by gravity, and smoke billowing
outwards.
Individual
particles eventually die and then are reborn as
newly emitted particles, allowing the system
overall to use a well-defined maximum number of
particles. As a responsible particle system
designer, you need to focus on keeping the
particle count small and the physics computations
simple.
|
The
Particle System Texture Image, and Cells Particle Systems are
truly 3D in the sense that each particle has a
real 3D position in the world. However, the image
drawn at that point is actually a 2D 'billboard'
(a 'square' image whose center is at the 3D
point, but which is always/usually drawn 'facing'
the camera)
The illusion of
a solid 3D mass of plasma comes from the
individual images not having hard outlines and
thus their points of overlaps are not apparent.
This also requires the use of 'alpha
transparency' so that you can control how much
one particle can be 'seen through' another. Over
the lifetime of a particle, it's opacity will
probably change. Most particles 'fade out' by
having their opacity go completely transparent
over time. Once the particle is completely
transparent, it can be recycled without the
viewer noticing it popping out of existence.
One axiom of a
Rocket Club particle system is that each system
has a SINGLE texture image associated with it.
And generally that is a PNG file (since the PNG
format is nicely compressed AND supports an
'alpha channel')
But before you
freak out (how can I have smoke AND fire in the
same particle system if there is only one
image?), the texture image can be broken into
'cells' (the image file is actually a 2D array of
images, with some number of rows and columns)
For example,
here is a portion of the image file used for the
example above:
This is four
'cells' (the actual image has more cells) and you
can see the 'alpha' implied by the checkerboard
background 'showing through' where the
transparency is high. You won't see the
checkerboard at runtime (this checkerboard is
from Gimp)
Your emitter and
stage configuration can descript which cell image
to be used for an individual particle. This might
be random, or you might vary it with stage or
emitter, or you might even play the cells in
order as a little cartoon over the life of the
particle.
The actual
Texture Images are in your Texture assets folder,
like:
rocket
club/assets/00000001/Textures/00000001.fire.png
Again,
substitute your own serNum for the 00000001. In
theory, you could use the same textures on your
models, in theory. but you probably wouldn't want
to.
If your particle
image file does NOT have alpha in it, then you
will see a bunch of square images with some
background color, instead of nice soft particles.
|
Physics I will probably add to
this over time, but the physics of motion/change
for individual particles include:
- An initial
position, relative to the emitter,
specified by a 3D 'box' inside of which
the particle is initially randomly
placed. Collapse the box dimensions to
zero to have all particles emitted at the
same point
- An initial
velocity ('muzzle velocity') again
specified by a separate 3D box whose
dimensions define the max and min values
for each of the 3 components of velocity
(x, y, and z). Generally, Y is 'up'
(opposite direction of gravity in any
case)
- A
sensitivity to gravity (a value of 1.0
means earth normal gravity, pulling
DOWN). Negative values push 'up'.
Remember: gravity is not a velocity, it
is an acceleration.
- Possible
ground collisions (particles can sense a
ground collision, and change stage as a
result). Only use this when needed, as it
is reasonably expensive.
- Radius
Change. A particle can expand/shrink its
"radius" (horizontal and
vertical scale) over the lifetime of a
stage
- Opacity
Change. A particle can vary its opacity
from a start value to an end value over
the lifetime of a stage.
- Lifetime. A
particle (stage) can have a finite
lifetime (in seconds) after which the
stage completes and the particle either
dies or switches to a new stage.
|
Configuration
Options in your Particle INI File A PARTICLE Asset INI file
has several sections in it
- [Texture]
defines the texture file asset and how
many rows and columns it includes.
- [General]
identifies how many stage and emitter
declarations there are
- [StageN]
declares the properties of stage N (N
starts at 1, since stage 0 is death)
- [EmitterN]
declares the properties of emitter N (N
starts at 0, just to confuse you)
Texture
[Texture]
name=00000001.glow.png
rows=1
columns=1
General
[General]
numEmitters=1
numStages=3
Emitter
Declaration
Stage
Declaration
|
Binding
to DNA Objects, and triggers Triggers are
un-documentable at this time, so we'll just cover
the simplest case of an object (like a campfire)
which just emits particles constantly.
Your object will
already have a PLAN file, to which you will add
the following:
[General]
name=Simple Campfire
...
numParticles = 1
[Particle0]
assetName=particle:00000001.campfire.ini
In the [general]
section you add that 'numParticles' line
indicating the number of particle systems used by
that object (limited to one as of this writing)
Then in each
[particleN] section, you define which particle
system configuration file is to be used, and
which node of the DNA to bind the emitters to.
(use of anything but 'root' is not yet
documented, so forget about that for now)
Eventually, I
will tell you how to:
- define
'meta node names' for emitters in the
particle INI script (like 'exhaust')
- define
'meta to actual' bindings in the PLAN
file so as to pick up appropriate nodes
from your model file (like 'engine
exhaust should be emitted here, in this
direction')
- define rate
'triggers' for emitters (so engine
exhaust can vary with accelerator value,
for example)(or damage smoke can vary
with % damaged)
|
Generating
Particle Art I won't kid you, I am not very
good at this. I struggle with mapZone2 to get
something useful. I know mapZone2 can do
ANYTHING, but it's still hard for me. When you
have been successful you have an image file in
some format (bmp? jpg?) where beautiful
flame/smoke/whatever plasma is on a black
background.
I then make a
NEW file, with a film-strip shape (say 1024 x 64
pixels to make one row of 16 columns) and make it
solid black, then copy bits of the beautiful
flame into individual cells (the original image
being a bunch of individual flamey bits) nicely
centered for my needs.
So that's:
- By hook or
by crook, a single file with beautiful
things scattered at random on a black
background
- Copied to a
filmstrip file where individual flames
are centered in their own cells
- Converted
to a PNG file with an alpha layer that
makes the black completely transparent,
and 'dim' colors semi-transparent.
|
Getting
an Alpha Channel from Source Art without One So, you have generated a
beautiful filmstrip of images in a single file
with a black background. Keep that file around
forever, as you might need to edit it someday.
But now we need to make a PNG file with that
black background turned into alpha transparency
(and the 'dimmer' parts of the image to be
SEMI_transparent).
Let's pretend
your original file is a JPG and the final file
will be a PNG. And that you are using GIMP
1.) start GIMP
2.) Load source.JPG
3.) From the LAYERS/MASK menu, select "Add
Layer Mask"
4.) From the dialog that appears, select 'gray
scale' then OK
5.) At this point the black background should be
gone, and you should see a checkerboard 'through'
the image
6.) From the LAYERS/MASK menu, select "Apply
Mask"
7.) No obvious change appears in the image, but
you have copied the layer mask to the alpha
channel of the image, and deleted the layer mask.
8.) From the FILE menu, SAVE AS...
0000001.myTexture.png
And, of course,
use your own serial number. Copy the file to your
assets/TEXTURES folder.
|
Debugging
without going crazy It can be tedious having
to restart the game and travelling to some
location every time you tweak some configuration
value in your particle script, so I added a
command to the DEBUG menu. It is currently the
'reload scripts' command and it causes all action
scripts and particle definitions to be reloaded.
So, on a good
day, you drop an object with your particle system
on it, decide what you need to change, then,
without stopping the game, edit the particle .ini
file, save the changes and select 'reload
scripts' to have it take effect.
You can also
spot-test a particle system by using the 'play'
command, by typing:
/play
particle:00000001.campfire.ini
Where you
provide the name of the particle asset you want
to try. For particle systems which are intended
to be bound to a DNA object, this can be a little
odd. Probably your avatar will be used as the
source object.
You can make
your own macros for things you do a log, like,
say:
/fog=/play
particle:00000001.fog1.ini
Then later you
just type "/fog" to play that. The
'play' command is just for you, no one else sees
the particles you are playing.
|
Sharing
Particles At some point the peer to peer
file system will automatically share the PARTICLE
assets and their attendent texture images. That
may be spotty right now, my apologies.
|
Example:
Fire from a point Generates particles in a
small box, let's them float up and out and fade
[texture]
name=00000001.flame3.png
rows=1
columns=16
blendMode=1
; There must be
at least one emitter (max of 16) and one stage
(max of 16)
[General]
numEmitters=1
numStages=1
[stage1]
name=puff
lifeTime = 3.0
gravity = -0.1
startOpacity = 1.0
endOpacity = 0.0
startRadius = 0.2 ; percent of emitter start
radius
endRadius = 2.0
; this is a
random box emitter, particles start at some
random spot in the box
[emitter0]
name=box
node=root
movementMode=0
stage=1
startRate = 1.0
spawnRate = 10
maxParticles = 80
posScale= 0.3
minPosX = -0.1
maxPosX = 0.1
minPosY = 1.0
maxPosY = 1.2
minPosZ = -0.01
maxPosZ = 0.01
velScale= 0.1
minVelX = 0.0
maxVelX = 0.0
minVelY = 1.0
maxVelY = 1.01
minVelZ = 0.0
maxVelZ = 0.0
radiusScale = 1.0
minRadius = 0.5
maxRadius = 1.5
minCell = 0
maxCell = 3
|
Example:
Fog in an Area Large blobs appear in a large
area, then fade
[texture]
name=00000001.glow.png
rows=1
columns=1
blendMode=1
sort=0
minCamDist = 2.0
wrapDist = 100.0
; There must be at least one emitter (max of 16)
and one stage (max of 16)
[General]
numEmitters=1
numStages=2
[stage1]
name=fadeIn
stageOnTimeOut=2
lifeTime = 1.0
gravity = 0.0
startOpacity = 0.0
endOpacity = 0.8
startRadius = 1.0
endRadius = 1.0
[stage2]
name=expandAndFade
stageOnTimeOut = 0
lifeTime = 9.0
gravity = -0.1
startOpacity = 0.8
endOpacity = 0.0
startRadius = 1.0
endRadius = 3.0
[emitter0]
name=box
node=camera
stage=1
startRate = 1.0
spawnRate = 100.0
maxParticles = 1000
posScale= 50.0
minPosX = -1.0
maxPosX = 1.0
minPosY = -0.3
maxPosY = 0.3
minPosZ = -1.0
maxPosZ = 1.0
velScale= 1.0
minVelX = -0.1
maxVelX = 0.1
minVelY = -0.1
maxVelY = 0.0
minVelZ = -0.1
maxVelZ = 0.1
radiusScale = 3
minRadius = 0.5
maxRadius = 2.5
|
Example:
Snow Zillions of tiny flaks all around
the camera (this is expensive, due to the
zillion)
[texture]
name=00000001.glow.png
rows=1
columns=1
wrapDist = 50.0
; There must be at least one emitter (max of 16)
and one stage (max of 16)
[General]
numEmitters=1
numStages=2
[stage1]
name=flake
stageOnCollision=2
lifeTime = 7.0
gravity = 0.0
startOpacity = 0.5
endOpacity = 0.5
[stage2]
name=onGround
stageOnTimeOut = 0
lifeTime = 3.0
gravity = 0
startOpacity = 1.0
endOpacity = 0.0
deltaVelY = 0.0
[emitter0]
name=box
node=camera
stage=1
startRate = 1.0
spawnRate = 200.0
maxParticles = 2000
posScale= 10.0
minPosX = -1.0
maxPosX = 1.0
minPosY = 0.0
maxPosY = 1.0
minPosZ = -1.0
maxPosZ = 1.0
velScale= 1.0
minVelX = -0.1
maxVelX = 0.1
minVelY = -1.0
maxVelY = 0.0
minVelZ = -0.1
maxVelZ = 0.1
radiusScale = 0.1
minRadius = 0.5
maxRadius = 1.5
|
Example:
Hail This example has hard particles
which fall rapidly in a straight line until they
hit the surface, at which point they 'bounce' by
going through a couple extra stages with an
inversion of Y velocity on each bounce.
[texture]
name=00000001.glow.png
rows=1
columns=1
[General]
numEmitters=1
numStages=3
[stage1]
name=falling
stageOnCollision=2
lifeTime = 7.0
gravity = 0.0
startOpacity = 1.0
endOpacity = 1.0
[stage2]
name=firstBounce
stageOnCollision=3
stageOnTimeOut = 0
lifeTime = 3.0
gravity = 1.0
startOpacity = 1.0
endOpacity = 1.0
deltaVelX = 10.0
deltaVelY = -0.8
deltaVelZ = 10.0
[stage3]
name=secondBounce
stageOnCollision=0
stageOnTimeOut = 0
lifeTime = 3.0
gravity = 1.0
startOpacity = 1.0
endOpacity = 0.0
deltaVelX = 1.0
deltaVelY = -0.8
deltaVelZ = 1.0
; this is a
random box emitter, particles start at some
random spot in the box
[emitter0]
name=box
node=camera
stage=1
startRate = 1.0
spawnRate = 200.0
maxParticles = 2000
posScale= 10.0
minPosX = -1.0
maxPosX = 1.0
minPosY = 0.0
maxPosY = 1.0
minPosZ = -1.0
maxPosZ = 1.0
velScale= 1.0
minVelX = -0.1
maxVelX = 0.1
minVelY = -8.0
maxVelY = 0.0
minVelZ = -0.1
maxVelZ = 0.1
radiusScale = 0.03
minRadius = 1.0
maxRadius = 1.0
|
|