main.java.com.YeAJG.game.entity.Entity.java Source code

Java tutorial

Introduction

Here is the source code for main.java.com.YeAJG.game.entity.Entity.java

Source

/*
 * The MIT License
 *
 * Copyright 2015 Richard Coan.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package main.java.com.YeAJG.game.entity;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import main.java.com.YeAJG.api.entity.IEntity;
import main.java.com.YeAJG.api.gfx.IRender;
import main.java.com.YeAJG.game.Game;
import main.java.com.YeAJG.game.gfx.ShaderHandler;
import main.java.com.YeAJG.game.gfx.TextureHandler;
import main.java.com.YeAJG.game.utils.Conversions;
import main.java.com.YeAJG.game.utils.VertexData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;

/**
 *
 * @author Richard Coan
 */
public abstract class Entity implements IEntity, IRender {
    protected static final Logger logger = LogManager.getLogger(Game.class.getName());

    protected boolean visible = true;

    protected Vector3f modelPos = null;
    protected Vector3f modelAngle = null;
    protected Vector3f modelScale = null;
    protected Matrix4f modelMatrix = null;

    protected float angle = 0;

    protected Vector3f modelVelcity = new Vector3f(0, 0, 0);
    protected Vector3f modelAccel = new Vector3f(0, 0, 0);;
    protected Vector3f modelSpin = new Vector3f(0, 0, 0);;

    protected int textureSelector = 0;

    protected int projectionMatrixLocation = 0;
    protected int viewMatrixLocation = 0;
    protected int modelMatrixLocation = 0;
    protected int ageLocation = 0;
    protected int decayLocation = 0;
    protected int limitLocation = 0;

    protected VertexData[] vertices = null;
    protected ByteBuffer verticesByteBuffer = null;
    protected int indicesCount = 0;
    protected int vaoId = 0;
    protected int vboId = 0;
    protected int vboiId = 0;
    protected int texId = 0;

    protected int vsId;
    protected int fsId;

    protected int pId = 0;

    @Override
    public void Setup(Vector3f pos, Vector3f angle, Vector3f scale, String shaderPath, String fragmentPath,
            String texturePath, Vector3f[] vertex, Vector3f[] color, Vector2f[] uv) {
        // Setup model matrix
        modelMatrix = new Matrix4f();

        //Default Position, Angle, Scale of the Quad.
        this.setModelPos(pos);
        this.setModelAngle(angle);
        this.setModelScale(scale);

        if (uv != null && color != null && vertex != null)
            this.SetupEntity(vertex, color, uv);

        if (!shaderPath.equals("") && !fragmentPath.equals(""))
            this.SetupShaders(shaderPath, fragmentPath);

        if (!texturePath.equals(""))
            this.texId = TextureHandler.loadTexture(texturePath);
    }

    private void SetupShaders(String shaderPath, String fragPath) {
        // Load the vertex shader and fragment shader
        vsId = ShaderHandler.loadShader(shaderPath);
        fsId = ShaderHandler.loadFrag(fragPath);

        // Create a new shader program that links both shaders
        pId = GL20.glCreateProgram();
        GL20.glAttachShader(pId, vsId);
        GL20.glAttachShader(pId, fsId);

        // Position information will be attribute 0
        GL20.glBindAttribLocation(pId, 0, "in_Position");
        // Color information will be attribute 1
        GL20.glBindAttribLocation(pId, 1, "in_Color");
        // Textute information will be attribute 2
        GL20.glBindAttribLocation(pId, 2, "in_TextureCoord");

        GL20.glLinkProgram(pId);
        GL20.glValidateProgram(pId);

        // Get matrices uniform locations
        projectionMatrixLocation = GL20.glGetUniformLocation(pId, "projectionMatrix");
        viewMatrixLocation = GL20.glGetUniformLocation(pId, "viewMatrix");
        modelMatrixLocation = GL20.glGetUniformLocation(pId, "modelMatrix");

        decayLocation = GL20.glGetUniformLocation(pId, "decay");

        Game.exitOnGLError("setupShaders");
    }

    private void SetupEntity(Vector3f[] vertex, Vector3f[] color, Vector2f[] uv) {

        // We'll define our quad using 4 vertices of the custom 'TexturedVertex' class
        vertices = new VertexData[vertex.length];

        for (int i = 0; i < vertex.length; i++) {
            vertices[i] = new VertexData();
            vertices[i].setXYZ(vertex[i].x, vertex[i].y, vertex[i].z);
            vertices[i].setRGBA(color[i].x, color[i].y, color[i].z, 1.0f);
            vertices[i].setST(uv[i].x, uv[i].y);
        }

        // Put each 'Vertex' in one FloatBuffer
        verticesByteBuffer = BufferUtils.createByteBuffer(vertices.length * VertexData.stride);
        FloatBuffer verticesFloatBuffer = verticesByteBuffer.asFloatBuffer();
        for (int i = 0; i < vertices.length; i++) {
            // Add position, color and texture floats to the buffer
            verticesFloatBuffer.put(vertices[i].getElements());
        }
        verticesFloatBuffer.flip();

        // OpenGL expects to draw vertices in counter clockwise order by default
        // TODO: Move this to Setup.
        byte[] indices = { 0, 1, 2, 2, 3, 0 };

        indicesCount = indices.length;
        ByteBuffer indicesBuffer = BufferUtils.createByteBuffer(indicesCount);
        indicesBuffer.put(indices);
        indicesBuffer.flip();

        // Create a new Vertex Array Object in memory and select it (bind)
        vaoId = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoId);

        // Create a new Vertex Buffer Object in memory and select it (bind)
        vboId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesFloatBuffer, GL15.GL_STREAM_DRAW);

        // Put the position coordinates in attribute list 0
        GL20.glVertexAttribPointer(0, VertexData.positionElementCount, GL11.GL_FLOAT, false, VertexData.stride,
                VertexData.positionByteOffset);
        // Put the color components in attribute list 1
        GL20.glVertexAttribPointer(1, VertexData.colorElementCount, GL11.GL_FLOAT, false, VertexData.stride,
                VertexData.colorByteOffset);
        // Put the texture coordinates in attribute list 2
        GL20.glVertexAttribPointer(2, VertexData.textureElementCount, GL11.GL_FLOAT, false, VertexData.stride,
                VertexData.textureByteOffset);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        // Deselect (bind to 0) the VAO
        GL30.glBindVertexArray(0);

        // Create a new VBO for the indices and select it (bind) - INDICES
        vboiId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

        Game.cameraPos = new Vector3f(0, 0, -1);

        Game.exitOnGLError("setupQuad");
    }

    @Override
    public void Render(float interpolation) {

        GL20.glUseProgram(pId);

        // Bind the texture
        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);

        // Bind to the VAO that has all the information about the vertices
        GL30.glBindVertexArray(vaoId);
        GL20.glEnableVertexAttribArray(0);
        GL20.glEnableVertexAttribArray(1);
        GL20.glEnableVertexAttribArray(2);

        // Bind to the index VBO that has all the information about the order of the vertices
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);

        // Draw the vertices
        GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_BYTE, 0);

        // Put everything back to default (deselect)
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL20.glDisableVertexAttribArray(0);
        GL20.glDisableVertexAttribArray(1);
        GL20.glDisableVertexAttribArray(2);
        GL30.glBindVertexArray(0);

        GL20.glUseProgram(0);

        Game.exitOnGLError("renderCycle");
    }

    @Override
    public void Tick() {
        // Update Positions
        Vector3f.add(this.modelAngle, this.modelSpin, this.modelAngle);
        Vector3f.add(this.modelVelcity, this.modelAccel, this.modelVelcity);
        Vector3f.add(this.modelPos, this.modelVelcity, this.modelPos);

        // Reset view and model matrices
        modelMatrix = new Matrix4f();

        // Scale, translate and rotate model
        Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
        Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
        Matrix4f.rotate(Conversions.degreesToRadians(modelAngle.z), new Vector3f(0, 0, 1), modelMatrix,
                modelMatrix);
        Matrix4f.rotate(Conversions.degreesToRadians(modelAngle.y), new Vector3f(0, 1, 0), modelMatrix,
                modelMatrix);
        Matrix4f.rotate(Conversions.degreesToRadians(modelAngle.x), new Vector3f(1, 0, 0), modelMatrix,
                modelMatrix);

        // Upload matrices to the uniform variables
        GL20.glUseProgram(pId);

        Game.projectionMatrix.store(Game.matrix44Buffer);
        Game.matrix44Buffer.flip();
        GL20.glUniformMatrix4(projectionMatrixLocation, false, Game.matrix44Buffer);
        Game.viewMatrix.store(Game.matrix44Buffer);
        Game.matrix44Buffer.flip();
        GL20.glUniformMatrix4(viewMatrixLocation, false, Game.matrix44Buffer);
        modelMatrix.store(Game.matrix44Buffer);
        Game.matrix44Buffer.flip();
        GL20.glUniformMatrix4(modelMatrixLocation, false, Game.matrix44Buffer);

        GL20.glUseProgram(0);
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public Vector3f getModelPos() {
        return modelPos;
    }

    public void setModelPos(Vector3f modelPos) {
        if (modelPos != null)
            this.modelPos = new Vector3f(modelPos);
    }

    public Vector3f getModelAngle() {
        return modelAngle;
    }

    public void setModelAngle(Vector3f modelAngle) {
        if (modelAngle != null)
            this.modelAngle = new Vector3f(modelAngle);
    }

    public Vector3f getModelScale() {
        return modelScale;
    }

    public void setModelScale(Vector3f modelScale) {
        if (modelScale != null)
            this.modelScale = new Vector3f(modelScale);
    }

    public Vector3f getModelVelcity() {
        return modelVelcity;
    }

    public void setModelVelcity(Vector3f modelVelcity) {
        if (modelVelcity != null)
            this.modelVelcity = new Vector3f(modelVelcity);
    }

    public Vector3f getModelAccel() {
        return modelAccel;
    }

    public void setModelAccel(Vector3f modelAccel) {
        if (modelAccel != null)
            this.modelAccel = new Vector3f(modelAccel);
    }

    public Vector3f getModelSpin() {
        return modelSpin;
    }

    public void setModelSpin(Vector3f modelSpin) {
        if (modelSpin != null)
            this.modelSpin = new Vector3f(modelSpin);
    }

    public void destroy() {
        // Delete the Program
        GL20.glUseProgram(0);
        GL20.glDeleteProgram(pId);

        // Select the VAO
        GL30.glBindVertexArray(vaoId);

        // Disable the VBO index from the VAO attributes list
        GL20.glDisableVertexAttribArray(0);
        GL20.glDisableVertexAttribArray(1);

        // Delete the vertex VBO
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL15.glDeleteBuffers(vboId);

        // Delete the index VBO
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        GL15.glDeleteBuffers(vboiId);

        // Delete the VAO
        GL30.glBindVertexArray(0);
        GL30.glDeleteVertexArrays(vaoId);
    }

}