Renderer/src/main/java/electrosphere/renderer/ModelUtils.java

619 lines
22 KiB
Java

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;
}
}