Package graphics.mesh

Source Code of graphics.mesh.Mesh

package graphics.mesh;

import graphics.material.Material;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;

/**
* Mesh is a representation of an object in 3d-space.
* (Vertices, texture coordinates, normals)
*
* Obj-file must have vertices, texture-coordinates, and normals (v/vt/vn)
*
* Polygons are automatically converted to triangles.
*
* @author simokr
*/
public class Mesh {
  private boolean ready;
  protected FloatBuffer VBO;
  private int VBOid, maxFloatCount, stride, usage;
  protected int indiceCount;
  protected int keyframeCount;
  protected Material defaultMaterial;
  private int primitiveType;
 
  public Mesh(){
    ready = false;
    VBOid = 0;
    VBO = null;
    indiceCount = 0;
    keyframeCount = 0;
    maxFloatCount = 0;
    stride = 0;
    usage = 0;
    defaultMaterial = new Material();
    primitiveType = GL_TRIANGLES;
  }

  /**
   * Builds a Mesh from given data
   *
   * @param data VBO contents
   * @param stride VBO stride
   * @param usage VBO usage (GL_STATIC_DRAW, GL_STREAM_DRAW..)
   * @param saveVBO
   * @return success
   */
  public boolean create(ArrayList<Float> data, int stride, int usage, boolean saveVBO){
    if(data == null)
      return false;
   
    FloatBuffer temporaryBuffer = BufferUtils.createFloatBuffer(data.size());
   
    for(int i=0;i<data.size();i++)
      temporaryBuffer.put(data.get(i));
   
    temporaryBuffer.flip();
   
    return this.create(temporaryBuffer, stride, usage, saveVBO);
  }
 
  /**
   * Builds a Mesh from given data. Also sets the maximum size of the VBO.
   *
   * @param data VBO contents
   * @param stride VBO stride
   * @param usage VBO usage (GL_STATIC_DRAW, GL_STREAM_DRAW..)
   * @param saveVBO
   * @return success
   */
  public boolean create(FloatBuffer data, int stride, int usage, boolean saveVBO){
    if(data == null)
      return false;
   
    if(stride < 1){
      System.err.println("Incorrect stride. Must be over 0.");
      return false;
    }
   
    if(this.isReady())
      this.free();
   
    data.rewind();

    if(data.remaining()%stride != 0){
      System.err.println("Incorrect VBO stride. Must have: "+stride);
      return false;
    }
   
    this.VBO = data;
   
    if(usage != GL_STATIC_DRAW && usage != GL_STREAM_DRAW){
      System.err.println("Incorrect VBO usage. Must have: GL_STATIC_DRAW or GL_STREAM_DRAW.");
      return false;
    }

    /* Create VBO handle */
    if(!createVBO(usage, this.VBO.remaining())){
      System.err.println("Failed to generate VBO handle");
      return false;
    }
   
    /* Update data to GPU */
    this.setVBO();
   
    this.maxFloatCount = this.VBO.remaining();
    this.indiceCount = this.VBO.remaining()/stride;
    this.keyframeCount = 1;
    this.stride = stride;
    this.usage = usage;
   
    if(!saveVBO)
      this.VBO = null;
   
    //System.out.println("Loaded a Mesh from data - " + this.indiceCount + " indices.");
    this.ready = true;
    return true;
  }
 
  /**
   * Builds a Mesh with multiple keyframes.
   * @param data
   * @param usage
   * @param saveVBO
   * @param keyframeCount
   * @param indiceCount
   * @return success
   */
  public boolean create(FloatBuffer data, int usage, boolean saveVBO, int keyframeCount, int indiceCount){
    if(data == null)
      return false;
   
    if(this.isReady())
      this.free();
   
    data.rewind();
   
    this.VBO = data;
   
    if(usage != GL_STATIC_DRAW && usage != GL_STREAM_DRAW){
      System.err.println("Incorrect VBO usage. Must have: GL_STATIC_DRAW or GL_STREAM_DRAW.");
      return false;
    }

    /* Create VBO handle */
    if(!createVBO(usage, this.VBO.remaining())){
      System.err.println("Failed to generate VBO handle");
      return false;
    }
   
    /* Update data to GPU */
    this.setVBO();
   
    this.maxFloatCount = this.VBO.remaining();
    this.indiceCount = indiceCount;
    this.keyframeCount = keyframeCount;
    this.usage = usage;
    this.stride = 9;
   
    if(!saveVBO)
      this.VBO = null;
   
    //System.out.println("Loaded a Mesh from data - " + this.indiceCount + " indices.");
    this.ready = true;
    return true;
  }
 
  protected boolean update(){
    if(!this.isReady())
      return false;
   
    if(this.VBO.remaining()%this.stride != 0){
      System.err.println("Incorrect VBO stride. Must have: "+stride);
      return false;
    }
   
    if(this.VBO.remaining() > this.maxFloatCount){
      System.err.println("Data overflow, failed to update. Max: "+this.maxFloatCount+", had: "+this.VBO.remaining());
      return false;
    }
   
    /* Update data to GPU */
    this.setVBO();
    this.indiceCount = this.VBO.remaining()/this.stride;
   
    return true;
  }
 
  /**
   * @return true is mesh is ready to be rendered
   */
  public boolean isReady(){
    return this.ready;
  }
 
  /**
   * Frees the mesh data from GPU
   */
  public void free(){
    if(this.ready){
      //System.out.print("Freeing mesh "+this.VBOid+" "+glIsBuffer(VBOid)+ " ");
      glDeleteBuffers(VBOid);
      //System.out.print("Freed mesh "+this.VBOid+" "+glIsBuffer(VBOid)+"\n");
    }
    else
      System.out.print("Failed to free "+this.VBOid+" status: "+glIsBuffer(VBOid)+"\n");
   
    if(this.VBO != null){
      this.VBO.clear();
      this.VBO = null;
    }
   
    this.VBOid = 0;
    this.indiceCount = 0;
    this.ready = false;
    this.defaultMaterial = new Material();
  }
  /**
   * Returns a FloatBuffer (read only) containing the mesh VBO.
   *
   * @return VBO or null
   */
  public FloatBuffer getData(){
    if(this.VBO == null)
      return null;
   
    return this.VBO.asReadOnlyBuffer();
  }
 
  public int getIndiceCount(){
    return this.indiceCount;
  }
 
  public int getKeyframeCount(){
    return this.keyframeCount;
  }
 
  public Material getDefaultMaterial(){
    return new Material(this.defaultMaterial);
  }
 
  /**
   * Render this mesh
   */
  public void render(){
    if(!this.ready)
      return;
   
    this.bind();
    glDrawArrays(this.primitiveType, 0, this.indiceCount);
    this.unbind();
  }
 
  public void render(int keyframe1, int keyframe2){
    if(!this.ready)
      return;
   
    keyframe1 = keyframe1%this.getKeyframeCount();
    keyframe2 = keyframe2%this.getKeyframeCount();
   
    glBindBuffer(GL_ARRAY_BUFFER, this.VBOid);
    this.setVertexPointers(keyframe1, keyframe2);
    glDrawArrays(this.primitiveType, 0, this.indiceCount);
    this.unsetVertexPointers((keyframe2 > -1));
    glBindBuffer(GL_ARRAY_BUFFER, 0);
  }
 
  protected void bind(){
    glBindBuffer(GL_ARRAY_BUFFER, this.VBOid);
    this.setVertexPointers();
  }
 
  protected void unbind(){
    this.unsetVertexPointers();
    glBindBuffer(GL_ARRAY_BUFFER, 0);
  }
 
  private int genVBOId(){
                IntBuffer buf = BufferUtils.createIntBuffer(1);
                glGenBuffers(buf);
                return buf.get(0);
        }
 
  /**
   * Creates a new Vertex Buffer Object with given parameters.
   *
   * @param usage VBO usage (GL_STATIC_DRAW, GL_STREAM_DRAW..)
   * @param floatCount number of floats in VBO (or space to be reserved)
   * @return
   */
        private boolean createVBO(int usage, int floatCount){
                this.VBOid = this.genVBOId();
    if(this.VBOid < 1){
      return false;
    }
    int dataSize = floatCount*4;
    glBindBuffer(GL_ARRAY_BUFFER, this.VBOid);
    glBufferData(GL_ARRAY_BUFFER, dataSize, usage);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
   
    return true;
        }
       
  /**
   * Updates VBO contents to GPU
   *
   * @return false if VBOid couldn't be generated
   */
  private void setVBO(){
    glBindBuffer(GL_ARRAY_BUFFER, this.VBOid);
    glBufferSubData(GL_ARRAY_BUFFER, 0, this.VBO);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
  }
 
  protected void setPrimitiveType(int type){
    if(type == GL_TRIANGLES || type == GL_POINTS){
      this.primitiveType = type;
    }
    else{
      System.err.println("Invalid primitive type given.");
    }
  }
 
  protected void setVertexPointers(){
    this.setVertexPointers(0, -1);
  }
 
  protected void setVertexPointers(int keyframe1, int keyframe2){
    int position1_offset = this.indiceCount*3*4*keyframe1;
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, position1_offset);
    int offset = this.indiceCount*3*4*this.keyframeCount;

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, offset);
    offset += this.indiceCount*2*4;
        
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, offset+position1_offset);
    offset += this.indiceCount*3*4*this.keyframeCount;
   
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 1, GL_FLOAT, false, 0, offset);
   
    if(keyframe2 > -1){
      int position2_offset = this.indiceCount*3*4*keyframe2;
     
      glEnableVertexAttribArray(4);
      glVertexAttribPointer(4, 3, GL_FLOAT, false, 0, position2_offset);
     
      position2_offset = (this.indiceCount*3*4*this.keyframeCount) + (this.indiceCount*2*4) + (this.indiceCount*3*4*keyframe2);
       
      glEnableVertexAttribArray(5);
      glVertexAttribPointer(5, 3, GL_FLOAT, false, 0, position2_offset);
    }
  }
 
  protected void unsetVertexPointers(){
    this.unsetVertexPointers(false);
  }
 
  protected void unsetVertexPointers(boolean isKeyframe2){
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
   
    if(isKeyframe2){
      glDisableVertexAttribArray(4);
      glDisableVertexAttribArray(5);
    }
  }
}
TOP

Related Classes of graphics.mesh.Mesh

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.