com.opengrave.og.base.Renderable3D.java Source code

Java tutorial

Introduction

Here is the source code for com.opengrave.og.base.Renderable3D.java

Source

/*
 * 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;
    }
}