Computer graphics/2013-2014/Laboratory 11
Appearance
Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, JOGL template.
Particle engine
[edit | edit source]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 | edit source]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 | edit source]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 | edit source]- 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.