Joined normals marching cubes

This commit is contained in:
austin 2023-04-23 12:51:06 -04:00
parent 094831ba22
commit edaa7c8ce2
2 changed files with 147 additions and 66 deletions

View File

@ -34,7 +34,7 @@ public class ClientTerrainManager {
ClientWorldData clientWorldData;
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = Collections.synchronizedList(new LinkedList<TerrainChunkGenQueueItem>());
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
public ClientTerrainManager(ClientWorldData clientWorldData){

View File

@ -322,12 +322,12 @@ public class TerrainChunkModelGeneration {
};
static class Triangle {
Vector3f[] points = new Vector3f[3]; //array of size 3
int[] indices = new int[3]; //array of size 3
public Triangle(Vector3f point0,Vector3f point1,Vector3f point2){
points[0] = point0;
points[1] = point1;
points[2] = point2;
public Triangle(int index0, int index1, int index2){
indices[0] = index0;
indices[1] = index1;
indices[2] = index2;
}
}
@ -347,7 +347,15 @@ public class TerrainChunkModelGeneration {
}
}
protected static int polygonize(GridCell grid, double isolevel, List<Triangle> triangles, Map<String,Integer> vertMap, List<Integer> indices){
protected static int polygonize(
GridCell grid,
double isolevel,
List<Triangle> triangles,
Map<String,Integer> vertMap,
List<Vector3f> verts,
List<Vector3f> normals,
List<Integer> trianglesSharingVert
){
int i;
int ntriang;
int cubeIndex = 0;
@ -411,22 +419,88 @@ public class TerrainChunkModelGeneration {
//Create the triangle
ntriang = 0;
for (i=0; triTable[cubeIndex][i]!=-1; i+=3) {
//
// Triangles calculation
//
//get indices
Vector3f vert0 = vertList[triTable[cubeIndex][i+0]];
Vector3f vert1 = vertList[triTable[cubeIndex][i+1]];
Vector3f vert2 = vertList[triTable[cubeIndex][i+2]];
getVertIndex(vert0,vertMap,indices);
getVertIndex(vert1,vertMap,indices);
getVertIndex(vert2,vertMap,indices);
Triangle newTriangle = new Triangle(
vertList[triTable[cubeIndex][i+0]],
vertList[triTable[cubeIndex][i+1]],
vertList[triTable[cubeIndex][i+2]]
);
int index0 = getVertIndex(vert0,vertMap,verts);
int index1 = getVertIndex(vert1,vertMap,verts);
int index2 = getVertIndex(vert2,vertMap,verts);
//add 0's to normals until it matches vert count
while(trianglesSharingVert.size() < verts.size()){
trianglesSharingVert.add(0);
normals.add(new Vector3f());
}
//add new triangle
Triangle newTriangle = new Triangle(index0,index1,index2);
triangles.add(newTriangle);
// triangles[ntriang].points[0] = vertList[triTable[cubeIndex][i+0]];
// triangles[ntriang].points[1] = vertList[triTable[cubeIndex][i+1]];
// triangles[ntriang].points[2] = vertList[triTable[cubeIndex][i+2]];
ntriang++;
//
// Normals calculation
//
//calculate normal for new triangle
Vector3f u = verts.get(index1).sub(verts.get(index0), new Vector3f());
Vector3f v = verts.get(index2).sub(verts.get(index1), new Vector3f());
Vector3f n = new Vector3f(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x).normalize();
//for each vertex, average the new normal with the normals that are already there
int trianglesSharingIndex0 = trianglesSharingVert.get(index0);
//calculate proportion of each normal
float oldProportion = trianglesSharingIndex0 / (float)(trianglesSharingIndex0 + 1);
float newProportion = 1.0f / (float)(trianglesSharingIndex0 + 1);
//increment number of triangles sharing vert
trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1);
Vector3f currentNormal = normals.get(index0);
currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index0).set(currentNormal);
int trianglesSharingIndex1 = trianglesSharingVert.get(index1);
//calculate proportion of each normal
oldProportion = trianglesSharingIndex1 / (float)(trianglesSharingIndex1 + 1);
newProportion = 1.0f / (float)(trianglesSharingIndex1 + 1);
//increment number of triangles sharing vert
trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1);
currentNormal = normals.get(index1);
currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index1).set(currentNormal);
int trianglesSharingIndex2 = trianglesSharingVert.get(index2);
//calculate proportion of each normal
oldProportion = trianglesSharingIndex2 / (float)(trianglesSharingIndex2 + 1);
newProportion = 1.0f / (float)(trianglesSharingIndex2 + 1);
//increment number of triangles sharing vert
trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1);
currentNormal = normals.get(index2);
currentNormal = averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index2).set(currentNormal);
}
return(ntriang);
@ -475,10 +549,21 @@ public class TerrainChunkModelGeneration {
// | / | / | / | /
// 0 +-------------+ 3 +------3------+
//the current grid cell
GridCell currentCell = new GridCell();
//the list of all triangles
List<Triangle> triangles = new LinkedList<Triangle>();
//the map of vertex to index
Map<String,Integer> vertMap = new HashMap<String,Integer>();
List<Integer> indices = new LinkedList<Integer>();
//the list of all verts
List<Vector3f> verts = new LinkedList<Vector3f>();
//the list of all normals
List<Vector3f> normals = new LinkedList<Vector3f>();
//the list of number of triangles that share a vert
List<Integer> trianglesSharingVert = new LinkedList<Integer>();
for(int x = 0; x < terrainGrid.length - 1; x++){
for(int y = 0; y < terrainGrid[0].length - 1; y++){
for(int z = 0; z < terrainGrid[0][0].length - 1; z++){
@ -490,7 +575,7 @@ public class TerrainChunkModelGeneration {
terrainGrid[x+0][y+1][z+0], terrainGrid[x+0][y+1][z+1], terrainGrid[x+1][y+1][z+1], terrainGrid[x+1][y+1][z+0]
);
//polygonize the current gridcell
polygonize(currentCell, 0, triangles, vertMap, indices);
polygonize(currentCell, 0, triangles, vertMap, verts, normals, trianglesSharingVert);
}
}
}
@ -504,24 +589,13 @@ public class TerrainChunkModelGeneration {
//
try {
mesh.vertexCount = triangles.size() * 3;
mesh.vertexCount = verts.size();
FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(mesh.vertexCount * 3);
float[] temp = new float[3];
for(Triangle triangle: triangles){
//vertex 1
temp[0] = triangle.points[0].x;
temp[1] = triangle.points[0].y;
temp[2] = triangle.points[0].z;
VertexArrayBufferData.put(temp);
//vertex 2
temp[0] = triangle.points[1].x;
temp[1] = triangle.points[1].y;
temp[2] = triangle.points[1].z;
VertexArrayBufferData.put(temp);
//vertex 3
temp[0] = triangle.points[2].x;
temp[1] = triangle.points[2].y;
temp[2] = triangle.points[2].z;
for(Vector3f vert : verts){
temp[0] = vert.x;
temp[1] = vert.y;
temp[2] = vert.z;
VertexArrayBufferData.put(temp);
}
VertexArrayBufferData.flip();
@ -539,14 +613,9 @@ public class TerrainChunkModelGeneration {
mesh.elementCount = triangles.size() * 3;
try {
IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(mesh.elementCount);
int i = 0;
int[] temp = new int[3];
for(Triangle triangle : triangles){
temp[0] = i * 3 + 0;
temp[1] = i * 3 + 1;
temp[2] = i * 3 + 2;
i++;
elementArrayBufferData.put(temp);
elementArrayBufferData.put(triangle.indices);
}
elementArrayBufferData.flip();
mesh.buffer_faces(elementArrayBufferData);
@ -561,33 +630,38 @@ public class TerrainChunkModelGeneration {
// NORMALS
//
try {
mesh.normalCount = triangles.size() * 3;
mesh.normalCount = normals.size();
FloatBuffer NormalArrayBufferData;
if(mesh.normalCount > 0){
NormalArrayBufferData = BufferUtils.createFloatBuffer(mesh.normalCount * 3);
float[] temp = new float[3];
for(Triangle triangle : triangles){
//calculate normal vector
Vector3f u = triangle.points[1].sub(triangle.points[0], new Vector3f());
Vector3f v = triangle.points[2].sub(triangle.points[1], new Vector3f());
Vector3f n = new Vector3f(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x);
//emit 3 normal vectors
//normal 0
temp[0] = n.x;
temp[1] = n.y;
temp[2] = n.z;
NormalArrayBufferData.put(temp);
//normal 1
temp[0] = n.x;
temp[1] = n.y;
temp[2] = n.z;
NormalArrayBufferData.put(temp);
//normal 2
temp[0] = n.x;
temp[1] = n.y;
temp[2] = n.z;
for(Vector3f normal : normals){
temp[0] = normal.x;
temp[1] = normal.y;
temp[2] = normal.z;
NormalArrayBufferData.put(temp);
}
// for(Triangle triangle : triangles){
// //emit 3 normal vectors
// //normal 0
// Vector3f normal = normals.get(triangle.indices[0]);
// temp[0] = normal.x;
// temp[1] = normal.y;
// temp[2] = normal.z;
// NormalArrayBufferData.put(temp);
// //normal 1
// normal = normals.get(triangle.indices[1]);
// temp[0] = normal.x;
// temp[1] = normal.y;
// temp[2] = normal.z;
// NormalArrayBufferData.put(temp);
// //normal 2
// normal = normals.get(triangle.indices[2]);
// temp[0] = normal.x;
// temp[1] = normal.y;
// temp[2] = normal.z;
// NormalArrayBufferData.put(temp);
// }
NormalArrayBufferData.flip();
mesh.buffer_normals(NormalArrayBufferData, 3);
}
@ -653,21 +727,28 @@ public class TerrainChunkModelGeneration {
return rVal;
}
//TODO: more optimal key creation
private static String getVertKeyFromPoints(float x, float y, float z){
return x + "-" + y + "-" + z;
}
private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Integer> indices){
private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Vector3f> verts){
int rVal = -1;
String vertKey = getVertKeyFromPoints(vert.x,vert.y,vert.z);
if(vertMap.containsKey(vertKey)){
return vertMap.get(vertKey);
} else {
rVal = indices.size();
indices.add(rVal);
rVal = verts.size();
verts.add(vert);
vertMap.put(vertKey,rVal);
return rVal;
}
}
private static Vector3f averageNormals(Vector3f normal0, float proportion0, Vector3f normal1, float proportion1){
Vector3f rVal = new Vector3f(normal0);
rVal = rVal.mul(proportion0).add(new Vector3f(normal1).mul(proportion1));
return rVal;
}
}