package electrosphere.renderer; import electrosphere.main.Globals; import electrosphere.renderer.assetmanager.AssetDataStrings; import electrosphere.renderer.texture.Texture; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import org.joml.Vector3f; import org.lwjgl.BufferUtils; import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glGenVertexArrays; /** * * @author satellite */ public class ModelUtils { // public static Model createTerrainModel(float[][] heightfield, 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.0 * width / stride); // int actualHeight = (int)Math.ceil(1.0 * height / stride); // //// System.out.println(actualWidth + " " + actualHeight); // //// System.out.println((actualWidth - 1) * (actualHeight - 1)); // // FloatBuffer vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3); // FloatBuffer normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3); // IntBuffer faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); // FloatBuffer texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 2); // for(int x = 0; x < width; x = x + stride){ // for(int y = 0; y < height; y = y + stride){ // //deal with vertex // vertices.put(x); // vertices.put(heightfield[x][y]); // vertices.put(y); // //deal with normal // 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]; // } // Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); // Normal.normalize(); // normals.put(Normal.x); // normals.put(Normal.y); // normals.put(Normal.z); // } 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]; // Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); // Normal.normalize(); // normals.put(Normal.x); // normals.put(Normal.y); // normals.put(Normal.z); // } // } 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]; // } // Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); // Normal.normalize(); // normals.put(Normal.x); // normals.put(Normal.y); // normals.put(Normal.z); // } else { // float hL = heightfield[x-1][y]; // float hR = heightfield[x][y]; // float hD = heightfield[x][y]; // float hU = heightfield[x][y-1]; // Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); // Normal.normalize(); // 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); // } 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); // } // } // //deal with faces // if(x / stride < actualWidth - 1 && y / stride < actualHeight - 1){ // faces.put((x / stride + 0) * actualHeight + (y / stride + 0)); // faces.put((x / stride + 0) * actualHeight + (y / stride + 1)); // faces.put((x / stride + 1) * actualHeight + (y / stride + 0)); // faces.put((x / stride + 1) * actualHeight + (y / stride + 0)); // faces.put((x / stride + 0) * actualHeight + (y / stride + 1)); // faces.put((x / stride + 1) * actualHeight + (y / stride + 1)); // } // } // } // 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.loadSpecificShader("/Shaders/terrain/terrain.vs", "/Shaders/terrain/terrain.fs"); // 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.set_material(groundMat); // // 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 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; } public static void printModelDimension(Model m){ float minX = 0; float maxX = 0; float minY = 0; float maxY = 0; float minZ = 0; float maxZ = 0; boolean initiated = false; for(Mesh currentMesh : m.meshes){ if(initiated){ if(currentMesh.vertexMinX < minX){ minX = currentMesh.vertexMinX; } if(currentMesh.vertexMaxX > maxX){ maxX = currentMesh.vertexMaxX; } if(currentMesh.vertexMinY < minY){ minY = currentMesh.vertexMinY; } if(currentMesh.vertexMaxY > maxY){ maxY = currentMesh.vertexMaxY; } if(currentMesh.vertexMinZ < minZ){ minZ = currentMesh.vertexMinZ; } if(currentMesh.vertexMaxZ > maxZ){ maxZ = currentMesh.vertexMaxZ; } } else { initiated = true; minX = currentMesh.vertexMinX; maxX = currentMesh.vertexMaxX; minY = currentMesh.vertexMinY; maxY = currentMesh.vertexMaxY; minZ = currentMesh.vertexMinZ; maxZ = currentMesh.vertexMaxZ; } } System.out.println("dimensions: " + (maxX - minX) + "," + (maxY - minY) + "," + (maxZ-minZ)); } 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.meshes.add(m); return rVal; } }