package electrosphere.renderer; import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.entity.CameraEntityUtils; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import electrosphere.main.Globals; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.BufferUtils; import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent; import static org.lwjgl.glfw.GLFW.glfwMaximizeWindow; import org.lwjgl.opengl.GL11; import static org.lwjgl.opengl.GL11.GL_FLOAT; import static org.lwjgl.opengl.GL11.GL_LEQUAL; import static org.lwjgl.opengl.GL11.GL_LESS; import static org.lwjgl.opengl.GL11.GL_TRIANGLES; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; import org.lwjgl.opengl.GL15; import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; import static org.lwjgl.opengl.GL15.glBindBuffer; import static org.lwjgl.opengl.GL15.glGenBuffers; import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glUniform3fv; import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import static org.lwjgl.opengl.GL20.glUseProgram; import static org.lwjgl.opengl.GL20.glVertexAttribPointer; import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glGenVertexArrays; /** * * @author amaterasu */ public class RenderUtils { static int createScreenTextureVAO(){ int rVal = glGenVertexArrays(); glBindVertexArray(rVal); //vertices FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(12); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.put(-1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.put( 1.0f); VertexArrayBufferData.flip(); int vertexBuffer = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); GL15.glBufferData(GL_ARRAY_BUFFER, VertexArrayBufferData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0); glEnableVertexAttribArray(0); //texture coords FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(12); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.put(0.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.put(1.0f); TextureArrayBufferData.flip(); int textureCoordBuffer = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, textureCoordBuffer); GL15.glBufferData(GL_ARRAY_BUFFER, TextureArrayBufferData, GL_STATIC_DRAW); glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0); glEnableVertexAttribArray(1); return rVal; } public static void recaptureScreen(){ //Makes the window that was just created the current OS-level window context glfwMakeContextCurrent(Globals.window); //Maximize it glfwMaximizeWindow(Globals.window); //apply mouse controls state if(Globals.controlHandler.isMouseVisible()){ Globals.controlHandler.showMouse(); } else { Globals.controlHandler.hideMouse(); } } public static Model createSkyboxModel(Material optionalMaterial){ Model skyboxModel = new Model(); skyboxModel.meshes = new ArrayList(); skyboxModel.modelMatrix = new Matrix4f(); boolean apply_lighting = false; boolean has_bones = false; Mesh skyboxmesh = new Mesh(){ @Override public void complexDraw(boolean setShader, boolean bufferStandardUniforms, boolean bufferNonStandardUniforms, boolean useMaterial, boolean useShadowMap, boolean setBones, boolean useLight){ if(setShader){ GL11.glDepthFunc(GL_LEQUAL); glUseProgram(shader.shaderProgram); } if(useMaterial){ if(material == null){ Globals.materialDefault.apply_material(0,1); Iterator colorIterator = Globals.skyboxColors.iterator(); int counter = 0; float[] temp = new float[3]; while(colorIterator.hasNext()){ Vector3f colorCurrent = colorIterator.next(); temp[0] = colorCurrent.x / 255.0f; temp[1] = colorCurrent.y / 255.0f; temp[2] = colorCurrent.z / 255.0f; // System.out.println("colors[" + counter + "] " + temp[0] + " " + temp[1] + " " + temp[2]); glUniform3fv(glGetUniformLocation(shader.shaderProgram, "colors[" + counter + "]"), temp); counter++; } } } glBindVertexArray(vertexArrayObject); if(bufferStandardUniforms){ //buffer model/view/proj matrices glUniformMatrix4fv(shader.shaderVertexModelLoc, false, parent.modelMatrix.get(new float[16])); glUniformMatrix4fv(shader.shaderVertexViewLoc, false, new Matrix4f(Globals.viewMatrix).scale(100).get(new float[16])); glUniformMatrix4fv(shader.shaderVertexProjectionLoc, false, Globals.projectionMatrix.get(new float[16])); glUniform3fv(shader.shaderVertexViewPosLoc, CameraEntityUtils.getCameraEye(Globals.playerCamera).get(BufferUtils.createFloatBuffer(3))); } GL11.glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_INT, 0); glBindVertexArray(0); if(setShader){ GL11.glDepthFunc(GL_LESS); } } }; skyboxmesh.mesh = null; // // VAO // skyboxmesh.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(skyboxmesh.vertexArrayObject); float[] vertexcoords = { 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,-100.0f, 100.0f,-100.0f, 100.0f, 100.0f,-100.0f,-100.0f, -100.0f, 100.0f, 100.0f, -100.0f, 100.0f,-100.0f, -100.0f,-100.0f, 100.0f, -100.0f,-100.0f,-100.0f, }; // //Buffer data to GPU // try { skyboxmesh.vertexCount = vertexcoords.length / 3; FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount * 3); float[] temp = new float[3]; for (int i = 0; i < skyboxmesh.vertexCount; i++) { temp[0] = vertexcoords[i * 3 + 0]; temp[1] = vertexcoords[i * 3 + 1]; temp[2] = vertexcoords[i * 3 + 2]; VertexArrayBufferData.put(temp); } VertexArrayBufferData.flip(); skyboxmesh.buffer_vertices(VertexArrayBufferData, 3); } catch (NullPointerException ex){ ex.printStackTrace(); } int[] facedata = { 0,1,4, 1,4,5, 1,3,5, 3,5,7, 4,5,7, 4,6,7, 0,2,4, 2,4,6, 0,1,2, 1,2,3, 2,3,6, 3,6,7, }; // // FACES // skyboxmesh.faceCount = facedata.length / 3; skyboxmesh.elementCount = facedata.length; IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(skyboxmesh.elementCount); for(int i = 0; i < skyboxmesh.faceCount; i++){ int[] temp = new int[3]; temp[0] = facedata[i * 3 + 0]; temp[1] = facedata[i * 3 + 1]; temp[2] = facedata[i * 3 + 2]; elementArrayBufferData.put(temp); } elementArrayBufferData.flip(); skyboxmesh.buffer_faces(elementArrayBufferData); if(optionalMaterial != null){ // // NORMALS // try { skyboxmesh.normalCount = vertexcoords.length / 3; FloatBuffer NormalArrayBufferData; if(skyboxmesh.normalCount > 0){ NormalArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.normalCount * 3); float[] temp = new float[3]; for (int i = 0; i < skyboxmesh.normalCount; i++) { temp[0] = vertexcoords[i * 3 + 0]; temp[1] = vertexcoords[i * 3 + 1]; temp[2] = vertexcoords[i * 3 + 2]; NormalArrayBufferData.put(temp); } NormalArrayBufferData.flip(); skyboxmesh.buffer_normals(NormalArrayBufferData, 3); } } catch (NullPointerException ex){ ex.printStackTrace(); } // // TEXTURE COORDINATES // /*try { skyboxmesh.textureCoordCount = mesh.mTextureCoords(0).capacity(); FloatBuffer TextureArrayBufferData; if(skyboxmesh.textureCoordCount > 0){ TextureArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.textureCoordCount * 2); float[] temp = new float[2]; for (int i = 0; i < skyboxmesh.textureCoordCount; i++) { AIVector3D normal = texturecoords.get(i); temp[0] = normal.x(); temp[1] = normal.y(); // temp[2] = normal.z(); TextureArrayBufferData.put(temp); } TextureArrayBufferData.flip(); skyboxmesh.buffer_texture_coords(TextureArrayBufferData); } } catch (NullPointerException ex){ ex.printStackTrace(); } skyboxmesh.shader = ShaderProgram.smart_assemble_shader(has_bones, apply_lighting); skybox_model.materials.add(optionalMaterial); */ } else { skyboxmesh.shader = ShaderProgram.loadSpecificShader("/Shaders/skybox/VertexShaderNoTexture.vs", "/Shaders/skybox/FragmentShaderNoTexture.fs"); try { FloatBuffer ColorArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount); for (int i = 0; i < skyboxmesh.vertexCount; i++) { ColorArrayBufferData.put(i); } ColorArrayBufferData.flip(); int idBuffer = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, idBuffer); GL15.glBufferData(GL_ARRAY_BUFFER, ColorArrayBufferData, GL_STATIC_DRAW); glVertexAttribPointer(1, 1, GL11.GL_FLOAT, false, 0, 0); glEnableVertexAttribArray(1); } catch (NullPointerException ex){ ex.printStackTrace(); } } skyboxmesh.hasBones = false; glBindVertexArray(0); skyboxmesh.nodeID = "skybox"; skyboxmesh.parent = skyboxModel; skyboxModel.meshes.add(skyboxmesh); return skyboxModel; } public static Model createParticleModel(){ Model particleModel = new Model(); particleModel.meshes = new ArrayList(); particleModel.modelMatrix = new Matrix4f(); Mesh particleMesh = new Mesh(); particleMesh.mesh = null; // // VAO // particleMesh.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(particleMesh.vertexArrayObject); float[] vertexcoords = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, }; // //Buffer data to GPU // try { particleMesh.vertexCount = vertexcoords.length / 3; FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(particleMesh.vertexCount * 3); float[] temp = new float[3]; for (int i = 0; i < particleMesh.vertexCount; i++) { temp[0] = vertexcoords[i * 3 + 0]; temp[1] = vertexcoords[i * 3 + 1]; temp[2] = vertexcoords[i * 3 + 2]; VertexArrayBufferData.put(temp); } VertexArrayBufferData.flip(); particleMesh.buffer_vertices(VertexArrayBufferData, 3); } catch (NullPointerException ex){ ex.printStackTrace(); } int[] facedata = { 0,1,2, 1,2,3, }; // // FACES // particleMesh.faceCount = facedata.length / 3; particleMesh.elementCount = facedata.length; IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(particleMesh.elementCount); for(int i = 0; i < particleMesh.faceCount; i++){ int[] temp = new int[3]; temp[0] = facedata[i * 3 + 0]; temp[1] = facedata[i * 3 + 1]; temp[2] = facedata[i * 3 + 2]; elementArrayBufferData.put(temp); } elementArrayBufferData.flip(); particleMesh.buffer_faces(elementArrayBufferData); // // TEXTURE COORDS // FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); float[] texturedata = { 0,0, 1,0, 0,1, 1,1 }; texture_coords.put(texturedata); texture_coords.flip(); particleMesh.buffer_texture_coords(texture_coords, 2); particleMesh.shader = ShaderProgram.loadSpecificShader("Shaders/particleBillboard/particleBillboard.vs", "Shaders/particleBillboard/particleBillboard.fs"); particleMesh.hasBones = false; glBindVertexArray(0); particleMesh.nodeID = "particleBillboard"; particleMesh.parent = particleModel; particleModel.meshes.add(particleMesh); return particleModel; } public static Model createPlaneModel(){ Model rVal = new Model(); rVal.meshes = new ArrayList(); rVal.modelMatrix = new Matrix4f(); Mesh planeMesh = new Mesh(); planeMesh.mesh = null; // // VAO // planeMesh.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(planeMesh.vertexArrayObject); float[] vertexcoords = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, }; // //Buffer data to GPU // try { planeMesh.vertexCount = vertexcoords.length / 3; FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(planeMesh.vertexCount * 3); float[] temp = new float[3]; for (int i = 0; i < planeMesh.vertexCount; i++) { temp[0] = vertexcoords[i * 3 + 0]; temp[1] = vertexcoords[i * 3 + 1]; temp[2] = vertexcoords[i * 3 + 2]; VertexArrayBufferData.put(temp); } VertexArrayBufferData.flip(); planeMesh.buffer_vertices(VertexArrayBufferData, 3); } catch (NullPointerException ex){ ex.printStackTrace(); } int[] facedata = { 0,1,2, 1,2,3, }; // // FACES // planeMesh.faceCount = facedata.length / 3; planeMesh.elementCount = facedata.length; IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(planeMesh.elementCount); for(int i = 0; i < planeMesh.faceCount; i++){ int[] temp = new int[3]; temp[0] = facedata[i * 3 + 0]; temp[1] = facedata[i * 3 + 1]; temp[2] = facedata[i * 3 + 2]; elementArrayBufferData.put(temp); } elementArrayBufferData.flip(); planeMesh.buffer_faces(elementArrayBufferData); // // TEXTURE COORDS // FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); float[] texturedata = { 0,1, 1,1, 0,0, 1,0 }; texture_coords.put(texturedata); texture_coords.flip(); planeMesh.buffer_texture_coords(texture_coords, 2); planeMesh.shader = ShaderProgram.loadSpecificShader("Shaders/plane/plane.vs", "Shaders/plane/plane.fs"); planeMesh.hasBones = false; glBindVertexArray(0); planeMesh.nodeID = "plane"; planeMesh.parent = rVal; rVal.meshes.add(planeMesh); return rVal; } public static Model createBitmapDisplay(){ Model rVal = new Model(); rVal.meshes = new ArrayList(); Mesh m = new Mesh(); m.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(m.vertexArrayObject); //vertices FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(12); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 0); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 1); VertexArrayBufferData.flip(); IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); faceArrayBufferData.put(0); faceArrayBufferData.put(1); faceArrayBufferData.put(2); faceArrayBufferData.put(3); faceArrayBufferData.put(4); faceArrayBufferData.put(5); faceArrayBufferData.flip(); //texture coords FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(12); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(1); TextureArrayBufferData.flip(); //buffer vertices m.buffer_vertices(VertexArrayBufferData, 2); //buffer normals m.buffer_normals(VertexArrayBufferData, 2); //buffer faces m.buffer_faces(faceArrayBufferData); //buffer texture coords m.buffer_texture_coords(TextureArrayBufferData, 2); m.shader = ShaderProgram.loadSpecificShader("/Shaders/font/basicbitmap/basicbitmap.vs", "/Shaders/font/basicbitmap/basicbitmap.fs"); glBindVertexArray(0); m.parent = rVal; m.nodeID = AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME; Material uiMat = new Material(); Globals.assetManager.addTexturePathtoQueue("/Textures/Fonts/myfont1-harsher.png"); uiMat.set_diffuse("/Textures/Fonts/myfont1-harsher.png"); uiMat.set_specular("/Textures/Fonts/myfont1-harsher.png"); m.setMaterial(uiMat); rVal.materials = new ArrayList(); rVal.materials.add(uiMat); rVal.meshes.add(m); return rVal; } public static Model createBitmapCharacter(){ Model rVal = new Model(); rVal.meshes = new ArrayList(); Mesh m = new Mesh(); m.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(m.vertexArrayObject); //vertices FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(12); VertexArrayBufferData.put(-1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put(-1); VertexArrayBufferData.put(-1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put(-1); VertexArrayBufferData.put(-1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put(-1); VertexArrayBufferData.put( 1); VertexArrayBufferData.put( 1); VertexArrayBufferData.flip(); IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); faceArrayBufferData.put(0); faceArrayBufferData.put(1); faceArrayBufferData.put(2); faceArrayBufferData.put(3); faceArrayBufferData.put(4); faceArrayBufferData.put(5); faceArrayBufferData.flip(); //texture coords FloatBuffer TextureArrayBufferData = BufferUtils.createFloatBuffer(12); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(1); TextureArrayBufferData.put(0); TextureArrayBufferData.put(1); TextureArrayBufferData.put(1); TextureArrayBufferData.flip(); //buffer vertices m.buffer_vertices(VertexArrayBufferData, 2); //buffer normals m.buffer_normals(VertexArrayBufferData, 2); //buffer faces m.buffer_faces(faceArrayBufferData); //buffer texture coords m.buffer_texture_coords(TextureArrayBufferData, 2); m.shader = ShaderProgram.loadSpecificShader("/Shaders/font/bitmapchar/bitmapchar.vs", "/Shaders/font/bitmapchar/bitmapchar.fs"); glBindVertexArray(0); m.parent = rVal; m.nodeID = AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME; Material uiMat = new Material(); Globals.assetManager.addTexturePathtoQueue("/Textures/Fonts/myfont1-harsher.png"); uiMat.set_diffuse("/Textures/Fonts/myfont1-harsher.png"); uiMat.set_specular("/Textures/Fonts/myfont1-harsher.png"); m.setMaterial(uiMat); rVal.materials = new ArrayList(); rVal.materials.add(uiMat); rVal.meshes.add(m); return rVal; } public static Model createTerrainModelPrecomputedShader(float[][] heightfield, float[][] texturemap, ShaderProgram program, int stride){ Model rVal = new Model(); rVal.meshes = new ArrayList(); Mesh m = new Mesh(); int width = heightfield.length; int height = heightfield[0].length; int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); // System.out.println(actualWidth + " " + actualHeight); // System.out.println((actualWidth - 1) * (actualHeight - 1)); FloatBuffer vertices; FloatBuffer normals; IntBuffer faces; FloatBuffer texture_coords; FloatBuffer textureIndices; if(stride * actualWidth > width){ int drawWidth = actualWidth + 1; int drawHeight = actualHeight + 1; vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); } else { vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); } int incrementer = 0; int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; for(int x = 0; x < width - 1; x = x + stride){ for(int y = 0; y < height - 1; y = y + stride){ //deal with vertex //0,0 vertices.put(x); vertices.put(heightfield[x][y]); vertices.put(y); //1,0 vertices.put(x + stride); vertices.put(heightfield[x+stride][y]); vertices.put(y); //0,1 vertices.put(x); vertices.put(heightfield[x][y+stride]); vertices.put(y + stride); //1,1 vertices.put(x + stride); vertices.put(heightfield[x+stride][y+stride]); vertices.put(y + stride); //deal with normal Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); //deal with texture coordinates // if(x / stride % 2 == 0){ // if(y / stride % 2 == 0){ // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(1); // texture_coords.put(1); // } else { // texture_coords.put(0); // texture_coords.put(1); // } // } else { // if(y / stride % 2 == 0){ // texture_coords.put(1); // texture_coords.put(0); // } else { // texture_coords.put(1); // texture_coords.put(1); // } // } texture_coords.put(0); texture_coords.put(0); texture_coords.put(1); texture_coords.put(0); texture_coords.put(0); texture_coords.put(1); texture_coords.put(1); texture_coords.put(1); if(x + stride < width - 1 && y + stride < height - 1){ // texturemap[x+stride][y+stride]; for(int i = 0; i < 4 ; i++){ // textureIndices.put(1); // textureIndices.put(0); // textureIndices.put(0); // textureIndices.put(0); textureIndices.put(texturemap[x][y]); textureIndices.put(texturemap[x+stride][y]); textureIndices.put(texturemap[x][y+stride]); textureIndices.put(texturemap[x+stride][y+stride]); } } else { for(int i = 0; i < 4 ; i++){ textureIndices.put(0); textureIndices.put(0); textureIndices.put(0); textureIndices.put(0); } } //deal with faces if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ faces.put(incrementer * 4 + 0); faces.put(incrementer * 4 + 1); faces.put(incrementer * 4 + 2); faces.put(incrementer * 4 + 1); faces.put(incrementer * 4 + 2); faces.put(incrementer * 4 + 3); } incrementer++; } } vertices.flip(); normals.flip(); faces.flip(); texture_coords.flip(); textureIndices.flip(); m.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(m.vertexArrayObject); //buffer vertices m.buffer_vertices(vertices, 3); //buffer normals m.buffer_normals(normals, 3); //buffer faces m.buffer_faces(faces); //buffer texture coords m.buffer_texture_coords(texture_coords, 2); //texture indices m.bufferCustomFloatAttribArray(textureIndices, 4, 5); m.shader = program; glBindVertexArray(0); m.parent = rVal; m.hasBones = false; Material groundMat = new Material(); Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse("/Textures/Ground/Dirt1.png"); groundMat.set_specular("/Textures/Ground/Dirt1.png"); m.setMaterial(groundMat); rVal.meshes.add(m); return rVal; } static float MINIMIZATION_DIFF_MAX = 0.1f; public static Model createMinimizedTerrainModelPrecomputedShader(float[][] heightfield, float[][] texturemap, ShaderProgram program, int stride){ class QuadToGenerate { //coords are inclusive int startX; int endX; int startY; int endY; float diff; float min; float max; float texture; boolean homogeneousTexture; QuadToGenerate(int startX, int startY, int endX, int endY, float diff, float min, float max, boolean homogeneousTexture, float texture){ this.startX = startX; this.startY = startY; this.endX = endX; this.endY = endY; this.diff = diff; this.min = min; this.max = max; this.texture = texture; this.homogeneousTexture = homogeneousTexture; } } Model rVal = new Model(); rVal.meshes = new ArrayList(); Mesh m = new Mesh(); int width = heightfield.length; int height = heightfield[0].length; int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); // System.out.println(actualWidth + " " + actualHeight); // System.out.println((actualWidth - 1) * (actualHeight - 1)); FloatBuffer vertices; FloatBuffer normals; IntBuffer faces; FloatBuffer texture_coords; FloatBuffer textureIndices; if(stride * actualWidth > width){ int drawWidth = actualWidth + 1; int drawHeight = actualHeight + 1; vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); } else { vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); } //merge along y List firstPhaseQuads = new LinkedList(); QuadToGenerate quadCurrent = null; float minVal = 0; float maxVal = 0; int textureVal = -1; for(int x = 0; x < width - 1; x = x + stride){ quadCurrent = null; for(int y = 0; y < height - 1; y = y + stride){ if((x == 5 && y == 2)){ // System.out.println(quadCurrent); // continue; } if(quadCurrent == null){ minVal = 100000000; maxVal = 0; textureVal = -1; //minval if(heightfield[x][y] < minVal){ minVal = heightfield[x][y]; } if(heightfield[x+stride][y] < minVal){ minVal = heightfield[x+stride][y]; } if(heightfield[x][y+stride] < minVal){ minVal = heightfield[x][y+stride]; } if(heightfield[x+stride][y+stride] < minVal){ minVal = heightfield[x+stride][y+stride]; } //maxval if(heightfield[x][y] > maxVal){ maxVal = heightfield[x][y]; } if(heightfield[x+stride][y] > maxVal){ maxVal = heightfield[x+stride][y]; } if(heightfield[x][y+stride] > maxVal){ maxVal = heightfield[x][y+stride]; } if(heightfield[x+stride][y+stride] > maxVal){ maxVal = heightfield[x+stride][y+stride]; } boolean textureMatch = false; float texture = -1; if(x+stride < width - 1 && y+stride < height -1 && texturemap[x][y] == texturemap[x+stride][y] && texturemap[x][y] == texturemap[x][y+stride] && texturemap[x][y] == texturemap[x+stride][y+stride]){ textureMatch = true; texture = texturemap[x][y]; } else { // if(x > 8 && (x+stride < width - 1) && (y+stride < height -1)){ // System.out.println( // (x+stride < width - 1) + " " + // (y+stride < height -1) + " " + // (texturemap[x][y] == texturemap[x+stride][y]) + " " + // (texturemap[x][y] == texturemap[x][y+stride]) + " " + // (texturemap[x][y] == texturemap[x+stride][y+stride]) // ); // } } if(textureMatch){ quadCurrent = new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture); } else { firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture)); // quadCurrent = null; } } else { float newMin = minVal; float newMax = maxVal; //min if(heightfield[x][y+stride] < newMin){ newMin = heightfield[x][y+stride]; } if(heightfield[x+stride][y+stride] < newMin){ newMin = heightfield[x+stride][y+stride]; } //max if(heightfield[x][y+stride] > newMax){ newMax = heightfield[x][y+stride]; } if(heightfield[x+stride][y+stride] > newMax){ newMax = heightfield[x+stride][y+stride]; } if(y+stride < height - 1 && x+stride < width - 1){ if(newMax - newMin < MINIMIZATION_DIFF_MAX && quadCurrent.texture == texturemap[x+stride][y] && quadCurrent.texture == texturemap[x ][y+stride] && quadCurrent.texture == texturemap[x+stride][y+stride] && quadCurrent.homogeneousTexture ){ //add to quad quadCurrent.endY = y + stride; quadCurrent.diff = newMax - newMin; quadCurrent.min = newMax; quadCurrent.max = newMax; } else { //push quad firstPhaseQuads.add(quadCurrent); firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,false,0)); quadCurrent = null; // System.out.println("Push"); } } else { if(newMax - newMin < MINIMIZATION_DIFF_MAX){ //add to quad quadCurrent.endY = y + stride; quadCurrent.diff = newMax - newMin; quadCurrent.min = newMax; quadCurrent.max = newMax; } else { //push quad firstPhaseQuads.add(quadCurrent); quadCurrent = null; // System.out.println("Push"); } } } } if(quadCurrent != null){ firstPhaseQuads.add(quadCurrent); } } List finalQuads = new LinkedList(); // for(QuadToGenerate current : firstPhaseQuads){ // finalQuads.add(current); // } // System.out.println(finalQuads.size()); //merge along x // QuadToGenerate currentQuad = null; List toSkip = new LinkedList(); for(QuadToGenerate currentQuad : firstPhaseQuads){ // toRemove.clear(); if(toSkip.contains(currentQuad)){ continue; } for(QuadToGenerate currentPotentialMatch : firstPhaseQuads){ if(currentPotentialMatch.startX <= currentQuad.startX){ continue; } if(currentPotentialMatch.startX > currentQuad.endX){ break; } if(currentPotentialMatch.startY != currentQuad.startY){ continue; } if(currentPotentialMatch.endY != currentQuad.endY){ continue; } if( !(currentQuad.homogeneousTexture && currentPotentialMatch.homogeneousTexture && currentQuad.texture == currentPotentialMatch.texture) ){ continue; } if(currentQuad.min < currentPotentialMatch.min && currentQuad.max < currentPotentialMatch.max){ float min = currentQuad.min; float max = currentPotentialMatch.max; if(max - min < MINIMIZATION_DIFF_MAX){ currentQuad.endX = currentPotentialMatch.endX; currentQuad.max = currentPotentialMatch.max; toSkip.add(currentPotentialMatch); } } else if(currentQuad.min > currentPotentialMatch.min && currentQuad.max > currentPotentialMatch.max){ float min = currentPotentialMatch.min; float max = currentQuad.max; if(max - min < MINIMIZATION_DIFF_MAX){ currentQuad.endX = currentPotentialMatch.endX; currentQuad.min = currentPotentialMatch.min; toSkip.add(currentPotentialMatch); } } else { if(currentQuad.min < currentPotentialMatch.min){ currentQuad.endX = currentPotentialMatch.endX; } else { currentQuad.endX = currentPotentialMatch.endX; currentQuad.min = currentPotentialMatch.min; currentQuad.max = currentPotentialMatch.max; } toSkip.add(currentPotentialMatch); } } finalQuads.add(currentQuad); } // for(QuadToGenerate currentIteration : firstPhaseQuads){ // if(currentQuad == null){ // currentQuad = currentIteration; // } else { // //if should merge: // if( // currentQuad.homogeneousTexture && // currentIteration.homogeneousTexture && // currentQuad.texture == currentIteration.texture // ){ // if(currentQuad.min < currentIteration.min && currentQuad.max < currentIteration.max){ // float min = currentQuad.min; // float max = currentIteration.max; // if(max - min < MINIMIZATION_DIFF_MAX){ // currentQuad.endX = currentIteration.endX; // currentQuad.max = currentIteration.max; // } else { // finalQuads.add(currentQuad); // currentQuad = currentIteration; // } // } else if(currentQuad.min > currentIteration.min && currentQuad.max > currentIteration.max){ // float min = currentIteration.min; // float max = currentQuad.max; // if(max - min < MINIMIZATION_DIFF_MAX){ // currentQuad.endX = currentIteration.endX; // currentQuad.min = currentIteration.min; // } else { // finalQuads.add(currentQuad); // currentQuad = currentIteration; // } // } else { // if(currentQuad.min < currentIteration.min){ // currentQuad.endX = currentIteration.endX; // } else { // currentQuad.endX = currentIteration.endX; // currentQuad.min = currentIteration.min; // currentQuad.max = currentIteration.max; // } // } // } else { // finalQuads.add(currentQuad); // currentQuad = currentIteration; // } // } // } // finalQuads.add(currentQuad); // for(QuadToGenerate current : finalQuads){ // if(current.startX > 0 && current.startY > 0 && current.endX < 99 && current.endY < 99){ // System.out.println(current.startX + " " + current.startY + " " + current.endX + " " + current.endY); // } // } // System.out.println("AAAAAAAAAAAAAAAAAA"); // System.out.println(finalQuads.size()); // System.exit(0); int incrementer = 0; for(QuadToGenerate current : finalQuads){ //deal with vertex //0,0 vertices.put(current.startX); vertices.put(heightfield[current.startX][current.startY]); vertices.put(current.startY); //1,0 vertices.put(current.endX); vertices.put(heightfield[current.endX][current.startY]); vertices.put(current.startY); //0,1 vertices.put(current.startX); vertices.put(heightfield[current.startX][current.endY]); vertices.put(current.endY); //1,1 vertices.put(current.endX); vertices.put(heightfield[current.endX][current.endY]); vertices.put(current.endY); //deal with normal Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.startY); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.startY); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.endY); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.endY); normals.put(normal.x); normals.put(normal.y); normals.put(normal.z); //deal with texture coordinates // if(x / stride % 2 == 0){ // if(y / stride % 2 == 0){ // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(1); // texture_coords.put(1); // } else { // texture_coords.put(0); // texture_coords.put(1); // } // } else { // if(y / stride % 2 == 0){ // texture_coords.put(1); // texture_coords.put(0); // } else { // texture_coords.put(1); // texture_coords.put(1); // } // } texture_coords.put(0); texture_coords.put(0); texture_coords.put(current.endX - current.startX); texture_coords.put(0); texture_coords.put(0); texture_coords.put(current.endY - current.startY); texture_coords.put(current.endX - current.startX); texture_coords.put(current.endY - current.startY); if(current.endX < width - 1 && current.endY < height - 1){ // texturemap[x+stride][y+stride]; for(int i = 0; i < 4 ; i++){ // textureIndices.put(1); // textureIndices.put(0); // textureIndices.put(0); // textureIndices.put(0); textureIndices.put(texturemap[current.startX][current.startY]); textureIndices.put(texturemap[current.endX][current.startY]); textureIndices.put(texturemap[current.startX][current.endY]); textureIndices.put(texturemap[current.endX][current.endY]); } } else { for(int i = 0; i < 4 ; i++){ textureIndices.put(0); textureIndices.put(0); textureIndices.put(0); textureIndices.put(0); } } //deal with faces faces.put(incrementer * 4 + 0); faces.put(incrementer * 4 + 1); faces.put(incrementer * 4 + 2); faces.put(incrementer * 4 + 1); faces.put(incrementer * 4 + 2); faces.put(incrementer * 4 + 3); incrementer++; } // int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; // for(int x = 0; x < width - 1; x = x + stride){ // for(int y = 0; y < height - 1; y = y + stride){ // //deal with vertex // //0,0 // vertices.put(x); // vertices.put(heightfield[x][y]); // vertices.put(y); // //1,0 // vertices.put(x + stride); // vertices.put(heightfield[x+stride][y]); // vertices.put(y); // //0,1 // vertices.put(x); // vertices.put(heightfield[x][y+stride]); // vertices.put(y + stride); // //1,1 // vertices.put(x + stride); // vertices.put(heightfield[x+stride][y+stride]); // vertices.put(y + stride); // //deal with normal // Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); // normals.put(normal.x); // normals.put(normal.y); // normals.put(normal.z); // normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); // normals.put(normal.x); // normals.put(normal.y); // normals.put(normal.z); // normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); // normals.put(normal.x); // normals.put(normal.y); // normals.put(normal.z); // normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); // normals.put(normal.x); // normals.put(normal.y); // normals.put(normal.z); // //deal with texture coordinates //// if(x / stride % 2 == 0){ //// if(y / stride % 2 == 0){ //// texture_coords.put(0); //// texture_coords.put(0); //// texture_coords.put(1); //// texture_coords.put(0); //// texture_coords.put(0); //// texture_coords.put(1); //// texture_coords.put(1); //// texture_coords.put(1); //// } else { //// texture_coords.put(0); //// texture_coords.put(1); //// } //// } else { //// if(y / stride % 2 == 0){ //// texture_coords.put(1); //// texture_coords.put(0); //// } else { //// texture_coords.put(1); //// texture_coords.put(1); //// } //// } // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(0); // texture_coords.put(0); // texture_coords.put(1); // texture_coords.put(1); // texture_coords.put(1); // // if(x + stride < width - 1 && y + stride < height - 1){ //// texturemap[x+stride][y+stride]; // for(int i = 0; i < 4 ; i++){ //// textureIndices.put(1); //// textureIndices.put(0); //// textureIndices.put(0); //// textureIndices.put(0); // textureIndices.put(texturemap[x][y]); // textureIndices.put(texturemap[x+stride][y]); // textureIndices.put(texturemap[x][y+stride]); // textureIndices.put(texturemap[x+stride][y+stride]); // } // } else { // for(int i = 0; i < 4 ; i++){ // textureIndices.put(0); // textureIndices.put(0); // textureIndices.put(0); // textureIndices.put(0); // } // } // // // //deal with faces // if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ // faces.put(incrementer * 4 + 0); // faces.put(incrementer * 4 + 1); // faces.put(incrementer * 4 + 2); // faces.put(incrementer * 4 + 1); // faces.put(incrementer * 4 + 2); // faces.put(incrementer * 4 + 3); // } // incrementer++; // } // } System.out.println(incrementer + " quads"); vertices.flip(); normals.flip(); faces.flip(); texture_coords.flip(); textureIndices.flip(); m.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(m.vertexArrayObject); //buffer vertices m.buffer_vertices(vertices, 3); //buffer normals m.buffer_normals(normals, 3); //buffer faces m.buffer_faces(faces); //buffer texture coords m.buffer_texture_coords(texture_coords, 2); //texture indices m.bufferCustomFloatAttribArray(textureIndices, 4, 5); m.shader = program; glBindVertexArray(0); m.parent = rVal; m.hasBones = false; Material groundMat = new Material(); Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse("/Textures/Ground/Dirt1.png"); groundMat.set_specular("/Textures/Ground/Dirt1.png"); m.setMaterial(groundMat); rVal.meshes.add(m); return rVal; } static Vector3f calculateTerrainNormal(float[][] heightfield, int actualWidth, int actualHeight, int stride, int x, int y){ Vector3f rVal = new Vector3f(); if(x / stride < actualWidth - 1){ if(y / stride < actualHeight - 1){ float hL; if(x > 0){ hL = heightfield[x-1][y]; } else { hL = heightfield[x][y]; } float hR = heightfield[x+1][y]; float hD = heightfield[x][y+1]; float hU; if(y > 0){ hU = heightfield[x][y-1]; } else { hU = heightfield[x][y]; } rVal = new Vector3f(hL - hR, 2.0f, hD - hU); rVal.normalize(); } else { float hL; if(x > 0){ hL = heightfield[x-1][y]; } else { hL = heightfield[x][y]; } float hR = heightfield[x+1][y]; float hD = heightfield[x][y]; float hU = heightfield[x][y-1]; rVal = new Vector3f(hL - hR, 2.0f, hD - hU); rVal.normalize(); } } else { if(y / stride < actualHeight - 1){ float hL = heightfield[x-1][y]; float hR = heightfield[x][y]; float hD = heightfield[x][y+1]; float hU; if(y > 0){ hU = heightfield[x][y-1]; } else { hU = heightfield[x][y]; } rVal = new Vector3f(hL - hR, 2.0f, hD - hU); rVal.normalize(); } else { float hL = heightfield[x-1][y]; float hR = heightfield[x][y]; float hD = heightfield[x][y]; float hU = heightfield[x][y-1]; rVal = new Vector3f(hL - hR, 2.0f, hD - hU); rVal.normalize(); } } return rVal; } public static Model createUnitCube(){ Model rVal = new Model(); rVal.meshes = new ArrayList(); Mesh m = new Mesh(); // System.out.println(actualWidth + " " + actualHeight); // System.out.println((actualWidth - 1) * (actualHeight - 1)); FloatBuffer vertices = BufferUtils.createFloatBuffer(8 * 3); FloatBuffer normals = BufferUtils.createFloatBuffer(8 * 3); IntBuffer faces = BufferUtils.createIntBuffer(6 * 2 * 3); FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8 * 2); //vertices //0,0,0 vertices.put(0); vertices.put(0); vertices.put(0); //1,0,0 vertices.put(1); vertices.put(0); vertices.put(0); //0,1,0 vertices.put(0); vertices.put(1); vertices.put(0); //1,1,0 vertices.put(1); vertices.put(1); vertices.put(0); //0,0,1 vertices.put(0); vertices.put(0); vertices.put(1); //1,0,1 vertices.put(1); vertices.put(0); vertices.put(1); //0,1,1 vertices.put(0); vertices.put(1); vertices.put(1); //1,1,1 vertices.put(1); vertices.put(1); vertices.put(1); //normals //-1,-1,-1 normals.put(-1); normals.put(-1); normals.put(-1); // 1,-1,-1 normals.put( 1); normals.put(-1); normals.put(-1); //-1, 1,-1 normals.put(-1); normals.put( 1); normals.put(-1); // 1, 1,-1 normals.put( 1); normals.put( 1); normals.put(-1); //-1,-1, 1 normals.put(-1); normals.put(-1); normals.put( 1); // 1,-1, 1 normals.put( 1); normals.put(-1); normals.put( 1); //-1, 1, 1 normals.put(-1); normals.put( 1); normals.put( 1); // 1, 1, 1 normals.put( 1); normals.put( 1); normals.put( 1); //faces //0,1,2 faces.put(0); faces.put(1); faces.put(2); //1,2,3 faces.put(1); faces.put(2); faces.put(3); //1,3,5 faces.put(1); faces.put(3); faces.put(5); //3,5,7 faces.put(3); faces.put(5); faces.put(7); //0,1,4 faces.put(0); faces.put(1); faces.put(4); //1,4,5 faces.put(1); faces.put(4); faces.put(5); //0,2,4 faces.put(0); faces.put(2); faces.put(4); //2,4,6 faces.put(2); faces.put(4); faces.put(6); //2,3,6 faces.put(2); faces.put(3); faces.put(6); //3,6,7 faces.put(3); faces.put(6); faces.put(7); //4,5,6 faces.put(4); faces.put(5); faces.put(6); //5,6,7 faces.put(5); faces.put(6); faces.put(7); //texture for(int i = 0; i < 8 * 2; i++){ texture_coords.put(0); } vertices.flip(); normals.flip(); faces.flip(); texture_coords.flip(); m.vertexArrayObject = glGenVertexArrays(); glBindVertexArray(m.vertexArrayObject); //buffer vertices m.buffer_vertices(vertices, 3); //buffer normals m.buffer_normals(normals, 3); //buffer faces m.buffer_faces(faces); //buffer texture coords m.buffer_texture_coords(texture_coords, 2); m.shader = ShaderProgram.smart_assemble_shader(false,true); glBindVertexArray(0); m.parent = rVal; Material groundMat = new Material(); Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse("/Textures/Ground/Dirt1.png"); groundMat.set_specular("/Textures/Ground/Dirt1.png"); m.setMaterial(groundMat); rVal.meshes.add(m); return rVal; } }