/*
* Copyright 2016 Nathan Howard
*
* This file is part of OpenGrave
*
* OpenGrave is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenGrave is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenGrave. If not, see <http://www.gnu.org/licenses/>.
*/
package com.opengrave.og.base;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
import com.opengrave.common.world.MaterialList;
import com.opengrave.og.Util;
import com.opengrave.og.light.Shadow;
import com.opengrave.og.resources.RenderStyle;
import com.opengrave.og.resources.Resources;
import com.opengrave.og.resources.Texture;
import com.opengrave.og.util.Matrix4f;
public abstract class RenderableBoneAnimated extends Renderable3D {
protected Texture texture;
private MaterialList matList;
IntBuffer bone;
int vertCount = -1;
int vao_ID = 0, vbo_pos_ID = 0, vbo_norm_ID = 0, vbo_tex_ID = 0, vbo_weight_ID = 0, vbo_bone_ID = 0;
public boolean visible = true;
public abstract void setBonesUniform(int pID);
public static void init() {
// pickingboneshader = Resources.loadShader("pickingmodel.vs",
// "pickingmodel.fs");
}
protected ArrayList<VertexAnimated> vertexList = new ArrayList<VertexAnimated>();
public Matrix4f matrix = new Matrix4f();
private int vbo_index_ID;
private int indexCount;
@Override
public void render(Matrix4f matrix, RenderStyle style) {
// if (!visible) {
// return;
// }
GL11.glDisable(GL11.GL_CULL_FACE); // TODO Enable Face Culling, and be
// absolutely sure that all tris are
// facing the correct way
dealWithChange();
int pID = Resources.loadShader("animmodel.vs", "animmodel.fs").getProgram();
GL20.glUseProgram(pID);
int texture = GL20.glGetUniformLocation(pID, "texture");
int shadow = GL20.glGetUniformLocation(pID, "shadowMap");
GL20.glUniform1i(texture, 0);
GL20.glUniform1i(shadow, 1);
GL30.glBindVertexArray(vao_ID);
GL20.glBindAttribLocation(pID, 0, "in_Position");
GL20.glBindAttribLocation(pID, 1, "in_Normal");
GL20.glBindAttribLocation(pID, 2, "in_TextureCoord");
GL20.glBindAttribLocation(pID, 3, "in_BoneID");
GL20.glBindAttribLocation(pID, 4, "in_BoneWeight");
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL20.glEnableVertexAttribArray(3);
GL20.glEnableVertexAttribArray(4);
if (matList != null && matList.valid()) {
matList.bind(pID, GL13.GL_TEXTURE0);
Util.loadMaterials(matList, pID);
}
setBonesUniform(pID);
getContext().setMatrices(pID, matrix);
getContext().bindShadowData(GL13.GL_TEXTURE2);
getContext().bindLights(pID, GL13.GL_TEXTURE3);
Util.setRenderStyle(pID, style);
// GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertCount);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo_index_ID);
GL11.glDrawElements(GL11.GL_TRIANGLES, indexCount, GL11.GL_UNSIGNED_INT, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
getContext().unbindLights();
getContext().unbindShadowData();
if (matList != null && matList.valid()) {
matList.unbind();
}
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL20.glDisableVertexAttribArray(3);
GL20.glDisableVertexAttribArray(4);
GL20.glUseProgram(0);
GL30.glBindVertexArray(0);
GL11.glEnable(GL11.GL_CULL_FACE);
}
@Override
public void renderShadows(Matrix4f matrix, Shadow shadow) {
// if (!visible) {
// return;
// }
dealWithChange();
int pID = Resources.loadShader("animmodel.vs", "animmodel.fs").getProgram();
GL20.glUseProgram(pID);
GL30.glBindVertexArray(vao_ID);
GL20.glBindAttribLocation(pID, 0, "in_Position");
GL20.glBindAttribLocation(pID, 3, "in_BoneID");
GL20.glBindAttribLocation(pID, 4, "in_BoneWeight");
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(3);
GL20.glEnableVertexAttribArray(4);
setBonesUniform(pID);
getContext().setShadowMatrices(pID, matrix, shadow);
// GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertCount);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo_index_ID);
GL11.glDrawElements(GL11.GL_TRIANGLES, indexCount, GL11.GL_UNSIGNED_INT, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(3);
GL20.glDisableVertexAttribArray(4);
GL20.glUseProgram(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
@Override
public void renderForPicking(Matrix4f matrix, Pickable object) {
dealWithChange();
int pID = Resources.loadShader("animmodel.vs", "pickingmodel.fs").getProgram();
GL20.glUseProgram(pID);
GL30.glBindVertexArray(vao_ID);
GL20.glBindAttribLocation(pID, 0, "in_Position");
GL20.glBindAttribLocation(pID, 3, "in_BoneID");
GL20.glBindAttribLocation(pID, 4, "in_BoneWeight");
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(3);
GL20.glEnableVertexAttribArray(4);
setBonesUniform(pID);
// Util.setShadowMatrices(pID, shadow, location, scale, rotation,
// matrix);
Picking.registerObject(pID, getContext(), object);
getContext().setMatrices(pID, matrix);
// GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertCount);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo_index_ID);
GL11.glDrawElements(GL11.GL_TRIANGLES, indexCount, GL11.GL_UNSIGNED_INT, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(3);
GL20.glDisableVertexAttribArray(4);
GL20.glUseProgram(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
@Override
public void dealWithChange() {
if (vao_ID == 0) {
vao_ID = GL30.glGenVertexArrays();
}
GL30.glBindVertexArray(vao_ID);
if (vbo_index_ID == 0) {
vbo_index_ID = GL15.glGenBuffers();
}
if (vbo_pos_ID == 0) {
vbo_pos_ID = GL15.glGenBuffers();
}
if (vbo_norm_ID == 0) {
vbo_norm_ID = GL15.glGenBuffers();
}
if (vbo_tex_ID == 0) {
vbo_tex_ID = GL15.glGenBuffers();
}
if (vbo_weight_ID == 0) {
vbo_weight_ID = GL15.glGenBuffers();
}
if (vbo_bone_ID == 0) {
vbo_bone_ID = GL15.glGenBuffers();
}
if (changed) {
// vertexList.clear();
recreate();
changed = false;
indexCount = vertexList.size();
IntBuffer indexList = BufferUtils.createIntBuffer(indexCount);
ArrayList<VertexAnimated> verts = new ArrayList<VertexAnimated>();
for (VertexAnimated thisVert : vertexList) {
int index = -1;
if (verts.indexOf(thisVert) == -1) {
verts.add(thisVert);
}
index = verts.indexOf(thisVert);
indexList.put(index);
}
int vertCount = verts.size();
indexList.flip();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo_index_ID);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indexList, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
FloatBuffer pos = BufferUtils.createFloatBuffer(vertCount * 3);
FloatBuffer norm = BufferUtils.createFloatBuffer(vertCount * 3);
FloatBuffer tex = BufferUtils.createFloatBuffer(vertCount * 3);
FloatBuffer bone = BufferUtils.createFloatBuffer(vertCount * 4);
FloatBuffer weight = BufferUtils.createFloatBuffer(vertCount * 4);
// box.clear();
for (int i = 0; i < verts.size(); i++) {
VertexAnimated v1 = verts.get(i);
// box.addVector3f(v1.getPos());
pos.put(v1.x).put(v1.y).put(v1.z);
norm.put(v1.nx).put(v1.ny).put(v1.nz);
tex.put(v1.tx).put(v1.ty).put(v1.tz);
bone.put(v1.influence.getBoneId(0)).put(v1.influence.getBoneId(1)).put(v1.influence.getBoneId(2)).put(v1.influence.getBoneId(3));
weight.put(v1.influence.getWeight(0)).put(v1.influence.getWeight(1)).put(v1.influence.getWeight(2)).put(v1.influence.getWeight(3));
}
pos.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_pos_ID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, pos, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
norm.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_norm_ID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, norm, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, true, 0, 0);
tex.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_tex_ID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tex, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(2, 3, GL11.GL_FLOAT, false, 0, 0);
bone.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_bone_ID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, bone, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(3, 4, GL11.GL_FLOAT, false, 0, 0);
weight.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_weight_ID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, weight, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(4, 4, GL11.GL_FLOAT, false, 0, 0);
/*
* changed = false;
*
* vertCount = vertexList.size(); FloatBuffer pos =
* BufferUtils.createFloatBuffer(vertCount * 3); FloatBuffer norm =
* BufferUtils.createFloatBuffer(vertCount * 3); FloatBuffer tex =
* BufferUtils.createFloatBuffer(vertCount * 3); FloatBuffer bone =
* BufferUtils.createFloatBuffer(vertCount * 4); FloatBuffer weight
* = BufferUtils.createFloatBuffer(vertCount * 4); for
* (VertexAnimated va : vertexList) {
* pos.put(va.x).put(va.y).put(va.z);
* norm.put(va.nx).put(va.ny).put(va.nz);
* tex.put(va.tx).put(va.ty).put(va.tz);
* bone.put(va.influence.getBoneId(0))
* .put(va.influence.getBoneId(1)) .put(va.influence.getBoneId(2))
* .put(va.influence.getBoneId(3));
* weight.put(va.influence.getWeight(0))
* .put(va.influence.getWeight(1)) .put(va.influence.getWeight(2))
* .put(va.influence.getWeight(3)); }
*
* pos.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_pos_ID);
* GL15.glBufferData(GL15.GL_ARRAY_BUFFER, pos,
* GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(0, 3,
* GL11.GL_FLOAT, false, 0, 0);
*
* norm.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,
* vbo_norm_ID); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, norm,
* GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(1, 3,
* GL11.GL_FLOAT, false, 0, 0);
*
* tex.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo_tex_ID);
* GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tex,
* GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(2, 3,
* GL11.GL_FLOAT, false, 0, 0);
*
* bone.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,
* vbo_bone_ID); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, bone,
* GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(3, 4,
* GL11.GL_FLOAT, false, 0, 0);
*
* weight.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,
* vbo_weight_ID); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, weight,
* GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(4, 4,
* GL11.GL_FLOAT, false, 0, 0);
*/
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
GL30.glBindVertexArray(0);
}
public ArrayList<VertexAnimated> getVertexList() {
return vertexList;
}
@Override
public void addVertex(VertexData vd) {
changed = true;
if (vd instanceof VertexAnimated) {
vertexList.add((VertexAnimated) vd);
} else {
throw (new RuntimeException("Wrong Vertex Type"));
}
}
public void setMatrix(Matrix4f matrix) {
// Wrong place to do it. Translates will all be wrong
// matrix.scale(new Vector3f(0.05f,0.05f,0.05f));
this.matrix = matrix;
}
public void setMaterialList(MaterialList mlist) {
this.matList = mlist;
}
}