optimize voxel rasterize data passthrough
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-11-19 13:01:44 -05:00
parent 4d9047d8cf
commit 8284697812
7 changed files with 427 additions and 264 deletions

View File

@ -1082,6 +1082,7 @@ Fix draw cells not deleting once all children have reported generation
Fix server data cells unloading before ready state
Fix terrain chunk generation trying to generate rigid body for no-vertex cell
Fix server homogenous chunk check on generation with variadic weights
Optimize data passing from voxel rasterizer to model generation

View File

@ -25,7 +25,7 @@ import electrosphere.entity.Entity;
import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
import electrosphere.renderer.model.Model;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager;
@ -298,7 +298,7 @@ public class ClientTerrainManager {
Globals.profiler.beginCpuSample("ClientTerrainManager.generateTerrainChunkGeometry");
lock.acquireUninterruptibly();
for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){
Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData(), queueItem.getAtlas());
Model terrainModel = TransvoxelModelGeneration.generateTerrainModel(queueItem.getData(), queueItem.getAtlas());
Globals.assetManager.registerModelToSpecificString(terrainModel, queueItem.getPromisedHash());
if(queueItem.notifyTarget != null){
queueItem.notifyTarget.alertToGeneration();

View File

@ -258,30 +258,10 @@ public class CollisionBodyCreation {
*/
public static DBody generateBodyFromTerrainData(CollisionEngine collisionEngine, TerrainChunkData data, long categoryBits){
DBody body = null;
int elementCount = data.getFaceElements().size();
float[] vertices = new float[elementCount * 3];
int vertexInserterPos = 0;
int[] indices = new int[elementCount];
int indexInserterPos = 0;
for(int element : data.getFaceElements()){
//add a new vertex
vertices[vertexInserterPos*3+0] = data.getVertices().get(element*3+0);
vertices[vertexInserterPos*3+1] = data.getVertices().get(element*3+1);
vertices[vertexInserterPos*3+2] = data.getVertices().get(element*3+2);
vertexInserterPos = vertexInserterPos + 1;
//push faces -- instead of pushing the element directly, instead use the incrementer because we want to draw a new vertex
//there should be no vertex-sharing between triangles. This keeps the meshes from blurring texture/lighting
indices[indexInserterPos] = indexInserterPos;
indexInserterPos++;
}
//create trimesh
if(vertices.length > 0){
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices,categoryBits);
if(data.getFaceElements().length > 0){
DTriMesh triMesh = collisionEngine.createTrimeshGeom(data.getVertices(),data.getFaceElements(),categoryBits);
body = collisionEngine.createDBody(triMesh);
collisionEngine.setKinematic(body);
collisionEngine.setGravityMode(body, false);

View File

@ -20,7 +20,6 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData;
import electrosphere.server.datacell.Realm;
@ -65,7 +64,7 @@ public class TerrainChunk {
if(Globals.clientScene.containsEntity(rVal)){
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas, notifyTarget, toDelete);
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
if(levelOfDetail == ClientDrawCellManager.FULL_RES_LOD && data.faceElements.size() > 0){
if(levelOfDetail == ClientDrawCellManager.FULL_RES_LOD && data.faceElements.length > 0){
PhysicsEntityUtils.clientAttachTerrainChunkRigidBody(rVal, data);
CollisionObjUtils.clientPositionCharacter(rVal, new Vector3d(EntityUtils.getPosition(rVal)), new Quaterniond());
} else {
@ -112,10 +111,11 @@ public class TerrainChunk {
*/
public static Entity serverCreateTerrainChunkEntity(Realm realm, Vector3d position, float[][][] weights, int[][][] values){
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
TransvoxelChunkData chunkData = new TransvoxelChunkData(weights, values, ClientDrawCellManager.FULL_RES_LOD);
TerrainChunkData data = TransvoxelModelGeneration.generateTerrainChunkData(chunkData);
Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
if(data.vertices.size() > 0){
if(data.vertices.length > 0){
PhysicsEntityUtils.serverAttachTerrainChunkRigidBody(rVal, data);
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
// ServerEntityUtils.initiallyPositionEntity(realm, rVal, position);

View File

@ -2,7 +2,6 @@ package electrosphere.entity.types.terrain;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.List;
import org.lwjgl.BufferUtils;
@ -12,17 +11,17 @@ import org.lwjgl.BufferUtils;
public class TerrainChunkData {
//the verts
List<Float> vertices;
float[] vertices;
//normals
List<Float> normals;
float[] normals;
//faces
List<Integer> faceElements;
int[] faceElements;
//UVs
List<Float> uvs;
float[] uvs;
//texture samplers
List<Float> textureSamplers; //what textures in the atlas to sample
float[] textureSamplers; //what textures in the atlas to sample
//texture ratio vector
List<Float> textureRatioVectors; //HOW MUCH of each texture in the atlas to sample
float[] textureRatioVectors; //HOW MUCH of each texture in the atlas to sample
/**
* The various buffers of data to send to the gpu
@ -49,7 +48,7 @@ public class TerrainChunkData {
* @param textureSamplers
* @param lod The LOD of the model
*/
public TerrainChunkData(List<Float> vertices, List<Float> normals, List<Integer> faceElements, List<Float> uvs, List<Float> textureSamplers, List<Float> textureRatioVectors, int lod){
public TerrainChunkData(float[] vertices, float[] normals, int[] faceElements, float[] uvs, float[] textureSamplers, float[] textureRatioVectors, int lod){
this.vertices = vertices;
this.normals = normals;
this.faceElements = faceElements;
@ -63,50 +62,30 @@ public class TerrainChunkData {
* Allocates and fills the buffers to send to the gpu
*/
public void constructBuffers(){
int elementCount = this.getFaceElements().size();
vertexArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3);
normalArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 3);
textureArrayBufferData = BufferUtils.createFloatBuffer(elementCount * 2);
elementArrayBufferData = BufferUtils.createIntBuffer(elementCount);
int incrementer = 0;
for(int element : this.getFaceElements()){
//for each element, need to push vert, normal, etc
vertexArrayBufferData = BufferUtils.createFloatBuffer(vertices.length);
vertexArrayBufferData.put(vertices);
//push current vertex
vertexArrayBufferData.put(this.getVertices().get(element*3+0));
vertexArrayBufferData.put(this.getVertices().get(element*3+1));
vertexArrayBufferData.put(this.getVertices().get(element*3+2));
normalArrayBufferData = BufferUtils.createFloatBuffer(normals.length);
normalArrayBufferData.put(normals);
//push current normals
normalArrayBufferData.put(this.getNormals().get(element*3+0));
normalArrayBufferData.put(this.getNormals().get(element*3+1));
normalArrayBufferData.put(this.getNormals().get(element*3+2));
textureArrayBufferData = BufferUtils.createFloatBuffer(uvs.length);
textureArrayBufferData.put(uvs);
//push current uvs
textureArrayBufferData.put(this.getUVs().get(element*2+0));
textureArrayBufferData.put(this.getUVs().get(element*2+1));
elementArrayBufferData = BufferUtils.createIntBuffer(faceElements.length);
elementArrayBufferData.put(faceElements);
//push faces -- instead of pushing the element directly, instead use the incrementer because we want to draw a new vertex
//there should be no vertex-sharing between triangles. This keeps the meshes from blurring texture/lighting
elementArrayBufferData.put(incrementer);
incrementer++;
}
int vertexCount = this.getTextureSamplers().size() / 3;
samplerBuffer = BufferUtils.createFloatBuffer(vertexCount * 3);
for(float samplerVec : this.getTextureSamplers()){
samplerBuffer.put(samplerVec);
}
ratioBuffer = BufferUtils.createFloatBuffer(vertexCount * 3);
for(float ratioVec : this.getTextureRatioVectors()){
ratioBuffer.put(ratioVec);
}
samplerBuffer = BufferUtils.createFloatBuffer(textureSamplers.length);
samplerBuffer.put(this.textureSamplers);
ratioBuffer = BufferUtils.createFloatBuffer(textureRatioVectors.length);
ratioBuffer.put(this.textureRatioVectors);
}
/**
* Gets the vertex data
* @return the vertex data
*/
public List<Float> getVertices(){
public float[] getVertices(){
return vertices;
}
@ -114,7 +93,7 @@ public class TerrainChunkData {
* Gets the normal data
* @return the normal data
*/
public List<Float> getNormals(){
public float[] getNormals(){
return normals;
}
@ -122,7 +101,7 @@ public class TerrainChunkData {
* Gets the face element data
* @return the face element data
*/
public List<Integer> getFaceElements(){
public int[] getFaceElements(){
return faceElements;
}
@ -130,7 +109,7 @@ public class TerrainChunkData {
* Gets the uv data
* @return the uv data
*/
public List<Float> getUVs(){
public float[] getUVs(){
return uvs;
}
@ -138,7 +117,7 @@ public class TerrainChunkData {
* Gets the texture sampler data
* @return the texture sampler data
*/
public List<Float> getTextureSamplers(){
public float[] getTextureSamplers(){
return textureSamplers;
}
@ -146,7 +125,7 @@ public class TerrainChunkData {
* Gets the texture ratio vector data
* @return the texture ratio vector data
*/
public List<Float> getTextureRatioVectors(){
public float[] getTextureRatioVectors(){
return textureRatioVectors;
}

View File

@ -2,8 +2,6 @@ package electrosphere.renderer.meshgen;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -624,147 +622,147 @@ public class TerrainChunkModelGeneration {
return new Vector3f(x,y,z);
}
public static TerrainChunkData generateTerrainChunkData(float[][][] terrainGrid, int[][][] textureGrid){
// public static TerrainChunkData generateTerrainChunkData(float[][][] terrainGrid, int[][][] textureGrid){
// 5 6
// +-------------+ +-----5-------+ ^ Y
// / | / | / | /| | _
// / | / | 4 9 6 10 | /\ Z
// 4 +-----+-------+ 7 | +-----+7------+ | | /
// | 1 +-------+-----+ 2 | +-----1-+-----+ | /
// | / | / 8 0 11 2 | /
// | / | / | / | / |/
// 0 +-------------+ 3 +------3------+ +---------------> X
// // 5 6
// // +-------------+ +-----5-------+ ^ Y
// // / | / | / | /| | _
// // / | / | 4 9 6 10 | /\ Z
// // 4 +-----+-------+ 7 | +-----+7------+ | | /
// // | 1 +-------+-----+ 2 | +-----1-+-----+ | /
// // | / | / 8 0 11 2 | /
// // | / | / | / | / |/
// // 0 +-------------+ 3 +------3------+ +---------------> X
//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>();
//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>();
//List of texture sampler values
List<Vector3f> samplerTriangles = new LinkedList<Vector3f>();
//List of UVs
List<Float> UVs = new LinkedList<Float>();
// //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>();
// //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>();
// //List of texture sampler values
// List<Vector3f> samplerTriangles = new LinkedList<Vector3f>();
// //List of UVs
// List<Float> UVs = new LinkedList<Float>();
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++){
//push the current cell's values into the gridcell
currentCell.setValues(
new Vector3f(x+0,y+0,z+0), new Vector3f(x+0,y+0,z+1), new Vector3f(x+1,y+0,z+1), new Vector3f(x+1,y+0,z+0),
new Vector3f(x+0,y+1,z+0), new Vector3f(x+0,y+1,z+1), new Vector3f(x+1,y+1,z+1), new Vector3f(x+1,y+1,z+0),
terrainGrid[x+0][y+0][z+0], terrainGrid[x+0][y+0][z+1], terrainGrid[x+1][y+0][z+1], terrainGrid[x+1][y+0][z+0],
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],
textureGrid[x+0][y+0][z+0], textureGrid[x+0][y+0][z+1], textureGrid[x+1][y+0][z+1], textureGrid[x+1][y+0][z+0],
textureGrid[x+0][y+1][z+0], textureGrid[x+0][y+1][z+1], textureGrid[x+1][y+1][z+1], textureGrid[x+1][y+1][z+0]
);
//polygonize the current gridcell
polygonize(currentCell, MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert);
}
}
}
// 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++){
// //push the current cell's values into the gridcell
// currentCell.setValues(
// new Vector3f(x+0,y+0,z+0), new Vector3f(x+0,y+0,z+1), new Vector3f(x+1,y+0,z+1), new Vector3f(x+1,y+0,z+0),
// new Vector3f(x+0,y+1,z+0), new Vector3f(x+0,y+1,z+1), new Vector3f(x+1,y+1,z+1), new Vector3f(x+1,y+1,z+0),
// terrainGrid[x+0][y+0][z+0], terrainGrid[x+0][y+0][z+1], terrainGrid[x+1][y+0][z+1], terrainGrid[x+1][y+0][z+0],
// 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],
// textureGrid[x+0][y+0][z+0], textureGrid[x+0][y+0][z+1], textureGrid[x+1][y+0][z+1], textureGrid[x+1][y+0][z+0],
// textureGrid[x+0][y+1][z+0], textureGrid[x+0][y+1][z+1], textureGrid[x+1][y+1][z+1], textureGrid[x+1][y+1][z+0]
// );
// //polygonize the current gridcell
// polygonize(currentCell, MIN_ISO_VALUE, triangles, samplerTriangles, vertMap, verts, normals, trianglesSharingVert);
// }
// }
// }
//all verts in order, flattened as an array of floats instead of vecs
List<Float> vertsFlat = new LinkedList<Float>();
//all normals in order, flattened as an array of floats instead of vecs
List<Float> normalsFlat = new LinkedList<Float>();
//all elements of faces in order
LinkedList<Integer> elementsFlat = new LinkedList<Integer>();
//List of texture sampler values
List<Float> textureSamplers = new LinkedList<Float>();
//List of texture ratio values
List<Float> textureRatioData = new LinkedList<Float>();
// //all verts in order, flattened as an array of floats instead of vecs
// List<Float> vertsFlat = new LinkedList<Float>();
// //all normals in order, flattened as an array of floats instead of vecs
// List<Float> normalsFlat = new LinkedList<Float>();
// //all elements of faces in order
// LinkedList<Integer> elementsFlat = new LinkedList<Integer>();
// //List of texture sampler values
// List<Float> textureSamplers = new LinkedList<Float>();
// //List of texture ratio values
// List<Float> textureRatioData = new LinkedList<Float>();
//flatten verts + normals
for(Vector3f vert : verts){
vertsFlat.add(vert.x);
vertsFlat.add(vert.y);
vertsFlat.add(vert.z);
}
// //flatten verts + normals
// for(Vector3f vert : verts){
// vertsFlat.add(vert.x);
// vertsFlat.add(vert.y);
// vertsFlat.add(vert.z);
// }
for(Vector3f normal : normals){
normalsFlat.add(normal.x);
normalsFlat.add(normal.y);
normalsFlat.add(normal.z);
}
// for(Vector3f normal : normals){
// normalsFlat.add(normal.x);
// normalsFlat.add(normal.y);
// normalsFlat.add(normal.z);
// }
for(Triangle triangle : triangles){
elementsFlat.add(triangle.indices[0]);
elementsFlat.add(triangle.indices[1]);
elementsFlat.add(triangle.indices[2]);
}
// for(Triangle triangle : triangles){
// elementsFlat.add(triangle.indices[0]);
// elementsFlat.add(triangle.indices[1]);
// elementsFlat.add(triangle.indices[2]);
// }
float[] temp = new float[3];
int i = 0;
for(Vector3f normal : normals){
Vector3f vert = verts.get(i);
// float[] temp = new float[3];
// int i = 0;
// for(Vector3f normal : normals){
// Vector3f vert = verts.get(i);
float absX = Math.abs(normal.x);
float absY = Math.abs(normal.y);
float absZ = Math.abs(normal.z);
// float absX = Math.abs(normal.x);
// float absY = Math.abs(normal.y);
// float absZ = Math.abs(normal.z);
float uvX = vert.z * absX + vert.x * absY + vert.x * absZ;
float uvY = vert.y * absX + vert.z * absY + vert.y * absZ;
temp[0] = uvX;
temp[1] = uvY;
// float uvX = vert.z * absX + vert.x * absY + vert.x * absZ;
// float uvY = vert.y * absX + vert.z * absY + vert.y * absZ;
// temp[0] = uvX;
// temp[1] = uvY;
// if(absX >= absZ && absX >= absY){
// temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY));
// } else if(absZ >= absX && absZ >= absY){
// temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY));
// } else if(absY >= absX && absY >= absZ){
// temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY));
// temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY));
// } else {
// temp[0] = vert.x / 1.5f + vert.z / 1.5f;
// temp[1] = vert.y / 1.5f + vert.z / 1.5f;
// }
i++;
UVs.add(temp[0]);
UVs.add(temp[1]);
}
// // if(absX >= absZ && absX >= absY){
// // temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// // temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY));
// // } else if(absZ >= absX && absZ >= absY){
// // temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// // temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY));
// // } else if(absY >= absX && absY >= absZ){
// // temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY));
// // temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY));
// // } else {
// // temp[0] = vert.x / 1.5f + vert.z / 1.5f;
// // temp[1] = vert.y / 1.5f + vert.z / 1.5f;
// // }
// i++;
// UVs.add(temp[0]);
// UVs.add(temp[1]);
// }
//flatten sampler indices
for(Vector3f samplerVec : samplerTriangles){
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.x));
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.y));
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.z));
}
// //flatten sampler indices
// for(Vector3f samplerVec : samplerTriangles){
// textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.x));
// textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.y));
// textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.z));
// }
//set ratio dat
for(int j = 0; j < triangles.size(); j++){
//first vertex
textureRatioData.add(1.0f);
textureRatioData.add(0.0f);
textureRatioData.add(0.0f);
// //set ratio dat
// for(int j = 0; j < triangles.size(); j++){
// //first vertex
// textureRatioData.add(1.0f);
// textureRatioData.add(0.0f);
// textureRatioData.add(0.0f);
//second vertex
textureRatioData.add(0.0f);
textureRatioData.add(1.0f);
textureRatioData.add(0.0f);
// //second vertex
// textureRatioData.add(0.0f);
// textureRatioData.add(1.0f);
// textureRatioData.add(0.0f);
//third vertex
textureRatioData.add(0.0f);
textureRatioData.add(0.0f);
textureRatioData.add(1.0f);
}
// //third vertex
// textureRatioData.add(0.0f);
// textureRatioData.add(0.0f);
// textureRatioData.add(1.0f);
// }
//List<Float> vertices, List<Float> normals, List<Integer> faceElements, List<Float> uvs
TerrainChunkData rVal = new TerrainChunkData(vertsFlat, normalsFlat, elementsFlat, UVs, textureSamplers, textureRatioData, 0);
return rVal;
}
// //List<Float> vertices, List<Float> normals, List<Integer> faceElements, List<Float> uvs
// TerrainChunkData rVal = new TerrainChunkData(vertsFlat, normalsFlat, elementsFlat, UVs, textureSamplers, textureRatioData, 0);
// return rVal;
// }
/**
* Generates a mesh based on a terrainchunkdata object
@ -797,7 +795,7 @@ public class TerrainChunkModelGeneration {
//
// Buffer data to GPU
//
int elementCount = data.getFaceElements().size();
int elementCount = data.getFaceElements().length;
try {
//actually buffer vertices
@ -883,6 +881,7 @@ public class TerrainChunkModelGeneration {
* @param atlas The atlas texture for the chunk
* @return The model
*/
@Deprecated
public static Model generateTerrainModel(TerrainChunkData data, VoxelTextureAtlas atlas){
Model rVal = new Model();
Mesh m = TerrainChunkModelGeneration.generateTerrainMesh(data);

View File

@ -1,15 +1,22 @@
package electrosphere.renderer.meshgen;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL40;
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
import electrosphere.engine.Globals;
import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.model.Material;
import electrosphere.renderer.model.Mesh;
import electrosphere.renderer.model.Model;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/**
@ -17,6 +24,41 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
*/
public class TransvoxelModelGeneration {
/**
* Number of ints required to store an element
*/
static final int INTS_PER_ELEMENT = 1;
/**
* Number of elements per triangle
*/
static final int ELEMENTS_PER_TRIANGLE = 3;
/**
* Number of floats per vert
*/
static final int FLOATS_PER_VERT = 3;
/**
* Number of vertices per triangle
*/
static final int VERTS_PER_TRIANGLE = ELEMENTS_PER_TRIANGLE;
/**
* Number of floats per UV
*/
static final int FLOATS_PER_UV = 2;
/**
* The number of sampler indices per triangle
*/
static final int SAMPLER_INDICES_PER_TRIANGLE = 3;
/**
* The number of sampler values to store for each vertex
*/
static final int SAMPLER_VALUES_PER_VERT = 3;
//this is the width of the transition cell
@ -1045,8 +1087,6 @@ public class TransvoxelModelGeneration {
List<Integer> trianglesSharingVert = new LinkedList<Integer>();
//List of texture sampler values
List<Vector3f> samplerTriangles = new LinkedList<Vector3f>();
//List of UVs
List<Float> UVs = new LinkedList<Float>();
@ -1601,96 +1641,123 @@ public class TransvoxelModelGeneration {
}
if (verts.size() != normals.size()){
throw new Error("Generated invalid number of elements in lists! " + verts.size() + " " + normals.size());
}
//incrementer
int i = 0;
//all verts in order, flattened as an array of floats instead of vecs
List<Float> vertsFlat = new LinkedList<Float>();
//all normals in order, flattened as an array of floats instead of vecs
List<Float> normalsFlat = new LinkedList<Float>();
//all elements of faces in order
List<Integer> elementsFlat = new LinkedList<Integer>();
int[] elementsFlat = new int[triangles.size() * ELEMENTS_PER_TRIANGLE * INTS_PER_ELEMENT];
//all verts in order, flattened as an array of floats instead of vecs
float[] vertsFlat = new float[triangles.size() * VERTS_PER_TRIANGLE * FLOATS_PER_VERT];
//all normals in order, flattened as an array of floats instead of vecs
float[] normalsFlat = new float[triangles.size() * VERTS_PER_TRIANGLE * FLOATS_PER_VERT];
//List of UVs
float[] UVs = new float[triangles.size() * VERTS_PER_TRIANGLE * FLOATS_PER_UV];
//List of texture sampler values
List<Float> textureSamplers = new LinkedList<Float>();
float[] textureSamplers = new float[samplerTriangles.size() * SAMPLER_INDICES_PER_TRIANGLE];
//List of texture ratio values
List<Float> textureRatioData = new LinkedList<Float>();
float[] textureRatioData = new float[triangles.size() * SAMPLER_INDICES_PER_TRIANGLE * SAMPLER_VALUES_PER_VERT];
float scalingFactor = (float)Math.pow(2,chunkData.levelOfDetail);
//flatten verts + normals
for(Vector3f vert : verts){
vertsFlat.add(vert.x * scalingFactor);
vertsFlat.add(vert.y * scalingFactor);
vertsFlat.add(vert.z * scalingFactor);
//store indices
for(int j = 0; j < elementsFlat.length; j++){
//assigning a unique number to each element guarantees there's no vertex sharing between triangles
//we don't want vertex sharing because then the UVs are shared
elementsFlat[j] = j;
}
for(Vector3f normal : normals){
normalsFlat.add(normal.x);
normalsFlat.add(normal.y);
normalsFlat.add(normal.z);
}
//flatten verts + normals + uvs
i = 0;
Vector3f vert = null;
Vector3f normal = null;
for(Triangle triangle : triangles){
elementsFlat.add(triangle.indices[0]);
elementsFlat.add(triangle.indices[1]);
elementsFlat.add(triangle.indices[2]);
}
float[] temp = new float[3];
int i = 0;
for(Vector3f normal : normals){
Vector3f vert = verts.get(i);
//
//point 1 of the triangle
vert = verts.get(triangle.indices[0]);
normal = normals.get(triangle.indices[0]);
vertsFlat[i*9+0] = vert.x * scalingFactor;
vertsFlat[i*9+1] = vert.y * scalingFactor;
vertsFlat[i*9+2] = vert.z * scalingFactor;
float absX = Math.abs(normal.x);
float absY = Math.abs(normal.y);
float absZ = Math.abs(normal.z);
normalsFlat[i*9+0] = normal.x;
normalsFlat[i*9+1] = normal.y;
normalsFlat[i*9+2] = normal.z;
float uvX = vert.z * absX + vert.x * absY + vert.x * absZ;
float uvY = vert.y * absX + vert.z * absY + vert.y * absZ;
temp[0] = uvX;
temp[1] = uvY;
UVs[i*6+0] = vert.z * Math.abs(normal.x) + vert.x * Math.abs(normal.y) + vert.x * Math.abs(normal.z);
UVs[i*6+1] = vert.y * Math.abs(normal.x) + vert.z * Math.abs(normal.y) + vert.y * Math.abs(normal.z);
// if(absX >= absZ && absX >= absY){
// temp[0] = normal.z / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// temp[1] = normal.y / 2.0f + 0.5f + vert.x * (absY / (absX + absY)) + vert.y * (absX / (absX + absY));
// } else if(absZ >= absX && absZ >= absY){
// temp[0] = normal.x / 2.0f + 0.5f + vert.z * (absX / (absX + absZ)) + vert.x * (absZ / (absX + absZ));
// temp[1] = normal.y / 2.0f + 0.5f + vert.z * (absY / (absZ + absY)) + vert.y * (absZ / (absZ + absY));
// } else if(absY >= absX && absY >= absZ){
// temp[0] = normal.x / 2.0f + 0.5f + vert.y * (absX / (absX + absY)) + vert.x * (absY / (absX + absY));
// temp[1] = normal.z / 2.0f + 0.5f + vert.y * (absZ / (absZ + absY)) + vert.z * (absY / (absZ + absY));
// } else {
// temp[0] = vert.x / 1.5f + vert.z / 1.5f;
// temp[1] = vert.y / 1.5f + vert.z / 1.5f;
// }
//
//point 2 of the triangle
vert = verts.get(triangle.indices[1]);
normal = normals.get(triangle.indices[1]);
vertsFlat[i*9+3] = vert.x * scalingFactor;
vertsFlat[i*9+4] = vert.y * scalingFactor;
vertsFlat[i*9+5] = vert.z * scalingFactor;
normalsFlat[i*9+3] = normal.x;
normalsFlat[i*9+4] = normal.y;
normalsFlat[i*9+5] = normal.z;
UVs[i*6+2] = vert.z * Math.abs(normal.x) + vert.x * Math.abs(normal.y) + vert.x * Math.abs(normal.z);
UVs[i*6+3] = vert.y * Math.abs(normal.x) + vert.z * Math.abs(normal.y) + vert.y * Math.abs(normal.z);
//
//point 3 of the triangle
vert = verts.get(triangle.indices[2]);
normal = normals.get(triangle.indices[2]);
vertsFlat[i*9+6] = vert.x * scalingFactor;
vertsFlat[i*9+7] = vert.y * scalingFactor;
vertsFlat[i*9+8] = vert.z * scalingFactor;
normalsFlat[i*9+6] = normal.x;
normalsFlat[i*9+7] = normal.y;
normalsFlat[i*9+8] = normal.z;
UVs[i*6+4] = vert.z * Math.abs(normal.x) + vert.x * Math.abs(normal.y) + vert.x * Math.abs(normal.z);
UVs[i*6+5] = vert.y * Math.abs(normal.x) + vert.z * Math.abs(normal.y) + vert.y * Math.abs(normal.z);
i++;
UVs.add(temp[0]);
UVs.add(temp[1]);
}
//flatten sampler indices
i = 0;
for(Vector3f samplerVec : samplerTriangles){
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.x));
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.y));
textureSamplers.add((float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.z));
textureSamplers[i*3+0] = (float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.x);
textureSamplers[i*3+1] = (float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.y);
textureSamplers[i*3+2] = (float)Globals.voxelTextureAtlas.getVoxelTypeOffset((int)samplerVec.z);
i++;
}
if(i * 3 < textureSamplers.length){
throw new Error("Did not add all elements! " + samplerTriangles.size() + " " + textureSamplers.length);
}
//set ratio dat
for(int j = 0; j < triangles.size(); j++){
for(int j = 0; j < textureRatioData.length / 9; j++){
//first vertex
textureRatioData.add(1.0f);
textureRatioData.add(0.0f);
textureRatioData.add(0.0f);
textureRatioData[j*9+0] = 1.0f;
textureRatioData[j*9+1] = 0.0f;
textureRatioData[j*9+2] = 0.0f;
//second vertex
textureRatioData.add(0.0f);
textureRatioData.add(1.0f);
textureRatioData.add(0.0f);
textureRatioData[j*9+3] = 0.0f;
textureRatioData[j*9+4] = 1.0f;
textureRatioData[j*9+5] = 0.0f;
//third vertex
textureRatioData.add(0.0f);
textureRatioData.add(0.0f);
textureRatioData.add(1.0f);
textureRatioData[j*9+6] = 0.0f;
textureRatioData[j*9+7] = 0.0f;
textureRatioData[j*9+8] = 1.0f;
}
//List<Float> vertices, List<Float> normals, List<Integer> faceElements, List<Float> uvs
@ -1699,6 +1766,143 @@ public class TransvoxelModelGeneration {
}
/**
* Generates a mesh based on a terrainchunkdata object
* @param data The terrain chunk data object
* @return The mesh
*/
protected static Mesh generateTerrainMesh(TerrainChunkData data){
Mesh mesh = new Mesh("terrainChunk");
//
// VAO
//
mesh.generateVAO();
FloatBuffer vertexArrayBufferData = data.getVertexArrayBufferData();
FloatBuffer normalArrayBufferData = data.getNormalArrayBufferData();
FloatBuffer textureArrayBufferData = data.getTextureArrayBufferData();
IntBuffer elementArrayBufferData = data.getElementArrayBufferData();
FloatBuffer samplerBuffer = data.getSamplerBuffer();
FloatBuffer ratioBuffer = data.getRatioBuffer();
//
// Buffer data to GPU
//
int elementCount = data.getFaceElements().length;
try {
//actually buffer vertices
if(vertexArrayBufferData.position() > 0){
vertexArrayBufferData.flip();
mesh.bufferVertices(vertexArrayBufferData, 3);
}
//actually buffer normals
if(normalArrayBufferData.position() > 0){
normalArrayBufferData.flip();
mesh.bufferNormals(normalArrayBufferData, 3);
}
//actually buffer UVs
if(textureArrayBufferData.position() > 0){
textureArrayBufferData.flip();
mesh.bufferTextureCoords(textureArrayBufferData, 2);
}
//buffer element indices
if(elementArrayBufferData.position() > 0){
elementArrayBufferData.flip();
mesh.bufferFaces(elementArrayBufferData, elementCount);
}
} catch (NullPointerException ex){
ex.printStackTrace();
}
//
// SAMPLER INDICES
//
try {
if(samplerBuffer.position() > 0){
samplerBuffer.flip();
mesh.bufferCustomFloatAttribArray(samplerBuffer, 3, SAMPLER_INDEX_ATTRIB_LOC);
}
} catch (NullPointerException ex){
ex.printStackTrace();
}
//
// SAMPLER RATIO DATA
//
try {
if(ratioBuffer.position() > 0){
ratioBuffer.flip();
mesh.bufferCustomFloatAttribArray(ratioBuffer, 3, SAMPLER_RATIO_ATTRIB_LOC);
}
} catch (NullPointerException ex){
ex.printStackTrace();
}
//bounding sphere logic
int distance = ServerTerrainChunk.CHUNK_DIMENSION / 2 * (int)Math.pow(2,data.getLOD());
mesh.updateBoundingSphere(
distance,
distance,
distance,
(float)Math.sqrt(
distance * distance +
distance * distance +
distance * distance
));
GL40.glBindVertexArray(0);
return mesh;
}
/**
* Generates a model based on a terrainchunkdata object
* @param data The terrain chunk data object
* @param atlas The atlas texture for the chunk
* @return The model
*/
public static Model generateTerrainModel(TerrainChunkData data, VoxelTextureAtlas atlas){
Model rVal = new Model();
Mesh m = TransvoxelModelGeneration.generateTerrainMesh(data);
//construct the material for the chunk
Material groundMat = new Material();
groundMat.setTexturePointer(atlas.getSpecular().getTexturePointer());
groundMat.setNormalTexturePointer(atlas.getNormal().getTexturePointer());
m.setMaterial(groundMat);
//shader logic
m.setShader(Globals.terrainShaderProgram);
m.setParent(rVal);
rVal.getMeshes().add(m);
rVal.setBoundingSphere(m.getBoundingSphere());
return rVal;
}