diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java index d6d86b11c..8aed301e1 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java @@ -211,19 +211,22 @@ public final class BufferQuad // get the width of this quad in the relevant axis short thisPerpendicularCompareWidth; short thisParallelCompareWidth; + short otherPerpendicularCompareWidth; short otherParallelCompareWidth; if (mergeDirection == BufferMergeDirectionEnum.EastWest) { thisPerpendicularCompareWidth = this.widthEastWest; - thisParallelCompareWidth = this.widthNorthSouthOrUpDown; + + otherPerpendicularCompareWidth = quad.widthEastWest; otherParallelCompareWidth = quad.widthNorthSouthOrUpDown; } else { thisPerpendicularCompareWidth = this.widthNorthSouthOrUpDown; - thisParallelCompareWidth = this.widthEastWest; + + otherPerpendicularCompareWidth = quad.widthNorthSouthOrUpDown; otherParallelCompareWidth = quad.widthEastWest; } @@ -241,14 +244,15 @@ public final class BufferQuad } else if (thisPerpendicularCompareStartPos + thisPerpendicularCompareWidth > otherPerpendicularCompareStartPos) { - // these quads are overlapping, they can't be merged - EVENT_LOGGER.warn("Overlapping quads detected!"); - quad.hasError = true; - this.hasError = true; + if (thisPerpendicularCompareStartPos < otherPerpendicularCompareStartPos + otherPerpendicularCompareWidth) { + // these quads are overlapping, they can't be merged + //EVENT_LOGGER.warn("Overlapping quads detected!"); + quad.hasError = true; + this.hasError = true; + } return false; } - - + // only merge quads that have the same width edges if (thisParallelCompareWidth != otherParallelCompareWidth) { diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/LodQuadBuilder.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/LodQuadBuilder.java index db094f5d0..368599c28 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/LodQuadBuilder.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/LodQuadBuilder.java @@ -25,16 +25,20 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; +import com.seibel.lod.core.api.internal.EventApi; +import com.seibel.lod.core.api.internal.InternalApiShared; import com.seibel.lod.core.builders.lodBuilding.LodBuilder; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.LodDirection.Axis; import com.seibel.lod.core.enums.config.GpuUploadMethod; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.logging.DhLoggerBuilder; import com.seibel.lod.core.render.LodRenderer; import com.seibel.lod.core.render.objects.GLVertexBuffer; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; +import net.minecraft.core.Direction; import static com.seibel.lod.core.render.LodRenderer.EVENT_LOGGER; @@ -163,7 +167,8 @@ public class LodQuadBuilder }, }; - + private int premergeCount = 0; + public LodQuadBuilder(boolean enableSkylightCulling, int skyLightCullingBelow) { for (int i = 0; i < 6; i++) @@ -184,7 +189,16 @@ public class LodQuadBuilder throw new IllegalArgumentException("addQuadAdj() is only for adj direction! Not UP or Down!"); if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) return; - quads[dir.ordinal()].add(new BufferQuad(x, y, z, widthEastWest, widthNorthSouthOrUpDown, color, skylight, blocklight, dir)); + BufferQuad quad = new BufferQuad(x, y, z, widthEastWest, widthNorthSouthOrUpDown, color, skylight, blocklight, dir); + ArrayList qs = quads[dir.ordinal()]; + if (!qs.isEmpty() && + (qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) { + premergeCount++; + return; + } + qs.add(quad); } // XZ @@ -192,48 +206,34 @@ public class LodQuadBuilder { if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) return; - quads[LodDirection.UP.ordinal()].add(new BufferQuad(x, y, z, width, wz, color, skylight, blocklight, LodDirection.UP)); + BufferQuad quad = new BufferQuad(x, y, z, width, wz, color, skylight, blocklight, LodDirection.UP); + ArrayList qs = quads[LodDirection.UP.ordinal()]; + if (!qs.isEmpty() && + (qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) { + premergeCount++; + return; + } + qs.add(quad); } public void addQuadDown(short x, short y, short z, short width, short wz, int color, byte skylight, byte blocklight) { if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) return; - quads[LodDirection.DOWN.ordinal()].add(new BufferQuad(x, y, z, width, wz, color, skylight, blocklight, LodDirection.DOWN)); - } - - // XY - public void addQuadN(short x, short y, short z, short width, short wy, int color, byte skylight, byte blocklight) - { - if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) + BufferQuad quad = new BufferQuad(x, y, z, width, wz, color, skylight, blocklight, LodDirection.DOWN); + ArrayList qs = quads[LodDirection.DOWN.ordinal()]; + if (!qs.isEmpty() && + (qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) { + premergeCount++; return; - quads[LodDirection.NORTH.ordinal()].add(new BufferQuad(x, y, z, width, wy, color, skylight, blocklight, LodDirection.NORTH)); + } + qs.add(quad); } - public void addQuadS(short x, short y, short z, short width, short wy, int color, byte skylight, byte blocklight) - { - if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) - return; - quads[LodDirection.SOUTH.ordinal()].add(new BufferQuad(x, y, z, width, wy, color, skylight, blocklight, LodDirection.SOUTH)); - } - - // ZY - public void addQuadW(short x, short y, short z, short width, short wy, int color, byte skylight, byte blocklight) - { - if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) - return; - quads[LodDirection.WEST.ordinal()].add(new BufferQuad(x, y, z, width, wy, color, skylight, blocklight, LodDirection.WEST)); - } - - public void addQuadE(short x, short y, short z, short width, short wy, int color, byte skylight, byte blocklight) - { - if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) - return; - quads[LodDirection.EAST.ordinal()].add(new BufferQuad(x, y, z, width, wy, color, skylight, blocklight, LodDirection.EAST)); - } - - - private static void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte skylight, byte blocklight, int mx, int my, int mz) { skylight %= 16; @@ -321,22 +321,22 @@ public class LodQuadBuilder long preQuadsCount = getCurrentQuadsCount(); if (preQuadsCount <= 1) return; - + for (int directionIndex = 0; directionIndex < 6; directionIndex++) { mergeCount += mergeQuadsInternal(directionIndex, BufferMergeDirectionEnum.EastWest); - - // only merge after the top has been merged - if (directionIndex == 1) - { - long pass2 = mergeQuadsInternal(directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown); - mergeCount += pass2; - } + // only run the second merge if the face is the top or bottom + //if (directionIndex == LodDirection.UP.ordinal() || directionIndex == LodDirection.DOWN.ordinal()) + //{ + // long pass2 = mergeQuadsInternal(directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown); + // mergeCount += pass2; + //} } long postQuadsCount = getCurrentQuadsCount(); //if (mergeCount != 0) EVENT_LOGGER.debug("Merged {}/{}({}) quads", mergeCount, preQuadsCount, mergeCount / (double) preQuadsCount); } + /** Merges all of this builder's quads for the given directionIndex (up, down, left, etc.) in the given direction */ private long mergeQuadsInternal(int directionIndex, BufferMergeDirectionEnum mergeDirection) { diff --git a/src/main/java/com/seibel/lod/core/objects/PosToRenderContainer.java b/src/main/java/com/seibel/lod/core/objects/PosToRenderContainer.java index 21c8b4ce0..16a453281 100644 --- a/src/main/java/com/seibel/lod/core/objects/PosToRenderContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/PosToRenderContainer.java @@ -20,6 +20,7 @@ package com.seibel.lod.core.objects; import java.lang.invoke.MethodHandles; +import java.util.ArrayList; import java.util.Arrays; import com.seibel.lod.core.api.internal.InternalApiShared; @@ -44,6 +45,14 @@ public class PosToRenderContainer private int numberOfPosToRender; private int[] posToRender; private byte[][] population; + + static class LodPos { + byte detail; + int posX; + int posZ; + } + + private LodPos[] lodPosList; public PosToRenderContainer(byte minDetail, int regionPosX, int regionPosZ) { @@ -54,6 +63,7 @@ public class PosToRenderContainer int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); posToRender = new int[size * size * 3]; population = new byte[size][size]; + lodPosList = new LodPos[size * size]; } public void addPosToRender(byte detailLevel, int posX, int posZ) @@ -72,9 +82,13 @@ public class PosToRenderContainer //if(numberOfPosToRender >= posToRender.length) // posToRender = Arrays.copyOf(posToRender, posToRender.length*2); - posToRender[numberOfPosToRender * 3] = detailLevel; - posToRender[numberOfPosToRender * 3 + 1] = posX; - posToRender[numberOfPosToRender * 3 + 2] = posZ; + lodPosList[numberOfPosToRender] = new LodPos(); + lodPosList[numberOfPosToRender].detail = detailLevel; + lodPosList[numberOfPosToRender].posX = posX; + lodPosList[numberOfPosToRender].posZ = posZ; + //posToRender[numberOfPosToRender * 3] = detailLevel; + //posToRender[numberOfPosToRender * 3 + 1] = posX; + //posToRender[numberOfPosToRender * 3 + 2] = posZ; numberOfPosToRender++; population[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel, posX, minDetail))] [LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel, posZ, minDetail))] = (byte) (detailLevel + 1); @@ -94,6 +108,7 @@ public class PosToRenderContainer this.numberOfPosToRender = 0; this.regionPosX = regionPosX; this.regionPosZ = regionPosZ; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); if (this.minDetail == minDetail) { Arrays.fill(posToRender, 0); @@ -103,10 +118,10 @@ public class PosToRenderContainer else { this.minDetail = minDetail; - int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); posToRender = new int[size * size * 3]; population = new byte[size][size]; } + lodPosList = new LodPos[size * size]; } public int getNumberOfPos() @@ -116,19 +131,32 @@ public class PosToRenderContainer public byte getNthDetailLevel(int n) { - return (byte) posToRender[n * 3]; + return lodPosList[n].detail; + //return (byte) posToRender[n * 3]; } public int getNthPosX(int n) { - return posToRender[n * 3 + 1]; + return lodPosList[n].posX; + //return posToRender[n * 3 + 1]; } public int getNthPosZ(int n) { - return posToRender[n * 3 + 2]; + return lodPosList[n].posZ; + //eturn posToRender[n * 3 + 2]; } - + + public void sort() { + Arrays.sort(lodPosList, 0, numberOfPosToRender, + (a,b) -> { + if (a.detail != b.detail) return a.detail - b.detail; + if (a.posX != b.posX) return a.posX - b.posX; + return a.posZ - b.posZ; + } + ); + } + @Override public String toString() { diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java index c01b35f4d..d91c883e6 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java @@ -19,6 +19,7 @@ package com.seibel.lod.core.objects.lod; +import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.concurrent.atomic.AtomicInteger; @@ -29,6 +30,7 @@ import com.seibel.lod.core.enums.config.GenerationPriority; import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.objects.LodDataView; +import com.seibel.lod.core.objects.Pos2D; import com.seibel.lod.core.objects.PosToGenerateContainer; import com.seibel.lod.core.objects.PosToRenderContainer; import com.seibel.lod.core.util.DataPointUtil; diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java index 4eb63ef61..b982f8bed 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java @@ -274,6 +274,7 @@ public class RenderRegion implements AutoCloseable // position PosToRenderContainer posToRender = new PosToRenderContainer(minDetail, region.regionPosX, region.regionPosZ); region.getPosToRender(posToRender, playerX, playerZ); + posToRender.sort(); PosArrayGridList chunkGrid = ClientApi.renderer.vanillaChunks; for (int index = 0; index < posToRender.getNumberOfPos(); index++) {