Java tutorial
/******************************************************************************* * MIT License * * Copyright (c) 2016 Ashur Rafiev * * 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 com.xrbpowered.gl.res; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import java.security.InvalidParameterException; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL31; import com.xrbpowered.gl.res.shaders.VertexInfo; public class StaticMesh { private FloatBuffer vertexBuffer = null; private int vaoId; private int vboId; private int vboiId = GL11.GL_INVALID_VALUE; private int countElements = 0; private int countAttribs; private int drawMode = GL11.GL_TRIANGLES; public StaticMesh(VertexInfo info, float[] vertexData, short[] indexData) { this(info, vertexData, indexData, 3, false); } public StaticMesh(VertexInfo info, float[] vertexData, int verticesPerElement, int countElements, boolean dynamic) { this(info, vertexData, null, verticesPerElement, dynamic); } public StaticMesh(VertexInfo info, float[] vertexData, short[] indexData, int verticesPerElement, boolean dynamic) { FloatBuffer vertexBuffer = BufferUtils.createByteBuffer(vertexData.length * 4).asFloatBuffer(); vertexBuffer.put(vertexData).flip(); int countElements; ShortBuffer indexBuffer = null; if (indexData != null) { countElements = indexData.length; indexBuffer = BufferUtils.createByteBuffer(countElements * 2).asShortBuffer(); indexBuffer.put(indexData).flip(); } else { countElements = vertexData.length / info.getSkip(); } create(info, vertexBuffer, indexBuffer, countElements, verticesPerElement, dynamic); } public StaticMesh(VertexInfo info, FloatBuffer vertexBuffer, ShortBuffer indexBuffer, int countElements, int verticesPerElement, boolean dynamic) { create(info, vertexBuffer, indexBuffer, countElements, verticesPerElement, dynamic); } private void create(VertexInfo info, FloatBuffer vertexBuffer, ShortBuffer indexBuffer, int countElements, int verticesPerElement, boolean dynamic) { this.countElements = countElements; this.drawMode = getDrawMode(verticesPerElement); int usage = dynamic ? GL15.GL_DYNAMIC_DRAW : GL15.GL_STATIC_DRAW; vaoId = GL30.glGenVertexArrays(); GL30.glBindVertexArray(vaoId); vboId = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexBuffer, usage); this.countAttribs = info.getAttributeCount(); info.initAttribPointers(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL30.glBindVertexArray(0); if (indexBuffer != null) { vboiId = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId); GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBuffer, usage); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); } } public static int getDrawMode(int verticesPerElement) { switch (verticesPerElement) { case 1: return GL11.GL_POINTS; case 2: return GL11.GL_LINES; case 3: return GL11.GL_TRIANGLES; default: throw new InvalidParameterException(); } } public void bindVAO() { GL30.glBindVertexArray(vaoId); } public void unbindVAO() { GL30.glBindVertexArray(0); } public void updateVertexData(float[] vertexData) { vertexBuffer.clear(); vertexBuffer.put(vertexData); vertexBuffer.flip(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId); GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, vertexBuffer); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } public void updateCountElements(int count) { this.countElements = count; } public int countTris() { return countElements / 3; } public void enableDraw(int[] attribMask) { GL30.glBindVertexArray(vaoId); if (attribMask == null) { for (int i = 0; i < countAttribs; i++) GL20.glEnableVertexAttribArray(i); } else { for (int i = 0; i < attribMask.length; i++) GL20.glEnableVertexAttribArray(attribMask[i]); } } public void disableDraw() { GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); for (int i = 0; i < countAttribs; i++) GL20.glDisableVertexAttribArray(i); GL30.glBindVertexArray(0); } public void drawCallInstanced(int count) { if (vboiId != GL11.GL_INVALID_VALUE) { GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId); GL31.glDrawElementsInstanced(drawMode, countElements, GL11.GL_UNSIGNED_SHORT, 0, count); } else { GL31.glDrawArraysInstanced(drawMode, 0, countElements, count); } } public void drawCall() { if (vboiId != GL11.GL_INVALID_VALUE) { GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId); GL11.glDrawElements(drawMode, countElements, GL11.GL_UNSIGNED_SHORT, 0); } else { GL11.glDrawArrays(drawMode, 0, countElements); } } public void draw(int[] attribMask) { enableDraw(attribMask); drawCall(); disableDraw(); } public void draw() { draw(null); } public void destroy() { GL30.glBindVertexArray(vaoId); for (int i = 0; i < countAttribs; i++) GL20.glDisableVertexAttribArray(i); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL15.glDeleteBuffers(vboId); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); if (vboiId != GL11.GL_INVALID_VALUE) GL15.glDeleteBuffers(vboiId); GL30.glBindVertexArray(0); GL30.glDeleteVertexArrays(vaoId); } }