Package graphics.emitter

Source Code of graphics.emitter.Emitter

package graphics.emitter;

import graphics.mesh.EmitterMesh;
import static engine.Engine.ShaderHandler;
import static engine.Engine.elapsedAppTime;
import graphics.material.Material;
import graphics.model.Model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.ARBVertexShader.GL_VERTEX_PROGRAM_POINT_SIZE_ARB;
import static org.lwjgl.opengl.ARBPointSprite.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Vector3f;

/**
*
* @author simokr
*/
public class Emitter extends Model{
  private ArrayList<Particle> particles;
  private int lifeTime, updateInterval;
  private float updateIntervalMultiplier;
  private long lastUpdate;
  private Vector3f velocity, acceleration, translation, startPositionRandomness;
  private EmitterMesh emitterMesh;
  private float startSize, endSize;
  private float startSizeRandomness, endSizeRandomness;
  private boolean isPaused;
  private int maxParticles;
 
  public Emitter(int maxParticles, int lifeTime) {
    this.maxParticles = maxParticles;
    particles = new ArrayList<>(maxParticles);
    this.lifeTime = lifeTime;
    updateInterval = lifeTime/maxParticles;
    updateIntervalMultiplier = 1f;
   
    velocity = new Vector3f();
    translation = new Vector3f();
    acceleration = new Vector3f();
   
    lastUpdate = 0;
   
    startSize = 0f;
    endSize = 1f;
    startSizeRandomness = 0f;
    endSizeRandomness = 0f;
    startPositionRandomness = new Vector3f();
   
    isPaused = false;
   
    emitterMesh = new EmitterMesh();
    emitterMesh.create(maxParticles);

    this.setMesh(emitterMesh);
   
    shader = ShaderHandler.get("./res/shaders/billboard.vert|./res/shaders/billboard.frag");
    material = new Material();
    material.setTexture(0, "res/texture/smoke.png");
  }
 
  /**
   *
   * @param start start size (in pixels)
   * @param end end size (in pixels)
   */
  public void setSizes(float start, float end){
    this.startSize = start;
    this.endSize = end;
  }
 
  /**
   * Sets the update interval multiplier. Values under 1.0f will clamp to 1.0f.
   * A new particle is emitted when: current_time > previous_particle_emitting_time + (update_interval * update_interval_multiplier)
   * This can be used to slow down the rate of particle emitting.
   *
   * @param multiplier the multiplier
   */
  public void setUpdateIntervalMultiplier(float multiplier) {
    this.updateIntervalMultiplier = Math.max(1.0f, multiplier);
  }
 
  public void setSizesRandomness(float startRandomness, float endRandomness){
    this.startSizeRandomness = startRandomness;
    this.endSizeRandomness = endRandomness;
  }
 
  public void setStartPositionRandomness(Vector3f randomness){
    this.startPositionRandomness.set(randomness);
  }
 
  public void setAcceleration(Vector3f acceleration){
    this.acceleration.set(acceleration);
  }
 
  public void setVelocity(Vector3f velocity){
    this.velocity.set(velocity);
  }
 
  public void setTranslation(Vector3f translation){
    this.translation.set(translation);
  }
 
  public void emit(int textureUnit){
    if(this.particles.size() >= this.maxParticles)
      return;
   
    long currentTime = elapsedAppTime();
    Random gen = new Random();
     
    float start = this.startSize;
    float end = this.endSize;

    if(this.startSizeRandomness != 0.0f)
      start += this.startSizeRandomness*(gen.nextFloat()-0.5f);

    if(this.endSizeRandomness != 0.0f)
      end += this.endSizeRandomness*(gen.nextFloat()-0.5f);
   
   
    Vector3f posRand = this.getPosition();
    if(this.startPositionRandomness.x != 0f && this.startPositionRandomness.y != 0f && this.startPositionRandomness.z != 0f){
      posRand = new Vector3f(
        (gen.nextFloat()-0.5f)*this.startPositionRandomness.x + posRand.x,
        (gen.nextFloat()-0.5f)*this.startPositionRandomness.y + posRand.y,
        (gen.nextFloat()-0.5f)*this.startPositionRandomness.z + posRand.z
      );
    }
   
    Particle particle = new Particle(currentTime, currentTime+this.lifeTime, start, end, posRand, this.velocity);
    particle.setTextureUnit(textureUnit);
   
    this.particles.add(particle);
    this.lastUpdate = currentTime;
  }
 
  public void update(){
    long currentTime = elapsedAppTime();
    if(!this.isPaused && currentTime > this.lastUpdate+(long)(this.updateInterval*this.updateIntervalMultiplier)){
      this.emit(0);
    }
   
    Iterator<Particle> it = particles.iterator();
    while(it.hasNext()){
      if(it.next().isOld(currentTime)){
        it.remove();
      }
    }
   
    it = particles.iterator();
    while(it.hasNext()){
      it.next().update(this.acceleration, currentTime);
    }
   
    this.emitterMesh.update(this.particles);
  }
 
  @Override
  protected void updateModelMatrix(){
    if(this.modelMatrixDirty){
      double rotYrad = Math.toRadians(this.rotation.y);
      float sin = (float)Math.sin(rotYrad);
      float cos = (float)Math.cos(rotYrad);
     
      this.modelMatrix.setIdentity();
      this.modelMatrix.translate(new Vector3f(
        (-cos*this.translation.x)+sin*this.translation.z,
        this.translation.y,
        sin*this.translation.x+cos*this.translation.z
      ));

      this.modelMatrixDirty = false;
    }
  }
 
  @Override
  protected boolean preRender(){
    if(this.mesh == null || !this.mesh.isReady() || this.shader == null || !this.shader.isReady())
      return false;
   
    this.updateModelMatrix();
 
    this.shader.setModelMatrix(this.modelMatrix);
    return true;
  }
 
  @Override
  public void render(){
    if(!this.preRender())
      return;
   
    //glDisable(GL_CULL_FACE);
    //glDisable(GL_DEPTH_TEST);
    glDepthMask(false);
    glEnable(GL_POINT_SPRITE_ARB);
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
    glEnable(GL_BLEND);
   
    this.shader.enable();

    this.material.bindTextures();
   
    this.mesh.render();

    this.material.unbindTextures();
   
    this.shader.disable();
   
    glDisable(GL_BLEND);
    glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
    glDisable(GL_POINT_SPRITE_ARB);
    glDepthMask(true);
    //glEnable(GL_CULL_FACE);
    //glEnable(GL_DEPTH_TEST);
  }
 
  public void pause(){
    this.isPaused = true;
  }
 
  public void resume(){
    this.isPaused = false;
  }
 
  @Override
  public void free(){
    this.mesh.free();
  }
}

TOP

Related Classes of graphics.emitter.Emitter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.