more memory work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-03-30 14:57:55 -04:00
parent 75eb75b2db
commit 0a3fbb8e27
9 changed files with 348 additions and 107 deletions

View File

@ -1389,6 +1389,8 @@ Work on optimization
Reorganizing terrain data Reorganizing terrain data
ServerGroundMovementTree concurrent modify fix ServerGroundMovementTree concurrent modify fix
TransvoxelModelGeneration allocation reduction TransvoxelModelGeneration allocation reduction
More allocation reduction
Vector pooling

View File

@ -2,7 +2,10 @@ package electrosphere.client.terrain.data;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import electrosphere.entity.state.collidable.TriGeomData; import electrosphere.entity.state.collidable.TriGeomData;
@ -42,6 +45,26 @@ public class TerrainChunkData implements TriGeomData {
*/ */
float[] textureRatioVectors; float[] textureRatioVectors;
/**
* The list of vertices as vectors
*/
List<Vector3f> vertList;
/**
* The list of normals as vectors
*/
List<Vector3f> normalList;
/**
* The list of number of triangles that share a vert
*/
List<Integer> triangleSharingVertList;
/**
* List of texture sampler values
*/
List<Vector3f> samplerTriangles;
/** /**
* The various buffers of data to send to the gpu * The various buffers of data to send to the gpu
*/ */
@ -77,6 +100,16 @@ public class TerrainChunkData implements TriGeomData {
this.lod = lod; this.lod = lod;
} }
/**
* Constructor used by the pool
*/
protected TerrainChunkData(){
this.vertList = new LinkedList<Vector3f>();
this.normalList = new LinkedList<Vector3f>();
this.triangleSharingVertList = new LinkedList<Integer>();
this.samplerTriangles = new LinkedList<Vector3f>();
}
/** /**
* Allocates and fills the buffers to send to the gpu * Allocates and fills the buffers to send to the gpu
*/ */
@ -197,6 +230,39 @@ public class TerrainChunkData implements TriGeomData {
public FloatBuffer getRatioBuffer() { public FloatBuffer getRatioBuffer() {
return ratioBuffer; return ratioBuffer;
} }
/**
* Gets the vertex list
* @return The vertex list
*/
public List<Vector3f> getVertList() {
return vertList;
}
/**
* Gets the normal list
* @return The normal list
*/
public List<Vector3f> getNormalList() {
return normalList;
}
/**
* Gets the triangle sharing vert list
* @return The triangle sharing vert list
*/
public List<Integer> getTriangleSharingVertList() {
return triangleSharingVertList;
}
/**
* Gets the sampler triangles list
* @return The sampler triangles list
*/
public List<Vector3f> getSamplerTriangles() {
return samplerTriangles;
}
} }

View File

@ -0,0 +1,48 @@
package electrosphere.client.terrain.data;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
/**
* Pools allocated terrain chunk data objects
*/
public class TerrainChunkDataPool {
/**
* Structure to store not-in-use objects
*/
static List<TerrainChunkData> pool = new LinkedList<TerrainChunkData>();
/**
* Lock for thread-safeing operations
*/
static ReentrantLock lock = new ReentrantLock();
/**
* Gets a terrain chunk object from the pool. Allocates if no free one is available.
* @return A terrain chunk object of the requested type
*/
public static TerrainChunkData get(){
TerrainChunkData rVal = null;
lock.lock();
if(pool.size() > 0){
rVal = pool.remove(0);
} else {
rVal = new TerrainChunkData();
}
lock.unlock();
return rVal;
}
/**
* Releases a terrain chunk data object back into the pool
* @param data The object to release
*/
public static void release(TerrainChunkData data){
lock.lock();
TerrainChunkDataPool.pool.add(data);
lock.unlock();
}
}

View File

@ -0,0 +1,89 @@
package electrosphere.mem;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3d;
import org.joml.Vector3f;
/**
* A pool for temporary vectors
*/
public class VectorPool {
/**
* Structure to store not-in-use objects
*/
static List<Vector3f> vec3fPool = new LinkedList<Vector3f>();
/**
* Structure to store not-in-use objects
*/
static List<Vector3d> vec3dPool = new LinkedList<Vector3d>();
/**
* Lock for thread-safeing operations
*/
static ReentrantLock lock = new ReentrantLock();
/**
* Gets a Vector3f from the pool. Allocates if no free one is available.
* @param type The type of the message
* @return A Vector3f
*/
public static Vector3f getF(){
Vector3f rVal = null;
lock.lock();
if(vec3fPool.size() > 0){
rVal = vec3fPool.remove(0);
} else {
rVal = new Vector3f();
}
lock.unlock();
return rVal;
}
/**
* Releases a Vector3f back into the pool
* @param data The object to release
*/
public static void release(Vector3f data){
data.x = 0;
data.y = 0;
data.z = 0;
lock.lock();
VectorPool.vec3fPool.add(data);
lock.unlock();
}
/**
* Gets a Vector3d from the pool. Allocates if no free one is available.
* @return A Vector3d
*/
public static Vector3d getD(){
Vector3d rVal = null;
lock.lock();
if(vec3dPool.size() > 0){
rVal = vec3dPool.remove(0);
} else {
rVal = new Vector3d();
}
lock.unlock();
return rVal;
}
/**
* Releases a Vector3d back into the pool
* @param data The object to release
*/
public static void release(Vector3d data){
data.x = 0;
data.y = 0;
data.z = 0;
lock.lock();
VectorPool.vec3dPool.add(data);
lock.unlock();
}
}

View File

@ -14,6 +14,7 @@ import electrosphere.client.terrain.cells.VoxelTextureAtlas;
import electrosphere.client.terrain.data.TerrainChunkData; import electrosphere.client.terrain.data.TerrainChunkData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.mem.VectorPool;
import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Material;
import electrosphere.renderer.model.Mesh; import electrosphere.renderer.model.Mesh;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
@ -236,22 +237,27 @@ public class TransvoxelModelGeneration {
double isolevel, double isolevel,
List<Triangle> triangles, List<Triangle> triangles,
List<Vector3f> samplerIndices, List<Vector3f> samplerIndices,
Map<Vector3f,Integer> vertMap, Map<String,Integer> vertMap,
List<Vector3f> verts, List<Vector3f> verts,
List<Vector3f> normals, List<Vector3f> normals,
List<Integer> trianglesSharingVert, List<Integer> trianglesSharingVert,
boolean invertNormals boolean invertNormals,
Vector3f[] vertList,
int[] samplerIndex,
boolean[] skip,
StringBuilder builder
){ ){
int i; int i;
int ntriang; int ntriang;
int cubeIndex = 0; int cubeIndex = 0;
Vector3f[] vertList = new Vector3f[12];
int[] samplerIndex = new int[12];
//essentially, because the iso level is 0, we can end up generating weird midpoints between 0 and negative values //essentially, because the iso level is 0, we can end up generating weird midpoints between 0 and negative values
//in order to not actually generate triangles for these edge cases, the skip table is populated if the current edge is between 0 and a negative value //in order to not actually generate triangles for these edge cases, the skip table is populated if the current edge is between 0 and a negative value
//when storing triangles, all skip edges trigger the loop to skip to the next triangle set //when storing triangles, all skip edges trigger the loop to skip to the next triangle set
boolean[] skip = new boolean[12]; for(int j = 0; j < 12; j++){
skip[j] = false;
vertList[j].set(0,0,0);
}
//get lookup key (index) for edge table //get lookup key (index) for edge table
//edge table tells us which vertices are inside of the surface //edge table tells us which vertices are inside of the surface
@ -273,51 +279,51 @@ public class TransvoxelModelGeneration {
//for each edge this code calculates where along the edge to place the vertex //for each edge this code calculates where along the edge to place the vertex
//this should dramatically smooth the surface //this should dramatically smooth the surface
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 1) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 1) > 0){
vertList[0] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[0],grid.points[1],grid.val[0],grid.val[1]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[0],grid.points[1],grid.val[0],grid.val[1],vertList[0]);
if(grid.val[0] <= 0 && grid.val[1] <= 0){ skip[0] = true; } if(grid.val[0] <= 0 && grid.val[1] <= 0){ skip[0] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 2) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 2) > 0){
vertList[1] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2],vertList[1]);
if(grid.val[1] <= 0 && grid.val[2] <= 0){ skip[1] = true; } if(grid.val[1] <= 0 && grid.val[2] <= 0){ skip[1] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 4) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 4) > 0){
vertList[2] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[3],grid.val[2],grid.val[3]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[3],grid.val[2],grid.val[3],vertList[2]);
if(grid.val[2] <= 0 && grid.val[3] <= 0){ skip[2] = true; } if(grid.val[2] <= 0 && grid.val[3] <= 0){ skip[2] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 8) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 8) > 0){
vertList[3] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[3],grid.points[0],grid.val[3],grid.val[0]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[3],grid.points[0],grid.val[3],grid.val[0],vertList[3]);
if(grid.val[3] <= 0 && grid.val[0] <= 0){ skip[3] = true; } if(grid.val[3] <= 0 && grid.val[0] <= 0){ skip[3] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 16) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 16) > 0){
vertList[4] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[4],grid.points[5],grid.val[4],grid.val[5]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[4],grid.points[5],grid.val[4],grid.val[5],vertList[4]);
if(grid.val[4] <= 0 && grid.val[5] <= 0){ skip[4] = true; } if(grid.val[4] <= 0 && grid.val[5] <= 0){ skip[4] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 32) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 32) > 0){
vertList[5] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[5],grid.points[6],grid.val[5],grid.val[6]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[5],grid.points[6],grid.val[5],grid.val[6],vertList[5]);
if(grid.val[5] <= 0 && grid.val[6] <= 0){ skip[5] = true; } if(grid.val[5] <= 0 && grid.val[6] <= 0){ skip[5] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 64) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 64) > 0){
vertList[6] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7],vertList[6]);
if(grid.val[6] <= 0 && grid.val[7] <= 0){ skip[6] = true; } if(grid.val[6] <= 0 && grid.val[7] <= 0){ skip[6] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 128) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 128) > 0){
vertList[7] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[7],grid.points[4],grid.val[7],grid.val[4]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[7],grid.points[4],grid.val[7],grid.val[4],vertList[7]);
if(grid.val[7] <= 0 && grid.val[4] <= 0){ skip[7] = true; } if(grid.val[7] <= 0 && grid.val[4] <= 0){ skip[7] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 256) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 256) > 0){
vertList[8] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[0],grid.points[4],grid.val[0],grid.val[4]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[0],grid.points[4],grid.val[0],grid.val[4],vertList[8]);
if(grid.val[0] <= 0 && grid.val[4] <= 0){ skip[8] = true; } if(grid.val[0] <= 0 && grid.val[4] <= 0){ skip[8] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 512) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 512) > 0){
vertList[9] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[5],grid.val[1],grid.val[5]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[5],grid.val[1],grid.val[5],vertList[9]);
if(grid.val[1] <= 0 && grid.val[5] <= 0){ skip[9] = true; } if(grid.val[1] <= 0 && grid.val[5] <= 0){ skip[9] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 1024) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 1024) > 0){
vertList[10] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6],vertList[10]);
if(grid.val[2] <= 0 && grid.val[6] <= 0){ skip[10] = true; } if(grid.val[2] <= 0 && grid.val[6] <= 0){ skip[10] = true; }
} }
if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 2048) > 0){ if((TerrainChunkModelGeneration.edgeTable[cubeIndex] & 2048) > 0){
vertList[11] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[3],grid.points[7],grid.val[3],grid.val[7]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[3],grid.points[7],grid.val[3],grid.val[7],vertList[11]);
if(grid.val[3] <= 0 && grid.val[7] <= 0){ skip[11] = true; } if(grid.val[3] <= 0 && grid.val[7] <= 0){ skip[11] = true; }
} }
@ -353,12 +359,12 @@ public class TransvoxelModelGeneration {
Vector3f vert0 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+0]]; Vector3f vert0 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+0]];
Vector3f vert1 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+1]]; Vector3f vert1 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+1]];
Vector3f vert2 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+2]]; Vector3f vert2 = vertList[TerrainChunkModelGeneration.triTable[cubeIndex][i+2]];
int index0 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts); int index0 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts,builder);
int index1 = TransvoxelModelGeneration.getVertIndex(vert1,vertMap,verts); int index1 = TransvoxelModelGeneration.getVertIndex(vert1,vertMap,verts,builder);
int index2 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts); int index2 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts,builder);
if(index0 == index1 || index1 == index2 || index0 == index2){ if(index0 == index1 || index1 == index2 || index0 == index2){
TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[6],grid.points[7],grid.val[6],grid.val[7],new Vector3f());
TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]); TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6],new Vector3f());
String message = "Identical indices!\n" + String message = "Identical indices!\n" +
"edge table: " + TerrainChunkModelGeneration.edgeTable[cubeIndex] + "\n" + "edge table: " + TerrainChunkModelGeneration.edgeTable[cubeIndex] + "\n" +
"cube index: " + cubeIndex + "\n" + "cube index: " + cubeIndex + "\n" +
@ -425,14 +431,14 @@ public class TransvoxelModelGeneration {
//calculate normal for new triangle //calculate normal for new triangle
Vector3f u = new Vector3f(verts.get(index1)).sub(verts.get(index0)); Vector3f u = VectorPool.getF().set(verts.get(index1)).sub(verts.get(index0));
Vector3f v = new Vector3f(verts.get(index2)).sub(verts.get(index1)); Vector3f v = VectorPool.getF().set(verts.get(index2)).sub(verts.get(index1));
float dotVal = u.dot(v); float dotVal = u.dot(v);
Vector3f n = new Vector3f(); Vector3f n;
// if(dotVal > NORMAL_DOT_THRESHOLD || dotVal < -NORMAL_DOT_THRESHOLD){ // if(dotVal > NORMAL_DOT_THRESHOLD || dotVal < -NORMAL_DOT_THRESHOLD){
// n.set(u); // n.set(u);
// } else { // } else {
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(); 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();
// } // }
if(invertNormals){ if(invertNormals){
n = n.mul(-1); n = n.mul(-1);
@ -449,6 +455,8 @@ public class TransvoxelModelGeneration {
dotVal dotVal
); );
} }
VectorPool.release(u);
VectorPool.release(v);
@ -461,8 +469,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1); trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1);
Vector3f currentNormal = normals.get(index0); Vector3f currentNormal = normals.get(index0);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index0).set(currentNormal);
@ -476,8 +483,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1); trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1);
currentNormal = normals.get(index1); currentNormal = normals.get(index1);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index1).set(currentNormal);
@ -494,8 +500,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1); trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1);
currentNormal = normals.get(index2); currentNormal = normals.get(index2);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index2).set(currentNormal);
} }
@ -522,11 +527,14 @@ public class TransvoxelModelGeneration {
double isolevel, double isolevel,
List<Triangle> triangles, List<Triangle> triangles,
List<Vector3f> samplerIndices, List<Vector3f> samplerIndices,
Map<Vector3f,Integer> vertMap, Map<String,Integer> vertMap,
List<Vector3f> verts, List<Vector3f> verts,
List<Vector3f> normals, List<Vector3f> normals,
List<Integer> trianglesSharingVert, List<Integer> trianglesSharingVert,
boolean invertNormals boolean invertNormals,
Vector3f[] vertList1,
int[] samplerIndex,
StringBuilder builder
){ ){
@ -590,8 +598,10 @@ public class TransvoxelModelGeneration {
int ntriang; int ntriang;
int caseIndex = 0; int caseIndex = 0;
Vector3f[] vertList = new Vector3f[12]; Vector3f[] vertList = new Vector3f[12];
int[] samplerIndex = new int[12]; for(int j = 0; j < 12; j++){
vertList[j] = new Vector3f();
samplerIndex[j] = 0;
}
/** /**
@ -792,7 +802,7 @@ public class TransvoxelModelGeneration {
Vector3f secondVertex = TransvoxelModelGeneration.getTransvoxelVectorByIndex(transitionCell,secondCornerSampleIndex); Vector3f secondVertex = TransvoxelModelGeneration.getTransvoxelVectorByIndex(transitionCell,secondCornerSampleIndex);
//calculate interpolated vertex between the two samples such that it lies on the edge of the isosurface //calculate interpolated vertex between the two samples such that it lies on the edge of the isosurface
vertList[i] = TransvoxelModelGeneration.VertexInterp(isolevel,firstVertex,secondVertex,firstSample,secondSample); TransvoxelModelGeneration.VertexInterp(isolevel,firstVertex,secondVertex,firstSample,secondSample,vertList[i]);
//figure out what sample we're pulling texture from //figure out what sample we're pulling texture from
if(firstSample > isolevel){ if(firstSample > isolevel){
@ -848,13 +858,13 @@ public class TransvoxelModelGeneration {
LoggerInterface.loggerRenderer.DEBUG(vert0 + ""); LoggerInterface.loggerRenderer.DEBUG(vert0 + "");
LoggerInterface.loggerRenderer.DEBUG(vert1 + ""); LoggerInterface.loggerRenderer.DEBUG(vert1 + "");
LoggerInterface.loggerRenderer.DEBUG(vert2 + ""); LoggerInterface.loggerRenderer.DEBUG(vert2 + "");
int index0 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts); int index0 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts,builder);
int index1 = TransvoxelModelGeneration.getVertIndex(vert1,vertMap,verts); int index1 = TransvoxelModelGeneration.getVertIndex(vert1,vertMap,verts,builder);
int index2 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts); int index2 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts,builder);
if(windingOrder == 1){ if(windingOrder == 1){
index0 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts); index0 = TransvoxelModelGeneration.getVertIndex(vert2,vertMap,verts,builder);
index2 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts); index2 = TransvoxelModelGeneration.getVertIndex(vert0,vertMap,verts,builder);
} }
//add 0's to normals until it matches vert count //add 0's to normals until it matches vert count
@ -897,12 +907,14 @@ public class TransvoxelModelGeneration {
//calculate normal for new triangle //calculate normal for new triangle
Vector3f u = verts.get(index1).sub(verts.get(index0), new Vector3f()); Vector3f u = VectorPool.getF().set(verts.get(index1)).sub(verts.get(index0));
Vector3f v = verts.get(index2).sub(verts.get(index1), new Vector3f()); Vector3f v = VectorPool.getF().set(verts.get(index2)).sub(verts.get(index1));
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(); 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();
if(invertNormals){ if(invertNormals){
n = n.mul(-1); n = n.mul(-1);
} }
VectorPool.release(u);
VectorPool.release(v);
@ -915,8 +927,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1); trianglesSharingVert.set(index0, trianglesSharingIndex0 + 1);
Vector3f currentNormal = normals.get(index0); Vector3f currentNormal = normals.get(index0);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index0).set(currentNormal);
@ -930,8 +941,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1); trianglesSharingVert.set(index1, trianglesSharingIndex1 + 1);
currentNormal = normals.get(index1); currentNormal = normals.get(index1);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index1).set(currentNormal);
@ -948,8 +958,7 @@ public class TransvoxelModelGeneration {
trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1); trianglesSharingVert.set(index2, trianglesSharingIndex2 + 1);
currentNormal = normals.get(index2); currentNormal = normals.get(index2);
currentNormal = TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion); TransvoxelModelGeneration.averageNormals(currentNormal,oldProportion,n,newProportion);
normals.get(index2).set(currentNormal);
} }
@ -1095,7 +1104,7 @@ public class TransvoxelModelGeneration {
} }
//interpolates the location that the edge gets cut based on the magnitudes of the scalars of the vertices at either end of the edge //interpolates the location that the edge gets cut based on the magnitudes of the scalars of the vertices at either end of the edge
protected static Vector3f VertexInterp(double isolevel, Vector3f p1, Vector3f p2, double valp1, double valp2){ protected static void VertexInterp(double isolevel, Vector3f p1, Vector3f p2, double valp1, double valp2, Vector3f vec){
double mu; double mu;
float x, y, z; float x, y, z;
@ -1103,13 +1112,15 @@ public class TransvoxelModelGeneration {
if(valp2 == 0){ if(valp2 == 0){
mu = 0.5f; mu = 0.5f;
} else if(valp2 > 0){ } else if(valp2 > 0){
return p2; vec.set(p2);
return;
} else { } else {
mu = 0.5; mu = 0.5;
} }
} else if(valp2 == 0){ } else if(valp2 == 0){
if(valp1 > 0){ if(valp1 > 0){
return p1; vec.set(p1);
return;
} else { } else {
mu = 0.5; mu = 0.5;
} }
@ -1137,7 +1148,7 @@ public class TransvoxelModelGeneration {
y = (float)(p1.y + mu * (p2.y - p1.y)); y = (float)(p1.y + mu * (p2.y - p1.y));
z = (float)(p1.z + mu * (p2.z - p1.z)); z = (float)(p1.z + mu * (p2.z - p1.z));
return new Vector3f(x,y,z); vec.set(x,y,z);
} }
/** /**
@ -1147,18 +1158,24 @@ public class TransvoxelModelGeneration {
* @param verts * @param verts
* @return * @return
*/ */
private static int getVertIndex(Vector3f vert, Map<Vector3f,Integer> vertMap, List<Vector3f> verts){ private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Vector3f> verts, StringBuilder builder){
if(vert == null){ if(vert == null){
throw new Error("Provided null value! " + vert); throw new Error("Provided null value! " + vert);
} }
builder.delete(0,builder.length());
builder.append(vert.x);
builder.append("_");
builder.append(vert.y);
builder.append("_");
builder.append(vert.z);
int rVal = -1; int rVal = -1;
// String vertKey = TransvoxelModelGeneration.getVertKeyFromPoints(vert.x,vert.y,vert.z); // String vertKey = TransvoxelModelGeneration.getVertKeyFromPoints(vert.x,vert.y,vert.z);
if(vertMap.containsKey(vert)){ if(vertMap.containsKey(builder.toString())){
return vertMap.get(vert); return vertMap.get(builder.toString());
} else { } else {
rVal = verts.size(); rVal = verts.size();
verts.add(vert); verts.add(new Vector3f(vert));
vertMap.put(vert,rVal); vertMap.put(builder.toString(),rVal);
return rVal; return rVal;
} }
} }
@ -1171,13 +1188,12 @@ public class TransvoxelModelGeneration {
* @param proportion1 The proportion of the second vector * @param proportion1 The proportion of the second vector
* @return The mixed vector * @return The mixed vector
*/ */
private static Vector3f averageNormals(Vector3f normal0, float proportion0, Vector3f normal1, float proportion1){ private static void averageNormals(Vector3f normal0, float proportion0, Vector3f normal1, float proportion1){
Vector3f rVal = new Vector3f( normal0.set(
normal0.x * proportion0 + normal1.x * proportion1, normal0.x * proportion0 + normal1.x * proportion1,
normal0.y * proportion0 + normal1.y * proportion1, normal0.y * proportion0 + normal1.y * proportion1,
normal0.z * proportion0 + normal1.z * proportion1 normal0.z * proportion0 + normal1.z * proportion1
); );
return rVal;
} }
@ -1208,7 +1224,7 @@ public class TransvoxelModelGeneration {
//the list of all triangles //the list of all triangles
List<Triangle> triangles = new LinkedList<Triangle>(); List<Triangle> triangles = new LinkedList<Triangle>();
//the map of vertex to index //the map of vertex to index
Map<Vector3f,Integer> vertMap = new HashMap<Vector3f,Integer>(); Map<String,Integer> vertMap = new HashMap<String,Integer>();
//the list of all verts //the list of all verts
List<Vector3f> verts = new LinkedList<Vector3f>(); List<Vector3f> verts = new LinkedList<Vector3f>();
//the list of all normals //the list of all normals
@ -1218,6 +1234,14 @@ public class TransvoxelModelGeneration {
//List of texture sampler values //List of texture sampler values
List<Vector3f> samplerTriangles = new LinkedList<Vector3f>(); List<Vector3f> samplerTriangles = new LinkedList<Vector3f>();
Vector3f[] vertList = new Vector3f[12];
int[] samplerIndex = new int[12];
boolean[] skip = new boolean[12];
for(int i = 0; i < 12; i++){
vertList[i] = new Vector3f();
}
StringBuilder builder = new StringBuilder();
//the vector pool //the vector pool
Vector3f[] vecPool = new Vector3f[VECTOR_POOL_SIZE]; Vector3f[] vecPool = new Vector3f[VECTOR_POOL_SIZE];
for(int i = 0; i < VECTOR_POOL_SIZE; i++){ for(int i = 0; i < VECTOR_POOL_SIZE; i++){
@ -1253,7 +1277,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1325,7 +1349,7 @@ public class TransvoxelModelGeneration {
chunkData.xPositiveEdgeAtlas[(y+0)*2+0][(z+0)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+0)*2+0], chunkData.xPositiveEdgeAtlas[(y+0)*2+0][(z+0)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+0)*2+0],
chunkData.xPositiveEdgeAtlas[(y+0)*2+0][(z+1)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+1)*2+0] chunkData.xPositiveEdgeAtlas[(y+0)*2+0][(z+1)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1347,7 +1371,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+1)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+0)*2+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+1)*2+0], chunkData.xPositiveEdgeAtlas[(y+1)*2+0][(z+0)*2+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1372,7 +1396,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1437,7 +1461,7 @@ public class TransvoxelModelGeneration {
chunkData.xNegativeEdgeAtlas[(y+0)*2+0][(z+0)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+0)*2+0], chunkData.xNegativeEdgeAtlas[(y+0)*2+0][(z+0)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+0)*2+0],
chunkData.xNegativeEdgeAtlas[(y+0)*2+0][(z+1)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+1)*2+0] chunkData.xNegativeEdgeAtlas[(y+0)*2+0][(z+1)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1459,7 +1483,7 @@ public class TransvoxelModelGeneration {
chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+0)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+1)*2+0], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+0)*2+0], chunkData.xNegativeEdgeAtlas[(y+1)*2+0][(z+1)*2+0], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1484,7 +1508,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1548,7 +1572,7 @@ public class TransvoxelModelGeneration {
chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+0)*2+0], chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+0)*2+0],
chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+1)*2+0] chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1570,7 +1594,7 @@ public class TransvoxelModelGeneration {
chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+0)*2+0] chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yPositiveEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+1)*2+0], chunkData.yPositiveEdgeAtlas[(x+1)*2+0][(z+0)*2+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1595,7 +1619,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1659,7 +1683,7 @@ public class TransvoxelModelGeneration {
chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+0)*2+0], chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+0)*2+0],
chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+1)*2+0] chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1681,7 +1705,7 @@ public class TransvoxelModelGeneration {
chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+0)*2+0] chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+0)*2+0], chunkData.yNegativeEdgeAtlas[(x+0)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+1)*2+0], chunkData.yNegativeEdgeAtlas[(x+1)*2+0][(z+0)*2+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1706,7 +1730,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1771,7 +1795,7 @@ public class TransvoxelModelGeneration {
chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+0)*2+0], chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+0)*2+0], chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+1)*2+0],
chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+0)*2+0], chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+1)*2+0] chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+0)*2+0], chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1793,7 +1817,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+1)*2+0], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.zPositiveEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zPositiveEdgeAtlas[(x+1)*2+0][(y+1)*2+0], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1818,7 +1842,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }
@ -1883,7 +1907,7 @@ public class TransvoxelModelGeneration {
chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+0)*2+0], chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+0)*2+0], chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+1)*2+0],
chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+0)*2+0], chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+1)*2+0] chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+0)*2+0], chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+1)*2+0]
); );
TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true); TransvoxelModelGeneration.polygonizeTransition(currentTransitionCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true, vertList, samplerIndex, builder);
// //
//Generate the normal cell with half width //Generate the normal cell with half width
@ -1905,7 +1929,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+1], chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+1)*2+0], chunkData.textureGrid[x+1][y+1][z+1] chunkData.textureGrid[x+0][y+1][z+1], chunkData.zNegativeEdgeAtlas[(x+0)*2+0][(y+1)*2+0], chunkData.zNegativeEdgeAtlas[(x+1)*2+0][(y+1)*2+0], chunkData.textureGrid[x+1][y+1][z+1]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, true, vertList, samplerIndex, skip, builder);
} }
} }
} else { } else {
@ -1930,7 +1954,7 @@ public class TransvoxelModelGeneration {
chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0] chunkData.textureGrid[x+0][y+1][z+0], chunkData.textureGrid[x+0][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+1], chunkData.textureGrid[x+1][y+1][z+0]
); );
//polygonize the current gridcell //polygonize the current gridcell
TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false); TransvoxelModelGeneration.polygonize(currentCell, TerrainChunkModelGeneration.MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert, false, vertList, samplerIndex, skip, builder);
} }
} }
} }

View File

@ -74,6 +74,7 @@ public class MainContentPipeline implements RenderPipeline {
Globals.profiler.beginCpuSample("MainContentPipeline.render - Solids non-instanced"); Globals.profiler.beginCpuSample("MainContentPipeline.render - Solids non-instanced");
Set<Entity> solidsNonInstanced = Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE); Set<Entity> solidsNonInstanced = Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE);
Vector3d positionVec = new Vector3d(); Vector3d positionVec = new Vector3d();
Vector3d scaleVec = new Vector3d();
Vector3d cameraCenterVec = CameraEntityUtils.getCameraCenter(Globals.playerCamera); Vector3d cameraCenterVec = CameraEntityUtils.getCameraCenter(Globals.playerCamera);
for(Entity currentEntity : solidsNonInstanced){ for(Entity currentEntity : solidsNonInstanced){
Vector3d position = EntityUtils.getPosition(currentEntity); Vector3d position = EntityUtils.getPosition(currentEntity);
@ -106,18 +107,18 @@ public class MainContentPipeline implements RenderPipeline {
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){ if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity); ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
//calculate model matrix //calculate model matrix
Vector3d cameraModifiedPosition = new Vector3d(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d cameraModifiedPosition = positionVec.set(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Quaterniond rotation = EntityUtils.getRotation(currentEntity); Quaterniond rotation = EntityUtils.getRotation(currentEntity);
// modelTransformMatrix.identity(); // modelTransformMatrix.identity();
modelTransformMatrix.identity().translationRotateScale( modelTransformMatrix.identity().translationRotateScale(
cameraModifiedPosition, cameraModifiedPosition,
new Quaterniond(rotation), rotation,
new Vector3d(EntityUtils.getScale(currentEntity)) scaleVec.set(EntityUtils.getScale(currentEntity))
); );
//set actor value //set actor value
currentActor.setAttribute(modelAttribute, new Matrix4d(modelTransformMatrix)); currentActor.setAttribute(modelAttribute, modelTransformMatrix);
//draw //draw
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition)); currentActor.draw(renderPipelineState, cameraModifiedPosition);
} else { } else {
currentActor.draw(renderPipelineState); currentActor.draw(renderPipelineState);
} }
@ -167,12 +168,12 @@ public class MainContentPipeline implements RenderPipeline {
//fetch actor //fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity); Actor currentActor = EntityUtils.getActor(currentEntity);
//calculate camera-modified vector3d //calculate camera-modified vector3d
Vector3d cameraModifiedPosition = new Vector3d(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d cameraModifiedPosition = positionVec.set(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
//calculate and apply model transform //calculate and apply model transform
modelTransformMatrix.identity(); modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition); modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity))); modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
currentActor.applySpatialData(modelTransformMatrix,position); currentActor.applySpatialData(modelTransformMatrix,position);
//draw //draw
currentActor.draw(renderPipelineState,openGLState); currentActor.draw(renderPipelineState,openGLState);
@ -189,18 +190,18 @@ public class MainContentPipeline implements RenderPipeline {
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){ if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity); ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
//calculate model matrix //calculate model matrix
Vector3d cameraModifiedPosition = new Vector3d(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d cameraModifiedPosition = positionVec.set(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Quaterniond rotation = EntityUtils.getRotation(currentEntity); Quaterniond rotation = EntityUtils.getRotation(currentEntity);
// modelTransformMatrix.identity(); // modelTransformMatrix.identity();
modelTransformMatrix.identity().translationRotateScale( modelTransformMatrix.identity().translationRotateScale(
cameraModifiedPosition, cameraModifiedPosition,
new Quaterniond(rotation), rotation,
new Vector3d(EntityUtils.getScale(currentEntity)) scaleVec.set(EntityUtils.getScale(currentEntity))
); );
//set actor value //set actor value
currentActor.setAttribute(modelAttribute, new Matrix4d(modelTransformMatrix)); currentActor.setAttribute(modelAttribute, modelTransformMatrix);
//draw //draw
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition)); currentActor.draw(renderPipelineState, cameraModifiedPosition);
} else { } else {
currentActor.draw(renderPipelineState); currentActor.draw(renderPipelineState);
} }

View File

@ -103,6 +103,8 @@ public class ShadowMapPipeline implements RenderPipeline {
// D R A W A L L E N T I T I E S // D R A W A L L E N T I T I E S
// //
modelTransformMatrix = new Matrix4d(); modelTransformMatrix = new Matrix4d();
Vector3d posVec = new Vector3d();
Vector3d scaleVec = new Vector3d();
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_CAST_SHADOW)){ for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_CAST_SHADOW)){
Vector3d position = EntityUtils.getPosition(currentEntity); Vector3d position = EntityUtils.getPosition(currentEntity);
if( if(
@ -111,13 +113,13 @@ public class ShadowMapPipeline implements RenderPipeline {
//fetch actor //fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity); Actor currentActor = EntityUtils.getActor(currentEntity);
//calculate camera-modified vector3d //calculate camera-modified vector3d
Vector3d cameraCenter = new Vector3d(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); Vector3d cameraCenter = posVec.set(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Vector3d cameraModifiedPosition = new Vector3d(position).sub(cameraCenter); Vector3d cameraModifiedPosition = position.sub(cameraCenter);
//calculate and apply model transform //calculate and apply model transform
modelTransformMatrix = modelTransformMatrix.identity(); modelTransformMatrix = modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition); modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity))); modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
currentActor.applySpatialData(modelTransformMatrix,position); currentActor.applySpatialData(modelTransformMatrix,position);
//draw //draw
currentActor.draw(renderPipelineState,openGLState); currentActor.draw(renderPipelineState,openGLState);

View File

@ -108,7 +108,7 @@ public class ServerBlockChunkDiskMap {
lock.lock(); lock.lock();
LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ); LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ);
BlockChunkData rVal = null; BlockChunkData rVal = null;
if(containsBlocksAtPosition(worldX, worldY, worldZ)){ if(this.containsBlocksAtPosition(worldX, worldY, worldZ)){
//read file //read file
String fileName = worldPosFileMap.get(getBlockChunkKey(worldX, worldY, worldZ)); String fileName = worldPosFileMap.get(getBlockChunkKey(worldX, worldY, worldZ));
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName); byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName);

View File

@ -20,7 +20,8 @@ public class TransvoxelModelGenerationTests {
new Vector3f(15, 0, 6), new Vector3f(15, 0, 6),
new Vector3f(16, 0, 6), new Vector3f(16, 0, 6),
0.08262646198272705, 0.08262646198272705,
0.009999990463256836 0.009999990463256836,
new Vector3f()
); );
}); });
// Vector3f vec2 = TransvoxelModelGeneration.VertexInterp( // Vector3f vec2 = TransvoxelModelGeneration.VertexInterp(
@ -35,19 +36,23 @@ public class TransvoxelModelGenerationTests {
@UnitTest @UnitTest
public void testVertexInterp2(){ public void testVertexInterp2(){
Vector3f vec1 = TransvoxelModelGeneration.VertexInterp( Vector3f vec1 = new Vector3f();
TransvoxelModelGeneration.VertexInterp(
TerrainChunkModelGeneration.MIN_ISO_VALUE, TerrainChunkModelGeneration.MIN_ISO_VALUE,
new Vector3f(1, 2, 0), new Vector3f(1, 2, 0),
new Vector3f(0, 2, 0), new Vector3f(0, 2, 0),
-0.338376522064209, -0.338376522064209,
0.0 0.0,
vec1
); );
Vector3f vec2 = TransvoxelModelGeneration.VertexInterp( Vector3f vec2 = new Vector3f();
TransvoxelModelGeneration.VertexInterp(
TerrainChunkModelGeneration.MIN_ISO_VALUE, TerrainChunkModelGeneration.MIN_ISO_VALUE,
new Vector3f(0, 2, 0), new Vector3f(0, 2, 0),
new Vector3f(0, 3, 0), new Vector3f(0, 3, 0),
0, 0,
-1.0 -1.0,
vec2
); );
assertNotEquals(vec1, vec2); assertNotEquals(vec1, vec2);
} }
@ -56,19 +61,23 @@ public class TransvoxelModelGenerationTests {
public void testVertexInterp3(){ public void testVertexInterp3(){
//vertList[1] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2]); //vertList[1] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[1],grid.points[2],grid.val[1],grid.val[2]);
//vertList[10] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]); //vertList[10] = TransvoxelModelGeneration.VertexInterp(isolevel,grid.points[2],grid.points[6],grid.val[2],grid.val[6]);
Vector3f vec1 = TransvoxelModelGeneration.VertexInterp( Vector3f vec1 = new Vector3f();
TransvoxelModelGeneration.VertexInterp(
TerrainChunkModelGeneration.MIN_ISO_VALUE, TerrainChunkModelGeneration.MIN_ISO_VALUE,
new Vector3f(8, 8, 15.5f), new Vector3f(8, 8, 15.5f),
new Vector3f(9, 8, 15.5f), new Vector3f(9, 8, 15.5f),
0.0, 0.0,
-1.0 -1.0,
vec1
); );
Vector3f vec2 = TransvoxelModelGeneration.VertexInterp( Vector3f vec2 = new Vector3f();
TransvoxelModelGeneration.VertexInterp(
TerrainChunkModelGeneration.MIN_ISO_VALUE, TerrainChunkModelGeneration.MIN_ISO_VALUE,
new Vector3f(9, 8, 15.5f), new Vector3f(9, 8, 15.5f),
new Vector3f(9, 9, 15.5f), new Vector3f(9, 9, 15.5f),
-1.0, -1.0,
0.0 0.0,
vec2
); );
assertNotEquals(vec1, vec2); assertNotEquals(vec1, vec2);
} }