This is an old revision of the document!


Particle System

General

A Particle System in general is used to create all kinds of visual effects, like Smoke,Fire and Explosions. It's aim is to make Virtual environments more eye-catching and in case of many Games more realistic. So what the System is doing to make this possible is basically controlling the movements and looks of many little graphical objects (Particles), usually Quads. In The System which is implemented now are 3 Classes responsible for creating those Visual Effects.

  • The Particle Class which forms one of those little graphical objects.
  • The ParticleEffect Class which currently builds an array of particles and controls their movements and looks.
  • The Effect Class contains a list of ParticleEffects because often there are more than one particle effect used to create visual effects like explosions e.g. for a simple explosion is fire and smoke needed.

Particle Class

Main Tasks

  1. Ordered List Item Unordered List Item Saving all the attributes that are needed to draw the particle and those who can vary between single particles.
  2. Ordered List Item Unordered List Item Drawing the particle.

Attributes

For drawing needed attributes are:

protected Vector3D pos; //Position of the particle
protected float particle_size,rotation,alpha; //size,current rotation,transparency of the particle
protected static Texture materialTex,alphaTex; //material texture, transparency map texture of the particle

The other from particle to particle varying attributes are:

protected Vector3D v,initial_v; //current speed, speed at the beginning of the effect
protected float maxLife,life,vRotation; //Maximal life, current life, rotation speed
protected float timeStampIniV,timeStampIniLife,timeStampSize,timeStampVRot; /* Timestamps in which the last time an defined 
attribute was changed is saved. */

Drawing

Currently possible drawing Modes are:

  • No texture drawing
  • One texture drawing
  • Two textures multi textured drawing

No texture drawing

It is just as the mode name says in this mode there is no texture used to draw the particle quads. Instead of that they have got all a color.

One texture drawing

In this drawing mode is one texture, the material texture, bind on the quad an used for drawing.

Two textures multi textured drawing

Now it's getting interesting because in OpenGL you have the possibility to draw more than one texture over the same graphical object. OpenGL has different options which define how those textures are mixed together, the option which is used in here is GL_MODULATE. In this option the colors of each particle of the texture are added up to create the final texture on the graphic object. This makes it possible to use transparency maps witch you can lay on a material texture in order to let the particle look like a quad or star, despite of the fact that the graphical object is a quad. This makes it easier to create the particle effect you want.

Class development problems

The only problem which occurred while developing this class where problems with OpenGL in the multi textured drawing mode. The problem was when I drawed this mode everything except of the particle effect on the screen disappeared, regardless of the fact that the textures were bind properly to the quad. at that time the code looked like this:

             glEnable(GL_TEXTURE_2D);
                glActiveTextureARB(GL_TEXTURE0_ARB);
                materialTex.bind();
                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
 
                glActiveTextureARB(GL_TEXTURE1_ARB);
                alphaTex.bind();
                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
 
 
                glBegin(GL_QUADS);
                    glColor4f(1, 1, 1, alpha);
                    //glTexCoord2f(0, 0);
                    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);
                    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
                    glVertex2f(-particle_size/2, -particle_size/2);
                    glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1f, 0);
                    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1f, 0);
                    //glTexCoord2f(0.5f, 0);
                    glVertex2f(particle_size/2, -particle_size/2);
                    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1f, 1f);
                    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1f, 1f);
                    // glTexCoord2f(0.5f, 0.5f);
                    glVertex2f(particle_size/2, particle_size/2);
                    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1f);
                    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1f);
                    //glTexCoord2f(0, 0.5f);
                    glVertex2f(-particle_size/2, particle_size/2);
                glEnd();

The source of the problem was that graphicards today usually have got 32 places where they can save Textures (OpenGl refers to them with GL_TEXTURE0_ARB to GL_TEXTURE31_ARB),and the first of the is by default used to handle single texturing. But if you want to use multi-texturing you have to use multiple of these places and only the one currently used is activated. The last one I activated in the code above was GL_TEXTURE1_ARB and so all graphic objects which uses single texturing couldn't be drawed since GL_TEXTURE0_ARB was deactivated. The problem was solved by adding those lines:

                glActiveTextureARB(GL_TEXTURE1_ARB);
                glDisable(GL_TEXTURE_2D);
                glActiveTextureARB(GL_TEXTURE0_ARB);

ParticleEffect class

Main Tasks

  1. build the particles which are used for this effect.
  2. control the particle movements and looks though the effect.

Particle building

The Particle building is a crucial thing for the particle effect and it's look. Because you want the particles to vary all in their attributes to make effects like smoke look more realistically. But although you want them not to be to random because if thats the case than you will be unable to design the effect you want. The methods that can be used to generate those different start attributes are:

protected float setRichtung(float Angle, float spannweite){...}
 
 
//Methoden zur berechnung eines Zufalls Geschwindikeitswerts
protected Vector3D setSpeed(float generalSpeed,float angle){...}
 
protected Vector3D setSpeed(float maxSpeed,float minSpeed, float angle){...}
 
//Generiert die Zufalls LebensWerte der Particel
protected float setLife(float maxLife,float minLife){...}
protected float setLife(float maxLifep){...}
 
//Erstellt die Rotations Geschwindigkeit und Richtung
protected float setRotation(){...}
protected float setVRotation(float vRotationGeneral){...}
 
protected float setVRotation(int richtung,float vRotationMax,float vRotationMin){...}
 
 
//Methode zur berechnung des Geschwindikeitsvektors eines Partikels.
private Vector3D setSpeedVect(float speed, float angle){...}

Controling particle movements and looks (Tick Function)

Only through doing that the particle effect really looks like one. If it wouldn't be done no particle would move, fade over time, rotate, change it's size and so on. The problem in doing this was to create a construct of methods which are easy to understand, well arranged, and easily adaptable. My current solution is a construct of methods which begins with this tick function:

public void tick(){
for(int i=0;i<particles.size();i++){
    timepassed = (System.nanoTime()-lastTick)/(float)Math.pow(10, 9);
    Particle tempParticle = (Particle) particles.get(i);
    if(tempParticle.getLife()>=tempParticle.getmaxLife()){
         dieTick(tempParticle);
    }
    else if(tempParticle.getLife()>=0){
         alifeTick(tempParticle);
    }
 
    }
    lastTick=System.nanoTime();
}

It basically divides the tick in two types the tick of an particle when its “alive” and the tick when it “dies”(when its current life would be grater than its maximal) which leads to the next two functions: The aliveTick

protected void 
        alifeTick(Particle tempParticle){
 
         tempParticle.setPos(positionTick(tempParticle));
         tempParticle.setV(VTick(tempParticle));
         tempParticle.setLife(lifeTick(tempParticle));
         rotationTickManager(tempParticle);
         if(change_Particle_Size){
            tempParticle.setParticle_size(particleSizeTick(tempParticle));
         }
}

this function only calls up all functions who are changing values when the particle is still alive. So if you got a new variable for the Particle that although has to be changed through the life of the particle, the only thing you have to do is write the changing method and add it here. The same idea follows the dieTick() function in which all functions are called up which changes particle attributes in case of its “dead” most of them are reset methods:

protected void dieTick(Particle tempParticle){
    if(!fadeOut){
         tempParticle.setPos(positionResetTick(tempParticle));
         tempParticle.setV(VResetTick(tempParticle));
         tempParticle.setLife(lifeResetTick(tempParticle));
        if(change_Particle_Size){
            tempParticle.setParticle_size(particleSizeResetTick(tempParticle));
         }
         if(editMode){
             changeTick(tempParticle);
         }
    }
    else{
 
    }
}

Class development problems

The most difficult thing to write in this class were the functions which controls the attribute changes in each Tick(). Thats because some of them have got some difficult algorithm in them. For example this one:

        Vector3D newV= new Vector3D(tempParticle.getInitial_v().getX()*(1-(speed_decay*tempParticle.getLife())),
                                    tempParticle.getInitial_v().getY()*(1-(speed_decay*tempParticle.getLife())),0f);
        return newV;

The first algorithm was about 4 times as long as this one and didn't work. Though there weren't many functions which did the thing I wanted them to do after the first try of writing them.

Effect Class

For this class i will keep the Description short because the only thing its needed for is that you can ad as many ParticleEffects to it as you want.

 
 documentation/particlesystem.1304919955.txt.gz · Last modified: 2011/05/09 07:45 by tim
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Driven by DokuWiki