com.timvisee.voxeltex.module.mesh.Mesh.java Source code

Java tutorial

Introduction

Here is the source code for com.timvisee.voxeltex.module.mesh.Mesh.java

Source

/******************************************************************************
 * Copyright (c) Tim Visee 2016. All rights reserved.                         *
 *                                                                            *
 * @author Tim Visee                                                          *
 * @website http://timvisee.com/                                              *
 *                                                                            *
 * Open Source != No Copyright                                                *
 *                                                                            *
 * 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.                     *
 *                                                                            *
 * You should have received a copy of The MIT License (MIT) along with this   *
 * program. If not, see <http://opensource.org/licenses/MIT/>.                *
 ******************************************************************************/

package com.timvisee.voxeltex.module.mesh;

import com.timvisee.voxeltex.module.material.Material;
import com.timvisee.voxeltex.module.model.RawModel;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;

import java.nio.FloatBuffer;

import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.glBindBuffer;

public class Mesh {

    /**
     * The raw mesh object containing the vertexes data.
     */
    private RawMesh raw;

    /**
     * The number of vertexes in the buffered mesh.
     */
    private int vertexCount;

    /**
     * The number of normals in the buffered mesh.
     */
    private int normalCount;

    /**
     * Vertex buffer.
     */
    private FloatBuffer vertexBuffer;

    /**
     * Vertex buffer.
     */
    private FloatBuffer normalBuffer;

    /**
     * Texture buffer.
     */
    private FloatBuffer textureBuffer;

    /**
     * VBO vertex buffer handle.
     */
    private int vboVertexHandle = 0;

    /**
     * VBO normal buffer handle.
     */
    private int vboNormalHandle = 0;

    /**
     * VBO texture buffer handle.
     */
    private int vboTextureHandle = 0;

    /**
     * Constructor.
     *
     * @param raw Raw mesh.
     */
    public Mesh(RawMesh raw) {
        // Set the raw mesh
        this.raw = raw;

        // Buffer the mesh
        bufferMesh();
    }

    /**
     * Constructor.
     *
     * @param raw Raw model.
     */
    public Mesh(RawModel raw) {
        // Set the raw mesh
        this.raw = raw.toRawMesh();

        // Buffer the mesh
        bufferMesh();
    }

    /**
     * Get the raw mesh.
     *
     * @return Raw mesh.
     */
    public RawMesh getRawMesh() {
        return raw;
    }

    /**
     * Get the vertex buffer.
     *
     * @return Vertex buffer.
     */
    public FloatBuffer getVertexBuffer() {
        return vertexBuffer;
    }

    /**
     * Get the normal buffer.
     *
     * @return Normal buffer.
     */
    public FloatBuffer getNormalBuffer() {
        return normalBuffer;
    }

    /**
     * Get the texture buffer.
     *
     * @return Texture buffer.
     */
    public FloatBuffer getTextureBuffer() {
        return textureBuffer;
    }

    /**
     * Get the VBO vertex buffer handle.
     *
     * @return VBO vertex buffer handle.
     */
    public int getVboVertexHandle() {
        return vboVertexHandle;
    }

    /**
     * Get the VBO texture buffer handle.
     *
     * @return VBO texture buffer handle.
     */
    public int getVboTextureHandle() {
        return vboTextureHandle;
    }

    /**
     * Check whether this mesh has any normal data.
     *
     * @return True if this mesh has normal data, false if not.
     */
    public boolean hasNormalData() {
        // Determine the result based on the stored buffers if data has been buffered
        if (isBuffered())
            return this.vboNormalHandle > 0;

        // The mesh isn't buffered, determine the result based on the raw mesh
        return this.raw.hasNormalData();
    }

    /**
     * Check whether this mesh has any texture data.
     *
     * @return True if this mesh has texture data, false if not.
     */
    public boolean hasTextureData() {
        // Determine the result based on the stored buffers if data has been buffered
        if (isBuffered())
            return this.vboTextureHandle > 0;

        // The mesh isn't buffered, determine the result based on the raw mesh
        return this.raw.hasTextureData();
    }

    /**
     * Check whether the mesh is buffered on the graphics card.
     *
     * @return True if this mash is buffered, false if not.
     */
    public boolean isBuffered() {
        return this.vboVertexHandle > 0;
    }

    /**
     * Build and buffer the mesh on the graphics card.
     */
    public void bufferMesh() {
        // Create a flipped float buffer for the vertexes
        this.vertexBuffer = BufferUtils
                .createFloatBuffer(this.raw.getVertexCount() * this.raw.getVertexAxisCount());
        this.vertexBuffer.put(this.raw.getVertexes());
        this.vertexBuffer.flip();

        // Create a VBO handle for the vertexes and bind the buffer
        vboVertexHandle = GL15.glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, this.vboVertexHandle);
        GL15.glBufferData(GL_ARRAY_BUFFER, this.vertexBuffer, GL15.GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        // Buffer the normal data if the mesh has any configured
        if (this.raw.hasNormalData()) {
            // Create a flipped float buffer for the normal coordinates
            this.normalBuffer = BufferUtils
                    .createFloatBuffer(this.raw.getNormalCount() * this.raw.getNormalAxisCount());
            this.normalBuffer.put(this.raw.getNormals());
            this.normalBuffer.flip();

            // Create a VBO handle for the normal coordinates and bind the buffer
            vboNormalHandle = GL15.glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, this.vboNormalHandle);
            GL15.glBufferData(GL_ARRAY_BUFFER, this.normalBuffer, GL15.GL_STATIC_DRAW);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }

        // Buffer the texture data if the mesh has any configured
        if (this.raw.hasTextureData()) {
            // Create a flipped float buffer for the texture coordinates
            this.textureBuffer = BufferUtils
                    .createFloatBuffer(this.raw.getVertexCount() * this.raw.getTextureAxisCount());
            this.textureBuffer.put(this.raw.getTextures());
            this.textureBuffer.flip();

            // Create a VBO handle for the texture coordinates and bind the buffer
            vboTextureHandle = GL15.glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, this.vboTextureHandle);
            GL15.glBufferData(GL_ARRAY_BUFFER, this.textureBuffer, GL15.GL_STATIC_DRAW);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }

        // Set the number of vertexes and normals
        this.vertexCount = this.raw.getVertexCount();
        this.normalCount = this.raw.getNormalCount();
    }

    /**
     * Update the buffered mesh on the graphics card to use the current raw mesh.
     */
    public void updateBuffer() {
        // Clear the buffers if they are already made
        clearMeshBuffer();

        // Buffer the new mesh
        bufferMesh();
    }

    /**
     * Clear the buffers for this mesh on the graphics card.
     */
    public void clearMeshBuffer() {
        // Delete data from old buffers if available
        if (this.vertexBuffer != null)
            this.vertexBuffer.clear();
        if (this.normalBuffer != null)
            this.normalBuffer.clear();
        if (this.textureBuffer != null)
            this.textureBuffer.clear();

        // Reset the buffer instances
        this.vertexBuffer = null;
        this.normalBuffer = null;
        this.textureBuffer = null;

        // Clear old VBO buffers
        if (this.vboVertexHandle != 0)
            GL15.glDeleteBuffers(this.vboVertexHandle);
        if (this.vboNormalHandle != 0)
            GL15.glDeleteBuffers(this.vboNormalHandle);
        if (this.vboTextureHandle != 0)
            GL15.glDeleteBuffers(this.vboTextureHandle);

        // Reset the VBO handles
        this.vboVertexHandle = 0;
        this.vboNormalHandle = 0;
        this.vboTextureHandle = 0;

        // Reset the vertex and normal count
        this.vertexCount = 0;
        this.normalCount = 0;
    }

    /**
     * Render or draw the mesh using OpenGL.
     */
    public void draw(Material material) {
        // Bind the vertex buffer
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        GL11.glVertexPointer(this.raw.getVertexAxisCount(), GL11.GL_FLOAT, 0, 0L);

        // Bind the normal coordinate buffer if available
        if (hasNormalData()) {
            glBindBuffer(GL_ARRAY_BUFFER, vboNormalHandle);
            GL11.glNormalPointer(GL11.GL_FLOAT, 0, 0L);
        }

        // Bind the texture coordinate buffer if available
        if (hasTextureData()) {
            glBindBuffer(GL_ARRAY_BUFFER, vboTextureHandle);
            GL11.glTexCoordPointer(this.raw.getTextureAxisCount(), GL11.GL_FLOAT, 0, 0L);
        }

        // Enable the client states for the buffers that were bound
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        if (hasNormalData())
            GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
        if (hasTextureData())
            GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        // Draw the mesh
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.vertexCount);

        // Disable the client used states
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        if (hasNormalData())
            GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
        if (hasTextureData())
            GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        // Unbind all buffers
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
}