Mesh - Fish-In-A-Suit/Conquest GitHub Wiki

Prerequisite knowledge

Class layout

Imports

  • import java.nio.FloatBuffer;

  • import java.nio.IntBuffer;

  • import java.util.ArrayList;

  • import static org.lwjgl.opengl.GL11.*;

  • import static org.lwjgl.opengl.GL15.*;

  • import static org.lwjgl.opengl.GL20.*;

  • import static org.lwjgl.opengl.GL30.*;

Private instance fields

  • int vaoID;
  • int verticesVboID;
  • int indicesVboID;
  • int vertexCount;
  • FloatBuffer verticesBuffer;

Public instance fields

Package acces instance fields

  • ArrayList vaos
  • ArrayList vbos

Constructors

  • public Mesh(float[] vertices, int[] indices)

Private methods

  • void bindIndicesBuffer(int[] indices)

Public methods

  • int getVaoID()
  • int getVertexCount()
  • int getVerticesVboID()
  • int getIndicesVboID()
  • void checkVerticesBufferContent(float[] vertices)

Explanation

The Mesh class represents a way to create objects which can be drawn to the screen. The vertex attribute of the mesh delivers all of the information the renderer needs for rendering that object (currently that's indices and shaders).

Instance creation

The constructor Mesh(float[] vertices, int[] indices) enables you to pass the corresponding arrays of vertices and indices to the creation process of the Mesh instance.

First, it sets the value of vertexCount to match the number of indices (vertexCount = indices.length).Then, a new vertex array object is created and bound to the context:

vaoID = glGenVertexArrays();
vaos.add(vaoID);
glBindVertexArray(vaoID);

Then, the indices array is bound to a VBO through the method bindIndicesBuffer(int[] indices (NOTE: Move this method to BufferUtilities class). This method first creates a new VBO object and references it to indicesVboID: indicesVboID = glGenBuffers();. Then, it adds the int value of the vbo to the vbos ArrayList** ( will be used l8r for cleanup purposes): vbos.add(indicesVboID);. After that, it binds the new vbo into context, therefore enabling operations to be performed on it: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVboID);.

Note that GL_ELEMENT_ARRAY_BUFFER is used to indicate that the buffer you're presenting contains the indices of each element in the GL_ARRAY_BUFFER buffer. In this example, the GL_ARRAY_BUFFER is the verticesVboID and the GL_ELEMENT_ARRAY_BUFFER is the indicesVboID. Imagine the following index buffer: {0, 1, 2} {0, 2, 3} and the data buffer contains {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}}. When you call glDrawElements, OpenGL will correctly pick out the vertices 0, 1 and 2 for the first triangle and 0, 2 and 3 for the second.

Just after that, it creates a new IntBuffer called indicesBuffer inside which the contents of the indices array are stored. Then, it sends (buffers) that IntBuffer to the currently bound (active) vbo:

indicesVboID = glGenBuffers();
vbos.add(indicesVboID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVboID);
		
IntBuffer indicesBuffer = BufferUtilities.storeDataInIntBuffer(indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);

A new vertex buffer object for storing the contents of vertices is then created (int verticesVboID = glGenBuffers()) and added to the ArrayList vbos (will be used l8r for cleanup). Then, as previously, we need some sort of storage (a buffer) to store the contents of vertices - they can't be just passed inside the vbo in their raw form. Since the vertices are represented as floats, we'll be using a FloatBuffer. This is achieved by verticesBuffer = BufferUtilities.storeDataInFloatBuffer(vertices);. The method storeDataInFloatBuffer(float[] result) takes in an array of floats and returns a FloatBuffer populated with the input array, which can be read from (it's flipped). This FloatBuffer is assigned to verticesBuffer.

Then, verticesBuffer has to be passed inside the vbo verticesVboID. To achieve this, first bind (activate) verticesVboID by binding it to the GL_ARRAY_BUFFER target in the OpenGL context: glBindBuffer(GL_ARRAY_BUFFER, verticesVboID);. Any further buffer-related method calls will now impact the currently bound buffer - the verticesVboID. For example, when calling glBufferData, it will affect only the currently bound buffer (which is currently in our case verticesVboID)

Then, having bound (activated) verticesVboID, you need to store the vertex data inside it. This is done with the method glBufferData(...): glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);.

The method glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0) stores the currently bound vbo to the specified attribute list of the vao (first parameter is zero, so the verticesVboID will be bound to the attribute list at index 0 of the currently bound vertexArray (which is vaoID). Along with that, some other parameters are specified: 3 represents that each vertex is associated with three values, GL_FLOAT specifies that the contents of the verticesVboID are floats, false denotes non-normalized data, and stride and offset are set to 0 (since we want to start to start "reading" vertices from the beginning).

The methods glBindBuffer(GL_ARRAY_BUFFER, 0) and glBindVertexArray(0) deselect the currently bound vbo and vao, since they are no longer used.

Cleanup

The method cleanUp() is responsible for disabling and deleting all of the vbos and vaos associated with a Mesh instance after the program ends.

First, the attribute array at index 0 is disabled: glDisableVertexAttribArray(0);. Then, the verticesVboID is deselected (unbound) and deleted:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(verticesVboID);

Then, the indicesVboID is unbound and deleted:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(indicesVboID);

Then, the currently bound vao is unbound and deleted:

glBindVertexArray(0);
glDeleteVertexArrays(vaoID);
⚠️ **GitHub.com Fallback** ⚠️