diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java index 7575be3fb..347e12b8b 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package com.seibel.lod.core.objects.opengl; import java.nio.ByteBuffer; @@ -36,18 +36,20 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import static com.seibel.lod.core.render.LodRenderer.EVENT_LOGGER; -public class LodQuadBuilder { +public class LodQuadBuilder +{ static final int MAX_BUFFER_SIZE = (1024 * 1024); static final int QUAD_BYTE_SIZE = (12 * 6); static final int MAX_QUADS_PER_BUFFER = MAX_BUFFER_SIZE / QUAD_BYTE_SIZE; //static final int MAX_MERGED_QUAD_SIZE = 64; - + static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class); - + public final boolean skipSkylight0Quads; public final short skyLightCullingBelow; - - static class Quad { + + static class Quad + { final short x; final short y; final short z; @@ -58,11 +60,14 @@ public class LodQuadBuilder { final byte blocklight; final LodDirection dir; double distance = 0d; - + Quad(short x, short y, short z, short w0, short w1, int color, byte skylight, byte blocklight, - LodDirection dir) { - if (w0 == 0 || w1 == 0) throw new IllegalArgumentException("Size 0 quad!"); - if (w0 < 0 || w1 < 0) throw new IllegalArgumentException("Negative sized quad!"); + LodDirection dir) + { + if (w0 == 0 || w1 == 0) + throw new IllegalArgumentException("Size 0 quad!"); + if (w0 < 0 || w1 < 0) + throw new IllegalArgumentException("Negative sized quad!"); this.x = x; this.y = y; this.z = z; @@ -74,22 +79,30 @@ public class LodQuadBuilder { this.dir = dir; } - private static double pow(double d) {return d*d;} - - // NOTE: This is only a rough but fast calculation! - void calculateDistance(double relativeX, double relativeY, double relativeZ) { - distance = pow(relativeX-x) + pow(relativeY-y) + pow(relativeZ-z); + private static double pow(double d) + { + return d * d; } - private static int _compondCompare(short a0, short a1, short a2, short b0, short b1, short b2) { - long a = (long)a0<<48 | (long)a1<<32 | (long)a2 << 16; - long b = (long)b0<<48 | (long)b1<<32 | (long)b2 << 16; + // NOTE: This is only a rough but fast calculation! + void calculateDistance(double relativeX, double relativeY, double relativeZ) + { + distance = pow(relativeX - x) + pow(relativeY - y) + pow(relativeZ - z); + } + + private static int _compondCompare(short a0, short a1, short a2, short b0, short b1, short b2) + { + long a = (long) a0 << 48 | (long) a1 << 32 | (long) a2 << 16; + long b = (long) b0 << 48 | (long) b1 << 32 | (long) b2 << 16; return Long.compare(a, b); } - public int compareTo1(Quad o) { - if (dir != o.dir) throw new IllegalArgumentException("The other quad is not in the same direction: " + o.dir + " vs "+dir); - switch (dir.getAxis()) { + public int compareTo1(Quad o) + { + if (dir != o.dir) + throw new IllegalArgumentException("The other quad is not in the same direction: " + o.dir + " vs " + dir); + switch (dir.getAxis()) + { case X: return _compondCompare(x, y, z, o.x, o.y, o.z); case Y: @@ -100,9 +113,13 @@ public class LodQuadBuilder { throw new IllegalArgumentException("Invalid Axis enum: " + dir.getAxis()); } } - public int compareTo2(Quad o) { - if (dir != o.dir) throw new IllegalArgumentException("The other quad is not in the same direction: " + o.dir + " vs "+dir); - switch (dir.getAxis()) { + + public int compareTo2(Quad o) + { + if (dir != o.dir) + throw new IllegalArgumentException("The other quad is not in the same direction: " + o.dir + " vs " + dir); + switch (dir.getAxis()) + { case X: return _compondCompare(x, z, y, o.x, o.z, o.y); case Y: @@ -182,7 +199,7 @@ public class LodQuadBuilder { throw new IllegalArgumentException("Invalid Axis enum: " + dir.getAxis()); } } - + public boolean tryMergeWith2(Quad o) { if (dir != o.dir) @@ -250,60 +267,77 @@ public class LodQuadBuilder { } } - - final ArrayList[] quads = (ArrayList[])new ArrayList[6]; - - public LodQuadBuilder(int initialSize, boolean enableSkylightCulling, int skyLightCullingBelow) { - for (int i=0; i<6; i++) quads[i] = new ArrayList(); + + final ArrayList[] quads = (ArrayList[]) new ArrayList[6]; + + public LodQuadBuilder(int initialSize, boolean enableSkylightCulling, int skyLightCullingBelow) + { + for (int i = 0; i < 6; i++) + quads[i] = new ArrayList(); this.skipSkylight0Quads = enableSkylightCulling; this.skyLightCullingBelow = (short) (skyLightCullingBelow - LodBuilder.MIN_WORLD_HEIGHT); } - + public void addQuadAdj(LodDirection dir, short x, short y, short z, short w0, short wy, int color, byte skylight, - byte blocklight) { + byte blocklight) + { if (dir.ordinal() <= LodDirection.DOWN.ordinal()) throw new IllegalArgumentException("addQuadAdj() is only for adj direction! Not UP or Down!"); - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[dir.ordinal()].add(new Quad(x, y, z, w0, wy, color, skylight, blocklight, dir)); } - + // XZ - public void addQuadUp(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + public void addQuadUp(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.UP.ordinal()].add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.UP)); } - - public void addQuadDown(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + + public void addQuadDown(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.DOWN.ordinal()].add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.DOWN)); } - + // XY - public void addQuadN(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + public void addQuadN(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.NORTH.ordinal()].add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.NORTH)); } - - public void addQuadS(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + + public void addQuadS(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.SOUTH.ordinal()].add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.SOUTH)); } - + // ZY - public void addQuadW(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + public void addQuadW(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.WEST.ordinal()].add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.WEST)); } - - public void addQuadE(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) { - if (skipSkylight0Quads && skylight==0 && y < skyLightCullingBelow) return; + + public void addQuadE(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) + { + if (skipSkylight0Quads && skylight == 0 && y < skyLightCullingBelow) + return; quads[LodDirection.EAST.ordinal()].add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.EAST)); } - - private static void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte skylight, byte blocklight) { + + private static void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte skylight, byte blocklight) + { skylight %= 16; blocklight %= 16; - + bb.putShort(x); bb.putShort(y); bb.putShort(z); @@ -318,15 +352,18 @@ public class LodQuadBuilder { bb.put(b); bb.put(a); } - - private static void putQuad(ByteBuffer bb, Quad quad) { + + private static void putQuad(ByteBuffer bb, Quad quad) + { int[][] quadBase = DIRECTION_VERTEX_QUAD[quad.dir.ordinal()]; short d0 = quad.w0; short d1 = quad.w1; Axis axis = quad.dir.getAxis(); - for (int i = 0; i < quadBase.length; i++) { + for (int i = 0; i < quadBase.length; i++) + { short dx, dy, dz; - switch (axis) { + switch (axis) + { case X: // ZY dx = 0; dz = quadBase[i][0] == 1 ? d0 : 0; @@ -350,251 +387,307 @@ public class LodQuadBuilder { } } - public void sort(double dPlayerPosX, double dPlayerPosY, double dPlayerPosZ) { + public void sort(double dPlayerPosX, double dPlayerPosY, double dPlayerPosZ) + { } - - private long mergeQuadsPass1(int dir) { - if (quads[dir].size()<=1) return 0; + + private long mergeQuadsPass1(int dir) + { + if (quads[dir].size() <= 1) + return 0; quads[dir].sort(Quad::compareTo1); ListIterator iter = quads[dir].listIterator(); long mergeCount = 0; Quad currentQuad = iter.next(); - while (iter.hasNext()) { + while (iter.hasNext()) + { Quad nextQuad = iter.next(); - if (currentQuad.tryMergeWith1(nextQuad)) { + if (currentQuad.tryMergeWith1(nextQuad)) + { mergeCount++; iter.set(null); - } else { + } + else + { currentQuad = nextQuad; } } - quads[dir].removeIf(o -> o==null); + quads[dir].removeIf(o -> o == null); return mergeCount; } - - private long mergeQuadsPass2(int dir) { - if (quads[dir].size()<=1) return 0; + + private long mergeQuadsPass2(int dir) + { + if (quads[dir].size() <= 1) + return 0; quads[dir].sort(Quad::compareTo2); ListIterator iter = quads[dir].listIterator(); long mergeCount = 0; Quad currentQuad = iter.next(); - while (iter.hasNext()) { + while (iter.hasNext()) + { Quad nextQuad = iter.next(); - if (currentQuad.tryMergeWith2(nextQuad)) { + if (currentQuad.tryMergeWith2(nextQuad)) + { mergeCount++; iter.set(null); - } else { + } + else + { currentQuad = nextQuad; } } - quads[dir].removeIf(o -> o==null); + quads[dir].removeIf(o -> o == null); return mergeCount; } - - public void mergeQuads() { + + public void mergeQuads() + { long mergeCount = 0; long preQuadsCount = getCurrentQuadsCount(); - if (preQuadsCount<=1) return; - for (int i=0; i<6; i++) { + if (preQuadsCount <= 1) + return; + for (int i = 0; i < 6; i++) + { mergeCount += mergeQuadsPass1(i); - if (i>=2) { + if (i >= 2) + { continue; //long pass2 = mergeQuadsPass2(i); //mergeCount += pass2; //skipperMerge += pass2; - } else { + } + else + { long pass2 = mergeQuadsPass2(i); mergeCount += pass2; } } long postQuadsCount = getCurrentQuadsCount(); //if (mergeCount != 0) - EVENT_LOGGER.debug("Merged {}/{}({}) quads", mergeCount, preQuadsCount, mergeCount/(double)preQuadsCount); + EVENT_LOGGER.debug("Merged {}/{}({}) quads", mergeCount, preQuadsCount, mergeCount / (double) preQuadsCount); } - public Iterator makeVertexBuffers() { - return new Iterator() { + public Iterator makeVertexBuffers() + { + return new Iterator() + { final ByteBuffer bb = ByteBuffer.allocateDirect(MAX_QUADS_PER_BUFFER * QUAD_BYTE_SIZE) .order(ByteOrder.nativeOrder()); int dir = skipEmpty(0); int quad = 0; - private int skipEmpty(int d) { - while(d<6 && quads[d].isEmpty()) d++; + private int skipEmpty(int d) + { + while (d < 6 && quads[d].isEmpty()) + d++; return d; } @Override - public boolean hasNext() { + public boolean hasNext() + { return dir < 6; } - + @Override - public ByteBuffer next() { - if (dir >= 6) { + public ByteBuffer next() + { + if (dir >= 6) + { return null; } bb.clear(); bb.limit(MAX_QUADS_PER_BUFFER * QUAD_BYTE_SIZE); - while (bb.hasRemaining() && dir < 6) { + while (bb.hasRemaining() && dir < 6) + { writeData(); } bb.limit(bb.position()); bb.rewind(); return bb; } - - private void writeData() { + + private void writeData() + { int startQ = quad; int i = startQ; - for (i = startQ; i= quads[dir].size()) { + if (i >= quads[dir].size()) + { quad = 0; dir++; dir = skipEmpty(dir); - } else { + } + else + { quad = i; } } }; } - public interface BufferFiller { + public interface BufferFiller + { boolean fill(LodVertexBuffer vbo); // If true: means more data is needed to be filled } - - public BufferFiller makeBufferFiller(GpuUploadMethod method) { - return new BufferFiller() { + + public BufferFiller makeBufferFiller(GpuUploadMethod method) + { + return new BufferFiller() + { int dir = 0; int quad = 0; - public boolean fill(LodVertexBuffer vbo) { - if (dir >= 6) { + + public boolean fill(LodVertexBuffer vbo) + { + if (dir >= 6) + { vbo.vertexCount = 0; return false; } int numOfQuads = _countRemainingQuads(); - if (numOfQuads > MAX_QUADS_PER_BUFFER) numOfQuads = MAX_QUADS_PER_BUFFER; - if (numOfQuads == 0) { + if (numOfQuads > MAX_QUADS_PER_BUFFER) + numOfQuads = MAX_QUADS_PER_BUFFER; + if (numOfQuads == 0) + { vbo.vertexCount = 0; return false; } - ByteBuffer bb = vbo.mapBuffer(numOfQuads*QUAD_BYTE_SIZE, method, MAX_QUADS_PER_BUFFER * QUAD_BYTE_SIZE); - if (bb == null) throw new NullPointerException("mapBuffer returned null"); + ByteBuffer bb = vbo.mapBuffer(numOfQuads * QUAD_BYTE_SIZE, method, MAX_QUADS_PER_BUFFER * QUAD_BYTE_SIZE); + if (bb == null) + throw new NullPointerException("mapBuffer returned null"); bb.clear(); bb.limit(numOfQuads * QUAD_BYTE_SIZE); - while (bb.hasRemaining() && dir < 6) { + while (bb.hasRemaining() && dir < 6) + { writeData(bb); } bb.rewind(); vbo.unmapBuffer(method); - vbo.vertexCount = numOfQuads*6; + vbo.vertexCount = numOfQuads * 6; return dir < 6; } - private int _countRemainingQuads() { + + private int _countRemainingQuads() + { int a = quads[dir].size() - quad; - for (int i=dir+1; i= quads[dir].size()) { + if (i >= quads[dir].size()) + { quad = 0; dir++; - while (dir<6 && quads[dir].isEmpty()) dir++; - } else { + while (dir < 6 && quads[dir].isEmpty()) + dir++; + } + else + { quad = i; } } }; } - public int getCurrentQuadsCount() { + public int getCurrentQuadsCount() + { int i = 0; - for (ArrayList qs : quads) i+=qs.size(); + for (ArrayList qs : quads) + i += qs.size(); return i; } - - public int getCurrentNeededVertexBuffers() { + + public int getCurrentNeededVertexBuffers() + { return LodUtil.ceilDiv(getCurrentQuadsCount(), MAX_QUADS_PER_BUFFER); } - + public static final int[][][] DIRECTION_VERTEX_QUAD = new int[][][] { // X,Z { // UP { 1, 0 }, // 0 { 1, 1 }, // 1 { 0, 1 }, // 2 - + { 1, 0 }, // 0 { 0, 1 }, // 2 { 0, 0 }, // 3 }, { // DOWN - { 0, 0 }, // 0 - { 0, 1 }, // 1 - { 1, 1 }, // 2 - - { 0, 0 }, // 0 - { 1, 1 }, // 2 - { 1, 0 }, // 3 - }, + { 0, 0 }, // 0 + { 0, 1 }, // 1 + { 1, 1 }, // 2 + + { 0, 0 }, // 0 + { 1, 1 }, // 2 + { 1, 0 }, // 3 + }, // X,Y { // NORTH { 0, 0 }, // 0 { 0, 1 }, // 1 { 1, 1 }, // 2 - + { 0, 0 }, // 0 { 1, 1 }, // 2 { 1, 0 }, // 3 }, { // SOUTH - { 1, 0 }, // 0 - { 1, 1 }, // 1 - { 0, 1 }, // 2 - - { 1, 0 }, // 0 - { 0, 1 }, // 2 - { 0, 0 }, // 3 - }, + { 1, 0 }, // 0 + { 1, 1 }, // 1 + { 0, 1 }, // 2 + + { 1, 0 }, // 0 + { 0, 1 }, // 2 + { 0, 0 }, // 3 + }, // Z,Y { // WEST { 0, 0 }, // 0 { 1, 0 }, // 1 { 1, 1 }, // 2 - + { 0, 0 }, // 0 { 1, 1 }, // 2 { 0, 1 }, // 3 }, { // EAST - { 0, 1 }, // 0 - { 1, 1 }, // 1 - { 1, 0 }, // 2 - - { 0, 1 }, // 0 - { 1, 0 }, // 2 - { 0, 0 }, // 3 - }, }; - + { 0, 1 }, // 0 + { 1, 1 }, // 1 + { 1, 0 }, // 2 + + { 0, 1 }, // 0 + { 1, 0 }, // 2 + { 0, 0 }, // 3 + }, }; + }