Computer graphics -- 2008-2009 -- info.uvt.ro/Laboratory 11

Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, JOGL template.


Particle engine edit

Particles engines can be used to simulate effects such as water, fire, cloud, comet tails, etc.

Each particle can be seen as a billboard (a texture always facing the camera) with several additional properties as:

  • physics related:
    • The position vector: (positionX, positionY, positionZ)
    • The speed vector: (speedX, speedY, speedY)
    • The acceleration vector: (accelerationX, accelerationY, accelerationZ)
  • display related:
    • Color, material, texture, etc.
    • Fading and fading factor -- how visible is the particle
  • Life: which should be decremented and when it reaches 0 the particle should be destroyed or reused
public class Particle
{
	double positionX, positionY, positionZ;
	double speedX, speedY, speedZ;
	double accelerationX, accelerationY, accelerationZ;
	double radius = 2;

	double life;
	TextureHandler texture = null;
	Random rand = null;

	public Particle(GL gl, GLU glu, String textName)
	{
		this.texture = new TextureHandler(gl, glu, textName, true);
		rand = new Random();
		this.init();
	}

	private void init()
	{
		this.positionX = rand.nextDouble() * 10;
		this.positionY = rand.nextDouble() * 10;
		this.positionZ = rand.nextDouble() * 10;

		this.accelerationX = rand.nextDouble();
		this.accelerationY = rand.nextDouble();
		this.accelerationZ = rand.nextDouble();

		this.speedX = 0;
		this.speedY = 0;
		this.speedZ = 0;

		this.life = 10;
	}
}

The physical laws are quite easy:

  • at each step we update the speed by using the acceleration and the position by using the speed
    • the time is considered constant (usually 1):
public class Particle
{
	[...]

	public void update()
	{
		// Consider time equal to the unit (1).

		// speed = acceleration * time
		this.speedX += this.accelerationX;
		this.speedY += this.accelerationY;
		this.speedZ += this.accelerationZ;

		// position = speed * time
		this.positionX += this.speedX;
		this.positionY += this.speedY;
		this.positionZ += this.speedZ;

		// Decrease life.
		this.life -= 0.5;

		// If the life of the particle has ended then reinitialize it.
		if (this.life < 0)
			this.init();
	}
}
  • usually the particles go in the opposite direction of their source; thus we could initialize their speed with the speed of the source, but negative
  • usually the particles are emitted to form a cone

Drawing a single particle edit

Drawing the particle is quite easy. We simply need to draw a QUAD based on the particle position and to apply a texture on it:

public class Particle
{
	[...]

	public void draw(GL gl)
	{

		this.texture.bind();
		this.texture.enable();

		gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);

		gl.glBegin(GL2.GL_POLYGON);
			gl.glTexCoord2d(0,0);
			gl.glVertex3d(this.positionX - this.radius, this.positionY - this.radius, this.positionZ);
			gl.glTexCoord2d(1,0);
			gl.glVertex3d(this.positionX + this.radius, this.positionY - this.radius, this.positionZ);
			gl.glTexCoord2d(1,1);
			gl.glVertex3d(this.positionX + this.radius, this.positionY + this.radius, this.positionZ);
			gl.glTexCoord2d(0,1);
			gl.glVertex3d(this.positionX - this.radius, this.positionY + this.radius, this.positionZ);
		gl.glEnd();

		this.texture.disable();
	}
}

Observations:

  • usually the number of particles is constant:
    • when a particle dies a new one is created. This is usually done by reusing and reinitializing the particle
  • the bigger the time variable is, the smaller the number of frames is needed, but the movement is more fragmented

NOTE: In this particular case the particle is not a billboard!

Calling the Particle engine edit

Once the Particle class is created we only need to create a few of them and render them on the screen. To do this add in the main (J)OGL application:

public class MainFrame
{

	final int PARTS_NUM = 10;
	Particle[] particles = new Particle()[this.PARTS_NUM];

	[...]

	void init(...)
	{
		[...]

		for (int i=0; i<this.PARTS_NUM; i++)
		{
			this.particles[i] = new Particle (gl, glu, "texture.jpg");
		}
		
	}

	void display(...)
	{

		[...]

		for (int i=0; i<this.PARTS_NUM; i++)
		{
			this.particles[i].draw(gl);
		}

		gl.glFlush();

		for (int i=0; i<this.PARTS_NUM; i++)
		{
			this.particles[i].update();
		}
	}

}

Exercise edit

  • Create a simple particle engine which emits particles only on the OY axis. The camera should be fixed and located at a conveniently distance from the source of the particles. Make each particle a billboard.
  • Create a simple scene containing a cube. Inside the cube we have 5 spheres bouncing of the edges. Each time two (or more) spheres touch each other they disappear.