aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/makamys/neodymium/renderer
diff options
context:
space:
mode:
authorFalsePattern <me@falsepattern.com>2023-11-27 14:07:21 +0100
committermakamys <makamys@outlook.com>2023-12-01 13:13:38 +0100
commit6dc520d17d6bc920a4b87e7536678bc11e32b0cd (patch)
tree2b9c6906832a023d7086a290f494f8cfeb2b3e41 /src/main/java/makamys/neodymium/renderer
parentb8e4d51f6966d7c74d1d5d8a504ed4200f29a2e2 (diff)
downloadNeodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.tar.gz
Neodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.tar.bz2
Neodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.zip
Removed the SimplifyMeshes feature
Diffstat (limited to 'src/main/java/makamys/neodymium/renderer')
-rw-r--r--src/main/java/makamys/neodymium/renderer/ChunkMesh.java72
-rw-r--r--src/main/java/makamys/neodymium/renderer/MeshQuad.java323
-rw-r--r--src/main/java/makamys/neodymium/renderer/NeoRenderer.java9
3 files changed, 13 insertions, 391 deletions
diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
index 9dd0af0..280772b 100644
--- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
+++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java
@@ -151,35 +151,7 @@ public class ChunkMesh extends Mesh {
public void finishConstruction() {
List<MeshQuad> quads = quadBuf.getAsList();
-
- if(Config.simplifyChunkMeshes) {
- ArrayList<ArrayList<MeshQuad>> quadsByPlaneDir = new ArrayList<>(); // XY, XZ, YZ
- for(int i = 0; i < 3; i++) {
- quadsByPlaneDir.add(new ArrayList<MeshQuad>());
- }
- for(MeshQuad quad : quads) {
- if(quad.getPlane() != MeshQuad.Plane.NONE) {
- quadsByPlaneDir.get(quad.getPlane().ordinal() - 1).add(quad);
- }
- }
- for(int plane = 0; plane < 3; plane++) {
- quadsByPlaneDir.get(plane).sort(MeshQuad.QuadPlaneComparator.quadPlaneComparators[plane]);
- }
-
- for(int plane = 0; plane < 3; plane++) {
- List<MeshQuad> planeDirQuads = quadsByPlaneDir.get(plane);
- int planeStart = 0;
- for(int quadI = 0; quadI < planeDirQuads.size(); quadI++) {
- MeshQuad quad = planeDirQuads.get(quadI);
- MeshQuad nextQuad = quadI == planeDirQuads.size() - 1 ? null : planeDirQuads.get(quadI + 1);
- if(!quad.onSamePlaneAs(nextQuad)) {
- simplifyPlane(planeDirQuads.subList(planeStart, quadI + 1));
- planeStart = quadI + 1;
- }
- }
- }
- }
-
+
quadCount = countValidQuads(quads);
buffer = createBuffer(quads, quadCount);
usedRAM += buffer.limit();
@@ -187,48 +159,6 @@ public class ChunkMesh extends Mesh {
quadBuf.reset();
}
- private static void simplifyPlane(List<MeshQuad> planeQuads) {
- // Exclude quads from merging if they have identical vertex positions to another quad.
- // Workaround for z-fighting issue that arises when merging fancy grass and the overlay quad
- // is a different dimension than the base quad.
- for(int i = 0; i < planeQuads.size(); i++) {
- MeshQuad a = planeQuads.get(i);
- for(int j = i + 1; j < planeQuads.size(); j++) {
- MeshQuad b = planeQuads.get(j);
- if(!a.noMerge && a.isPosEqual(b)) {
- a.noMerge = true;
- b.noMerge = true;
- } else {
- // Due to sorting, identical quads will always be next to each other
- break;
- }
- }
- }
-
- MeshQuad lastQuad = null;
- // Pass 1: merge quads to create rows
- for(MeshQuad quad : planeQuads) {
- if(lastQuad != null) {
- lastQuad.tryToMerge(quad);
- }
- if(MeshQuad.isValid(quad)) {
- lastQuad = quad;
- }
- }
-
- for(int i = 0; i < planeQuads.size(); i++) {
- planeQuads.get(i).mergeReference = null;
- }
-
- // Pass 2: merge rows to create rectangles
- // TODO optimize?
- for(int i = 0; i < planeQuads.size(); i++) {
- for(int j = i + 1; j < planeQuads.size(); j++) {
- planeQuads.get(i).tryToMerge(planeQuads.get(j));
- }
- }
- }
-
private static int countValidQuads(List<MeshQuad> quads) {
int quadCount = 0;
for(MeshQuad quad : quads) {
diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java
index ff2b1fc..94b981c 100644
--- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java
+++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java
@@ -12,22 +12,6 @@ import makamys.neodymium.config.Config;
import makamys.neodymium.util.BufferWriter;
import makamys.neodymium.util.Util;
-/*
- * This is what a quad looks like.
- *
- * 0--1
- * | |
- * 3--2
- *
- * We can glue quads together, forming a megaquad.
- * In the fragment shader we need to know which quad of the megaquad we are operating on.
- * For this reason, we store the "megaquad X" and "megaquad Y" coordinates in the vertices.
- * Their values at vertex 0: (0, 0)
- * Their values at vertex 1: (megaquad width, 0)
- * Their values at vertex 2: (megaquad width, megaquad height)
- * Their values at vertex 3: (0, megaquad height)
- */
-
public class MeshQuad {
private final static int DEFAULT_BRIGHTNESS = Util.createBrightness(15, 15);
private final static int DEFAULT_COLOR = 0xFFFFFFFF;
@@ -35,38 +19,16 @@ public class MeshQuad {
public float[] xs = new float[4];
public float[] ys = new float[4];
public float[] zs = new float[4];
- public float minX = Float.POSITIVE_INFINITY;
- public float minY = Float.POSITIVE_INFINITY;
- public float minZ = Float.POSITIVE_INFINITY;
- public float maxX = Float.NEGATIVE_INFINITY;
- public float maxY = Float.NEGATIVE_INFINITY;
- public float maxZ = Float.NEGATIVE_INFINITY;
public float[] us = new float[4];
public float[] vs = new float[4];
- public int[] bs = new int[4];
public int[] cs = new int[4];
// TODO normals?
+ public int[] bs = new int[4];
+
public boolean deleted;
- public boolean noMerge;
-
+
public QuadNormal normal;
- public int offset;
- public ChunkMesh.Flags flags;
-
- // Is positive U direction parallel to edge 0-1?
- public boolean uDirectionIs01;
-
- public boolean isRectangle;
-
- // 0: quads glued together on edge 1-2 or 3-0 ("megaquad row length")
- // 1: quads glued together on edge 0-1 or 2-3 ("megaquad column length")
- private int[] quadCountByDirection = {1, 1};
- public static int[] totalMergeCountByPlane = new int[3];
-
- // When we merge with another quad, we forget what we used to be like.
- // Keep a reference to the quad we first merged with, and use it as a reminder.
- public MeshQuad mergeReference;
-
+
private static Vector3f vectorA = new Vector3f();
private static Vector3f vectorB = new Vector3f();
private static Vector3f vectorC = new Vector3f();
@@ -82,10 +44,13 @@ public class MeshQuad {
us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]);
vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]);
-
- bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS;
+
cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR;
-
+
+ // TODO normals?
+
+ bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS;
+
i += 8;
}
@@ -104,8 +69,8 @@ public class MeshQuad {
}
public void setState(int[] rawBuffer, int offset, ChunkMesh.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ) {
- resetState();
-
+ deleted = false;
+
read(rawBuffer, offset, offsetX, offsetY, offsetZ, drawMode, flags);
if(xs[0] == xs[1] && xs[1] == xs[2] && xs[2] == xs[3] && ys[0] == ys[1] && ys[1] == ys[2] && ys[2] == ys[3]) {
@@ -114,15 +79,6 @@ public class MeshQuad {
return;
}
- uDirectionIs01 = us[0] != us[1];
-
- updateMinMaxXYZ();
- updateIsRectangle();
- if(!isRectangle) {
- // merging non-rectangles (e.g. Carpenter's Blocks wedge) is buggy, don't do it
- noMerge = true;
- }
-
vectorA.set(xs[1] - xs[0], ys[1] - ys[0], zs[1] - zs[0]);
vectorB.set(xs[2] - xs[1], ys[2] - ys[1], zs[2] - zs[1]);
Vector3f.cross(vectorA, vectorB, vectorC);
@@ -130,36 +86,9 @@ public class MeshQuad {
normal = QuadNormal.fromVector(vectorC);
}
- private void resetState() {
- Arrays.fill(xs, 0);
- Arrays.fill(ys, 0);
- Arrays.fill(zs, 0);
- Arrays.fill(us, 0);
- Arrays.fill(vs, 0);
- Arrays.fill(bs, 0);
- Arrays.fill(cs, 0);
-
- minX = Float.POSITIVE_INFINITY;
- minY = Float.POSITIVE_INFINITY;
- minZ = Float.POSITIVE_INFINITY;
- maxX = Float.NEGATIVE_INFINITY;
- maxY = Float.NEGATIVE_INFINITY;
- maxZ = Float.NEGATIVE_INFINITY;
-
- deleted = noMerge = false;
- normal = null;
- offset = 0;
- flags = null;
- uDirectionIs01 = false;
- Arrays.fill(quadCountByDirection, 1);
- Arrays.fill(totalMergeCountByPlane, 0);
- mergeReference = null;
- }
-
public void writeToBuffer(BufferWriter out) throws IOException {
for(int vertexI = 0; vertexI < 4; vertexI++) {
int vi = vertexI;
- int provokingI = 3;
float x = xs[vi];
float y = ys[vi];
@@ -188,250 +117,22 @@ public class MeshQuad {
out.writeInt(c);
- if(Config.simplifyChunkMeshes) {
- if((quadCountByUVDirection(false) == 1 && quadCountByUVDirection(true) == 1)) {
- // let the fragment shader know this is not a megaquad
- out.writeByte((byte)255);
- out.writeByte((byte)255);
- out.writeByte((byte)255);
- out.writeByte((byte)255);
- } else {
- out.writeByte(us[vi] == us[provokingI] ? 0 : (byte)quadCountByUVDirection(false));
- out.writeByte(vs[vi] == vs[provokingI] ? 0 : (byte)quadCountByUVDirection(true));
- out.writeByte(us[vi] == us[provokingI] ? (byte)0 : 1);
- out.writeByte(vs[vi] == vs[provokingI] ? (byte)0 : 1);
- }
- }
-
assert out.position() % getStride() == 0;
//System.out.println("[" + vertexI + "] x: " + x + ", y: " + y + " z: " + z + ", u: " + u + ", v: " + v + ", b: " + b + ", c: " + c);
}
}
- public int quadCountByUVDirection(boolean v) {
- if(v) {
- return quadCountByDirection[uDirectionIs01 ? 0 : 1];
- } else {
- return quadCountByDirection[uDirectionIs01 ? 1 : 0];
- }
- }
-
public static int getStride() {
return
3 * 4 // XYZ (float)
+ 2 * (Config.shortUV ? 2 : 4) // UV (float)
+ 4 // B (int)
+ 4 // C (int)
- + (Config.simplifyChunkMeshes ? 4 : 0) // megaquad XY (byte)
;
}
- private boolean isTranslatedCopyOf(MeshQuad o, boolean checkValid) {
- if((!isValid(this) && checkValid) || !isValid(o) || normal != o.normal) return false;
-
- if(mergeReference != null) {
- return mergeReference.isTranslatedCopyOf(o, false);
- }
-
- for(int i = 1; i < 4; i++) {
- double relX = xs[i] - xs[0];
- double relY = ys[i] - ys[0];
- double relZ = zs[i] - zs[0];
-
- if(o.xs[i] != o.xs[0] + relX || o.ys[i] != o.ys[0] + relY || o.zs[i] != o.zs[0] + relZ) {
- return false;
- }
- }
-
- for(int i = 0; i < 4; i++) {
- if(us[i] != o.us[i] || vs[i] != o.vs[i] || bs[i] != o.bs[i] || cs[i] != o.cs[i]) {
- return false;
- }
- }
-
- return true;
- }
-
- public void tryToMerge(MeshQuad o) {
- if(noMerge || o.noMerge) return;
-
- if(isTranslatedCopyOf(o, true)) {
- int numVerticesTouching = 0;
- boolean[] verticesTouching = new boolean[4];
- for(int i = 0; i < 4; i++) {
- for(int j = 0; j < 4; j++) {
- if(xs[i] == o.xs[j] && ys[i] == o.ys[j] && zs[i] == o.zs[j]) {
- verticesTouching[i] = true;
- numVerticesTouching++;
- }
- }
- }
- if(numVerticesTouching == 2) {
- for(int i = 0; i < 4; i++) {
- if(verticesTouching[i]) {
- copyVertexFrom(o, i, i);
- }
- }
-
- if((verticesTouching[0] && verticesTouching[1]) || (verticesTouching[2] && verticesTouching[3])) {
- quadCountByDirection[0] += o.quadCountByDirection[0];
- }
- if((verticesTouching[1] && verticesTouching[2]) || (verticesTouching[3] && verticesTouching[0])) {
- quadCountByDirection[1] += o.quadCountByDirection[1];
- }
-
- totalMergeCountByPlane[getPlane().ordinal() - 1]++;
-
- mergeReference = o;
-
- o.deleted = true;
- }
- }
- }
-
- private void copyVertexFrom(MeshQuad o, int src, int dest) {
- xs[dest] = o.xs[src];
- ys[dest] = o.ys[src];
- zs[dest] = o.zs[src];
- us[dest] = o.us[src];
- vs[dest] = o.vs[src];
- bs[dest] = o.bs[src];
- cs[dest] = o.cs[src];
-
- updateMinMaxXYZ(); // TODO isn't doing this a waste? I should get rid of the min/maxXYZ variables entirely.
- }
-
- private void updateMinMaxXYZ() {
- for(int i = 0; i < 4; i++) {
- minX = Math.min(minX, xs[i]);
- minY = Math.min(minY, ys[i]);
- minZ = Math.min(minZ, zs[i]);
- maxX = Math.max(maxX, xs[i]);
- maxY = Math.max(maxY, ys[i]);
- maxZ = Math.max(maxZ, zs[i]);
- }
- }
-
- private void updateIsRectangle() {
- isRectangle =
- vertexExists(minX, minY, minZ) &&
- vertexExists(minX, minY, maxZ) &&
- vertexExists(minX, maxY, minZ) &&
- vertexExists(minX, maxY, maxZ) &&
- vertexExists(maxX, minY, minZ) &&
- vertexExists(maxX, minY, maxZ) &&
- vertexExists(maxX, maxY, minZ) &&
- vertexExists(maxX, maxY, maxZ);
- }
-
- private boolean vertexExists(float x, float y, float z) {
- for(int i = 0; i < 4; i++) {
- if(xs[i] == x && ys[i] == y && zs[i] == z) {
- return true;
- }
- }
- return false;
- }
-
- // maybe minXYZ and maxXYZ should be arrays instead
- public double getMin(int coord) {
- return coord == 0 ? minX : coord == 1 ? minY : coord == 2 ? minZ : -1;
- }
-
- public double getMax(int coord) {
- return coord == 0 ? maxX : coord == 1 ? maxY : coord == 2 ? maxZ : -1;
- }
-
- public boolean onSamePlaneAs(MeshQuad o) {
- return isValid(this) && isValid(o) && getPlane() == o.getPlane() &&
- ((getPlane() == Plane.XY && minZ == o.minZ) ||
- (getPlane() == Plane.XZ && minY == o.minY) ||
- (getPlane() == Plane.YZ && minX == o.minX));
- }
-
- public Plane getPlane() {
- return Plane.fromNormal(normal);
- }
-
public static boolean isValid(MeshQuad q) {
return q != null && !q.deleted;
}
-
- public boolean isClockwiseXZ() {
- return (xs[1] - xs[0]) * (zs[2] - zs[0]) - (xs[2] - xs[0]) * (zs[1] - zs[0]) < 0;
- }
-
- @Override
- public String toString() {
- return String.format(Locale.ENGLISH, "%s(%.1f, %.1f, %.1f -- %.1f, %.1f, %.1f)", deleted ? "XXX " : "", minX, minY, minZ, maxX, maxY, maxZ);
- //return String.format(Locale.ENGLISH, "%s[(%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f)]", deleted ? "XXX " : "", xs[0], ys[0], zs[0], xs[1], ys[1], zs[1], xs[2], ys[2], zs[2], xs[3], ys[3], zs[3]);
- }
-
- public static class QuadPlaneComparator implements Comparator<MeshQuad> {
-
- public static final QuadPlaneComparator[] quadPlaneComparators = new QuadPlaneComparator[]{
- new QuadPlaneComparator(2, 1, 0), // PLANE_XY -> ZYX
- new QuadPlaneComparator(1, 2, 0), // PLANE_XZ -> YZX
- new QuadPlaneComparator(0, 2, 1) // PLANE_YZ -> XZY
- };
-
- private int c0, c1, c2;
-
- public QuadPlaneComparator(int firstCoordToCompare, int secondCoordToCompare, int thirdCoordToCompare) {
- this.c0 = firstCoordToCompare;
- this.c1 = secondCoordToCompare;
- this.c2 = thirdCoordToCompare;
- }
-
- @Override
- public int compare(MeshQuad a, MeshQuad b) {
- if(a.getMin(c0) < b.getMin(c0)) {
- return -1;
- } else if(a.getMin(c0) > b.getMin(c0)) {
- return 1;
- } else {
- if(a.getMin(c1) < b.getMin(c1)) {
- return -1;
- } else if(a.getMin(c1) > b.getMin(c1)) {
- return 1;
- } else {
- if(a.getMin(c2) < b.getMin(c2)) {
- return -1;
- } else if(a.getMin(c2) > b.getMin(c2)) {
- return 1;
- } else {
- return (int)Math.signum(a.offset - b.offset);
- }
- }
- }
- }
- }
-
- public static enum Plane {
- NONE,
- XY,
- XZ,
- YZ;
-
- public static Plane fromNormal(QuadNormal normal) {
- switch(normal) {
- case POSITIVE_X:
- case NEGATIVE_X:
- return YZ;
- case POSITIVE_Y:
- case NEGATIVE_Y:
- return XZ;
- case POSITIVE_Z:
- case NEGATIVE_Z:
- return XY;
- default:
- return NONE;
- }
- }
- }
-
- public boolean isPosEqual(MeshQuad b) {
- return Arrays.equals(xs, b.xs) && Arrays.equals(ys, b.ys) && Arrays.equals(zs, b.zs);
- }
}
diff --git a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java
index b3564ff..1aa83b6 100644
--- a/src/main/java/makamys/neodymium/renderer/NeoRenderer.java
+++ b/src/main/java/makamys/neodymium/renderer/NeoRenderer.java
@@ -396,17 +396,11 @@ public class NeoRenderer {
int uvEnd = Config.shortUV ? 4 * 4 : 5 * 4;
glVertexAttribPointer(2, 2, GL_SHORT, false, stride, uvEnd);
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, false, stride, uvEnd + 1 * 4);
- if(Config.simplifyChunkMeshes) {
- glVertexAttribPointer(4, 4, GL_UNSIGNED_BYTE, false, stride, uvEnd + 2 * 4);
- }
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
- if(Config.simplifyChunkMeshes) {
- glEnableVertexAttribArray(4);
- }
for(int i = 0; i < 2; i++) {
piFirst[i] = BufferUtils.createIntBuffer(MAX_MESHES);
@@ -427,9 +421,6 @@ public class NeoRenderer {
if(hasFog == 1) {
defines.add("RENDER_FOG");
}
- if(Config.simplifyChunkMeshes) {
- defines.add("SIMPLIFY_MESHES");
- }
if(Config.shortUV) {
defines.add("SHORT_UV");
}