
  1. Code
  2. Effects

Create 3D Effects With the Stardust Particle Engine


In my previous tutorial Shoot Out Stars with the Stardust Particle Engine, I explained the basic workflow of Stardust. This time, we'll take things further and examine a couple of techniques for creating true 3D particle effects!


We'll begin with a demonstration of how to use the Stardust's native 3D engine. Then, I'll show you how to get Stardust to work with Papervision3D; we'll be creating 3D particle effects with Papervision3D's Particles class and DisplayObject3D class.


We're going to pick up where we left off in the first tutorial. Last time we created star and circle particles shooting out from a point, growing to a maximum size and then shrinking to nothing, while moving gradually slower over time (called a damping effect). This time, we'll do the same thing, but in 3D. Instead of the particles moving out in a circle, they'll move out in a sphere.

Step 1: Create a New Flash Document

Just as before, first create a new Flash document with dimensions of 640x400, a frame rate of 60fps, and a dark background (I used a dark blue gradient).

Step 2: Draw the Particles

Draw a star and a white circle, then convert them to symbols, separately. These are the two symbols we are going to use as particles later. Name the star symbol "Star" and circle symbol "Circle", exported for ActionScript with the same class names.

(If you're not much of an artist, you can download the source at the top of the page and use my symbols from the library of my FLA.)

Step 3: Create the Pause Button

Click Window > Components to bring up the Components Panel, then drag a Button from the User Interface folder onto the stage. Set the label to "Pause" and name it "pause_btn". We are going to use this button to pause the 3D particle effects, thereby allowing users to spin the camera around in order to get a better taste of the 3D environment.

Step 4: Create the Document Class

Create a new document class and name it StarParticles3D.

Not sure how to use a document class? Read this Quick Tip.

3D Initializers and Actions

The three main packages in Stardust are:

  • idv.cjcat.stardust.common: contains general elements for both 2D and 3D particle effects.
  • idv.cjcat.stardust.twoD: contains specific elements for 2D particle effects.
  • idv.cjcat.stardust.threeD: contains specific elements for 3D particle effects.

In the previous tutorial we used initializers and actions from the common and twoD packages. In this tutorial, we'll still be using elements from the common package, but not from the twoD package. Instead, we will use elements from the threeD package.

The class structure of the threeD package is pretty much the same as in the twoD package, except that the elements have an extra dimension. A 3D element possesses the same name as its 2D counterpart, but its name ends with "3D". For example, the Move3D action in the 3D package updates particle positions in 3D space according to the velocities, just like its 2D counterpart in the 2D package, the Move action.

Step 5: Extend the Emitter

Create a new AS file called StarEmitter.as; inside it, create a new class StarEmitter, which extends the Emitter3D class:

Remember the Clock parameter? It's used to control the rate of particle creation. We need to include it in the constructor function, so that we can pass a Clock to it later.

Since we are allowing users to pause the particle effects, we're going to pack all the actions into a single CompositeAction object, which is essentially a group of actions. By deactivating this single composite action, we can "turn off" all the underlying actions. Declare a variable for a composite action in the emitter class. We'll access this variable in the document class, so it needs to be public:

Step 6: Declare the Particle Constants

Declare constants that will be used as particle parameters in the emitter class. We already covered the purpose of these constants in the previous tutorial. Most of the names are self-explanatory. These go inside the class but outside the constructor function. Feel free to come back here later and alter the numbers to see the effects.

Step 7: The Switch Initializer for Particle Display Objects

In the previous tutorial I demonstrated how to use the SwitchInitializer to create particles with different display objects. I was using the DisplayObjectClass initializer, which initializes particle appearance with display Objects. That was for 2D particle effects; here we are going to use its 3D counterpart, the DisplayObject3D initializer.

Add the following code to the emitter's constructor function:

Step 8: Add the Remaining Initializers

Same as the previous tutorial; add the other initializers shown below. Note that some of them have similar names to those in the previous tutorial, but end in "3D".

  • The Position3D initializer initializes particle positions. Just as its 2D counterpart, the Position initializer, it accepts one constructor parameter, a zone object. However, this time it does not accept a Zone object, which represents a 2D zone; instead, it accepts a Zone3D object, representing a zone in 3D space. The SinglePoint3D class extends the Zone3D class and is the 3D version of the SinglePoint class.
  • The same goes for the Velocity3D class. The SphereShell class is essentially the 3D version of the SectorZone class. Here we set the center of the sphere shell to (0, 0, 0), average radius to SPEED_AVG, and radius variation to SPEED_VAR.
  • The Rotation3D and Omega3D initializers work exactly the same as their 2D counterparts, Rotation and Omega. However, there is one little difference about the constructor parameters: they accept three Random objects instead of one. That is because now, in 3D space, there are three axes of rotation, so they require three random rotation values for these axes. In this example we are creating "2D billboards" in 3D space (i.e. flat objects), so only the rotation for the Z axis is apparent; that's why the first two parameters, Random objects for the X and Y axes, are assigned with null values.

This code goes in the StarEmitter's constructor function:

Step 9: Add the Actions

Create a composite action, and add some actions to it. Then add this composite action to the emitter; this will make the particles perform the actions. You've seen these actions in the previous tutorial (some of them in 2D version), so I won't explain them all over again. Again, this code goes in the StarEmitter's constructor function:

Step 10: Back to The Document Class

All right, we're done with the emitter. Now it's time to build our document class.

First, declare constants for the orbiting camera's radius, the camera distance from the origin and the emitter's rate:

(As before, consts go inside the class but outside the constructor function.)

Then, declare variables for an emitter, a steady clock and a DisplayObjectRenderer3D (in the same place as the consts):

In the constructor, initialize the clock, emitter and renderer. Also, set the initial camera's position and direction, making it look at the origin:

Step 11: Program the Pause

Create a handler function in the document class to handle the click event of the pause button:

..then register the listener for the pause button, in the constructor function:

Step 12: The Main Loop

Create a handler for the ENTER_FRAME event. This is our main loop. It updates the camera's position by calling the updateCamera() method (which we will code in a minute) and calls the emitter's step() method, which keeps the particle effects running:

Again, register a listener in the constructor:

Step 13: Update the Camera's Position

Now define the updateCamera() method called in the previous step. This is used to move the camera in 3D space depending on the mouse's position. (If you'd like more information on how it works check out this Wikipedia article.)

The magic numbers used to generate theta and phi are just the result of trial and error; feel free to try your own equations.

Note that I used the StardustMath.clamp() method; this makes sure the phi value is kept between positive and negative half PI.

Milestone: Native Stardust Engine Complete

Okay, we're done! That's all we need to do to get a 3D emitter working with Stardust's native 3D engine. Let's look at the result. You can click the pause button to pause the particle effect, and move the mouse around to orbit the camera:

If you'd like to see the full source code, look in the folder called "01 - Stardust Native 3D Engine" in the Source.

Time for Papervision3D

To switch from Stardust's native 3D engine to Papervision3D is easy. We'll just have to use a different renderer and display object initializer.

(Never used Papervision3D before? Take a look at this beginner's tutorial.)

First we'll use Papervision3D's Particles class. You might not be familiar with this; I'll show you how to use the more common DisplayObject3D class later.

Step 14: Change the Display Object Initializer

Change the following code in the emitter class:

to this:

As you may already know, the MovieParticleMaterial class allows us to use display objects as particles' appearance in Papervision3D. We create a Star and Circle instance to be used as particle material. The PV3DParticle initializer takes the place of the DisplayObjectClass3D initializer; its constructor accepts an array of parameters, which will all be added to a Particles object.

This is all we have to do regarding the emitter. Next we'll modify the document class.

Step 15: Set Up the Papervision3D Environment

The target container for our renderer is no longer a Sprite object. Instead, we are going to create particles in a Particles object. We'll have to switch the renderer's type from DisplayObjectRenderer3D to PV3DParticleRenderer.

Declare the following variables for Papervision3D-related objects:

The code in the document class's constructor is now:

The initPV3D() method sets up the Papervision3D Environment. Here's the code:

Step 16: The New Main Loop

Now Stardust only updates the 3D objects' properties; Papervision3D's render engine is taking over the responsibility of rendering. This is what our new main loop looks like:

Step 17: Updating the Camera

Now that we are using Papervision3D's camera, we'll also have to modify the updateCamera() method:

Milestone: Papervision3D with Particles Completed

Okay, we have successfully switched from Stardust's native 3D engine to Papervision3D. Now let's check out the result. Note the pixelation effect on the particles. That is because Papervision3D first draws vector objects into bitmaps before using them as particle materials.

You can find all the source code for this in the "02 - Papervision3D Particles" folder.

Papervision3D's DisplayObject3D Class

So far, we have been working with "2D billboards" - flat objects, like paper. It's possible to create "real" 3D particle objects, like Papervision3D's DisplayObject3D objects. We're just going to have to use another initializer. Now let's get down to the final part of this tutorial. We will create red and blue cube particles.

Step 18: Change the Display Object Initializer, Again

We're going to change the initializer concerning the particle appearance for the last time.

Before that, declare a LightObject3D variable in the emitter class. We are going to use the FlatShadeMaterial for the DisplayObject3D objects, which require a light source. Also, declare the following constants - we'll use these as parameters for the FlastShadeMaterial, and for determining the cubes' sizes:

Now change the following code in the emitter class:

to this:

The new particle appearance will be initialized as red and blue 3D cubes. The first constructor parameter for the PV3DDisplayObject3DClass initializer is the class we wish to instantiate for the particles (so here, it is the Cube class) and the second parameter is an array of constructor parameters for this Cube class.

Step 19: The Three Axes of Rotation

Previously, because we were working with "2D billboards", only the rotation about the Z axis mattered. Now that we are working with true 3D objects, we need to pass three Random object references to the Rotation3D and Omega3D constructors, one for each axis.

Change the following code in the emitter class:

to this:

Step 20: Modify the Document Class

This time, instead of using a Particles object as our particle container, we're using a DisplayObject3D as the container. Declare a variable for this container in the document class:

Also, we'll need another type of renderer for creating particles in the new container. Change the renderer's type from PV3DParticleRenderer to PV3DDisplayObject3DRenderer. The code in the document class's constructor should now look like this:

Step 21: Modify the initPV3D() Method

In the initPV3D() function, we now need to initialize the container variable and add it to the scene. Add these two lines to the end of that function:

Step 22: Modify the updateCamera() Method

In the updateCamera() method, we wish to make the light follow the camera, so we'll have an illusion that the light always "shoots" out from our eyes. Change the following code:

to this:

Now the light source is always at the same point as the camera.

Milestone: Papervision3D with DisplayObject3D Completed

Yep, we're finally done with this tutorial. No more coding. Let's take a look at our final result, with fancy red and blue 3D cubes!

The source code for this can be found in the "Papervision3D DisplayObject3D" folder.


The workflow for creating 3D particle effects with Stardust is pretty much the same as that for 2D effects. You just choose a different set of initializers, actions, and renderers. Stardust also supports other 3D engines, including ZedBox and ND3D. The usage is almost the same. You'll just have to use a different set of initializers and renderers. You may even extend the Initializer, Action, and Renderer classes to work with whichever 3D engines you like!

Now you've got the basics, why not go back to the consts created in Step 6 and play with them to see the effects?

I hope this tutorial helps you understand Stardust more and makes you more familiar and comfortable with Stardust's workflow. Thanks for reading!

Looking for something to help kick start your next project?