Super Awesome Ultimate sprite Rig
by Mike Rhone
This tutorial has been written so that the novice artist can create a working particle rig. It is assumed you are comfortable with the basic concepts of 3d and Maya. Before I made the career move to effects, I was a character rigger. I have found that many of the skills I learned in the rigging department have helped me to make fast, re-useable particle rigs that are easy to animate. This tutorial will prepare you to approach an effects setup like a rigger would. Not only does this make the animation process much simpler, it allows the effects to be done by animators without having to train them in the deeper parts of Maya dynamics.
Set the project
Set up a new project, and name it ‘explosion_rig’. When you are working with particles, it is essential that you set up a project, as your scene will be uploading, downloading and referencing information from/to these folders.
Setting up your preferences to work with particles
When working with particles, you need to set your preferences to ‘play every frame’. Go into Window –> Settings and preferences –> play every frame. This is necessary to have Maya evaluate the particle system correctly. You will no longer be able to playback your scene in ‘real time’, so any timing and animation will have to be done either via a playblast the scene or rendering it out. This is generally good practice anyway.
You should never rely on Maya when it comes to timing out animations. Slow networks and computers can all throw off your frame rate. With that in mind it is also a good idea to turn on ‘frame rate’ in your heads up display. To do this, go into Display –> heads up display –> Frame Rate.
We could start off this rig with a basic omni or directional emitter and work from there, but I prefer to use a half of a polygon sphere to emit our particles from. This gives us exact control of the overall shape of particle emission. For example; it would be difficult to create a ring of smoke with a regular emitter, but a sphere can be easily edited to give us that exact result Using a polygonal object also allows for advanced control over particles via the particleShapes inherit factor.
A large number of sprite effect elements I create all start off with this half polygon sphere. Create a polygonal sphere with divisions U = 16, V = 16. Delete the lower half of the faces on the object. Name this sphere emissionObject. This is a great shape to work with, and the pivot point is in the perfect location for what we will need later.
Dust Puff emission
Now we are going to get Maya to emit particles from the surface of this object. Select emissionObject, go into particles –> emit from object (options). In the dialog box, change the emitter type to ‘surface’. Name the emitter dustEmitter. Name the particle dust.
** NOTE: ‘Scale rate by Object Size’ is a handy feature. It automatically emits more or less particles depending on the scale of the object. I have found this to be a little difficult to control, so I prefer to control rate all by hand. For this lesson leave this feature turned OFF.
Play the scene. You should see the particle being emitted outward from the sphere. The default settings on the emitter are fine for what we need at this point. In the outliner select the particle object dust.
Standard Particle Attributes
In the shapes section of the channel box you will see a ton of attributes in the dustShape attributes list. The ones worth covering are:
Conserve: How much the motion the each particle retains their motion (momentum). This is calculated by Maya on a frame by frame basis. It is similar but is not to be confused with drag. Conserve is a finicky attribute. A conserve of 1 means the particles will maintain momentum infinitely. A conserve of .9 means that the particle will keep 90% of its forward momentum every frame. I usually use values of between .9 – .99.
Inherit factor: How much velocity is transferred to the particle from the emission object. For this to have any effect, the emitter needs to have some animation applied to it.
Start Frame: This is an attribute that many people overlook. It tells Maya what frame to start calculating the particle object. If you only need to see your particle system after frame 200, set the start frame to 200 so Maya knows to ignore the particle until that point. This saves a lot of CPU time. In cases where you have your time slider set to higher than one, this will prevent Maya from calculating run-up before that point. A great time saver.
Max Count: If you need to limit the number of particles, set this number to what you want the max to be, otherwise Maya will just keep emitting particles until you tell it to stop or Maya crashes. ** Note: a value of -1 means infinite number of particles, a value of 0 means 0 particles. Default is -1.
Lifespan Mode: 99 times out of 100 you will want to set this to lifespanPP. This is the same control as is available in the particleShape attribute editor.
Particle attributes and expressions: Creation vs Runtime vs Array mappers
This is the single most important distinction you need to learn before you can work with particle expressions. All perParticle attributes are accessible to runtime or creation expressions.
Creation expression: Calculated on each particles birth frame only. (age = 0). This is where you usually tell maya how long a particles lifespan should be, what its mass is etc.
Runtime expression: Calculated on every frame except the particles birth frame. This is where you input variables that control how a particle fades out over time, how fast a particle spins over its lifetime, what colors it changes over the course of its life etc.
Array Mapper/Ramp: The other option for controlling per particle attributes is to map a ramp to the attribute. Instead of working with confusing math and variables, Maya will allow you to use a ramp that will control anything from a particles color, scale, size etc… This is done through Maya by comparing the particles’ age to the ramp.
**Note: No matter how many lines that you add to an expression, Maya only has one expression for each of: creation, runtime before dynamics, runtime after dynamics. It is for this reason that when you make your first expression you need to create an expression, and then everything added after that is an edit to the main expression.
LifespanPP creation expression
Select dust and open the attribute editor. Change the lifespan mode to lifespanPP. Set Particle render type to sprites. Turn on depth sort.
Lets start off by adding a creation expression for lifespanPP. Right-click on lifespanPP in the per particle Array attributes tab. Choose creation expression, and add this line of code:
dustShape.lifespanPP = rand(1.0,2.0);
This will give each particle a random lifespan of between 1 and 2 seconds. ‘rand’ is one of many operations you can apply in an expression. Note that this is an operation and not a command like in MEL.
What is age? What is ageNormalized? What is LifespanPP?
lifespanPP is the length of time in seconds that a particle will live for.
age is the length of time in seconds that a particle has lived for.
ageNormalized is how long the particle has lived for along its lifespan as a percentage.
The ageNormalized attribute is a good concept to understand. This is the attribute Maya uses to determine where on the PP ramp each particle gets its info from. Maya will compare each particles ageNormailzed to the V value on the ramp, and will return the corresponding RGB value back to the particle system,
**Note: Maya doesn’t give you access to the ageNormalized attribute readily. I “encourage” Maya to allow access to this attribute by connecting a particle attribute to a ramp, then deleting the connection I just made. This forces Maya to create the ageNormalized attribute. It’s a total hack, but it works perfectly.
Adding custom particle attributes
If you take a look at the per particle array attributes, you will see only a few of the attributes listed of the total attributes that we need in our particle system. Click on Add Dynamic Attributes –> general. Click on the particle tab, highlight spriteScaleYPP, spriteScaleXPP and spriteTwistPP. Click on the add button. You should now see all of these attributes added to the list of PP array attributes.
Right click on spriteScaleXPP and choose create ramp. You should now see a line that says arrayMapper1.outValuePP. Right click on this and click edit ramp.
When you map perParticle attribute ramps, the bottom of the ramp is the value outputted for the particles birth, and the top of the ramp is the value at its death. For spriteScaleXPP we are mapping a ramp to control the particles scale. Press play and you will see the sprites are born with a scale of 1, and die at a scale of 0. Not quite what we are looking for. In this dust rig you will want the particles to start small, and grow up and fade out as the particle ages. Set the ramps bottom color to black, and the top color to white.
Rename the ramp to scaleRamp. Click on the output connection button to get to the array mapper. Rename the array mapper to scaleXArrayMap. The array mapper is an extra node that Maya uses to convert the data from the ramp into usable date. The min Value tells Maya what black values in the ramp are to be calculates as, and the Max Value tells maya what the white values are. In English, think of this as a “multiplier” of sorts.
Press play. You will see that the scale is only working on one axis for the scale. We COULD just do the same process we did above to control the spriteScaleYPP, but that would be awkward to have to edit 2 ramps every time you wanted to make an adjustment. Go back into the perParticle array attributes. Right click on spriteScaleYPP and choose create ramp–>Options. Change the “map to” tab to scaleRamp. Hit OK.
Select the dustShape and right click on the arrayMapper.outValuePP–>Edit Array Mapper. Rename the arraymapper to scaleXArrayMap.
Texturing the sprites
Ok, so far things are looking as they should but it is not a very impressive system just yet. Lets apply a texture to the dust. I have supplied you with a single .tif image we will use for the sprite. I prefer .tifs because Maya never seems to have a problem with the image format. Tif’s also have an alpha channel imbedded in the texture, so when you assign the file to the color channel, the alpha get applied automatically.
Create a new lambert texture and name it dustLambert. Assign the dust.tif to the color channel. Select dust and assign the lambert to it. You can now see the particle system with its new image applied. (Make sure you are in ‘textured mode’. (Press 6 on your keyboard).
dust.tif can be downloaded from here
**Special thanks to Miles Van Ypren for creating the dust sprite a few years back.
Working with spriteTwist
Right now all of the sprites look the exact same because, well, they are the exact same. Let’s apply some randomization in the sprite twist. If we were to assign a ramp to spriteTwistPP right now, all of the particles would spin at the same rate, in the same direction. That isn’t’t what we want, so we need to add a few attributes of our own to get things working the way we like.
In the add dynamic attributes of the dustShape, click on general. Click on the New tab. Click on the per particle (array) dialog box, and add an attribute named spriteTwistStart. Click ok. Add another one called spriteTwistRamp, and another one called spriteTwistDirection.
Add this to the creation Expression for dustShape:
spriteTwistStart = rand(360);
This will output a random value between 0 and 360, and we will use that as the starting point for the sprite twist. Note that this has NO effect on the twist of the sprite yet. The only attribute that controls twist is the spriteTwistPP attribute.
Create a ramp for spriteTwistRamp. Name the ramp twistRamp. Set the interpolation to ‘linear’. Rename the arraymapper to twistArrayMap. Set the twistArrayMap’s max value to 180. This will cause each particle to spin twice over the course of its life. (180 degrees from birth to death)
Now tie these 2 attributes together in the spriteTwistPP attribute. Add this line to the creation expression:
spriteTwistPP = spriteTwistStart;
Add this line to the runtime before dynamics expression:
spriteTwistPP = spriteTwistStart + twistArrayMap.outValuePP;
You can see how powerful particle expressions can be now that we have combined the output from a perParticle ramp with a creation attribute. To use the values from a ramp, you need to specify the outValuePP of the arraymapper.
Press play. It ALMOST is what we are looking for, but all of the particles are spinning in the same direction. To have 50% of the particle spin clockwise and the other half spin counterclockwise, add this line to the creation expression:
spriteTwistDirection = rand(-1,1);
Now we need to edit the spriteTwistPP runtime expression. Change it so it reads
dustShape.spriteTwistPP = dustShape.spriteTwistStart + (twistArrayMap.outValuePP * dustShape.spriteTwistDirection);
Now when you press play, we should have ourselves a working dust element. This is a good time to save.
We are moving along pretty well, but we still need to set up the sprites so it fades off as it dies. You should be comfortable adding ramps to the particle system now. Add an opacityPP attribute to the particle system. Assign a ramp to opacityPP. Name the ramp opacityRamp. Name the arraymapper opacityArrayMap.
Fading the particles into and out of existence
A key to a good smoke or dust element is to have the particles quickly fade on in the beginning of its life, and slowly fade off as it dies. Set opacityRamp to look similar to what I have here:
**If you like you can add an RGB particle attribute to the system. (If you do, be sure to stick to the naming convention: rgbRamp and rgbArrayMap)
Rigging the dust system
Whew. By this point you have a sprite rig that can be dropped into a scene and rendered. This is fine, but as far as a rig goes, its very un-intuitive. If you want to scale the particles up, make then twist a little bit faster and increase the lifespan you have to dig through arrayMappers, Particle expressions, Ramps… Boring and slow. There is no way this system can be handed over to your typical low-IQ animator. What we need to do is set this system up so all of the controls are easy to get to, and don’t take a degree in physics to adjust. This is where some basic rigging knowledge comes into play. When it comes to setting up a character rig, there is such a thing as having too much control. Many rigging TD’s haven’t worked in an animation dept before, so they get tempted to give too much control to a rig. The key is to make sure the ones who will be animating the rig are happy. It’s a good idea to talk to the animators and find out how much control to give them.
For the main controller, use the CV curve tool and draw an icon to represent the explosion rig. Name it control.
Select control, dust, and emissionObject. Group them together and name the group dust_top. Deselect the objects and create an empty group (CTRL + G). This will create a node named null1. parent null1 to dustTop, and rename it to TD_NODE.
Open your outliner to make sure you have the same hierarchy as I have set up here. You can move nodes around and reorganize the outliner by middle-mouse dragging nodes into position.
Setting up the control object
I have separated the controls into 2 different levels. Commonly used ones will be on the control, and the advanced ones will be on the TD_NODE. (Special credit to Dan Weir for suggesting this)
control (Common controls) TD_NODE (Advanced controls)
Before we can start tying the particle attributes to the controls, we need to add these attributes the control and TD_NODE nodes. Select the control and add all of the attributes listed above for control. Now do the same for the TD_NODE and the advanced controls. You can also hide the translate, rotate and scale attributes on both the control and TD_NODE by selecting those attributes in the channel box, right click –> Hide.
**Note: it is extremely important you type these names in exactly as I have written above. Maya is case sensitive. I have named these nodes in the typical MEL format: lowercaseUppercaseUppercase. Maya will automatically display spaces in the channel box to make things easier to read. If you neglect to do this, you will get errors when you edit the particle expressions. This is the area that everyone struggles with in this tutorial, so let me type it in a way you wont forget….
Maya is case-sensitive!
Add these attributes exactly as I have typed above or your rig will not work correctly!
Set these values before we start:
Rate = 200
Speed = 3 conserve = .95
speedRandom = 2 inheritFactor = .3
scaleMin = 0 twistSpeed = 180
scaleMax = 3 lifespanMin = 1
lifespanMax = 2
Making the connections
Lets start tying these items all together. Open the connection editor by going into window–>GeneralEditors–>ConnectionEditor.
Select the control. Now in the channel box click reload left. This sets control ready to drive other objects attributes. Now select dustEmitter. Click reload right. Now we are ready to have control drive attributes on dustEmitter. Click on “rate” in both columns. You will see that the 2 attributes get highlighted and italicized. This shows they are connected.
Using this, connect the following attributes:
control.speed to dustEmitter.speed
control.speedRandom to dustEmitter.speedRandom
control.scaleMin to scaleArrayMap.minValue
control.scaleMax to scaleArrayMap.maxValue
TD_NODE.conserve to dustShape.conserve
TD_NODE.inheritFactor to dustShape.inheritFactor
TD_NODE.twistSpeed to twistArrayMap.maxValue
The final connection we need to make is to tie the lifespan controls to the lifespanPP creation expression. This involves editing our creation expression slightly. Right now our creation expression looks like this:
dustShape.lifespanPP = rand(1.0,2.0);
dustShape.spriteTwistStart = rand(360);
dustShape.spriteTwistPP = dustShape.spriteTwistStart;
dustShape.spriteTwistDirection = rand(-1,1);
Now edit the creation expression to read:
dustShape.lifespanPP = rand(TD_NODE.lifespanMin,TD_NODE.lifespanMax);
dustShape.spriteTwistStart = rand(360);
dustShape.spriteTwistPP = dustShape.spriteTwistStart;
dustShape.spriteTwistDirection = rand(-1,1);
Click edit. Now your lifespanPP expression is controlled by the TD_NODE. Controlling lifespan via a controller is a great advantage because you can actually keyframe lifespan per particle. It’s a much more powerful way to control particle rate/emission, especially in cases like fire.
That is it. Now save your rig somewhere you can access it again. Re-creating rigs is a waste of time, so try and get in the habit of building re-usable systems whenever possible. This exact rig can be modified by changing the emissionSurface, sprite texture, and the attributes to create rain, snow, fire, lasers, mist, fog, smoke…