Work on minimizing terrain poly count
This commit is contained in:
parent
b2fe119348
commit
dda5cb59e5
@ -93,7 +93,7 @@ public class DrawCell {
|
||||
if(modelEntity != null){
|
||||
Globals.entityManager.deregisterEntity(modelEntity);
|
||||
}
|
||||
Model terrainModel = ModelUtils.createTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
|
||||
Model terrainModel = ModelUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
|
||||
Mesh terrainMesh = terrainModel.meshes.get(0);
|
||||
terrainMesh.useTextureList = true;
|
||||
terrainMesh.textureList.add(groundTextureOne);
|
||||
|
||||
@ -6,6 +6,8 @@ import electrosphere.renderer.texture.Texture;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import static org.lwjgl.opengl.GL30.glBindVertexArray;
|
||||
@ -340,6 +342,492 @@ public class ModelUtils {
|
||||
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<QuadToGenerate> 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(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 &&
|
||||
texturemap[quadCurrent.startX][quadCurrent.startY] == texturemap[x+stride][y] &&
|
||||
texturemap[quadCurrent.startX][quadCurrent.startY] == texturemap[x][y+stride] &&
|
||||
texturemap[quadCurrent.startX][quadCurrent.startY] == texturemap[x+stride][y+stride]
|
||||
){
|
||||
//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");
|
||||
}
|
||||
} 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<QuadToGenerate> finalQuads = new LinkedList();
|
||||
for(QuadToGenerate current : firstPhaseQuads){
|
||||
finalQuads.add(current);
|
||||
}
|
||||
|
||||
// System.out.println(finalQuads.size());
|
||||
|
||||
//merge along x
|
||||
|
||||
// QuadToGenerate currentQuad = null;
|
||||
// for(QuadToGenerate currentIteration : firstPhaseQuads){
|
||||
// if(currentQuad == null){
|
||||
// currentQuad = currentIteration;
|
||||
// } else {
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// finalQuads.add(currentQuad);
|
||||
|
||||
for(QuadToGenerate current : finalQuads){
|
||||
// System.out.println(current.startX + " " + current.startY + " " + current.endX + " " + current.endY);
|
||||
}
|
||||
|
||||
// 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++;
|
||||
// }
|
||||
// }
|
||||
|
||||
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){
|
||||
|
||||
Loading…
Reference in New Issue
Block a user