Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package dataAccess.lwjgl; import dataAccess.TextureData; import toolbox.Convert; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import game.entity.models.RawModel; import org.lwjgl.opengl.EXTTextureFilterAnisotropic; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GLContext; import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.TextureLoader; import static toolbox.AttributeListPosition.NORMAL_VECTORS; import static toolbox.AttributeListPosition.TEXTURE_COORDS; import static toolbox.AttributeListPosition.VERTEX_POSITIONS; import toolbox.Settings; /** * An instance of this class is responsible for loading data into a VAO and * creating a VAO. * * @author Blackened */ public class VAO_Loader { //<editor-fold defaultstate="collapsed" desc="Static Properties"> /** * Keeps track of all VAO's, VBO's and textures, so they can be deleted from * memory once the program exits. */ private static final List<Integer> vaos = new ArrayList<>(); private static final List<Integer> vbos = new ArrayList<>(); private static final Map<String, Integer> textureMap = new HashMap<>(); //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Static Methods"> /** * Creates a new VAO, binds the data to one of the attribute lists. * * @param modelData The data to be bound to the VAO. * @return A new instance of RawModel containing the VAO ID and vertex * count. */ public static RawModel loadToVAO(ModelData modelData) { int vaoID = createVAO(); unbindVAO(); bindIndicesBuffer(vaoID, modelData.getIndices()); storeDataInAttributeList(vaoID, VERTEX_POSITIONS, 3, modelData.getVertexPositions()); storeDataInAttributeList(vaoID, TEXTURE_COORDS, 2, modelData.getTextureCoords()); storeDataInAttributeList(vaoID, NORMAL_VECTORS, 3, modelData.getNormals()); RawModel rawModel = new RawModel(vaoID, modelData.getIndices().length); return rawModel; } /** * Used for fonts so far! * * @param positions * @param textureCoords * @return */ public static int loadToVAO(float[] positions, float[] textureCoords) { int vaoID = createVAO(); unbindVAO(); storeDataInAttributeList(vaoID, VERTEX_POSITIONS, 2, positions); storeDataInAttributeList(vaoID, TEXTURE_COORDS, 2, textureCoords); return vaoID; } /** * Used for cube maps so far! * * @param positions * @param dimensions * @return */ public static RawModel loadToVAO(float[] positions, int dimensions) { int vaoID = createVAO(); storeDataInAttributeList(vaoID, VERTEX_POSITIONS, dimensions, positions); unbindVAO(); return new RawModel(vaoID, positions.length / dimensions); } public static int loadTexture(File file) { int textureID; if (textureMap.containsKey(file.getAbsolutePath())) { textureID = textureMap.get(file.getAbsolutePath()); } else { Texture texture = null; try { texture = TextureLoader.getTexture("PNG", new FileInputStream(file)); } catch (IOException ex) { Logger.getLogger(VAO_Loader.class.getName()).log(Level.SEVERE, null, ex); } textureID = texture.getTextureID(); textureMap.put(file.getAbsolutePath(), textureID); } GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0f); if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) { if (Settings.ANISOTROPIC_FILTERING) { float amount = Math.min(4f, GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, amount); } } else { System.out.println("no anisotropic filtering possible!"); } return textureID; } public static int loadCubeMap(String... textureFiles) { int texID = GL11.glGenTextures(); GL13.glActiveTexture(texID); GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID); for (int i = 0; i < textureFiles.length; i++) { TextureData data = dataAccess.fileLoaders.TextureLoader .decodeTextureFile("res/textures/skybox/" + textureFiles[i] + ".png"); GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data.getBuffer()); } GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE); GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE); textureMap.put("cubeMap", texID); return texID; } /** * Creates a new VAO. * * @return Its ID that points to the VAO in memory. */ private static int createVAO() { int vaoID = GL30.glGenVertexArrays(); // Adds VAO to list so that it can be cleared when needed. vaos.add(vaoID); return vaoID; } /** * Stores data in an attribute list of a VAO. * * @param vaoID The id of the VAO to which data will be added. * @param attributeNumber The number of the attribute list in which the data * will be stored. * @param data The data that will be stored in the attribute list. */ private static void storeDataInAttributeList(int vaoID, int attributeNumber, int coordinateSize, float[] data) { // bind VAO so that it can be used. bindVAO(vaoID); // Create new VBO. int vboID = GL15.glGenBuffers(); // Adds VBO to list so that it can be cleared when needed. vbos.add(vboID); // VBO has to be bound aswel. bindArrayBuffer(vboID); // Converts float array to an instance of FloatBuffer, which can // be stored in a VBO. FloatBuffer buffer = Convert.toReadableFloatBuffer(data); // Puts the buffer into the VBO, and GL_STATIC_DRAW tells it that it // won't ever be modified. GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); // Specifies that this is for the Vertex Array. GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0); // Unbind the VBO. unbindArrayBuffer(); // unbind VAO so that another may be bound. unbindVAO(); } /** * Stores data in an attribute list of a VAO. * * @param vaoID The id of the VAO to which data will be added. * @param attributeNumber The number of the attribute list in which the data * will be stored. * @param data The data that will be stored in the attribute list. */ private static void bindIndicesBuffer(int vaoID, int[] data) { // bind VAO so that it can be used. bindVAO(vaoID); // Create new VBO. int vboID = GL15.glGenBuffers(); // Adds VBO to list so that it can be cleared when needed. vbos.add(vboID); // VBO has to be bound aswel. bindElementArrayBuffer(vboID); // Converts int array to an instance of IntBuffer, which can // be stored in a VBO. IntBuffer buffer = Convert.toReadableIntBuffer(data); // Puts the buffer into the VBO, and GL_STATIC_DRAW tells it that it // won't ever be modified. GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); // Unbind the VBO. //unbindElementArrayBuffer(); // unbind VAO so that another may be bound. unbindVAO(); } /** * Unbinds the VAO. */ private static void unbindVAO() { GL30.glBindVertexArray(0); } /** * Binds the VAO, so that it can be modified. * * @param vaoID The ID of the VAO that will be bound. */ private static void bindVAO(int vaoID) { GL30.glBindVertexArray(vaoID); } /** * Binds the VBO, so that it can be modified. * * @param vboID The ID of the VBO that will be bound. */ private static void bindArrayBuffer(int vboID) { GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID); } /** * Binds the VBO, so that it can be modified. * * @param vboID The ID of the VBO that will be bound. */ private static void bindElementArrayBuffer(int vboID) { GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID); } /** * Unbinds the VBO. */ private static void unbindElementArrayBuffer() { GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); } /** * Unbinds the VBO. */ private static void unbindArrayBuffer() { GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } /** * Cleans the memory of all VAO's and VBO's. */ public static void cleanUp() { vaos.forEach(x -> GL30.glDeleteVertexArrays(x)); vbos.forEach(x -> GL15.glDeleteBuffers(x)); textureMap.values().forEach(x -> GL11.glDeleteTextures(x)); } //</editor-fold> }