Computer graphics -- 2008-2009 -- info.uvt.ro/Laboratory 11
From Wikiversity
Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, JOGL template.
Contents |
[edit] Particle engine
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
[edit] Drawing a single particle
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(GL.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!
[edit] Calling the Particle engine
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(); } } }
[edit] Exercise
- 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.