Jump to content

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

From Wikiversity

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.