Contents /
Previous /
Next
Particle System Source Code
public class ParticleSystem {
///////////////// Constants /////////////////////////
private final int MAX_PARTICLES = 500;
// We may want more than one texture for particl evolution.
final int nbTexture = 2;
//////////////// Variables /////////////////////////
private Particle p[] = new Particle[MAX_PARTICLES];
// Array for texture ids.
// Texturs are share by particles
private int[] textures = new int[ nbTexture ] ;
///////////////// Functions /////////////////////////
public void init( GL gl)
{
// Particles are tranparent.
gl.glEnable( GL.GL_BLEND );
gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE );
// Prepare textures for paricles.
gl.glEnable( GL.GL_TEXTURE_2D );
gl.glGenTextures( nbTexture, textures, 0 );
// Square textures size.
byte b[]; // Array for texture data.
final int size = 256;
// Texture 0.
b = calcTextureData( size, 4, 250, 50, 5, 2f );
initTexture( gl, b, 0, size );
// Texture 1.
b = calcTextureData( size, 4, 50, 50, 55, 1f );
initTexture( gl, b, 1, size );
}
private void initTexture( GL gl, byte b[], int index, int size )
{
gl.glBindTexture( GL.GL_TEXTURE_2D,textures[ index ] );
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
// Set texture data.
ByteBuffer texture = BufferUtil.newByteBuffer(b.length);
texture.put( b, 0, b.length );
gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, size, size, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, texture.rewind() ) ;
}
//Create particle Texture.
private byte[] calcTextureData( int size, int bytesPerPixel,
int r, int g, int b,
float alphaScale )
{
final int halfSize = size/2;
final int nbBytes = size*size*bytesPerPixel;
final int nbBytesRow = size*bytesPerPixel;
// Byte-Array for Image.
byte[] data = new byte[nbBytes];
//RGB-Werte 150,150,255 (some blue)
for(int i=0; i < nbBytes; i+=bytesPerPixel){
data[i] = (byte)r;
data[i+1] = (byte)g;
data[i+2] = (byte)b;
//data[i+3] = (byte)255; // Calc below.
}
// Re-calc Alpha with max in center and radia reduction.
final int maxAlpha = 100;
for(int y=0; y < size; y++) {
for(int x=0; x < size; x++) {
int dx = x - halfSize;
int dy = y - halfSize;
int a = maxAlpha -
(int) ( Math.sqrt((double)(dx*dx+dy*dy))
* alphaScale );
if (a < 0) { a = 0; }
data[ y * nbBytesRow + x * bytesPerPixel + 3 ] = (byte)a;
}
}
return data;
}
private Particle createParticle()
{
Particle p = new Particle( 500f, 0f, 0f );
p.setSpeed( // Init random Speed.
0.001f - (float)Math.random() / 500.0f,
0.008f - (float)Math.random() / 1000.0f,
0.001f - (float)Math.random() / 500.0f
);
return p;
}
////////////////// draw ////////////////////////////////
public void draw( GL gl )
{
gl.glDepthMask( false );
// Loop over particles.
for( int i=0; i < MAX_PARTICLES; i++ )
{
// Create new particles for continuous effect.
if ( p[i] == null )
{
p[i] = createParticle();
break; // Create one particle per time step.
}
// Kill particle if it hits the ground or died.
if ( p[i].getPosY() < 0.0f || ! p[i].isAlive() )
{
p[i] = createParticle();
}
// Apply gravity.
p[i].incSpeedY( -0.00004f );
p[i].evolve();
// Select texture and draw.
if( p[i].getLifetime() > 200 ) {
gl.glBindTexture( GL.GL_TEXTURE_2D,textures[0] );
} else {
gl.glBindTexture( GL.GL_TEXTURE_2D,textures[1] );
}
p[i].draw( gl );
} // end particle loop.
gl.glDepthMask( true );
}
}