package graphics.model;
import graphics.mesh.Mesh;
import static engine.Engine.ShaderHandler;
import graphics.material.Material;
import graphics.shader.Shader;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
/**
* A model has a mesh, matrial, shader, world xyz-coordinates (position, rotation, scale).
*
* Each unique 3d-model in the game world is one Model.
*
* @author simokr
*/
public class Model {
protected Mesh mesh;
protected Shader shader;
protected Material material;
protected Vector3f position,rotation,scale;
protected final Matrix4f modelMatrix;
protected boolean modelMatrixDirty;
private int keyframe1, keyframe2;
private float keyframeBlend;
public Model(){
mesh = null;
shader = ShaderHandler.get("./res/shaders/mesh.vert|./res/shaders/mesh.frag");
material = new Material();
position = new Vector3f();
rotation = new Vector3f();
scale = new Vector3f(1f,1f,1f);
modelMatrix = new Matrix4f();
modelMatrixDirty = true;
keyframe1 = 0;
keyframe2 = -1;
keyframeBlend = 0.0f;
}
public void setPosition(float x, float y, float z){
this.position.set(x, y, z);
this.modelMatrixDirty = true;
}
public void setPosition(Vector3f position){
if(position != null){
this.position.set(position);
this.modelMatrixDirty = true;
}
}
public Vector3f getPosition(){
return new Vector3f(this.position);
}
public Vector3f getRotation(){
return new Vector3f(this.rotation);
}
public void move(float x, float y, float z){
this.position.x += x;
this.position.y += y;
this.position.z += z;
this.modelMatrixDirty = true;
}
public void move(Vector3f positionDelta){
if(positionDelta != null){
Vector3f.add(this.position, positionDelta, this.position);
this.modelMatrixDirty = true;
}
}
public void setRotation(float x, float y, float z){
this.rotation.set(x, y, z);
this.modelMatrixDirty = true;
}
public void setRotation(Vector3f rotation){
if(rotation != null){
this.rotation.set(rotation);
this.modelMatrixDirty = true;
}
}
public void turn(float x, float y, float z){
this.rotation.x += x;
this.rotation.y += y;
this.rotation.z += z;
this.modelMatrixDirty = true;
}
public void turn(Vector3f rotationDelta){
if(rotationDelta != null){
Vector3f.add(this.rotation, rotationDelta, this.rotation);
this.modelMatrixDirty = true;
}
}
public void setScale(float x, float y, float z){
this.scale.x = x;
this.scale.y = y;
this.scale.z = z;
this.modelMatrixDirty = true;
}
public void setScale(Vector3f scale){
if(scale != null){
this.scale.set(scale);
this.modelMatrixDirty = true;
}
}
public void setMesh(Mesh mesh){
this.mesh = mesh;
this.material = this.mesh.getDefaultMaterial();
//this.material.setTexture(0, "res/texture/steamtrain_painted.png");
}
public void setMaterial(Material mat){
this.material = new Material(mat);
//this.material.setTexture(0, "res/texture/steamtrain_painted.png");
}
protected void updateModelMatrix(){
if(this.modelMatrixDirty){
this.modelMatrix.setIdentity();
this.modelMatrix.translate(this.position);
this.modelMatrix.scale(this.scale);
this.modelMatrix.rotate((float) Math.toRadians(this.rotation.x), new Vector3f(1.0f,0.0f,0.0f));
this.modelMatrix.rotate((float) Math.toRadians(this.rotation.y), new Vector3f(0.0f,1.0f,0.0f));
this.modelMatrix.rotate((float) Math.toRadians(this.rotation.z), new Vector3f(0.0f,0.0f,1.0f));
this.modelMatrixDirty = false;
}
}
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;
}
public void render(){
if(!this.preRender())
return;
this.shader.enable();
if(this.keyframe2 > -1){
this.shader.setKeyframeBlend(this.keyframeBlend);
}
this.material.bindTextures();
if(this.keyframe2 > -1){
this.mesh.render(keyframe1, keyframe2);
}
else{
this.mesh.render();
}
this.material.unbindTextures();
if(this.keyframe2 > -1){
this.shader.setKeyframeBlend(0.0f);
}
this.shader.disable();
}
public void animate(float blend, int keyframe1, int keyframe2){
this.keyframeBlend = Math.min(1.0f,Math.max(0.0f, blend));
this.keyframe1 = keyframe1;
this.keyframe2 = keyframe2;
}
public void free(){
}
}