diff options
author | FalsePattern <me@falsepattern.com> | 2023-11-27 14:07:21 +0100 |
---|---|---|
committer | makamys <makamys@outlook.com> | 2023-12-01 13:13:38 +0100 |
commit | 6dc520d17d6bc920a4b87e7536678bc11e32b0cd (patch) | |
tree | 2b9c6906832a023d7086a290f494f8cfeb2b3e41 /src/main/java/makamys/neodymium/renderer | |
parent | b8e4d51f6966d7c74d1d5d8a504ed4200f29a2e2 (diff) | |
download | Neodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.tar.gz Neodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.tar.bz2 Neodymium-6dc520d17d6bc920a4b87e7536678bc11e32b0cd.zip |
Removed the SimplifyMeshes feature
Diffstat (limited to 'src/main/java/makamys/neodymium/renderer')
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"); } |