Java tutorial
/* * 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.engine.BoundingBox; import com.opengrave.og.light.Shadow; import com.opengrave.og.resources.RenderStyle; import com.opengrave.og.resources.Resources; import com.opengrave.og.util.Matrix4f; import com.opengrave.og.util.Vector4f; /** * Rendering mostly-static models. Can deal with change if data is replaced and * this.setChanged() is run Not the best object for animating anything * * @author triggerhapp * */ public abstract class Renderable3D extends Renderable { private int indexCount = 0; // protected Matrix4f matrix = new Matrix4f(); // public TextureAtlas texture; public static void init() { // pickingmodel = new ShaderProgram("model.vs", "pickingmodel.fs"); } public ArrayList<Vertex3D> vertexList = new ArrayList<Vertex3D>(); FloatBuffer buffer; int vao_ID = 0, vbo_pos_ID = 0, vbo_norm_ID = 0, vbo_tex_ID = 0; public boolean visible = false; protected Vector4f color = new Vector4f(0f, 0f, 0f, 1f); // private int vertCount; protected MaterialList matList; private int vbo_index_ID; protected BoundingBox box = new BoundingBox(); public void setMaterialList(MaterialList mlist) { this.matList = mlist; } @Override public void render(Matrix4f matrix, RenderStyle style) { dealWithChange(); int pID = Resources.loadShader("model.vs", "model.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.glEnableVertexAttribArray(0); GL20.glEnableVertexAttribArray(1); GL20.glEnableVertexAttribArray(2); GL20.glBindAttribLocation(pID, 0, "in_Position"); GL20.glBindAttribLocation(pID, 1, "in_Normal"); GL20.glBindAttribLocation(pID, 2, "in_TextureCoord"); Util.checkErr(); if (matList != null && matList.valid()) { matList.bind(pID, GL13.GL_TEXTURE0); Util.loadMaterials(matList, pID); } Util.checkErr(); getContext().setMatrices(pID, matrix); getContext().bindShadowData(GL13.GL_TEXTURE2); getContext().bindLights(pID, GL13.GL_TEXTURE3); Util.setRenderStyle(pID, style); 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(); } Util.checkErr(); GL20.glDisableVertexAttribArray(0); GL20.glDisableVertexAttribArray(1); GL20.glDisableVertexAttribArray(2); Util.checkErr(); GL20.glUseProgram(0); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL30.glBindVertexArray(0); } @Override public void renderShadows(Matrix4f matrix, Shadow shadow) { dealWithChange(); int pID = Resources.loadShader("model.vs", "castshadow.fs").getProgram(); GL20.glUseProgram(pID); GL30.glBindVertexArray(vao_ID); GL20.glEnableVertexAttribArray(0); GL20.glBindAttribLocation(pID, 0, "in_Position"); Util.checkErr(); getContext().setShadowMatrices(pID, matrix, shadow); 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); Util.checkErr(); GL20.glDisableVertexAttribArray(0); Util.checkErr(); 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(); changed = true; } // set VAO object 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 (changed) { recreate(); changed = false; indexCount = vertexList.size(); IntBuffer indexList = BufferUtils.createIntBuffer(indexCount); ArrayList<Vertex3D> verts = new ArrayList<Vertex3D>(); for (Vertex3D thisVert : vertexList) { // Vertex3D thisVert = vertexList.get(i); 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); box.clear(); for (int i = 0; i < verts.size(); i++) { Vertex3D 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); } // Set Vertex data 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); // Set Norm data 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); // Set Texture Co-ord data 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); // Unset VBO object GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } // Unset VAO object GL30.glBindVertexArray(0); } @Override public void addVertex(VertexData vd) { changed = true; if (vd instanceof Vertex3D) { vertexList.add((Vertex3D) vd); } } @Override public void renderForPicking(Matrix4f matrix, Pickable object) { dealWithChange(); int pID = Resources.loadShader("model.vs", "pickingmodel.fs").getProgram(); GL20.glUseProgram(pID); GL30.glBindVertexArray(vao_ID); GL20.glEnableVertexAttribArray(0); GL20.glBindAttribLocation(pID, 0, "in_Position"); Util.checkErr(); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo_index_ID); getContext().setMatrices(pID, matrix); Picking.registerObject(pID, getContext(), object); GL11.glDrawElements(GL11.GL_TRIANGLES, indexCount, GL11.GL_UNSIGNED_INT, 0); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); Util.checkErr(); GL20.glDisableVertexAttribArray(0); Util.checkErr(); GL20.glUseProgram(0); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL30.glBindVertexArray(0); } public BoundingBox getBoundingBox() { dealWithChange(); return box; } }