Header Sep
Mobile Java 3D Tips, Tricks & Code
 
Score
Login to rate page

September 2005
Compliments of Redikod:
3D programming tutorial part three: Particle systems and immediate mode rendering

We've now reached part three in the "3D programming for mobile devices using M3G (JSR 184)" series of tutorials from Mikael Baros, Senior Programmer at Redikod. Having outlined some basics in parts one and two, he now guides you through several more advanced M3G programming techniques.

Below you can download the source code and application package zip files for part three, as well as a chance to refresh your memory about the first two installments of the tutorial.

[Back]

Part three: Particle systems and immediate mode rendering

Part one: Quick jump into the world of Mobile Java 3D programming>>

Part two: Light 3D theory and orientation>>

Over to Mikael for part three.


Introduction

Welcome to the third installment of the M3G tutorial! Today I'll go through how to gain total control over the rendering process (immediate rendering) and how to create a very nice particle system. Again, here are some links, in case you get lost: 

First of all, and probably most importantly, the dedicated Mobile Java 3D web section on Sony Ericsson Developer World. Second, if you ever get stuck, go to the Sony Ericsson Mobile Java 3D forum. For everything else, use the Sony Ericsson World Developer web portal, there you will find the answers to your questions and more.

The goal of this tutorial is to show you how to render the same object several times, with different transformations. This is called immediate mode. You'll learn how powerful such a mode is for very many things. Also, this tutorial will be the base of the more advanced tutorials to come, since we'll be almost exclusively using immediate mode for rendering from now on.

Since the code is meant for educational purposes it isn't optimal nor does it cover all the errors that might occur. These are more advanced topics that will be addressed later on.

 

 Mikael Baros, Senior Programmer at Redikod.

What you should know
Before you start reading this, you should have read the first two tutorials to have a somewhat firm grasp of basic M3G functionality.

Retained Mode contra Immediate Mode Rendering
The Retained mode is the mode used when you render an entire world with all the information that a world holds, including cameras and lights. This is a pretty restricted mode, since we almost always want to draw a single model multiple times, with different transformations, without invoking an entire scene graph. So, when we render a single group, node or a submesh in M3G it is called immediate mode rendering. These are the immediate mode methods:

render ( Node  node, Transform  transform)
render ( VertexBuffer  vertices, IndexBuffer  triangles, Appearance  appearance, Transform  transform)
render ( VertexBuffer  vertices, IndexBuffer  triangles, Appearance  appearance, Transform  transform, int scope)

As you can see, all three of the methods require some kind of vertex data: Node and VertexBuffer/IndexBuffer. A node can basically be any part of a scene graph, even a world is considered a Node. Usually you'll pass a Mesh or a Group to the first render method. The VertexBuffer, which we talked about in the second tutorial, is a gathering of mesh data that describes a model in 3D space. The last two methods also require Appearance classes to understand how to display the mesh data. In this tutorial we'll only use the first method, to show you how immediate mode works.

Another thing that all methods have in common is that they all need a Transform class that describes the model's transformation from local to world space. Remember, we talked about this in the last tutorial. Also, a thing to remember is that most objects you want to render are Transformables. Meaning they have their own internal transformation matrix. However, the immediate mode rendering ignores all such transformation information and uses only the Transform matrix supplied to the method. This is actually very handy, as you can hold one Mesh of a spaceship in memory, but render it many times with different Transform matrices to display many different spaceships. You'll see this in action as we start to design the particle engine.

Is that all?
The "problem" with immediate mode rendering is that you need to take care of more things before rendering, because you don't have the comfort of a handy World class that stores all camera, background and lighting information. So what you need to control manually now is the clearing of the viewport buffer with a Background object, the lighting of your scene and the camera.

Background
To render in immediate mode, we have to clear the viewport manually, thus preparing for the next drawing cycle. This can be done either before, or after a rendering loop, but it needs to be done after you've bound the Graphics3D object and before you've released it. M3G uses a Background class to help you with this. The Background class holds a lot of nifty information such as what background color to clear the screen with and what image to draw as a background. It is also very useful, for you can use a large image as a background, but only show bits and parts of it as you move around. For instance, you could have a large PNG of your horizon, and then as the player moves in the game world, you can move your Background's crop area to display other parts of the horizon. Beware however, using large PNGs is not only very slow, but also very memory inefficient. The most important methods of the Background class are the following:

setColor (int ARGB)
setCrop (int cropX, int cropY, int width, int height)
setImageMode (int modeX, int modeY)
setImage ( Image2D  image)
 
Let's look at them one by one. The first method is the easiest and most used. It sets the color of the background (the color that the screen will be cleared with) in 0xAARRGGBB format. So for instance a bright red background would be 0xFFFF0000. Most people set this to either black, or to the color of the sky. Default color, however, is white.
 
The setCrop method is very useful if you are using a background image to display as a background. With this method, you can decide what part of the entire background image will be rendered. There are some special cases to think about here, like when the crop rectangle is outside the bounds of the background image. This is where the third method comes in. It determines what happens to the pixels that are "outside" of the source image. There are two valid modes; REPEAT and BORDER. REPEAT means that the picture repeats itself indefinitely, like a tiled texture, while BORDER means that pixels outside of the source image are painted with the background color supplied in the setColor method. One nifty thing is that you can determine the behavior of the image mode for the x and y-axes separately. This means that you could have a background image wrap around the x-axis (horizontally) but be static on the y-axis (vertically).
 
The last method, setImage is the one that determines which image will be used as a background. You can supply null to this method to turn off background image rendering and just have the screen fill up with the background color. This is the default mode. Note though, that the image is required to be an Image2D, and not the standard Java ME Platform Image. It's not hard to create an Image2D from an Image though, you can either use the very useful Loader class to point it directly onto a .PNG image, or just use the Image2D constructor that looks like this:
 
Image2D (int format, java.lang.Object image) 
 
It's a very simple constructor that first takes the format of the image (which is in 99% of the cases an Image2D.RGBA or Image2D. RGB depending on if you use transparency or not) and then the Image itself. The second parameter should be your Image class. So this is how you would convert a normal Java ME Platform Image to an Image2D: 

Image img = Image.createImage("/myimage.png");
Image2D img2d = new Image2D(Image2D.RGBA, img);
 
Easy as pie! So the Image2D isn't anything intimidating, just an Image wrapper that is used by the M3G system.
 
Now you might be wondering how you would clear the background by using the Background class before you start rendering anything. It's very easy and here's first a code snippet that shows you how:
 
// The background
Background back = null;

// Initializes our background
public void initBackground()
{
    back = new Background();
    back.setColor(0);

}
 
public void draw(Grahics g)
{
    // Here you bind your Graphics3D object
    //...

    // Now simply clear the screen
    g3d.clear(back);
}
 
See how easy that was? That is the first thing you need to control by yourself when using the immediate mode rendering and now we're one step closer to our goal: the particle engine.
 
Lighting
Another thing you need to control manually is the lighting. You need to create lights and position them in 3D space with Transform matrices. This is all done inside the Graphics3D class with the following methods:
 
addLight ( Light  light, Transform  transform)
setLight (int index, Light  light, Transform  transform)
resetLights ()
 
They are pretty self-explanatory but I'll go over them quickly. You should already know how to create a Light in M3G as we've done it in the past two tutorials. The first method simply adds a light to the internal array of lights that are to be rendered. You add a light by supplying an actual Light class and its Transform. This Transform matrix determines where the Light will be rendered. The addLight method also returns the index of the current light, which is neccessary to know in order to change the Light later on, via the setLight method that actually requires a specific index. It needs the index of the light to change and the new Light and Transform. By calling setLight with null as Light, you will actually remove that light from the array. The last method is a simple purge method that removes all lights associated with this Graphics3D-object.
 
Camera
You also need to create your own camera, instead of just using the one supplied in the World class, as we've done before. In this tutorial, we'll only create a Camera by calling its default constructor. In later parts of the tutorial we'll go through the more advanced things you can do with a Camera such as changing the projection matrix. I won't talk more about this topic right now, instead I'll just show you a code snippet on how this can be done:
 
Camera cam = new Camera();
Graphics3D g3d = Graphics3D.getInstance();
g3d.setCamera(cam, getCameraTransform());
 
Setting a camera is very similar to setting a light, since you add your Camera, and the Transform matrix that transforms the camera to a point in 3D space. Again! Be careful, since when you add the camera in this fashion, the internal node transformations of the Camera class will be ignored. Only the transformations in the Transform matrix supplied in the setCamera method are used.

Setting the stage
Now you know of the three things that we need to control manually and you're ready to render something in immediate mode. Before I show you any code, let's recap the steps needed:
  1. We need to add lights to our Graphics3D object, which is usually done when the scene is being initialized.
  2. We need to add the camera to the Graphics3D object. You can choose to do this once, or every game loop, depending on how you handle the Camera's Transform matrix.
  3. We need to clear the background so we can render onto a freshly painted canvas.
  4. We just render our meshes and release.
Let's see what this can look like in code:
 
// Get the Graphics3D context
 g3d = Graphics3D.getInstance();
 
 // First bind the graphics object. We use our pre-defined rendering hints.
 g3d.bindTarget(g, true, RENDERING_HINTS);
 
 // Clear background
 g3d.clear(back);
 
 // Bind camera at fixed position in origo
 g3d.setCamera(cam, identity);
 
 // Render some mesh
 g3d.render(someMesh, someMeshTransform);
 
It's a bit more complex than rendering a World, which was done with a single method call (g3d.render(world);) but in immediate mode you gain so much more control over the rendering process. Now, let's see how we can use immediate mode to actually do something useful! A particle system!

Particle Systems
A 3D-particle system usually consists of a data structure that represents a particle and its physical qualities (velocity, life and position) and of a system that handles the emittance of particles. This is a very simple model as you can make a particle system as complex as you wish. So, let's first create our Particle class. To represent a Particle in 3D space we'll probably need its position in 3D space, consisting of an x, y and z coordinate. We also need its velocity, since we want the Particle to move around in the 3D world. We could also need the color of a particle, so that we can make different particles different colors. Finally, we'll also need the life of a particle. The life of a particle is how long it stays in the 3D universe before it is either discarded, or re-animated at a new position with new velocities and colors. Here is a Particle class that'll cover our basic needs:
 
/**
 * Holds all the information of a particle.
 * A particle's alpha is controlled directly by its life. Its alpha is always
 * life * 255.
 */
public class Particle
{
    // The life of the particle. Goes from 1.0f to 0.0f
    private float life = 1.0f;
   
    // The degradation of the particle
    private float degradation = 0.1f;
   
    // The velocities of the particle
    private float[] vel = {0.0f, 0.0f, 0.0f};
   
    // The position of the particle
    private float[] pos = {0.0f, 0.0f, 0.0f};
   
    // The color of the particle (RGB format 0xRRGGBB)
    private int color = 0xffffff;
   
    /** Empty initialization */
    public Particle()
    {
       
    }
   
    /**
     * Initializes the particle
     * @param velocity Sets the velocity
     * @param position Sets the position
     * @param color Sets the color (no alpha)
     */
    public Particle(float[] velocity, float[] position, int color)
    {
        setVel(velocity);
        setPos(position);
        this.setColor(color);
    }
 /**
   * @param life The life to set.
   */
   void setLife(float life) {
   this.life = life;
   }
 /**
   * @return Returns the life.
   */
   float getLife() {
   return life;
   }
 /**
   * @param vel The vel to set.
   */
   void setVel(float[] tvel) {
   System.arraycopy(tvel, 0, vel, 0, vel.length);
   }
 /**
   * @return Returns the vel.
   */
   float[] getVel() {
   return vel;
   }
 /**
   * @param pos The pos to set.
   */
   void setPos(float[] tpos) {
   System.arraycopy(tpos, 0, pos, 0, pos.length);
   }
 /**
   * @return Returns the pos.
   */
   float[] getPos() {
   return pos;
   }
 /**
   * @param color The color to set.
   */
   void setColor(int color) {
   this.color = color;
   }
 /**
   * @return Returns the color.
   */
   int getColor() {
   return color;
   }
 /**
   * @param degradation The degradation to set.
   */
   public void setDegradation(float degradation) {
   this.degradation = degradation;
   }
 /**
   * @return Returns the degradation.
   */
   public float getDegradation() {
   return degradation;
   }
   }
 
Since we want our particle system to be somewhat advanced, we'll also fade the particles to nothing as their life diminishes. This is also a very nice effect and I'll explain how we do it in M3G later. For now, let's look at the next part of the Particle system, the ParticleEffect. The ParticleEffect interface defines a common interface for all ParticleEffects. The init method is called on a Particle when it is brought to life, and the update method is then called periodically each game loop to update the particle's parameters. Finally the render method is used for rendering a Particle and is done after the update method.

import javax.microedition.m3g.Graphics3D;
/**
   * The interface that determines which effect the particle engine will display.
   * The ParticleEffect class also holds information about the bitmap used
   * for displaying particles (if any)
   */
   public interface ParticleEffect
   {
   // Initializes a particle
   public void init(Particle p);
  
   // Updates a particle
   public void update(Particle p);
  
   // Renders a particle
   public void render(Particle p, Graphics3D g3d);
   }

Now, finally we'll need a ParticleSystem, that actually creates Particles, emits them and applies a ParticleEffect onto them. Here is how I've chosen to write the class:
 
import javax.microedition.m3g.Graphics3D;      
/**
   * Manages emission of particles in our 3D world
   */
   public class ParticleSystem
   {
   // The effect
   private ParticleEffect effect = null;
  
   // The particles
   Particle[] parts = null;
  
   /**
   * Creates a particle system that emits particles according to a defined effect.
   * @param effect The effect that controls the behaviour of the particles
   * @param numParticles The number of particles to emit
   */
   public ParticleSystem(ParticleEffect effect, int numParticles)
   {
   // Copy the effect
   setEffect(effect);
  
   // Init the particles
   parts = new Particle[numParticles];
   for(int i = 0; i < numParticles; i++)
   {
   parts[i] = new Particle();
   effect.init(parts[i]);
   }
   }
  
   /** The method that does it all. Needs to be called every tick of a game loop */
   public void emit(Graphics3D g3d)
   {
   for(int i = 0; i < parts.length; i++)
   {
   getEffect().update(parts[i]);
   getEffect().render(parts[i], g3d);
   }
   }
 /**
   * @param effect The effect to set.
   */
   public void setEffect(ParticleEffect effect) {
   this.effect = effect;
   }
 /**
   * @return Returns the effect.
   */
   public ParticleEffect getEffect() {
   return effect;
   }
   }
 
As you can see, it's a pretty simple class that just creates a defined number of particles, runs them through the effect's init method and then keeps running them through the update method when its own emit method is invoked. It's a pretty simple but powerful particle system, since it allows us to do something like the following:
 
// We create a ParticleEffect class that we wrote
ParticleEffect pFx = createParticleEffect();

// Now we create a ParticleSystem with 20 particles
ParticleSystem pSys = new ParticleSystem(pFx, 20);

// Somewhere inside our game loop...
pSys.emit(g3d);
 
See how clean and simple it is? Those three lines initialize and use our new Particle System. Now, before I show you the actual rendering and updating of the particle system, let's look at another topic.
 
Creating Meshes in Code
To represent a particle in 3D space the best thing would be to use a Mesh that consists of a simple textured Quad. A Quad, as you might remember, is actually two triangles arranged so that they represent a square. Now, instead of creating a Mesh in 3D studio and exporting it as M3G and loading it into our program, it's much easier and faster to create the Mesh in code. If you remember the last tutorial, a model consists of faces, that themselves are composed of 3D-points, or vertrices. So to create a Quad, we'll need four points, one for each corner. In M3G a model is described by the Mesh class, which holds all kinds of information such as vertrices, texture coordinates, faces, polygon rendering modes, etc. We'll be creating a Mesh class from code. To be created, the Mesh class needs three things to display a model: a VertexBuffer, an IndexBuffer and an Appearance. Let's see how we'll create all of them in order.

The VertexBuffer
This class is a very handy one. It holds a lot of information about a model, including vertrices, texture coordinates, normals and colors. For our very simple model, we'll need vertrices and texture coordinates. We won't be using normals or colors this time since we don't need them. Now, the VertexBuffer stores vertex and texture information in a class called the VertexArray. The VertexArray is a pretty simple class that internally stores values in an array. When you create it you define how many elements each of your points has and how many bytes each element will occupy. Now you might be wondering, why do I choose the number of elements? Aren't 3D-coordinates always a triple of coordinates; x, y and z? Well, you are right of course, 3D-coordinates are always placed along three axes and do have three elements. However, there are other coordinates that are interesting as well, such as texture coordinates. In this example we will use a simple texture coordinate model that only uses pairs of coordinates. Now, before we actually start creating our VertexArrays, let's look at the coordinates. Here are the vertrices of our model (a simple limited plane with four corners). 
 
// The vertrices of the plane
 short vertrices[] = new short[] {-1, -1, 0,
 1, -1, 0,
 1, 1, 0,
 -1, 1, 0};
 
As you can see, our plane is set with corners on the x and y-planes. Nothing really hard here, basic 3D coordinates. Before I show you the texture coordinates though, I'll have to tell you how the texture coordinates work in M3G. A texture is mapped onto a polygon by giving two coordinates. This is a bit of a complicated topic that we'll address in later parts of the tutorial but I'd like to tell you a bit about it already. Imagine that you have a cookie cutter and want to make cookies from an image. The texture coordinates actually tell you the size of your cookie cutter, meaning you use the texture coordinates to tell the M3G system which part of the texture you want mapped. You can even transform texture coordinates, to rotate your cookie cutter if you want. We won't be doing that today though. So the corners of a texture are then (0, 0), (0, 255), (255, 0) and (255, 255) and these coordinates tell the 3D engine that we want to use the entire texture on our polygon. Knowing this and knowing that we will use the entire texture, we can create the very simple texture coordinates.
 
// Texture coords of the plane
 short texCoords[] = new short[] {0, 255,
 255, 255,
 255, 0,
 0, 0};
 
All right, that wasn't so hard, was it? Now all we need to do is stuff our vertrices and texture coordinates into VertexArray classes and stuff them into a VertexBuffer. Then we're halfway there! Let's see how we do that in code:
 
// Create the model's vertrices
 vertexArray = new VertexArray(vertrices.length/3, 3, 2);
 vertexArray.set(0, vertrices.length/3, vertrices);
 
Let me now explain what we are doing here. First of all, we're creating a VertexArray. The constructor of a VertexArray takes three things; the number of vertrices (or points if you wish) that the Array will hold, the number of elements each vertex has (2, 3 or 4 is allowed) and the component size, which tells the array how many bytes it will use for storing each component of a vertex. The difference here is that if you supply it a value of 2 (2 bytes per component) it will use short integers to store components and if you supply a value of 1 (1 byte per component) it will use bytes to store them. So, let's see what we are doing: first we supply the number of the vertrices, which is of course our raw vertex array's length divided by three (remember, vertrices have three components). Next, we supply the number of components, which is 3 for vertex coordinates and lastly, we supply the number of bytes. We use two bytes here to store each component. Remember that using more bytes also consumes twice the amount of memory, so try using single-byte vertrices where ever you can. Now when our VertexArray is created, we can set the values into it. The set method is really simple and needs three arguments. The first one is the starting index to place vertrices on. This is of course 0, since we haven't placed any vertrices into the array yet. The second argument is the number of vertrices to copy in, which is again the length of our array divided by three. The third argument is the actual array to copy values from. See, simple! The same goes for creating a VertexArray that holds texture coordinates. Here's the code for it, so why don't you think about what's different here from the above example and think about why. Remember what I said about texture coordinates.
 
// Create the model's texture coords
 texArray = new VertexArray(texCoords.length / 2, 2, 2);
 texArray.set(0, texCoords.length / 2, texCoords);
 
All right, we're done with creating space coordinates and texture coordinates for our model and now we have to define what faces the model consists out of. Remember faces from the second tutorial? Well, we have to create the triangles that our plane will consist of.
 
The IndexBuffer
The M3G system stores face (triangle) information in a class called the IndexBuffer. We talked about such a class in the second part of the tutorial so you should know what it does, but I will refresh your memory anyway. The IndexBuffer holds indices in the array of vertrices and describes the faces (triangles) that compose our model. Since our model is a simple plane (a quad) it consists of two triangles. Since the IndexBuffer class is an abstract class, we need to use a class that extends the IndexBuffer. This class is the TriangleStripArray. As you can tell by its name, it stores triangles in an array, nifty eh? Now, there are two ways to describe triangles in a TriangleStripArray: explicit and implicit. The explicit description is the most common one, since you get to define the vertex coordinates that the triangles consist of. However, the implicit form can also be very useful. The difference is that in explicit form you need to supply an array that holds all the triangle coordinates, while in the implicit form you just supply the first vertex of the first triangle and the TriangleStripArray calculates the rest, assuming that each next vertex is one greater than the previous.
 

In this example we will use the explicit form for simplicity's sake. The TriangleStripArray demands that triangles in an array are defined in a special way, which is that you only define three indices for the first triangle, and then only define one more for each triangle to come. This is what's generally called a triangle strip. How does this work, you might wonder? Well as you know, stacking triangles next to each other in a model (such as our simple plane) results in the fact that all triangles share two points with another triangle (remember our cube from tutorial 2?). So this means that we can actually define a triangle by using two points from the previous triangle, and one extra point. You probably remember from our plane coordinates that we created our plane counter-clockwise starting from the point (-1, -1, 0). So these are the triangles we want to create:

As you see, we cut the mesh in two from point 3 to point 1, leaving us two triangles. These triangles are the (0, 1, 3) and the (1, 3, 2). Can you already see the pattern? The first triangle actually shares points 1 and 3 with the second triangle, so we can describe them like this: (0, 1, 3, 2) and the TriangleStripArray will understand that we have two triangles that share the middle indices. Let's see how we will do this in code.

 
 
// Create indices and face lengths
int indices[] = new int[] {0, 1, 3, 2};
int[] stripLengths = new int[] {4};
       
// Create the model's triangles
triangles = new TriangleStripArray(indices, stripLengths);
 
So the index array is exactly what we talked about, it holds our triangles. The stripLengths array is something I haven't mentioned yet but it's fairly simple. It just defines the length (in indices) of a strip. Since we define two triangles, our length in indices will be four. This is a useful variable for defining multiple-length strips in a single TriangleStripArray but we won't worry about it today. It will be a topic in later tutorials. Just know that today it's four. So, having all this we can create the TriangleStripArray easily by using the explicit mode constructor, which takes an array (the array of triangles) and the stripLengths array. Very easy!
 
All that is left for us to do now, is to create the Appearance class, which basically tells the M3G system how to render the faces contained within the VertexBuffer and IndexBuffer classes.

 
Appearance
The Appearance class is a great class that holds a lot of information on how to render the model. Alpha blending, textures, culling, you name it. We will need one of these if we are to create our model. Today we'll only use a few of the functions. First let's start with culling. Culling is a technique used to speed up rendering by telling the system that it shouldn't render certain parts of a model, such as its back or its front. For a particle engine for instance, we really never want to see the back of a particle so we can always use back culling on our particles. The available culling methods are these:
 
PolygonMode.CULL_BACK
PolygonMode.CULL_FRONT
PolygonMode.CULL_NONE
 
The CULL_BACK defines back culling, meaning that the back of the polygon will never be drawn. The cull front does the same, but for the front of the polygon. The last one disables culling altogether. The culling settings are available in a class called the PolygonMode which is a component of the Appearance class. So in order to set culling to anything, using a variable called cullFlags we can do the following:
 
Appearance appearance = new Appearance();
 PolygonMode pm = new PolygonMode();
 pm.setCulling(cullFlags);
 appearance.setPolygonMode(pm);
 
Wasn't that really, really easy? Yeah, it was. Now we have defined a culling form (usually it's CULL_BACK). Next thing on the agenda is creating a texture and setting it into the Appearance class (remember, Appearance also stores texture information). This is done in a very simple manner by creating an Image2D that holds the image. We've already talked about how to do this earlier in this tutorial, so I won't cover it again. However, the Image2D is stored in a class called Texture2D and that's the class I will be explaining.

 
Textures
In order to create a texture that a model can use, you need two things; a Image2D containing the picture data and a Texture2D class. The Texture2D class holds all relevant texture information, including image data and texture transformation that transforms our cookie cutter, remember? It even holds other useful things such as blending (alpha blending), wrapping (if the texture wraps across the polygon) and filtering (the quality of the texture projection). We will be using all of the above today, but the blending will be explained a bit later. Let's start step by step. First we create a Image2D and the corresponding Texture2D object:
 
// Open image
 Image texImage = Image.createImage(texFilename);
 Texture2D theTexture = new Texture2D(new Image2D(Image2D.RGBA, texImage));
 
That was fairly simple and it really needs no explanation. You create the Image2D and just hand it to the Texture2D's constructor. Now let's talk about blending.
You can blend surfaces with the color of your polygon (yes, models can have colors) in many different ways. I won't go into detail of all the different blending methods, instead I'll ask you to check out the M3G API documentation and the documentation of the Texture2D class. Just know that there are various ways to blend your texture, according to alpha and color, with the underlying color of the model itself. For no blending at all, we'd do the following:
 
// Replace the mesh's original colors (no blending)
 theTexture.setBlending(Texture2D.FUNC_REPLACE);
 
The above piece of code actually tells the system to ignore all underlying colors of the model and is very useful for many things, since it makes the transparent parts of the texture image transparent on the model as well! Nice, isn't it? You won't be able to alpha-blend the texture with the model this way though. We will blend textures later on in this tutorial, but for now I want you to know about the above method.
 
The last two things we will do are the wrapping and filtering. These are fairly simple procedures and I won't go into detail. Again, if you want to see what different kinds of filtering and wrapping that's available to you, check the M3G API documentation. Here, we use no wrapping, meaning that the texture is drawn only once onto the polygon, and we use the simplest filtering which produces the lowest quality but also the highest speed. Remember, devices that implement M3G are still far away from today's graphic card performance on consoles and PC, so we have to exchange quality for speed most of the time.
 
// Set wrapping and filtering
 theTexture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
 theTexture.setFiltering(Texture2D.FILTER_BASE_LEVEL, Texture2D.FILTER_NEAREST);
 
Now all that's left is to actually add the texture to the Appearance. Yes, I said add and not set. This is because a model can actually have multiple textures! This is a very nice technique for many things like animation, lightmapping, etc. They are however advanced tutorials and we won't be covering them today. Instead I'll go into detail on those subjects in a later part of the series. To add a texture, you simply use the setTexture method (yes, dumb name) and supply an index and a Texture2D. So to add only one texture, you do this:
 
// Add texture to the appearance
 appearance.setTexture(0, theTexture);
 
All right, we're all done now! We have created our appearance and all other things vital to a Mesh. All that's left now is to actually compose the Mesh from the parts we've just created.

 
The Mesh
Creating a Mesh is very simple. All we need to do is supply the parts we just created and compose it. This is done with a single line of code, like this:
 
// Finally create the Mesh
 Mesh mesh = new Mesh(vertexBuffer, triangles, appearance);
 
That's it! Now we have a textured plane that we can render into our scene.

 
The first impression of the above method to create a Mesh might strike you as very complicated, but it actually isn't. Just use it a few times and you'll realize that it's actually very easy and fast, but also very intuitive. Now we can render our Mesh using immediate mode rendering, which I've already talked about, and supply a Transform matrix to place it somewhere in 3D-space.
Before we start coding away on a ParticleEffect class that will do something cool, let's first talk a bit about alpha blending of textures and polygons.
 
Alpha Blending
Often you want to blend a model and its texture to its surroundings, creating semi-transparent models. This can be used for many different things, such as windows, water surface, particle engines, etc. The list is actually endless and only your imagination sets the limits. In M3G this process is very simple and today I will show you how to do it in our particle engine. We want our particles to fade away and become more and more transparent as they progress in their life and completely disappear when they die, so we will need alpha blending for this. This is done in two steps.
 
The first step of setting alpha blending to a Mesh is actually telling it how much it should fade, by giving it an alpha value AND a color of the model. This is done in the Mesh's VertexBuffer class, remember that? It's a method called setDefaultColor and is used for flat-coloring (meaning giving the entire model the same color). M3G also supports per-vertex colors and smooth color shading, which means you can give different parts of the model different colors, but we won't be doing that today. Instead, we just want to supply a single color with an alpha value to the entire model and blend it with its surroundings. To do this we just supply a color in 0xAARRGGBB format to the setDefaultColor method.
 
mesh.getVertexBuffer().setDefaultColor(0x80FF0000);
 
The above line of code will take the Mesh mesh and make it semi transparent (an alpha value of 0x80, or 128 which is half-transparent) with the color bright red (0xFF or 255 red). If the Mesh didn't have a texture, it would now be a bright red model that is semi-transparent. However, we also want to blend our texture into the model. Why? Well, if we blend our texture as well, we can actually change the color of the texture to anything we want, without using multiple textures. For a particle engine this is very useful since we use a single texture and just blend it with the Mesh's default color to get particles of all different colors. Nifty, isn't it? So, to blend a texture we have to go back to the Appearance class and one of its attributes, the CompositingMode.

The CompositingMode tells the Appearance class exactly how to composit (or blend) the model with its surroundings. There are a number of ways to blend a model with its surroundings and all produce a bit different results. We will be using the most common and simplest method, ALPHA blending. This is how you would set the CompositingMode to ALPHA blending and add it to a Mesh's Appearance. 
 
CompositingMode cm = new CompositingMode();
 cm.setBlending(CompositingMode.ALPHA);
 m.getAppearance(0).setCompositingMode(cm);
 
See how easy that was? If you want to know about the other blending modes (ALPHA_ADD, MODULATE, MODULATE_X2 and REPLACE) check the M3G API documentation of the CompositingMode class.
 
We're almost done setting up our blending. All that's left is to modify the texture. Remember when we created the texture and set it to blend with FUNC_REPLACE that completely ignored the underlying Mesh's color and transparency? Well, we can't use that to blend our texture to our Mesh, so it has to be changed. There are three ways to blend a texture to the underlying model and they are FUNC_REPLACE (which we've already seen), FUNC_BLEND (that actually blends), FUNC_DECAL and FUNC_MODULATE which are special modes you'll have to read about in the API documentation or wait for a later part of this tutorial series. Today we'll be using FUNC_BLEND. It will simply blend our texture (and the texture's alpha values) with the model's color and alpha value. To do this, we need to retrieve a mesh's texture (or textures if we have many) and set the correct blending. To fetch the first texture of a model (which we will do today) we do like this:
 
m.getAppearance(0).getTexture(0).setBlending(textureBlending);
 
See, it's that easy! Now we've set up blending for our model and can display it in a variety of colors and transparency. Before we do anything though, let's talk about the kind of texture image we need for blending.
 
Blending Image
To blend a texture image with the underlying model, you can't use any kind of texture. Well, actually you can but you won't get the desired results. For instance; if the texture is fully white, it won't be able to be blended with the texture, since we use an algorithm that adds the color of the model and the color of the texture. This is a problem for white textures since white is the highest color (255) and no matter how much you add to it, you won't be able to produce anything but white. For best blending and complete color control with the Mesh's default color, use a completely black texture. This way you can set whatever color you want to the Mesh's default color, and the texture will be of the same color as well.
 

Here is a picture of the texture we'll use in the game. As you can see, it's completely black and blurs out to create a nice and smooth effect. You don't have to use black if you don't want to, but just remember that the color of the texture is always blended with the color of the Mesh, so you might get a completely different color out, than you had in mind.

 
Controlling the Alpha
Now, to actually control the alpha (transparency) of the model and texture, you just manipulate the Mesh's default color (which is in the Mesh's VertexBuffer, remember?). The lower the Alpha value is in the default color, the more transparent the Mesh will be. To construct a color with a specific alpha value, you could do this:
 
int color = (alpha << 24) | (red << 16) | (green << 8) | blue;
 
The above piece of code will combine an alpha component with a red, green and blue color and create the type of color that the VertexBuffer expects in its setDefaultColor method. So by changing the alpha variable, you also change the transparency. You'll see a practical example of this later on.

 
Finishing the Particle System
Now that we can actually create Meshes from code, let's create a utility function that will do it for us. First let's make something that'll make any Mesh blendable. It could look something like this:
 
/** Sets the alpha blending of a mesh. Only meaningful if the mesh already is alpha blended */
 public static void setMeshAlpha(Mesh m, int alpha)
 {
 m.getVertexBuffer().setDefaultColor(alpha);
 }
 
 /**
 *
 * @param m The mesh to convert to a blended one
 * @param alpha The alpha color to blend with
 * @param textureBlending The texture blending parameter.
 */
 public static void convertToBlended(Mesh m, int alpha, int textureBlending)
 {
 // Set the alpha
 setMeshAlpha(m, alpha);
 
 // Fix the compositing mode
 CompositingMode cm = new CompositingMode();
 cm.setBlending(CompositingMode.ALPHA);
 m.getAppearance(0).setCompositingMode(cm);
 m.getAppearance(0).getTexture(0).setBlending(textureBlending);
 }
 
Those two methods can convert any Mesh to be blendable with the rest of our scene. That's always nice to have. Now let's get a method that actually does the whole creating process:
 
/**
 * Creates a textured plane.
 * @param texFilename The name of the texture image file
 * @param cullFlags The flags for culling. See PolygonMode.
 * @return The finished textured mesh
 */
 public static Mesh createPlane(String texFilename, int cullFlags)
 {
 // The vertrices of the plane
 short vertrices[] = new short[] {-1, -1, 0,
 1, -1, 0,
 1, 1, 0,
 -1, 1, 0};
 // Texture coords of the plane
   short texCoords[] = new short[] {0, 255,
   255, 255,
   255, 0,
   0, 0};
 
   // The classes
   VertexArray vertexArray, texArray;
   IndexBuffer triangles;
 // Create the model's vertrices
   vertexArray = new VertexArray(vertrices.length/3, 3, 2);
   vertexArray.set(0, vertrices.length/3, vertrices);
  
   // Create the model's texture coords
   texArray = new VertexArray(texCoords.length / 2, 2, 2);
   texArray.set(0, texCoords.length / 2, texCoords);
  
   // Compose a VertexBuffer out of the previous vertrices and texture coordinates
   VertexBuffer vertexBuffer = new VertexBuffer();
   vertexBuffer.setPositions(vertexArray, 1.0f, null);
   vertexBuffer.setTexCoords(0, texArray, 1.0f/255.0f, null);
  
   // Create indices and face lengths
   int indices[] = new int[] {0, 1, 3, 2};
   int[] stripLengths = new int[] {4};
  
   // Create the model's triangles
   triangles = new TriangleStripArray(indices, stripLengths);
 // Create the appearance
   Appearance appearance = new Appearance();
   PolygonMode pm = new PolygonMode();
   pm.setCulling(cullFlags);
   appearance.setPolygonMode(pm);
 // Create and set the texture
   try
   {
   // Open image
   Image texImage = Image.createImage(texFilename);
   Texture2D theTexture = new Texture2D(new Image2D(Image2D.RGBA, texImage));
  
   // Replace the mesh's original colors (no blending)
   theTexture.setBlending(Texture2D.FUNC_REPLACE);
  
   // Set wrapping and filtering
   theTexture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
   theTexture.setFiltering(Texture2D.FILTER_BASE_LEVEL, Texture2D.FILTER_NEAREST);
 // Add texture to the appearance
   appearance.setTexture(0, theTexture);
 }
   catch(Exception e)
   {
   // Something went wrong
   System.out.println("Failed to create texture");
   System.out.println(e);
   }
  
   // Finally create the Mesh
   Mesh mesh = new Mesh(vertexBuffer, triangles, appearance);
 // All done
   return mesh;
   }
 
That's a lot of code, but it's not really that hard. Check it out and then backtrack to the part of the tutorial where I explained how to create a Mesh from code, and you'll realize it's simple.
Now that we can create Meshes, we need to create a ParticleEffect class to use with our ParticleSystem and get some kind of effect. I am aiming for a fountain effect that you can rotate around the screen as much as you want. A good exercise after this tutorial would be to create your own ParticleEffect class that does some kind of cool effect. Try creating a circular explosion (like fireworks) or maybe even something as advanced as a flickering flame? Anyhow, first we'll use some nice Object Oriented Programming to abstract behavior that many ParticleEffects will have; using a flat Mesh as a particle. This is how that class will look like:
 
/**
 * Represents a particle effect that uses a bitmap.
 */
 public abstract class BitmapParticleEffect implements ParticleEffect
 {
 // The mesh
 Mesh mesh = null;
 
 // The transformation matrix
 Transform trans = new Transform();
 
 // The scale
 float scale = 1.0f;
 
 /** Initializes the bitmap used to render particles */
 public BitmapParticleEffect(String filename, float scale)
 {
 // Load the plane with the wanted texture
 mesh = MeshFactory.createAlphaPlane(filename, PolygonMode.CULL_BACK, 0xffffffff);
 
 // Make sure we set the scale
 this.scale = scale;
 }
 
 /**
 * @see ParticleEffect#render(Particle, Graphics3D)
 */
 public void render(Particle p, Graphics3D g3d)
 {
 // Calculate the alpha
 int alpha = (int)(255 * p.getLife());
 
 // Create the color
 int color = p.getColor() | (alpha << 24);
 
 // Set alpha
 MeshOperator.setMeshAlpha(mesh, color);
 
 // Transform
 trans.setIdentity();
 trans.postScale(scale, scale, scale);
 float[] pos = p.getPos();
 trans.postTranslate(pos[0], pos[1], pos[2]);
 
 // Render
 g3d.render(mesh, trans);
 }
}
 
As you can see, it is an abstract class that already fixes a lot for us, such as the immediate mode rendering. Check out the render method and see if you recognize what I talked about earlier in this tutorial. As you can see, we also set the alpha of the Mesh in respect to the particle's life. Since each particle already has a color in the format 0xRRGGBB all we do is insert the alpha value and set it as the Mesh's default color. The MeshFactory.createAlphaPlane method that is used in the constructor is very simple. It first calls our createPlane method that I showed earlier, and then uses our utility functions to make the Mesh blendable.
 
The above class does a lot of the work for us so all we need to do now is actually make the particles move around. I chose to create a fountain effect and here is the result:
 
/**
 * Creates a nice fountain effect for the particles, that shoots particles
 * in a certain direction, determined by its angle. The angle can be changed in real-time.
 */
 public class FountainEffect extends BitmapParticleEffect
 {
 // The angle of particle emission
 private int angle = 90;
 
 // The sine and cosine of the current angle
 private float[] trig = {1.0f, 0.0f};
 
 // The emitting origin
 private float[] pos = {0.0f, 0.0f, 0.0f};
 
 // The randomizer
 Random rand = null;
 
 /**
 * @param angle The angle of particle emission
 */
 public FountainEffect(int angle)
 {
 // Init the bitmap
 super("/res/particle.png", 0.05f);
 
 // Set the angle
 setAngle(angle);
 
 // Get randomizer
 rand = new Random();
 }
 /**
   * @see ParticleEffect#init(Particle)
   */
   public void init(Particle p)
   {
   // Set the particle's life
   p.setLife(1.0f);
  
   // Set the particle's position
   p.setPos(pos);
  
   // Create the particle's velocties
   float[] vel = new float[3];
  
   // We want velocities from 0.2f to 1.0f
   float xyvel = rand.nextFloat() * 0.8f + 0.2f;
  
   // We want the particle to die slowly
   p.setDegradation(xyvel / 18);
  
   // Set velocities according to trigonometry with a small deviation
   vel[0] = xyvel * trig[1] + rand.nextFloat() * 0.125f - 0.0625f;
   vel[1] = xyvel * trig[0] + rand.nextFloat() * 0.125f - 0.0625f;
  
   // No movement in depth
   vel[2] = 0.0f;
  
   // Set the velocity
   p.setVel(vel);
  
   // Set the random color
   int r = (int)(120 * rand.nextFloat()) + 135;
   int g = (int)(120 * rand.nextFloat()) + 135;
   int b = (int)(120 * rand.nextFloat()) + 135;
   int col = (r << 16) | (g << 8) | b;
   p.setColor(col);
   }
 /**
   * @see ParticleEffect#update(Particle)
   */
   public void update(Particle p)
   {
   // Simply update position
   float[] ppos = p.getPos();
   float[] vel = p.getVel();
   ppos[0] += vel[0];
   ppos[1] += vel[1];
   ppos[2] += vel[2];
  
   // Update life
   p.setLife(p.getLife() - p.getDegradation());
  
   // Check life. If it is dead, we just reinit it
   if(p.getLife() < -0.001f)
   {
   init(p);
   }
   }
 /**
   * @param angle The angle to set.
   */
   public void setAngle(int angle) {
   this.angle = angle;
   trig[0] = (float)Math.sin(Math.toRadians(angle));
   trig[1] = (float)Math.cos(Math.toRadians(angle));
   }
 /**
   * @return Returns the angle.
   */
   public int getAngle() {
   return angle;
   }
 /**
   * @param pos The pos to set.
   */
   void setEmittingOrigin(float[] pos) {
   this.pos = pos;
   }
 /**
   * @return Returns the pos.
   */
   float[] getEmittingOrigin() {
   return pos;
   }
}
 
I won't go into detail here, since it is really basic trigonometry stuff. You can throw that class out and replace it with a class of your own that does some cool particle effect. All it does is to randomize a particle's velocity depending on the angle of the fountain, and then move it along until it dies. You can change the angle in real-time to be able to rotate the fountain. I've added this to the main game loop and it looks something like this:
 
// Check controls for fountain rotation
 if(key[LEFT])
 fx.setAngle(fx.getAngle() + 5);
 if(key[RIGHT])
 fx.setAngle(fx.getAngle() - 5);
 
The fx object is actually the FountainEffect reference that we change the angle of. As you see pressing left increases the angle counter-clockwise and right decreases the angle clockwise.
 
Setting up the Scene for Immediate Mode rendering
Now that we've done everything, I'll just show you how I've set up the immediate mode rendering. You should already know this since I went through it earlier in this part of the tutorial, so I'll just repeat the info. Here is how we construct the canvas:
 
/** Constructs the canvas
 */
 public M3GCanvas(int fps)
 {
 // We don't want to capture keys normally
 super(true);
 
 // We want a fullscreen canvas
 setFullScreenMode(true);
 
 // Load our camera
 loadCamera();
 
 // Load our background
 loadBackground();
 
 // Set up graphics 3d
 setUp();
 }
 
The loadCamera method creates a camera that our 3D-system will use and is very simple. All it does is creates a default camera. You can see what it does in the code listing below. The loadBackground method creates a background and sets its color to black (0x0). Also very simple. The last method, the setUp finishes the initialization by actually adding an ambient light to our rendering context. It looks like this:
 
/** Prepares the Graphics3D engine for immediate mode rendering by adding a light */
 private void setUp()
 {
 // Get the instance
 g3d = Graphics3D.getInstance();
 
 // Add a light to our scene, so we can see something
 g3d.addLight(createAmbientLight(), identity);
 }
 
 
 /** Creates a simple ambient light */
 private Light createAmbientLight()
 {
 Light l = new Light();
 l.setMode(Light.AMBIENT);
 l.setIntensity(1.0f);
 return l;
 }
 
Nothing new there really. We've created ambient lights many times before and you should know this by heart.
So, now our scene is ready for rendering and all we need to do is emit some particles onscreen. As I already mentioned, this is done by calling the emit method on the ParticleSystem object. We create a ParticleSystem, add a ParticleEffect to it (our FountainEffect) and then we just call emit each iteration of the game loop. This is what I placed into the main game loop:
 
// Envelop all in a try/catch block just in case
 try
 {
 // Get the Graphics3D context
 g3d = Graphics3D.getInstance();
 
 // First bind the graphics object. We use our pre-defined rendering hints.
 g3d.bindTarget(g, true, RENDERING_HINTS);
 
 // Clear background
 g3d.clear(back);
 
 // Bind camera at fixed position in origo
 g3d.setCamera(cam, identity);
 
 // Init particles
 if(ps == null)
 {
 fx = new FountainEffect(90);
 ps = new ParticleSystem(fx, 20);
 }
 
 // Emit the particles
 ps.emit(g3d);
 
 // Check controls for fountain rotation
 if(key[LEFT])
 fx.setAngle(fx.getAngle() + 5);
 if(key[RIGHT])
 fx.setAngle(fx.getAngle() - 5);
 
 // Quit if user presses fire
 if(key[FIRE])
 TutorialMidlet.die();
 }
 catch(Exception e)
 {
 reportException(e);
 }
 finally
 {
 // Always remember to release!
 g3d.releaseTarget();
 }
 
Let's dissect that code now to understand it. First it's pretty basic, we get the instance of the Graphics3D object and bind it to our Graphics object (the above method is the draw(Graphics g) method, so we already have the Graphics object). After this, we clear the background and depth buffer by calling g3d.clear on our Background object. This gives us a clean, black canvas. Now we need to set our camera into the world with its own transform (it's clumsy to do this every iteration of the game loop, but I'm doing it here for clarity). We'll always use the identity transform, since we don't want to move the camera in this tutorial. Next, we check if our particle system still is null, and init it if necessary. We just create a nice fountain effect that starts at the angle of 90 degrees (pointing straight upwards) and a particle system that holds 20 particles. After this is done we call the emit method and the particles will get updated and rendered into our world. When all is done we check for some keys, such as joystick keys for rotation of our nice particle system and the Fire key for exiting the application.

 
There! It wasn't that hard now was it? As I said, to practice you can actually replace the FountainEffect class with something you wrote yourself, to get a personal particle effect. You can also try loading a lot of different Meshes into memory with a lot of different textures, since now you have the methods that do the work for you.
 
Conclusion
So to wrap it all up, here are a few screenshots of the code in action. Pretty, pretty colors! 
 
 
 
There's our particle system! Note how pretty it is when the particles actually fade away, the older they get. I also chose to randomize the colors of the particles from 128 to 255, so that we don't get any dark and moody colors. We just want warm and bright happiness! Here is the code listing. You can even download the full source package including the resources at the bottom of the document. 
 
TutorialMidlet
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class TutorialMidlet extends MIDlet implements CommandListener
{
    // A variable that holds the unique display
 private Display display = null;
 
 // The canvas
 private M3GCanvas canvas = null;
 
 // The MIDlet itself
 private static MIDlet self = null;
 /** Called when the application starts, and when it is resumed.
  * We ignore the resume here and allocate data for our canvas
  * in the startApp method. This is generally very bad practice.
  */
 protected void startApp() throws MIDletStateChangeException
 {
     // Allocate
  display = Display.getDisplay(this);
  canvas = new M3GCanvas(30);
  
  // Add a quit command to the canvas
  // This command won't be seen, as we
  // are running in fullScreen mode
  // but it's always nice to have a quit command
  canvas.addCommand(new Command("Quit", Command.EXIT, 1));
  
  // Set the listener to be the MIDlet
  canvas.setCommandListener(this);
  
  // Start canvas
  canvas.start();
  display.setCurrent(canvas);
  
  // Set the self
  self = this;
 }
 /** Called when the game should pause, such as during a call */
 protected void pauseApp()
 {
  
 }
 /** Called when the application should shut down */
 protected void destroyApp(boolean unconditional) throws MIDletStateChangeException
 {
     // Method that shuts down the entire MIDlet
  notifyDestroyed();
 }
 /** Listens to commands and processes */
    public void commandAction(Command c, Displayable d) {
        // If we get an EXIT command we destroy the application
        if(c.getCommandType() == Command.EXIT)
            notifyDestroyed();
    }
   
    /** Static method that quits our application
     * by using the static field 'self' */
    public static void die()
    {
        self.notifyDestroyed();
    }
}
 
M3GCanvas
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.m3g.Background;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Light;
import javax.microedition.m3g.Transform;
public class M3GCanvas
extends GameCanvas
implements Runnable {
    // Thread-control
    boolean running = false;
    boolean done = true;
   
    // If the game should end
    public static boolean gameOver = false;
   
    // Rendering hints
    public static final int STRONG_RENDERING_HINTS = Graphics3D.ANTIALIAS | Graphics3D.TRUE_COLOR | Graphics3D.DITHER;
    public static final int WEAK_RENDERING_HINTS = 0;
    public static int RENDERING_HINTS = STRONG_RENDERING_HINTS;
   
    // Key array
    boolean[] key = new boolean[5];
   
    // Key constants
    public static final int FIRE = 0;
    public static final int UP = FIRE + 1;
    public static final int DOWN = UP + 1;
    public static final int LEFT = DOWN + 1;
    public static final int RIGHT = LEFT + 1;
   
    // Global identity matrix
    Transform identity = new Transform();
   
    // Global Graphics3D object
    Graphics3D g3d = null;
   
    // The background
    Background back = null;
   
    // The global camera object
    Camera cam = null;
   
    // The particle system
    ParticleSystem ps = null;
    FountainEffect fx = null;
   
    /** Constructs the canvas
     */
    public M3GCanvas(int fps)
    {
        // We don't want to capture keys normally
        super(true);
       
        // We want a fullscreen canvas
        setFullScreenMode(true);
       
        // Load our camera
        loadCamera();
       
        // Load our background
        loadBackground();
       
        // Set up graphics 3d
        setUp();
    }
   
    /** Prepares the Graphics3D engine for immediate mode rendering by adding a light */
    private void setUp()
    {
        // Get the instance
        g3d = Graphics3D.getInstance();
       
        // Add a light to our scene, so we can see something
        g3d.addLight(createAmbientLight(), identity);
    }
   
   
    /** Creates a simple ambient light */
    private Light createAmbientLight()
    {
        Light l = new Light();
        l.setMode(Light.AMBIENT);
        l.setIntensity(1.0f);
        return l;
    }
    /** When fullscreen mode is set, some devices will call
     * this method to notify us of the new width/height.
     * However, we don't really care about the width/height
     * in this tutorial so we just let it be
     */
    public void sizeChanged(int newWidth, int newHeight)
    {
       
    }
   
    /** Loads our camera */
    private void loadCamera()
    {
        // Create a new camera
        cam = new Camera();
    }
   
    /** Loads the background */
    private void loadBackground()
    {
        // Create a new background, set bg color to black
        back = new Background();
        back.setColor(0);
    }
    /** Draws to screen
     */   
    private void draw(Graphics g)
    {
        // Envelop all in a try/catch block just in case
        try
        {           
            // Get the Graphics3D context
            g3d = Graphics3D.getInstance();
           
         // First bind the graphics object. We use our pre-defined rendering hints.
         g3d.bindTarget(g, true, RENDERING_HINTS);
        
         // Clear background
         g3d.clear(back);
        
         // Bind camera at fixed position in origo
         g3d.setCamera(cam, identity);
        
         // Init particles
         if(ps == null)
         {
             fx = new FountainEffect(90);
             ps = new ParticleSystem(fx, 20);
         }
        
         // Emit the particles
         ps.emit(g3d);
        
         // Check controls for fountain rotation
         if(key[LEFT])
             fx.setAngle(fx.getAngle() + 5);
         if(key[RIGHT])
             fx.setAngle(fx.getAngle() - 5);
        
         // Quit if user presses fire
         if(key[FIRE])
             TutorialMidlet.die();
        }
        catch(Exception e)
        {
            reportException(e);
        }
        finally
        {
            // Always remember to release!
            g3d.releaseTarget();
        }
    }
    /** Starts the canvas by firing up a thread
     */
    public void start() {
        Thread myThread = new Thread(this);
       
        // Make sure we know we are running
        running = true;
        done = false;
       
        // Start
        myThread.start();
    }
   
    /** Run, runs the whole thread. Also keeps track of FPS
     */
    public void run() {
        while(running) {
            try {               
                // Call the process method (computes keys)
                process();
               
                // Draw everything
                draw(getGraphics());
                flushGraphics();
               
                // Sleep to prevent starvation
                try{ Thread.sleep(30); } catch(Exception e) {}
            }
            catch(Exception e) {
                reportException(e);
            }
        }
       
        // Notify completion
        done = true;
    }
   
    /**
     * @param e
     */
    private void reportException(Exception e) {
        System.out.println(e.getMessage());
        System.out.println(e);
        e.printStackTrace();
    }
    /** Pauses the game
     */
    public void pause() {}
   
    /** Stops the game
     */
    public void stop() { running = false; }
   
    /** Processes keys
     */
    protected void process()
    {
        int keys = getKeyStates();
       
        if((keys & GameCanvas.FIRE_PRESSED) != 0)
            key[FIRE] = true;
        else
            key[FIRE] = false;
       
        if((keys & GameCanvas.UP_PRESSED) != 0)
            key[UP] = true;
        else
            key[UP] = false;
       
        if((keys & GameCanvas.DOWN_PRESSED) != 0)
            key[DOWN] = true;
        else
            key[DOWN] = false;
       
        if((keys & GameCanvas.LEFT_PRESSED) != 0)
            key[LEFT] = true;
        else
            key[LEFT] = false;
       
        if((keys & GameCanvas.RIGHT_PRESSED) != 0)
            key[RIGHT] = true;
        else
            key[RIGHT] = false;
    }
   
    /** Checks if thread is running
     */
    public boolean isRunning() { return running; }
   
    /** checks if thread has finished its execution completely
     */
    public boolean isDone() { return done; }
}
MeshFactory
import javax.microedition.lcdui.Image;
import javax.microedition.m3g.Appearance;
import javax.microedition.m3g.Image2D;
import javax.microedition.m3g.IndexBuffer;
import javax.microedition.m3g.Mesh;
import javax.microedition.m3g.PolygonMode;
import javax.microedition.m3g.Texture2D;
import javax.microedition.m3g.TriangleStripArray;
import javax.microedition.m3g.VertexArray;
import javax.microedition.m3g.VertexBuffer;
/**
 * Static class that handles creation of code-generated Meshes
 */
public class MeshFactory
{
    /** Creates a texture plane that is alpha-blended
     *
     * @param texFilename The name of the texture image file
     * @param cullFlags The flags for culling. See PolygonMode.
     * @param alpha The alpha value of blending. Is a full color in 0xAARRGGBB format
     * @return The finished textured mesh
     */
    public static Mesh createAlphaPlane(String texFilename, int cullFlags, int alpha)
    {
        // Create a normal mesh
        Mesh mesh = createPlane(texFilename, cullFlags);
       
        // Make it blended
        MeshOperator.convertToBlended(mesh, alpha, Texture2D.FUNC_BLEND);
        return mesh;
    }
   
    /**
     * Creates a textured plane.
     * @param texFilename The name of the texture image file
     * @param cullFlags The flags for culling. See PolygonMode.
     * @return The finished textured mesh
     */
    public static Mesh createPlane(String texFilename, int cullFlags)
    {
        // The vertrices of the plane
        short vertrices[] = new short[] {-1, -1, 0,
                                       1, -1, 0,
                                       1, 1, 0,
                                       -1, 1, 0};
        // Texture coords of the plane
        short texCoords[] = new short[] {0, 255,
                                         255, 255,
                                         255, 0,
                                         0, 0};
       
        // The classes
        VertexArray vertexArray, texArray;
        IndexBuffer triangles;
        // Create the model's vertrices
        vertexArray = new VertexArray(vertrices.length/3, 3, 2);
        vertexArray.set(0, vertrices.length/3, vertrices);
       
        // Create the model's texture coords
        texArray = new VertexArray(texCoords.length / 2, 2, 2);
        texArray.set(0, texCoords.length / 2, texCoords);
       
        // Compose a VertexBuffer out of the previous vertrices and texture coordinates
        VertexBuffer vertexBuffer = new VertexBuffer();
        vertexBuffer.setPositions(vertexArray, 1.0f, null);
        vertexBuffer.setTexCoords(0, texArray, 1.0f/255.0f, null);
       
        // Create indices and face lengths
        int indices[] = new int[] {0, 1, 3, 2};
        int[] stripLengths = new int[] {4};
       
        // Create the model's triangles
        triangles = new TriangleStripArray(indices, stripLengths);
        // Create the appearance
        Appearance appearance = new Appearance();
        PolygonMode pm = new PolygonMode();
        pm.setCulling(cullFlags);
        appearance.setPolygonMode(pm);
        // Create and set the texture
        try
        {
            // Open image
            Image texImage = Image.createImage(texFilename);
            Texture2D theTexture = new Texture2D(new Image2D(Image2D.RGBA, texImage));
           
            // Replace the mesh's original colors (no blending)
            theTexture.setBlending(Texture2D.FUNC_REPLACE);
           
            // Set wrapping and filtering
            theTexture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
            theTexture.setFiltering(Texture2D.FILTER_BASE_LEVEL, Texture2D.FILTER_NEAREST);
            // Add texture to the appearance
            appearance.setTexture(0, theTexture);
        }
        catch(Exception e)
        {
            // Something went wrong
            System.out.println("Failed to create texture");
            System.out.println(e);
        }
       
        // Finally create the Mesh
        Mesh mesh = new Mesh(vertexBuffer, triangles, appearance);
        // All done
        return mesh;
    }
}
MeshOperator
import javax.microedition.m3g.CompositingMode;
import javax.microedition.m3g.Mesh;
/**
 * Performs some basic operations on Mesh objects
 */
public class MeshOperator
{
    /** Sets the alpha blending of a mesh. Only meaningful if the mesh already is alpha blended */
    public static void setMeshAlpha(Mesh m, int alpha)
    {
        m.getVertexBuffer().setDefaultColor(alpha);
    }
   
    /**
     *
     * @param m The mesh to convert to a blended one
     * @param alpha The alpha color to blend with
     * @param textureBlending The texture blending parameter.
     */
    public static void convertToBlended(Mesh m, int alpha, int textureBlending)
    {
        // Set the alpha
        setMeshAlpha(m, alpha);
       
        // Fix the compositing mode
        CompositingMode cm = new CompositingMode();
        cm.setBlending(CompositingMode.ALPHA);
        m.getAppearance(0).setCompositingMode(cm);
        m.getAppearance(0).getTexture(0).setBlending(textureBlending);
    }
}
Particle
/**
 * Holds all the information of a particle.
 * A particle's alpha is controlled directly by its life. Its alpha is always
 * life * 255.
 */
public class Particle
{
    // The life of the particle. Goes from 1.0f to 0.0f
    private float life = 1.0f;
   
    // The degradation of the particle
    private float degradation = 0.1f;
   
    // The velocities of the particle
    private float[] vel = {0.0f, 0.0f, 0.0f};
   
    // The position of the particle
    private float[] pos = {0.0f, 0.0f, 0.0f};
   
    // The color of the particle (RGB format 0xRRGGBB)
    private int color = 0xffffff;
   
    /** Empty initialization */
    public Particle()
    {
       
    }
   
    /**
     * Initializes the particle
     * @param velocity Sets the velocity
     * @param position Sets the position
     * @param color Sets the color (no alpha)
     */
    public Particle(float[] velocity, float[] position, int color)
    {
        setVel(velocity);
        setPos(position);
        this.setColor(color);
    }
    /**
     * @param life The life to set.
     */
    void setLife(float life) {
        this.life = life;
    }
    /**
     * @return Returns the life.
     */
    float getLife() {
        return life;
    }
    /**
     * @param vel The vel to set.
     */
    void setVel(float[] tvel) {
        System.arraycopy(tvel, 0, vel, 0, vel.length);
    }
    /**
     * @return Returns the vel.
     */
    float[] getVel() {
        return vel;
    }
    /**
     * @param pos The pos to set.
     */
    void setPos(float[] tpos) {
        System.arraycopy(tpos, 0, pos, 0, pos.length);
    }
    /**
     * @return Returns the pos.
     */
    float[] getPos() {
        return pos;
    }
    /**
     * @param color The color to set.
     */
    void setColor(int color) {
        this.color = color;
    }
    /**
     * @return Returns the color.
     */
    int getColor() {
        return color;
    }
    /**
     * @param degradation The degradation to set.
     */
    public void setDegradation(float degradation) {
        this.degradation = degradation;
    }
    /**
     * @return Returns the degradation.
     */
    public float getDegradation() {
        return degradation;
    }
}
ParticleEffect
import javax.microedition.m3g.Graphics3D;
/**
 * The interface that determines which effect the particle engine will display.
 * The ParticleEffect class also holds information about the bitmap used
 * for displaying particles (if any)
 */
public interface ParticleEffect
{
    // Initializes a particle
    public void init(Particle p);
   
    // Updates a particle
    public void update(Particle p);
   
    // Renders a particle
    public void render(Particle p, Graphics3D g3d);
}
BitmapParticleEffect
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Mesh;
import javax.microedition.m3g.PolygonMode;
import javax.microedition.m3g.Transform;
/**
 * Represents a particle effect that uses a bitmap.
 */
public abstract class BitmapParticleEffect implements ParticleEffect
{
    // The mesh
    Mesh mesh = null;
   
    // The transformation matrix
    Transform trans = new Transform();
   
    // The scale
    float scale = 1.0f;
   
    /** Initializes the bitmap used to render particles */
    public BitmapParticleEffect(String filename, float scale)
    {
        // Load the plane with the wanted texture
        mesh = MeshFactory.createAlphaPlane(filename, PolygonMode.CULL_BACK, 0xffffffff);
       
        // Make sure we set the scale
        this.scale = scale;
    }
   
    /**
     * @see ParticleEffect#render(Particle, Graphics3D)
     */
    public void render(Particle p, Graphics3D g3d)
    {
        // Calculate the alpha
        int alpha = (int)(255 * p.getLife());
       
        // Create the color
        int color = p.getColor() | (alpha << 24);
       
        // Set alpha
        MeshOperator.setMeshAlpha(mesh, color);
       
        // Transform
        trans.setIdentity();
        trans.postScale(scale, scale, scale);
        float[] pos = p.getPos();
        trans.postTranslate(pos[0], pos[1], pos[2]);
       
        // Render
        g3d.render(mesh, trans);
    }
}
FountainEffect
import java.util.Random;
/*
 * Created on 2005-aug-31
 */
/**
 * Creates a nice fountain effect for the particles, that shoots particles
 * in a certain direction, determined by its angle. The angle can be changed in real-time.
 */
public class FountainEffect extends BitmapParticleEffect
{
    // The angle of particle emission
    private int angle = 90;
   
    // The sine and cosine of the current angle
    private float[] trig = {1.0f, 0.0f};
   
    // The emitting origin
    private float[] pos = {0.0f, 0.0f, 0.0f};
   
    // The randomizer
    Random rand = null;
   
    /**
     * @param angle The angle of particle emission
     */
    public FountainEffect(int angle)
    {
        // Init the bitmap
        super("/res/particle.png", 0.05f);
       
        // Set the angle
        setAngle(angle);
       
        // Get randomizer
        rand = new Random();
    }
    /**
     * @see ParticleEffect#init(Particle)
     */
    public void init(Particle p)
    {
        // Set the particle's life
        p.setLife(1.0f);
       
        // Set the particle's position
        p.setPos(pos);
       
        // Create the particle's velocties
        float[] vel = new float[3];
       
        // We want velocities from 0.2f to 1.0f
        float xyvel = rand.nextFloat() * 0.8f + 0.2f;
       
        // We want the particle to die slowly
        p.setDegradation(xyvel / 18);
       
        // Set velocities according to trigonometry with a small deviation
        vel[0] = xyvel * trig[1] + rand.nextFloat() * 0.125f - 0.0625f;
        vel[1] = xyvel * trig[0] + rand.nextFloat() * 0.125f - 0.0625f;
       
        // No movement in depth
        vel[2] = 0.0f;
       
        // Set the velocity
        p.setVel(vel);
       
        // Set the random color
        int r = (int)(120 * rand.nextFloat()) + 135;
        int g = (int)(120 * rand.nextFloat()) + 135;
        int b = (int)(120 * rand.nextFloat()) + 135;
        int col = (r << 16) | (g << 8) | b;
        p.setColor(col);
    }
    /**
     * @see ParticleEffect#update(Particle)
     */
    public void update(Particle p)
    {
        // Simply update position
        float[] ppos = p.getPos();
        float[] vel = p.getVel();
        ppos[0] += vel[0];
        ppos[1] += vel[1];
        ppos[2] += vel[2];
       
        // Update life
        p.setLife(p.getLife() - p.getDegradation());
       
        // Check life. If it is dead, we just reinit it
        if(p.getLife() < -0.001f)
        {
            init(p);
        }
    }
    /**
     * @param angle The angle to set.
     */
    public void setAngle(int angle) {
        this.angle = angle;
        trig[0] = (float)Math.sin(Math.toRadians(angle));
        trig[1] = (float)Math.cos(Math.toRadians(angle));
    }
    /**
     * @return Returns the angle.
     */
    public int getAngle() {
        return angle;
    }
    /**
     * @param pos The pos to set.
     */
    void setEmittingOrigin(float[] pos) {
        this.pos = pos;
    }
    /**
     * @return Returns the pos.
     */
    float[] getEmittingOrigin() {
        return pos;
    }
}
ParticleSystem
import javax.microedition.m3g.Graphics3D;
/**
 * Manages emission of particles in our 3D world
 */
public class ParticleSystem
{
    // The effect
    private ParticleEffect effect = null;
   
    // The particles
    Particle[] parts = null;
   
    /**
     * Creates a particle system that emits particles according to a defined effect.
     * @param effect The effect that controls the behaviour of the particles
     * @param numParticles The number of particles to emit
     */
    public ParticleSystem(ParticleEffect effect, int numParticles)
    {
        // Copy the effect
        setEffect(effect);
       
        // Init the particles
        parts = new Particle[numParticles];
        for(int i = 0; i < numParticles; i++)
        {
            parts[i] = new Particle();
            effect.init(parts[i]);
        }
    }
   
    /** The method that does it all. Needs to be called every tick of a game loop */
    public void emit(Graphics3D g3d)
    {
        for(int i = 0; i < parts.length; i++)
        {
            getEffect().update(parts[i]);
            getEffect().render(parts[i], g3d);
        }
    }
    /**
     * @param effect The effect to set.
     */
    public void setEffect(ParticleEffect effect) {
        this.effect = effect;
    }
    /**
     * @return Returns the effect.
     */
    public ParticleEffect getEffect() {
        return effect;
    }
}
 
About Redikod
Redikod from Malmo, Sweden, has been developing web and mobile games since 1997, and this small company is now one of the leaders in the Nordic games industry. Its disproportionate influence stems from strategic initiatives such as Nordic Game Potential, the yearly conference, and the Nordic booth at E3 2006. Redikod is commissioned to design the Nordic public support system and funding for games development, including mobile, that, pending final political decision this fall, will come into effect in 2006. But 3D and multiplayer mobile games development are their day job. To find out more, visit Redikod's website>> 
 
 
Score
Login to rate page