package electrosphere.renderer; 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.smart_assemble_shader(false,true); glBindVertexArray(0); m.parent = rVal; Material groundMat = new Material(); Texture groundTex = new Texture("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse(groundTex); groundMat.set_specular(groundTex); m.set_material(groundMat); rVal.meshes.add(m); return rVal; } public static Model createTerrainModelPrecomputedShader(float[][] heightfield, 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; if(stride * actualWidth > width){ int drawWidth = actualWidth + 1; int drawHeight = actualHeight + 1; vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 3); normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 3); faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 2); } else { vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3); normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3); faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); 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(1.0f * x / stride < actualWidth - 1 && 1.0f * 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 = program; glBindVertexArray(0); m.parent = rVal; Material groundMat = new Material(); Texture groundTex = new Texture("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse(groundTex); groundMat.set_specular(groundTex); m.set_material(groundMat); rVal.meshes.add(m); 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(); Texture groundTex = new Texture("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse(groundTex); groundMat.set_specular(groundTex); m.set_material(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(); Texture uiTex = new Texture("/Textures/Fonts/myfont1-harsher.png"); uiMat.set_diffuse(uiTex); uiMat.set_specular(uiTex); m.set_material(uiMat); rVal.meshes.add(m); return rVal; } }