aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/makamys/neodymium/renderer/ChunkMesh.java')
-rw-r--r--src/main/java/makamys/neodymium/renderer/ChunkMesh.java95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
index 2284c6c..d5bf1b7 100644
--- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
+++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
@@ -9,6 +9,8 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@@ -35,6 +37,8 @@ public class ChunkMesh extends Mesh {
Flags flags;
+ private int[] subMeshStart = new int[NORMAL_ORDER.length];
+
// TODO move this somewhere else
List<String> nameList = (List<String>) ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites.keySet().stream().collect(Collectors.toList());
@@ -43,6 +47,21 @@ public class ChunkMesh extends Mesh {
private static RecyclingList<MeshQuad> quadBuf = new RecyclingList<>(() -> new MeshQuad());
+ private static final QuadNormal[] NORMAL_ORDER = new QuadNormal[] {QuadNormal.NONE, QuadNormal.POSITIVE_Y, QuadNormal.POSITIVE_X, QuadNormal.POSITIVE_Z, QuadNormal.NEGATIVE_X, QuadNormal.NEGATIVE_Z, QuadNormal.NEGATIVE_Y};
+ private static final Comparator<MeshQuad> MESH_QUAD_RENDER_COMPARATOR = new MeshQuadRenderOrderComparator();
+ private static final int[] QUAD_NORMAL_TO_NORMAL_ORDER;
+
+ static {
+ QUAD_NORMAL_TO_NORMAL_ORDER = new int[QuadNormal.values().length];
+ for(int i = 0; i < QuadNormal.values().length; i++) {
+ int idx = Arrays.asList(NORMAL_ORDER).indexOf(QuadNormal.values()[i]);
+ if(idx == -1) {
+ idx = 0;
+ }
+ QUAD_NORMAL_TO_NORMAL_ORDER[i] = idx;
+ }
+ }
+
public ChunkMesh(int x, int y, int z, Flags flags, int quadCount, List<MeshQuad> quads, int pass) {
this.x = x;
this.y = y;
@@ -50,6 +69,7 @@ public class ChunkMesh extends Mesh {
this.flags = flags;
this.quadCount = quadCount;
this.pass = pass;
+ Arrays.fill(subMeshStart, -1);
buffer = createBuffer(quads, quadCount);
usedRAM += buffer.limit();
@@ -184,13 +204,21 @@ public class ChunkMesh extends Mesh {
ByteBuffer buffer = BufferUtils.createByteBuffer(quadCount * 4 * MeshQuad.getStride());
BufferWriter out = new BufferWriter(buffer);
+ quads.sort(MESH_QUAD_RENDER_COMPARATOR);
+
try {
int i = 0;
for(MeshQuad quad : quads) {
if(i < quadCount) {
if(MeshQuad.isValid(quad)) {
+ int subMeshStartIdx = QUAD_NORMAL_TO_NORMAL_ORDER[quad.normal.ordinal()];
+ if(subMeshStart[subMeshStartIdx] == -1) {
+ subMeshStart[subMeshStartIdx] = i;
+ }
quad.writeToBuffer(out);
i++;
+ } else {
+ break;
}
}
}
@@ -295,6 +323,58 @@ public class ChunkMesh extends Mesh {
return ((IWorldRenderer)wr).getChunkMeshes();
}
+ @Override
+ public void writeToIndexBuffer(IntBuffer piFirst, IntBuffer piCount, int[] renderedMeshesReturn,
+ int[] renderedQuadsReturn, int cameraXDiv, int cameraYDiv, int cameraZDiv) {
+ if(!Config.cullFaces) {
+ super.writeToIndexBuffer(piFirst, piCount, renderedMeshesReturn, renderedQuadsReturn, cameraXDiv, cameraYDiv, cameraZDiv);
+ return;
+ }
+
+ renderedMeshesReturn[0] = 0;
+ renderedQuadsReturn[0] = 0;
+
+ int startIndex = -1;
+ for(int i = 0; i < NORMAL_ORDER.length + 1; i++) {
+ if(i < subMeshStart.length && subMeshStart[i] == -1) continue;
+
+ QuadNormal normal = i < NORMAL_ORDER.length ? NORMAL_ORDER[i] : null;
+ boolean isVisible = normal != null && isNormalVisible(normal, cameraXDiv, cameraYDiv, cameraZDiv);
+
+ if(isVisible && startIndex == -1) {
+ startIndex = subMeshStart[QUAD_NORMAL_TO_NORMAL_ORDER[normal.ordinal()]];
+ } else if(!isVisible && startIndex != -1) {
+ int endIndex = i < subMeshStart.length ? subMeshStart[i] : quadCount;
+
+ piFirst.put(iFirst + (startIndex*4));
+ piCount.put((endIndex - startIndex)*4);
+ renderedMeshesReturn[0]++;
+ renderedQuadsReturn[0] += endIndex - startIndex; // TODO remove this, it's redundant
+
+ startIndex = -1;
+ }
+ }
+ }
+
+ private boolean isNormalVisible(QuadNormal normal, int interpXDiv, int interpYDiv, int interpZDiv) {
+ switch(normal) {
+ case POSITIVE_X:
+ return interpXDiv >= ((x + 0));
+ case NEGATIVE_X:
+ return interpXDiv < ((x + 1));
+ case POSITIVE_Y:
+ return interpYDiv >= ((y + 0));
+ case NEGATIVE_Y:
+ return interpYDiv < ((y + 1));
+ case POSITIVE_Z:
+ return interpZDiv >= ((z + 0));
+ case NEGATIVE_Z:
+ return interpZDiv < ((z + 1));
+ default:
+ return true;
+ }
+ }
+
public double distSq(Entity player) {
int centerX = x * 16 + 8;
int centerY = y * 16 + 8;
@@ -341,5 +421,20 @@ public class ChunkMesh extends Mesh {
}
}
+ private static class MeshQuadRenderOrderComparator implements Comparator<MeshQuad> {
+
+ @Override
+ public int compare(MeshQuad a, MeshQuad b) {
+ if(!MeshQuad.isValid(b)) {
+ return 1;
+ } else if(!MeshQuad.isValid(a)) {
+ return -1;
+ } else {
+ return QUAD_NORMAL_TO_NORMAL_ORDER[a.normal.ordinal()] - QUAD_NORMAL_TO_NORMAL_ORDER[b.normal.ordinal()];
+ }
+ }
+
+ }
+
}