From f76fa17e25a29253a48a1af59c29ebef57a8dee9 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 17:23:22 +0200 Subject: [PATCH 1/8] Removed level pos and data arrays --- .../lod/builders/GenerationRequest.java | 28 -- .../seibel/lod/builders/LodBufferBuilder.java | 265 +++-------- .../com/seibel/lod/builders/LodBuilder.java | 56 +-- .../lodTemplates/AbstractLodTemplate.java | 5 +- .../lodTemplates/CubicLodTemplate.java | 232 +++++----- .../lodTemplates/DynamicLodTemplate.java | 5 +- .../lodTemplates/TriangularLodTemplate.java | 5 +- .../worldGeneration/LodWorldGenerator.java | 148 ++----- .../com/seibel/lod/objects/DataPoint.java | 85 +++- .../seibel/lod/objects/LevelContainer.java | 58 +-- .../objects/LevelPos/ImmutableLevelPos.java | 7 - .../seibel/lod/objects/LevelPos/LevelPos.java | 415 ------------------ .../lod/objects/LevelPos/MutableLevelPos.java | 14 - .../com/seibel/lod/objects/LevelPosUtil.java | 82 ++-- .../com/seibel/lod/objects/LodDimension.java | 196 ++++----- .../com/seibel/lod/objects/LodRegion.java | 329 ++++---------- .../lod/objects/PosToGenerateContainer.java | 44 +- .../lod/objects/PosToRenderContainer.java | 77 +++- .../com/seibel/lod/render/LodRenderer.java | 16 +- .../java/com/seibel/lod/util/LodUtil.java | 14 +- 20 files changed, 660 insertions(+), 1421 deletions(-) delete mode 100644 src/main/java/com/seibel/lod/builders/GenerationRequest.java delete mode 100644 src/main/java/com/seibel/lod/objects/LevelPos/ImmutableLevelPos.java delete mode 100644 src/main/java/com/seibel/lod/objects/LevelPos/LevelPos.java delete mode 100644 src/main/java/com/seibel/lod/objects/LevelPos/MutableLevelPos.java diff --git a/src/main/java/com/seibel/lod/builders/GenerationRequest.java b/src/main/java/com/seibel/lod/builders/GenerationRequest.java deleted file mode 100644 index a04edd53a..000000000 --- a/src/main/java/com/seibel/lod/builders/GenerationRequest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.seibel.lod.builders; - -import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.LevelPos.LevelPos; -import com.seibel.lod.util.LodUtil; -import net.minecraft.util.math.ChunkPos; - -/** - * @author Leonardo Amato - * @version 22-08-2021 - */ -public class GenerationRequest -{ - public final LevelPos levelPos; - public final DistanceGenerationMode generationMode; - - public GenerationRequest(LevelPos levelPos, DistanceGenerationMode generationMode) - { - this.levelPos = levelPos; - this.generationMode = generationMode; - } - - public ChunkPos getChunkPos() - { - LevelPos chunkLevelPos = levelPos.getConvertedLevelPos(LodUtil.CHUNK_DETAIL_LEVEL); - return new ChunkPos(chunkLevelPos.posX, chunkLevelPos.posZ); - } -} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 106f8b480..676a3d275 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -20,20 +20,15 @@ package com.seibel.lod.builders; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; -import org.apache.commons.lang3.mutable.MutableBoolean; +import com.seibel.lod.objects.*; import org.lwjgl.opengl.GL11; import com.seibel.lod.config.LodConfig; -import com.seibel.lod.objects.LodDimension; -import com.seibel.lod.objects.RegionPos; -import com.seibel.lod.objects.LevelPos.LevelPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.render.LodRenderer; import com.seibel.lod.util.LodThreadFactory; @@ -49,7 +44,7 @@ import net.minecraft.util.math.ChunkPos; * This object is used to create NearFarBuffer objects. * * @author James Seibel - * @version 9-6-2021 + * @version 8-24-2021 */ public class LodBufferBuilder { @@ -105,15 +100,18 @@ public class LodBufferBuilder */ private ReentrantLock bufferLock = new ReentrantLock(); + private static final int NUMBER_OF_DIRECTION = 4; + //in order -x, +x, -z, +z + private static final int[][] ADJ_DIRECTION = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + private volatile Object[][] setsToRender; private volatile RegionPos center; - + /** This is the ChunkPos the player was at the last time the buffers were built. * IE the center of the buffers last time they were built */ private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0,0); private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0,0); - - + public LodBufferBuilder() { @@ -148,6 +146,8 @@ public class LodBufferBuilder ChunkPos playerChunkPos = new ChunkPos(playerBlockPos); BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition(); + // this will be the center of the VBOs once they have been built + buildableCenterChunkPos = playerChunkPos; Thread thread = new Thread(() -> { @@ -165,8 +165,11 @@ public class LodBufferBuilder ArrayList> nodeToRenderThreads = new ArrayList<>(lodDim.regions.length * lodDim.regions.length); startBuffers(fullRegen, lodDim); - - + + // =====================// + // RENDERING PART // + // =====================// + RegionPos playerRegionPos = new RegionPos(playerChunkPos); if (center == null) center = playerRegionPos; @@ -176,16 +179,8 @@ public class LodBufferBuilder if (setsToRender.length != lodDim.regions.length) setsToRender = new Object[lodDim.regions.length][lodDim.regions.length]; - - // this will be the center of the VBOs once they have been built - buildableCenterChunkPos = playerChunkPos; - - RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ()); - if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0) - { - move(worldRegionOffset, Math.floorDiv(lodDim.getWidth(), 2)); - } + for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++) { @@ -199,117 +194,98 @@ public class LodBufferBuilder // local position in the vbo and bufferBuilder arrays BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion]; - + LodRegion region = lodDim.getRegion(regionPos.x, regionPos.z); + if (region == null) continue; + byte minDetail = region.getMinDetailLevel(); // make sure the buffers weren't // changed while we were running this method if (currentBuffer == null || (currentBuffer != null && !currentBuffer.building())) return; - //previous setToRender chache - if (setsToRender[xRegion][zRegion] == null) - { - setsToRender[xRegion][zRegion] = new ConcurrentHashMap(); - } - ConcurrentMap nodeToRender = (ConcurrentMap) setsToRender[xRegion][zRegion]; + final int xR = xRegion; + final int zR = zRegion; Callable dataToRenderThread = () -> { + + //previous setToRender chache + if (setsToRender[xR][zR] == null) + { + setsToRender[xR][zR] = new PosToRenderContainer(minDetail, regionPos.x, regionPos.z); + } + PosToRenderContainer posToRender = (PosToRenderContainer) setsToRender[xR][zR]; + posToRender.clear(minDetail, regionPos.x, regionPos.z); + lodDim.getDataToRender( - nodeToRender, + posToRender, regionPos, playerBlockPosRounded.getX(), playerBlockPosRounded.getZ()); + byte detailLevel; int posX; int posZ; - byte detailLevel; + int xAdj; + int zAdj; int chunkXdist; int chunkZdist; - short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length/2 - 1); - for (LevelPos posToRender : nodeToRender.keySet()) + short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1); + long lodData; + long[] adjData; + for (int index = 0; index < posToRender.getNumberOfPos(); index++) { - if (!nodeToRender.get(posToRender).booleanValue()) + detailLevel = posToRender.getNthDetailLevel(index); + posX = posToRender.getNthPosX(index); + posZ = posToRender.getNthPosZ(index); + // skip any chunks that Minecraft is going to render + chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.x; + chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.z; + if (gameChunkRenderDistance >= Math.abs(chunkXdist) + && gameChunkRenderDistance >= Math.abs(chunkZdist) + && detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL + && renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]) { - nodeToRender.remove(posToRender); continue; } - nodeToRender.get(posToRender).setFalse(); // skip any chunks that Minecraft is going to render - chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x; - chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z; - if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist) && posToRender.detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL) - { - if (renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]) - { - continue; - } - } - posX = posToRender.posX; - posZ = posToRender.posZ; - detailLevel = posToRender.detailLevel; - // skip any chunks that Minecraft is going to render - - try { boolean disableFix = false; - if (lodDim.doesDataExist(posToRender.clone())) + if (lodDim.doesDataExist(detailLevel, posX, posZ)) { - short[] lodData = lodDim.getData(posToRender); - short[][][] adjData = new short[2][2][]; - /**TODO The following two for are too complex*/ - for (int x : new int[]{0, 1}) + lodData = lodDim.getData(detailLevel, posX, posZ); + adjData = new long[NUMBER_OF_DIRECTION]; + for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) { - posToRender.changeParameters(detailLevel, posX + x * 2 - 1, posZ); - chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x; - chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z; - if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) + xAdj = posX + ADJ_DIRECTION[direction][0]; + zAdj = posZ + ADJ_DIRECTION[direction][1]; + chunkXdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.x; + chunkZdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.z; + + if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) { if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] - && (nodeToRender.containsKey(posToRender) || disableFix)) + && (posToRender.contains(detailLevel, xAdj, zAdj) || disableFix)) { - adjData[0][x] = lodDim.getData(posToRender); + adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj); } - }else{ - if (nodeToRender.containsKey(posToRender) || disableFix) - { - adjData[0][x] = lodDim.getData(posToRender); - - } - } - } - - for (int z : new int[]{0, 1}) - { - posToRender.changeParameters(detailLevel, posX, posZ + z * 2 - 1); - chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x; - chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z; - if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) + } else { - if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance+ 1] - && (nodeToRender.containsKey(posToRender) || disableFix)) + if (posToRender.contains(detailLevel, xAdj, zAdj) || disableFix) { - adjData[1][z] = lodDim.getData(posToRender); - } - }else{ - if (nodeToRender.containsKey(posToRender) || disableFix) - { - adjData[1][z] = lodDim.getData(posToRender); - + adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj); } } } - posToRender.changeParameters(detailLevel, posX, posZ); - - LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, lodData, adjData, - posToRender, renderer.previousDebugMode); + LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData, + detailLevel, posX, posZ, renderer.previousDebugMode); } } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); return false; } }// for pos to in list to render - // the thread executed successfully return true; }; @@ -344,7 +320,7 @@ public class LodBufferBuilder // ClientProxy.LOGGER.info("Buffer Build time: " + buildTime + " ms" + '\n' + // "Tree cutting time: " + treeTime + " ms" + '\n' + // "Rendering time: " + renderingTime + " ms"); - + // mark that the buildable buffers as ready to swap switchVbos = true; } catch (Exception e) @@ -367,110 +343,12 @@ public class LodBufferBuilder } }); - + mainGenThread.execute(thread); return; } - - /** - * Move the center of this LodDimension and move all owned - * regions over by the given x and z offset.

- *

- * Synchronized to prevent multiple moves happening on top of each other. - */ - public void move(RegionPos regionOffset, int width) - { - int xOffset = regionOffset.x; - int zOffset = regionOffset.z; - - // if the x or z offset is equal to or greater than - // the total size, just delete the current data - // and update the centerX and/or centerZ - if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width) - { - for (int x = 0; x < width; x++) - { - for (int z = 0; z < width; z++) - { - setsToRender[x][z] = null; - } - } - - // update the new center - center.x += xOffset; - center.z += zOffset; - - return; - } - - - // X - if (xOffset > 0) - { - // move everything over to the left (as the center moves to the right) - for (int x = 0; x < width; x++) - { - for (int z = 0; z < width; z++) - { - if (x + xOffset < width) - setsToRender[x][z] = setsToRender[x + xOffset][z]; - else - setsToRender[x][z] = null; - } - } - } else - { - // move everything over to the right (as the center moves to the left) - for (int x = width - 1; x >= 0; x--) - { - for (int z = 0; z < width; z++) - { - if (x + xOffset >= 0) - setsToRender[x][z] = setsToRender[x + xOffset][z]; - else - setsToRender[x][z] = null; - } - } - } - - - // Z - if (zOffset > 0) - { - // move everything up (as the center moves down) - for (int x = 0; x < width; x++) - { - for (int z = 0; z < width; z++) - { - if (z + zOffset < width) - setsToRender[x][z] = setsToRender[x][z + zOffset]; - else - setsToRender[x][z] = null; - } - } - } else - { - // move everything down (as the center moves up) - for (int x = 0; x < width; x++) - { - for (int z = width - 1; z >= 0; z--) - { - if (z + zOffset >= 0) - setsToRender[x][z] = setsToRender[x][z + zOffset]; - else - setsToRender[x][z] = null; - } - } - } - - - // update the new center - center.x += xOffset; - center.z += zOffset; - } - //===============================// // BufferBuilder related methods // //===============================// @@ -573,7 +451,6 @@ public class LodBufferBuilder } } - /** * Get the newly created VBOs */ @@ -586,9 +463,9 @@ public class LodBufferBuilder VertexBuffer[][] tmp = drawableVbos; drawableVbos = buildableVbos; buildableVbos = tmp; - + drawableCenterChunkPos = buildableCenterChunkPos; - + // the vbos have been swapped switchVbos = false; bufferLock.unlock(); @@ -603,7 +480,7 @@ public class LodBufferBuilder { public VertexBuffer[][] vbos; public ChunkPos drawableCenterChunkPos; - + public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos) { vbos = newVbos; diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 2d5e0ee2d..15f703113 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -20,19 +20,18 @@ package com.seibel.lod.builders; import java.awt.Color; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.enums.LodDetail; -import com.seibel.lod.objects.DataPoint; -import com.seibel.lod.objects.LodDimension; -import com.seibel.lod.objects.LodWorld; -import com.seibel.lod.objects.LevelPos.LevelPos; +import com.seibel.lod.objects.*; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; -import com.seibel.lod.wrapper.MinecraftWrapper; +import com.seibel.lod.wrapper.MinecraftWrapper; +import com.sun.org.apache.xpath.internal.operations.Bool; import net.minecraft.block.AbstractPlantBlock; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -41,6 +40,7 @@ import net.minecraft.block.GrassBlock; import net.minecraft.block.IGrowable; import net.minecraft.block.LeavesBlock; import net.minecraft.block.material.MaterialColor; +import net.minecraft.client.Minecraft; import net.minecraft.world.DimensionType; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; @@ -131,7 +131,6 @@ public class LodBuilder generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode)); } catch (IllegalArgumentException | NullPointerException e) { - System.out.println("Chunk pos " + chunk.getPos()); e.printStackTrace(); // if the world changes while LODs are being generated // they will throw errors as they try to access things that no longer @@ -161,7 +160,6 @@ public class LodBuilder public void generateLodNodeFromChunk(LodDimension lodDim, IChunk chunk, LodBuilderConfig config) throws IllegalArgumentException { - if (chunk == null) throw new IllegalArgumentException("generateLodFromChunk given a null chunk"); @@ -169,17 +167,22 @@ public class LodBuilder int startZ; int endX; int endZ; - short[] color; + int color; short height; short depth; - short[] data; - LevelPos levelPos = new LevelPos((byte) 0, 0, 0); - levelPos.changeParameters(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); - levelPos.convert(LodUtil.REGION_DETAIL_LEVEL); + long data; try { - byte minDetailLevel = lodDim.getRegion(levelPos).getMinDetailLevel(); - LodDetail detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel); + LodDetail detail; + LodRegion region = lodDim.getRegion(chunk.getPos().getRegionX(), chunk.getPos().getRegionZ()); + if (region == null) + return; + byte minDetailLevel = region.getMinDetailLevel(); + detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel); + + byte detailLevel = detail.detailLevel; + int posX; + int posZ; for (int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++) { startX = detail.startX[i]; @@ -199,23 +202,23 @@ public class LodBuilder startZ, endX, endZ); depth = 0; } - levelPos.changeParameters((byte) 0, - chunk.getPos().x * 16 + startX, - chunk.getPos().z * 16 + startZ); - levelPos.convert(detail.detailLevel); + posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); + posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - data = DataPoint.createDataPoint(height, depth, color[0], color[1], color[2]); - lodDim.addData(levelPos, + data = DataPoint.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color)); + lodDim.addData(detailLevel, + posX, + posZ, data, false, isServer); } - levelPos.changeParameters(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); - lodDim.updateData(levelPos); + lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); } catch (Exception e) { - //e.printStackTrace(); + e.printStackTrace(); } + } @@ -352,8 +355,8 @@ public class LodBuilder * otherwise only use the block's * material color */ - private short[] generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, - int endZ) + private int generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, + int endZ) { ChunkSection[] chunkSections = chunk.getSections(); @@ -427,8 +430,7 @@ public class LodBuilder red /= numbOfBlocks; green /= numbOfBlocks; blue /= numbOfBlocks; - - return new short[]{(short) red, (short) green, (short) blue}; + return ColorUtil.rgbToInt(red,green,blue); } /** diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index 899290f75..7d9ca9d42 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -18,7 +18,6 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.objects.LevelPos.LevelPos; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.math.BlockPos; @@ -32,8 +31,8 @@ import net.minecraft.util.math.BlockPos; */ public abstract class AbstractLodTemplate { - public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData, - LevelPos levelPos, DebugMode debugging); + public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, + byte detailLevel, int posX, int posZ,DebugMode debugging); /** * add the given position and color to the buffer diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 07b7e764f..147ea9982 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -21,7 +21,7 @@ import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.enums.ShadingMode; import com.seibel.lod.objects.DataPoint; -import com.seibel.lod.objects.LevelPos.LevelPos; +import com.seibel.lod.objects.LevelPosUtil; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.LodUtil; @@ -35,71 +35,63 @@ import net.minecraft.util.math.BlockPos; * Builds LODs as rectangular prisms. * * @author James Seibel - * @version 9-6-2021 + * @version 8-10-2021 */ public class CubicLodTemplate extends AbstractLodTemplate { private final int CULL_OFFSET = 16; - + public CubicLodTemplate() { - + } - + @Override - public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, short[] data, short[][][] adjData, - LevelPos levelPos, DebugMode debugging) + public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, long data, long[] adjData, + byte detailLevel, int posX, int posZ,DebugMode debugging) { AxisAlignedBB bbox; - - int width = 1 << levelPos.detailLevel; - + int width = 1 << detailLevel; + // add each LOD for the detail level bbox = generateBoundingBox( DataPoint.getHeight(data), DataPoint.getDepth(data), width, - levelPos.posX * width, + posX * width, 0, - levelPos.posZ * width, - bufferCenterBlockPos); - + posZ * width); + int color = DataPoint.getColor(data); if (debugging != DebugMode.OFF) { - color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[levelPos.detailLevel].getRGB(); + color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); } - + if (bbox != null) { - addBoundingBoxToBuffer(buffer, bbox, color, bufferCenterBlockPos, adjData); + addBoundingBoxToBuffer(buffer, bbox, color, playerBlockPos, adjData); } - + } - - private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos) + + private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset) { // don't add an LOD if it is empty if (height == -1 && depth == -1) return null; - + if (depth == height) { // if the top and bottom points are at the same height // render this LOD as 1 block thick height++; } - - // offset the AABB by it's x/z position in the world since - // it uses doubles to specify its location, unlike the model view matrix - // which only uses floats - double x = -bufferCenterBlockPos.getX(); - double z = -bufferCenterBlockPos.getZ(); - - return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset).move(x, 0, z); + + return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset); } - - private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, short[][][] adjData) + + private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, long[] adjData) { int topColor = c; int bottomColor = c; @@ -107,7 +99,7 @@ public class CubicLodTemplate extends AbstractLodTemplate int southColor = c; int westColor = c; int eastColor = c; - + // darken the bottom and side colors if requested if (LodConfig.CLIENT.graphics.shadingMode.get() == ShadingMode.DARKEN_SIDES) { @@ -123,11 +115,11 @@ public class CubicLodTemplate extends AbstractLodTemplate westColor = ColorUtil.applyShade(c, mc.level.getShade(Direction.WEST, true)); eastColor = ColorUtil.applyShade(c, mc.level.getShade(Direction.EAST, true)); } - + // apply the user specified saturation and brightness float saturationMultiplier = LodConfig.CLIENT.graphics.saturationMultiplier.get().floatValue(); float brightnessMultiplier = LodConfig.CLIENT.graphics.brightnessMultiplier.get().floatValue(); - + if (saturationMultiplier != 1 || brightnessMultiplier != 1) { topColor = ColorUtil.applySaturationAndBrightnessMultipliers(topColor, saturationMultiplier, brightnessMultiplier); @@ -139,8 +131,8 @@ public class CubicLodTemplate extends AbstractLodTemplate } int minY; int maxY; - short[] data; - + long data; + int red; int green; int blue; @@ -171,83 +163,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); } - - if (playerBlockPos.getZ() > bb.minZ - CULL_OFFSET || disableCulling) - { - red = ColorUtil.getRed(northColor); - green = ColorUtil.getGreen(northColor); - blue = ColorUtil.getBlue(northColor); - alpha = ColorUtil.getAlpha(northColor); - // south (facing -Z) - data = adjData[1][1]; - if (data == null) - { - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); - } - else - { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) - { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha); - } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) - { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); - } - } - } - - if (playerBlockPos.getZ() < bb.maxZ + CULL_OFFSET || disableCulling) - { - red = ColorUtil.getRed(southColor); - green = ColorUtil.getGreen(southColor); - blue = ColorUtil.getBlue(southColor); - alpha = ColorUtil.getAlpha(southColor); - data = adjData[1][0]; - // north (facing +Z) - if (data == null) - { - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); - } - else - { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) - { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha); - } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) - { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); - } - } - } - + if (playerBlockPos.getX() < bb.maxX + CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(westColor); @@ -255,8 +171,8 @@ public class CubicLodTemplate extends AbstractLodTemplate blue = ColorUtil.getBlue(westColor); alpha = ColorUtil.getAlpha(westColor); // west (facing -X) - data = adjData[0][0]; - if (data == null) + data = adjData[0]; + if (data == 0) { addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); @@ -285,7 +201,7 @@ public class CubicLodTemplate extends AbstractLodTemplate } } } - + if (playerBlockPos.getX() > bb.minX - CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(eastColor); @@ -293,8 +209,8 @@ public class CubicLodTemplate extends AbstractLodTemplate blue = ColorUtil.getBlue(eastColor); alpha = ColorUtil.getAlpha(eastColor); // east (facing +X) - data = adjData[0][1]; - if (data == null) + data = adjData[1]; + if (data == 0) { addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); @@ -323,13 +239,89 @@ public class CubicLodTemplate extends AbstractLodTemplate } } } + + if (playerBlockPos.getZ() > bb.minZ - CULL_OFFSET || disableCulling) + { + red = ColorUtil.getRed(northColor); + green = ColorUtil.getGreen(northColor); + blue = ColorUtil.getBlue(northColor); + alpha = ColorUtil.getAlpha(northColor); + data = adjData[3]; + // north (facing +Z) + if (data == 0) + { + addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); + } + else + { + maxY = DataPoint.getHeight(data); + if (maxY < bb.maxY) + { + minY = (int) Math.max(maxY, bb.minY); + addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha); + } + minY = DataPoint.getDepth(data); + if (minY > bb.minY) + { + maxY = (int) Math.min(minY, bb.maxY); + addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); + } + } + } + + if (playerBlockPos.getZ() < bb.maxZ + CULL_OFFSET || disableCulling) + { + red = ColorUtil.getRed(southColor); + green = ColorUtil.getGreen(southColor); + blue = ColorUtil.getBlue(southColor); + alpha = ColorUtil.getAlpha(southColor); + data = adjData[2]; + // south (facing -Z) + if (data == 0) + { + addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + } + else + { + maxY = DataPoint.getHeight(data); + if (maxY < bb.maxY) + { + minY = (int) Math.max(maxY, bb.minY); + addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha); + } + minY = DataPoint.getDepth(data); + if (minY > bb.minY) + { + maxY = (int) Math.min(minY, bb.maxY); + addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + } + } + } } - + @Override public int getBufferMemoryForSingleNode() { // (sidesOnACube * pointsInASquare * (positionPoints + colorPoints))) return (6 * 4 * (3 + 4)); } - + } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java index bb7efb31c..d5de6f7db 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java @@ -18,7 +18,6 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.objects.LevelPos.LevelPos; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.math.BlockPos; @@ -35,8 +34,8 @@ import net.minecraft.util.math.BlockPos; public class DynamicLodTemplate extends AbstractLodTemplate { @Override - public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData, - LevelPos levelPos, DebugMode debugging) + public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, + byte detailLevel, int posX, int posZ,DebugMode debugging) { System.err.println("DynamicLodTemplate not implemented!"); } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java index 449ba91c0..f8158c7da 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java @@ -18,7 +18,6 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.objects.LevelPos.LevelPos; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.math.BlockPos; @@ -33,8 +32,8 @@ import net.minecraft.util.math.BlockPos; public class TriangularLodTemplate extends AbstractLodTemplate { @Override - public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData, - LevelPos levelPos, DebugMode debugging) + public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, + byte detailLevel, int posX, int posZ,DebugMode debugging) { System.err.println("DynamicLodTemplate not implemented!"); } diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index f1e7e100a..769670b35 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -1,33 +1,24 @@ package com.seibel.lod.builders.worldGeneration; -import java.util.ArrayList; -import java.util.Comparator; import java.util.HashSet; -import java.util.List; import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.commons.lang3.mutable.MutableBoolean; +import com.seibel.lod.objects.LevelPosUtil; +import com.seibel.lod.objects.PosToGenerateContainer; -import com.seibel.lod.builders.GenerationRequest; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.objects.LodDimension; -import com.seibel.lod.objects.LevelPos.LevelPos; import com.seibel.lod.render.LodRenderer; import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; -import com.seibel.lod.wrapper.MinecraftWrapper; -import net.minecraft.util.math.BlockPos; +import com.seibel.lod.wrapper.MinecraftWrapper; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.WorldWorkerManager; @@ -75,10 +66,6 @@ public class LodWorldGenerator */ public static final LodWorldGenerator INSTANCE = new LodWorldGenerator(); - public volatile ConcurrentMap nodeToGenerate; - - SortedSet nodeToGenerateListNear; - SortedSet nodeToGenerateListFar; private LodWorldGenerator() { @@ -108,14 +95,9 @@ public class LodWorldGenerator try { // round the player's block position down to the nearest chunk BlockPos - ChunkPos playerChunkPos = new ChunkPos(mc.getPlayer().blockPosition()); - BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition(); + int playerPosX = mc.getPlayer().blockPosition().getX(); + int playerPosZ = mc.getPlayer().blockPosition().getZ(); - // used when determining which chunks are closer when queuing distance - // generation - int minChunkDist = Integer.MAX_VALUE; - - ArrayList chunksToGen = new ArrayList<>(maxChunkGenRequests); // if we don't have a full number of chunks to generate in chunksToGen // we can top it off from this reserve @@ -123,92 +105,34 @@ public class LodWorldGenerator //=======================================// // create the generation Request objects // //=======================================// - List generationRequestList = new ArrayList<>(maxChunkGenRequests); - - if (nodeToGenerate == null) - nodeToGenerate = new ConcurrentHashMap<>(); - - - Comparator posNearComparator = LevelPos.getPosComparator( - playerBlockPosRounded.getX(), - playerBlockPosRounded.getZ()); - Comparator posFarComparator = LevelPos.getPosAndDetailComparator( - playerBlockPosRounded.getX(), - playerBlockPosRounded.getZ()); - nodeToGenerateListNear = new TreeSet(posNearComparator); - nodeToGenerateListFar = new TreeSet(posFarComparator); - - lodDim.getDataToGenerate( - nodeToGenerate, - playerBlockPosRounded.getX(), - playerBlockPosRounded.getZ()); + ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); + byte farDetail = (byte) 8; + PosToGenerateContainer posToGenerate = lodDim.getDataToGenerate( + farDetail, + maxChunkGenRequests, + 0.25, + playerPosX, + playerPosZ); + //System.out.println(posToGenerate); //here we prepare two sorted set //the first contains the near pos to render //the second contain the far pos to render - byte farDetail = (byte) 7; - for (LevelPos pos : nodeToGenerate.keySet()) + byte detailLevel; + int posX; + int posZ; + int[] levelPos; + for (int index = 0; index < posToGenerate.getNumberOfPos(); index++) { - if (!nodeToGenerate.get(pos).booleanValue()) - { - nodeToGenerate.remove(pos); - } else - { - if (pos.detailLevel > farDetail){ - nodeToGenerateListFar.add(pos); - } - nodeToGenerateListNear.add(pos); - nodeToGenerate.get(pos).setFalse(); - } - } + levelPos = posToGenerate.getNthPos(index); + if(levelPos[0] == 0) + continue; + detailLevel = (byte) (levelPos[0] -1); + posX = levelPos[1]; + posZ = levelPos[2]; - int maxDistance; - byte circle; - LevelPos levelPos; - int requesting = maxChunkGenRequests; - int requestingFar = maxChunkGenRequests / 4; - while (requesting > 0 && !nodeToGenerateListNear.isEmpty()) - { - levelPos = nodeToGenerateListNear.first(); - //.out.println(levelPos); - nodeToGenerate.remove(levelPos); - nodeToGenerateListNear.remove(levelPos); - nodeToGenerateListFar.remove(levelPos); - - //maxDistance = levelPos.maxDistance( - // playerBlockPosRounded.getX(), - // playerBlockPosRounded.getZ()); - //circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance); - generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(levelPos.detailLevel))); - requesting--; - if (requestingFar > 0 && !nodeToGenerateListFar.isEmpty()) - { - levelPos = nodeToGenerateListFar.first(); - nodeToGenerate.remove(levelPos); - nodeToGenerateListNear.remove(levelPos); - nodeToGenerateListFar.remove(levelPos); - if (levelPos.detailLevel >= farDetail) - { - //maxDistance = levelPos.maxDistance( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ()); - //circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance); - generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(levelPos.detailLevel))); - requestingFar--; - requesting--; - } - } - } - - - //====================================// - // get the closet generation requests // - //====================================// - - // determine which points in the posListToGenerate - // should actually be queued to generate - for (GenerationRequest generationRequest : generationRequestList) - { - ChunkPos chunkPos = generationRequest.getChunkPos(); + ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel,posX), LevelPosUtil.getChunkPos(detailLevel,posZ)); if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) { // prevent generating the same chunk multiple times @@ -216,32 +140,16 @@ public class LodWorldGenerator { continue; } - chunksToGen.add(generationRequest); + } - } // lod null and can generate more chunks - } // positions to generate - - - //=============================// - // start the LodNodeGenWorkers // - //=============================// - - // issue #19 - // TODO add a way for a server side mod to generate chunks requested here - ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - - // start chunk generation - for (GenerationRequest generationRequest : generationRequestList) - { // don't add null chunkPos (which shouldn't happen anyway) // or add more to the generation queue - ChunkPos chunkPos = generationRequest.getChunkPos(); if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) continue; positionWaitingToBeGenerated.add(chunkPos); numberOfChunksWaitingToGenerate.addAndGet(1); - LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, generationRequest.generationMode, renderer, lodBuilder, lodDim, serverWorld); + LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), renderer, lodBuilder, lodDim, serverWorld); WorldWorkerManager.addWorker(genWorker); } diff --git a/src/main/java/com/seibel/lod/objects/DataPoint.java b/src/main/java/com/seibel/lod/objects/DataPoint.java index 3d8d2e6dc..397f23375 100644 --- a/src/main/java/com/seibel/lod/objects/DataPoint.java +++ b/src/main/java/com/seibel/lod/objects/DataPoint.java @@ -2,47 +2,96 @@ package com.seibel.lod.objects; public class DataPoint { + public final static int HEIGHT_SHIFT = 54; + public final static int DEPTH_SHIFT = 44; + public final static int RED_SHIFT = 36; + public final static int GREEN_SHIFT = 28; + public final static int BLUE_SHIFT = 20; + public final static int GEN_TYPE_SHIFT = 17; + public final static int LIGHT_SHIFT = 13; + public final static int EXISTENCE_SHIFT = 0; - public static short[] createDataPoint(int height, int depth, int red, int green, int blue) + public final static long HEIGHT_MASK = Long.parseUnsignedLong("1111111111", 2); + public final static long DEPTH_MASK = Long.parseUnsignedLong("1111111111", 2); + public final static long RED_MASK = Long.parseUnsignedLong("11111111", 2); + public final static long GREEN_MASK = Long.parseUnsignedLong("11111111", 2); + public final static long BLUE_MASK = Long.parseUnsignedLong("11111111", 2); + public final static long GEN_TYPE_MASK = Long.parseUnsignedLong("111", 2); + public final static long LIGHT_MASK = Long.parseUnsignedLong("1111", 2); + public final static long EXISTENCE_MASK = 1; + + public static long createDataPoint(int height, int depth, int color) { - return new short[]{(short) height, (short) depth, (short) red, (short) green, (short) blue}; + int red = (getRed(color) << 16) & 0x00FF0000; + int green = (getGreen(color) << 8) & 0x0000FF00; + int blue = getBlue(color)& 0x000000FF; + return createDataPoint(height, depth, red, green, blue); + } + public static long createDataPoint(int height, int depth, int red, int green, int blue) + { + long dataPoint = 0; + dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; + dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; + dataPoint += (red & RED_MASK) << RED_SHIFT; + dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; + dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; + dataPoint += 1; + return dataPoint; } - public static short getHeight(short[] dataPoint) + public static short getHeight(long dataPoint) { - return dataPoint[0]; + return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK); } - public static short getDepth(short[] dataPoint) + public static short getDepth(long dataPoint) { - return dataPoint[1]; + + return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK); } - public static short getRed(short[] dataPoint) + public static short getRed(long dataPoint) { - return dataPoint[2]; + + return (short) ((dataPoint >> RED_SHIFT) & RED_MASK); } - public static short getGreen(short[] dataPoint) + public static short getGreen(long dataPoint) { - return dataPoint[3]; + return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK); } - public static short getBlue(short[] dataPoint) + public static short getBlue(long dataPoint) { - return dataPoint[4]; + return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK); } - public static short[] getHeightDepth(short[] dataPoint) + public static boolean doesItExist(long dataPoint) { - return new short[]{dataPoint[0], dataPoint[1]}; + return ((dataPoint & EXISTENCE_MASK) == 1); } - public static int getColor(short[] dataPoint) + public static int getColor(long dataPoint) { - int R = (dataPoint[2] << 16) & 0x00FF0000; - int G = (dataPoint[3] << 8) & 0x0000FF00; - int B = dataPoint[4] & 0x000000FF; + int R = (getRed(dataPoint) << 16) & 0x00FF0000; + int G = (getGreen(dataPoint) << 8) & 0x0000FF00; + int B = getBlue(dataPoint)& 0x000000FF; return 0xFF000000 | R | G | B; } + + public static String toString(long dataPoint) + { + StringBuilder s = new StringBuilder(); + s.append(getHeight(dataPoint)); + s.append(" "); + s.append(getDepth(dataPoint)); + s.append(" "); + s.append(getRed(dataPoint)); + s.append(" "); + s.append(getBlue(dataPoint)); + s.append(" "); + s.append(getGreen(dataPoint)); + s.append('\n'); + return s.toString(); + } } diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index da1d47aae..08517fe43 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -11,61 +11,33 @@ public class LevelContainer implements Serializable public final byte detailLevel; - public final byte[][][] colors; + public final long[][] data; - public final short[][] height; - - public final short[][] depth; - - public final boolean[][] dataExistence; - - public LevelContainer(byte detailLevel, byte[][][] colors, short[][] height, short[][] depth, boolean[][] dataExistence) + public LevelContainer(byte detailLevel, long[][] data) { this.detailLevel = detailLevel; - this.colors = colors; - this.height = height; - this.depth = depth; - this.dataExistence = dataExistence; + this.data = data; } - public LevelContainer(String data) + public LevelContainer(String inputString) { int index = 0; int lastIndex = 0; - index = data.indexOf(DATA_DELIMITER, 0); - this.detailLevel = (byte) Integer.parseInt(data.substring(0, index)); + index = inputString.indexOf(DATA_DELIMITER, 0); + this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.colors = new byte[size][size][3]; - this.height = new short[size][size]; - this.depth = new short[size][size]; - this.dataExistence = new boolean[size][size]; - int intCol; + this.data = new long[size][size]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { lastIndex = index; - index = data.indexOf(DATA_DELIMITER, lastIndex + 1); - intCol = Integer.parseInt(data.substring(lastIndex + 1, index), 16); - colors[x][z][0] = (byte) ((intCol >> 16) - 128); - colors[x][z][1] = (byte) ((intCol >> 8) - 128); - colors[x][z][2] = (byte) (intCol - 128); - - lastIndex = index; - index = data.indexOf(DATA_DELIMITER, lastIndex + 1); - height[x][z] = Short.parseShort(data.substring(lastIndex + 1, index), 16); - - lastIndex = index; - index = data.indexOf(DATA_DELIMITER, lastIndex + 1); - depth[x][z] = Short.parseShort(data.substring(lastIndex + 1, index), 16); - - lastIndex = index; - index = data.indexOf(DATA_DELIMITER, lastIndex + 1); - dataExistence[x][z] = Boolean.parseBoolean(data.substring(lastIndex + 1, index)); + index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); + data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); } } @@ -75,7 +47,6 @@ public class LevelContainer implements Serializable public String toString() { StringBuilder stringBuilder = new StringBuilder(); - int combinedCol; int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); stringBuilder.append(detailLevel); stringBuilder.append(DATA_DELIMITER); @@ -83,15 +54,8 @@ public class LevelContainer implements Serializable { for (int z = 0; z < size; z++) { - //Converting the colors to intColor and then to HEX - combinedCol = ((colors[x][z][0] + 128) << 16) | ((colors[x][z][1] + 128) << 8) | ((colors[x][z][2] + 128)); - stringBuilder.append(Integer.toHexString(combinedCol)); - stringBuilder.append(DATA_DELIMITER); - stringBuilder.append(Integer.toHexString(height[x][z] & 0xffff)); - stringBuilder.append(DATA_DELIMITER); - stringBuilder.append(Integer.toHexString(depth[x][z] & 0xffff)); - stringBuilder.append(DATA_DELIMITER); - stringBuilder.append(dataExistence[x][z]); + //Converting the dataToHex + stringBuilder.append(Long.toHexString(data[x][z])); stringBuilder.append(DATA_DELIMITER); } } diff --git a/src/main/java/com/seibel/lod/objects/LevelPos/ImmutableLevelPos.java b/src/main/java/com/seibel/lod/objects/LevelPos/ImmutableLevelPos.java deleted file mode 100644 index 1d75dd605..000000000 --- a/src/main/java/com/seibel/lod/objects/LevelPos/ImmutableLevelPos.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.seibel.lod.objects.LevelPos; - -public interface ImmutableLevelPos -{ - public LevelPos getConvertedLevelPos(byte newDetailLevel); - public LevelPos getRegionModuleLevelPos(); -} diff --git a/src/main/java/com/seibel/lod/objects/LevelPos/LevelPos.java b/src/main/java/com/seibel/lod/objects/LevelPos/LevelPos.java deleted file mode 100644 index 0d20eb490..000000000 --- a/src/main/java/com/seibel/lod/objects/LevelPos/LevelPos.java +++ /dev/null @@ -1,415 +0,0 @@ -package com.seibel.lod.objects.LevelPos; - -import com.seibel.lod.objects.RegionPos; -import com.seibel.lod.util.LodUtil; -import net.minecraft.util.math.ChunkPos; - -import java.util.Comparator; - -public class LevelPos implements Cloneable, ImmutableLevelPos, MutableLevelPos, Comparable -{ - public byte detailLevel; - public int posX; - public int posZ; - public boolean flag; - - public LevelPos() - { - } - - public LevelPos(byte detailLevel, int posX, int posZ) - { - this.posX = posX; - this.posZ = posZ; - this.detailLevel = detailLevel; - } - - /** - * this operation does not change the state - */ - public LevelPos getConvertedLevelPos(byte newDetailLevel) - { - if (newDetailLevel >= detailLevel) - { - int width = 1 << (newDetailLevel - detailLevel); - return new LevelPos( - newDetailLevel, - Math.floorDiv(posX, width), - Math.floorDiv(posZ, width)); - } else - { - int width = 1 << (detailLevel - newDetailLevel); - return new LevelPos( - newDetailLevel, - posX * width, - posZ * width); - } - } - - /** - * this operation does not change the state - */ - public LevelPos getRegionModuleLevelPos() - { - int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - return new LevelPos( - detailLevel, - Math.floorMod(posX, width), - Math.floorMod(posZ, width)); - } - - /** - * this operation changes the state - */ - public void convert(byte newDetailLevel) - { - if (newDetailLevel >= detailLevel) - { - int width = 1 << (newDetailLevel - detailLevel); - detailLevel = newDetailLevel; - posX = Math.floorDiv(posX, width); - posZ = Math.floorDiv(posZ, width); - } else - { - int width = 1 << (detailLevel - newDetailLevel); - detailLevel = newDetailLevel; - posX = posX * width; - posZ = posZ * width; - } - } - - /** - * this operation changes the state - */ - public void performRegionModule() - { - int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - posX = Math.floorMod(posX, width); - posZ = Math.floorMod(posZ, width); - } - - /** - * this operation changes the state - */ - public void applyOffset(int xOffset, int zOffset) - { - posX = posX + xOffset; - posX = posZ + zOffset; - } - - /** - * this operation changes the state - */ - public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ) - { - detailLevel = newDetailLevel; - posX = newPosX; - posZ = newPosZ; - } - - public RegionPos getRegionPos() - { - int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - return new RegionPos( - Math.floorDiv(posX, width), - Math.floorDiv(posZ, width)); - } - - public int getRegionPosX() - { - int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - return Math.floorDiv(posX, width); - } - - public int getRegionPosZ() - { - int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - return Math.floorDiv(posZ, width); - } - - public int getChunkPosX() - { - if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel) - { - int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel); - return Math.floorDiv(posX, width); - } else - { - int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL); - return posX * width; - } - } - - public int getChunkPosZ() - { - if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel) - { - int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel); - return Math.floorDiv(posZ, width); - } else - { - int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL); - return posZ * width; - } - } - - public ChunkPos getChunkPos() - { - if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel) - { - int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel); - return new ChunkPos( - Math.floorDiv(posX, width), - Math.floorDiv(posZ, width)); - } else - { - int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL); - return new ChunkPos( - posX * width, - posZ * width); - } - } - - /** - * TODO fix the region disappearing for a second - */ - - public int maxDistance(int playerPosX, int playerPosZ, int regionPosX, int regionPosZ) - { - int width = 1 << detailLevel; - - int startPosX = regionPosX * 512 + posX * width; - int startPosZ = regionPosZ * 512 + posZ * width; - int endPosX = startPosX + width; - int endPosZ = startPosZ + width; - - int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2))); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - - return maxDistance; - } - - public int maxDistance(int playerPosX, int playerPosZ) - { - int width = 1 << detailLevel; - - int startPosX = posX * width; - int startPosZ = posZ * width; - int endPosX = startPosX + width; - int endPosZ = startPosZ + width; - - int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2))); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - - return maxDistance; - } - - public int minDistance(int playerPosX, int playerPosZ, int regionPosX, int regionPosZ) - { - int width = 1 << detailLevel; - - int startPosX = regionPosX * 512 + posX * width; - int startPosZ = regionPosZ * 512 + posZ * width; - int endPosX = startPosX + width; - int endPosZ = startPosZ + width; - - boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX; - boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ; - if (inXArea && inZArea) - { - return 0; - } else if (inXArea) - { - return Math.min( - Math.abs(playerPosZ - startPosZ), - Math.abs(playerPosZ - endPosZ) - ); - } else if (inZArea) - { - return Math.min( - Math.abs(playerPosX - startPosX), - Math.abs(playerPosX - endPosX) - ); - } else - { - int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2))); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - return minDistance; - } - } - - public int minDistance(int playerPosX, int playerPosZ) - { - int width = 1 << detailLevel; - - int startPosX = posX * width; - int startPosZ = posZ * width; - int endPosX = startPosX + width; - int endPosZ = startPosZ + width; - - boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX; - boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ; - if (inXArea && inZArea) - { - return 0; - } else if (inXArea) - { - return Math.min( - Math.abs(playerPosZ - startPosZ), - Math.abs(playerPosZ - endPosZ) - ); - } else if (inZArea) - { - return Math.min( - Math.abs(playerPosX - startPosX), - Math.abs(playerPosX - endPosX) - ); - } else - { - int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2))); - minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); - return minDistance; - } - } - - public static LevelPosDistanceComparator getPosComparator(int playerPosX, int playerPosZ) - { - return new LevelPosDistanceComparator(playerPosX, playerPosZ); - } - - public static LevelPosDetailComparator getPosAndDetailComparator(int playerPosX, int playerPosZ) - { - return new LevelPosDetailComparator(playerPosX, playerPosZ); - } - - public static class LevelPosDistanceComparator implements Comparator - { - int playerPosX; - int playerPosZ; - - public LevelPosDistanceComparator(int playerPosX, int playerPosZ) - { - this.playerPosX = playerPosX; - this.playerPosZ = playerPosZ; - } - - @Override - public int compare(LevelPos first, LevelPos second) - { - return Integer.compare( - first.minDistance(playerPosX, playerPosZ), - second.minDistance(playerPosX, playerPosZ)); - } - } - - public static class LevelPosDetailComparator implements Comparator - { - int playerPosX; - int playerPosZ; - - public LevelPosDetailComparator(int playerPosX, int playerPosZ) - { - this.playerPosX = playerPosX; - this.playerPosZ = playerPosZ; - } - - @Override - public int compare(LevelPos first, LevelPos second) - { - int compareResult = Integer.compare(second.detailLevel, first.detailLevel); - if (compareResult == 0) - { - compareResult = Integer.compare( - first.minDistance(playerPosX, playerPosZ), - second.minDistance(playerPosX, playerPosZ)); - } - return compareResult; - } - } - - public static LevelPosComparator getComparator() - { - return new LevelPosComparator(); - } - - public static class LevelPosComparator implements Comparator - { - @Override - public int compare(LevelPos first, LevelPos second) - { - int compareResult = Integer.compare(first.detailLevel, second.detailLevel); - if (compareResult == 0) - { - compareResult = Integer.compare( - first.posX, - second.posX); - } - if (compareResult == 0) - { - compareResult = Integer.compare( - first.posZ, - second.posZ); - } - return compareResult; - } - } - - @Override - public int compareTo(LevelPos other) - { - int compareResult = Integer.compare(this.detailLevel, other.detailLevel); - if (compareResult == 0) - { - compareResult = Integer.compare( - this.posX, - other.posX); - } - if (compareResult == 0) - { - compareResult = Integer.compare( - this.posZ, - other.posZ); - } - return compareResult; - } - - - @Override - public LevelPos clone() - { - return new LevelPos(detailLevel, posX, posZ); - } - - @Override - public int hashCode() - { - int hash = 7; - hash = 31 * hash + (int) detailLevel; - hash = 31 * hash + posX; - hash = 31 * hash + posZ; - return hash; - } - - @Override - public boolean equals(Object other) - { - return (this.detailLevel == ((LevelPos) other).detailLevel && - this.posX == ((LevelPos) other).posX && - this.posZ == ((LevelPos) other).posZ); - } - - @Override - public String toString() - { - String s = (detailLevel + " " + posX + " " + posZ); - return s; - } -} diff --git a/src/main/java/com/seibel/lod/objects/LevelPos/MutableLevelPos.java b/src/main/java/com/seibel/lod/objects/LevelPos/MutableLevelPos.java deleted file mode 100644 index 324fbb47b..000000000 --- a/src/main/java/com/seibel/lod/objects/LevelPos/MutableLevelPos.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.seibel.lod.objects.LevelPos; - -import com.seibel.lod.util.LodUtil; - -public interface MutableLevelPos -{ - public void convert(byte newDetailLevel); - - public void performRegionModule(); - - public void applyOffset(int xOffset, int zOffset); - - public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ); -} diff --git a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java b/src/main/java/com/seibel/lod/objects/LevelPosUtil.java index 41ff5531a..fb7c10cef 100644 --- a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java +++ b/src/main/java/com/seibel/lod/objects/LevelPosUtil.java @@ -37,11 +37,29 @@ public class LevelPosUtil return new int[]{detailLevel, posX, posZ}; } - public static int[] createLevelPos(byte detailLevel, int posX, int posZ, int distance) + public static int convert(byte detailLevel, int pos, byte newDetailLevel) { - return new int[]{detailLevel, posX, posZ, distance}; + int width; + if (newDetailLevel >= detailLevel) + { + width = 1 << (newDetailLevel - detailLevel); + return Math.floorDiv(pos, width); + } else + { + width = 1 << (detailLevel - newDetailLevel); + return pos * width; + } } + public static int getRegion(byte detailLevel, int pos) + { + return Math.floorDiv(pos, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel)); + } + + public static int getRegionModule(byte detailLevel, int pos) + { + return Math.floorMod(pos, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel)); + } public static byte getDetailLevel(int[] levelPos) { @@ -105,6 +123,11 @@ public class LevelPosUtil return Math.floorDiv(getPosZ(levelPos), width); } + public static int getChunkPos(byte detailLevel, int pos) + { + return convert(detailLevel,pos, LodUtil.CHUNK_DETAIL_LEVEL); + } + public static int getChunkPosX(int[] levelPos) { levelPos = convert(levelPos, LodUtil.CHUNK_DETAIL_LEVEL); @@ -139,6 +162,23 @@ public class LevelPosUtil return maxDistance; } + public static int maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ, int xRegion, int zRegion) + { + int width = 1 << detailLevel; + + int startPosX = xRegion * 512 + posX * width; + int startPosZ = zRegion * 512 + posZ * width; + int endPosX = startPosX + width; + int endPosZ = startPosZ + width; + + int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)); + maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); + maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2))); + maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2))); + + return maxDistance; + } + public static int minDistance(int[] levelPos, int playerPosX, int playerPosZ) { @@ -181,40 +221,24 @@ public class LevelPosUtil } } - public static int compareDistance(int posX, int posZ, int[] first, int[] second) + public static int compareDistance(int firstDistance, int secondDistance) { return Integer.compare( - minDistance(first, posX, posZ), - minDistance(second, posX, posZ)); + firstDistance, + secondDistance); } - public static int compareDistance(int[] first, int[] second) - { - return Integer.compare( - getDistance(first), - getDistance(second)); - } - public static int compareLevelAndDistance(int[] first, int[] second) + public static int compareLevelAndDistance(byte firstDetail, int firstDistance, byte secondDetail, int secondDistance) { - int compareResult = Integer.compare(getDetailLevel(second), getDetailLevel(first)); + int compareResult = Integer.compare( + secondDetail, + firstDetail); if (compareResult == 0) { compareResult = Integer.compare( - getDistance(first), - getDistance(second)); - } - return compareResult; - } - - public static int compareLevelAndDistance(int posX, int posZ, int[] first, int[] second) - { - int compareResult = Integer.compare(getDetailLevel(second), getDetailLevel(first)); - if (compareResult == 0) - { - compareResult = Integer.compare( - minDistance(first, posX, posZ), - minDistance(second, posX, posZ)); + firstDistance, + secondDistance); } return compareResult; } @@ -223,4 +247,8 @@ public class LevelPosUtil { return (getDetailLevel(levelPos) + " " + getPosX(levelPos) + " " + getPosZ(levelPos)); } + public static String toString(byte detailLevel, int posX, int posZ) + { + return (detailLevel + " " + posX + " " + posZ); + } } diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 3230a9a20..2ed33d849 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -24,21 +24,22 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import com.seibel.lod.wrapper.MinecraftWrapper; import org.apache.commons.lang3.mutable.MutableBoolean; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.handlers.LodDimensionFileHandler; -import com.seibel.lod.objects.LevelPos.LevelPos; import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; -import com.seibel.lod.wrapper.MinecraftWrapper; +import net.minecraft.client.Minecraft; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.DimensionType; import net.minecraft.world.server.ServerChunkProvider; import net.minecraft.world.server.ServerWorld; +import org.lwjgl.system.CallbackI; /** @@ -47,7 +48,7 @@ import net.minecraft.world.server.ServerWorld; * * @author Leonardo Amato * @author James Seibel - * @version 9-6-2021 + * @version 8-8-2021 */ public class LodDimension { @@ -67,8 +68,10 @@ public class LodDimension public volatile LodRegion regions[][]; public volatile boolean isRegionDirty[][]; public volatile boolean regen[][]; - /** if true that means there are regions in this dimension - * that need to have their buffers rebuilt. */ + /** + * if true that means there are regions in this dimension + * that need to have their buffers rebuilt. + */ public volatile boolean regenDimension = false; private volatile RegionPos center; @@ -243,6 +246,8 @@ public class LodDimension */ public int getMinMemoryNeeded() { + int regionX; + int regionZ; int count = 0; LodRegion region; @@ -260,25 +265,29 @@ public class LodDimension return count; } + /** * Gets the region at the given X and Z *
* Returns null if the region doesn't exist * or is outside the loaded area. */ - public LodRegion getRegion(LevelPos levelPos) + public LodRegion getRegion(byte detailLevel, int posX, int posZ) { + int xRegion = LevelPosUtil.getRegion(detailLevel, posX); + int zRegion = LevelPosUtil.getRegion(detailLevel, posZ); + int xIndex = (xRegion - center.x) + halfWidth; + int zIndex = (zRegion - center.z) + halfWidth; - RegionPos regionPos = levelPos.getRegionPos(); - int xIndex = (regionPos.x - center.x) + halfWidth; - int zIndex = (regionPos.z - center.z) + halfWidth; - - if (!regionIsInRange(regionPos.x, regionPos.z)) - throw new ArrayIndexOutOfBoundsException("Region for level pos " + levelPos + " out of range"); + if (!regionIsInRange(xRegion, zRegion)) + return null; + //throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range"); else if (regions[xIndex][zIndex] == null) - throw new InvalidParameterException("Region for level pos " + levelPos + " not currently initialized"); - else if (regions[xIndex][zIndex].getMinDetailLevel() > levelPos.detailLevel) - throw new InvalidParameterException("Region for level pos " + levelPos + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel()); + return null; + //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " not currently initialized"); + else if (regions[xIndex][zIndex].getMinDetailLevel() > detailLevel) + return null; + //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel()); return regions[xIndex][zIndex]; } @@ -288,15 +297,17 @@ public class LodDimension * Returns null if the region doesn't exist * or is outside the loaded area. */ - public LodRegion getRegion(RegionPos regionPos) + public LodRegion getRegion(int regionPosX, int regionPosZ) { - int xIndex = (regionPos.x - center.x) + halfWidth; - int zIndex = (regionPos.z - center.z) + halfWidth; + int xIndex = (regionPosX - center.x) + halfWidth; + int zIndex = (regionPosZ - center.z) + halfWidth; - if (!regionIsInRange(regionPos.x, regionPos.z)) - throw new ArrayIndexOutOfBoundsException("Region " + regionPos + " out of range"); + if (!regionIsInRange(regionPosX, regionPosZ)) + return null; + //throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range"); else if (regions[xIndex][zIndex] == null) - throw new InvalidParameterException("Region " + regionPos + " not currently initialized"); + return null; + //throw new InvalidParameterException("Region " + regionPosX + " " + regionPosZ + " not currently initialized"); return regions[xIndex][zIndex]; } @@ -308,7 +319,7 @@ public class LodDimension public synchronized void addOrOverwriteRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException { int xIndex = (newRegion.regionPosX - center.x) + halfWidth; - int zIndex = (center.z - newRegion.regionPosZ) + halfWidth; + int zIndex = (newRegion.regionPosZ - center.z) + halfWidth; if (!regionIsInRange(newRegion.regionPosX, newRegion.regionPosZ)) // out of range @@ -323,7 +334,7 @@ public class LodDimension */ public void treeCutter(int playerPosX, int playerPosZ) { - ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos(); + ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ)); if (lastCutChunk == null) lastCutChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1); if (newPlayerChunk.x != lastCutChunk.x || newPlayerChunk.z != lastCutChunk.z) @@ -336,7 +347,6 @@ public class LodDimension int minDistance; byte detail; byte levelToCut; - LevelPos levelPos = new LevelPos(); for (int x = 0; x < regions.length; x++) { @@ -349,8 +359,7 @@ public class LodDimension //if this is not the case w if (regions[x][z] != null) { - levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ); - minDistance = levelPos.minDistance(playerPosX, playerPosZ); + minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ); detail = DetailDistanceUtil.getDistanceTreeCutInverse(minDistance); levelToCut = DetailDistanceUtil.getCutLodDetail(detail); if (regions[x][z].getMinDetailLevel() > levelToCut) @@ -373,7 +382,7 @@ public class LodDimension public void treeGenerator(int playerPosX, int playerPosZ) { DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get(); - ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos(); + ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ)); if (lastGenChunk == null) lastGenChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1); @@ -388,20 +397,17 @@ public class LodDimension int minDistance; byte detail; byte levelToGen; - LevelPos levelPos = new LevelPos(); for (int x = 0; x < regions.length; x++) { for (int z = 0; z < regions.length; z++) { regionX = (x + center.x) - halfWidth; regionZ = (z + center.z) - halfWidth; - levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ); final RegionPos regionPos = new RegionPos(regionX, regionZ); region = regions[x][z]; //We require that the region we are checking is loaded with at least this level - levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ); - minDistance = levelPos.minDistance(playerPosX, playerPosZ); + minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ); detail = DetailDistanceUtil.getDistanceTreeGenInverse(minDistance); levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel; if (region == null || region.getGenerationMode() != generationMode) @@ -437,32 +443,31 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinates it will be overwritten. */ - public synchronized Boolean addData(LevelPos levelPos, short[] lodDataPoint, boolean dontSave, boolean serverQuality) + public synchronized Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality) { // don't continue if the region can't be saved - RegionPos regionPos = levelPos.getRegionPos(); - if (!regionIsInRange(regionPos.x, regionPos.z)) - { + int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); + int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); + + LodRegion region = getRegion(regionPosX, regionPosZ); + if (region == null) return false; - } - - LodRegion region = getRegion(levelPos); - - boolean nodeAdded = region.addData(levelPos, lodDataPoint, serverQuality); + boolean nodeAdded = region.addData(detailLevel, posX, posZ, lodDataPoint, serverQuality); // only save valid LODs to disk if (!dontSave && fileHandler != null) { try { // mark the region as dirty so it will be saved to disk - int xIndex = (regionPos.x - center.x) + halfWidth; - int zIndex = (regionPos.z - center.z) + halfWidth; + int xIndex = (regionPosX - center.x) + halfWidth; + int zIndex = (regionPosZ - center.z) + halfWidth; isRegionDirty[xIndex][zIndex] = true; regen[xIndex][zIndex] = true; regenDimension = true; } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); // This method was probably called when the dimension was changing size. // Hopefully this shouldn't be an issue. } @@ -470,7 +475,8 @@ public class LodDimension return nodeAdded; } - public void setToRegen(int xRegion, int zRegion){ + public void setToRegen(int xRegion, int zRegion) + { int xIndex = (xRegion - center.x) + halfWidth; int zIndex = (zRegion - center.z) + halfWidth; regen[xIndex][zIndex] = true; @@ -481,32 +487,26 @@ public class LodDimension * * @return list of quadTrees */ - public void getDataToGenerate(ConcurrentMap dataToGenerate, int playerPosX, int playerPosZ) + public PosToGenerateContainer getDataToGenerate(byte farDetail, int maxDataToGenerate, double farRatio, int playerPosX, int playerPosZ) { - + PosToGenerateContainer posToGenerate = new PosToGenerateContainer(farDetail, maxDataToGenerate, (int) (maxDataToGenerate * farRatio), playerPosX, playerPosZ); int n = regions.length; int xIndex; int zIndex; LodRegion region; - RegionPos regionPos; for (int xRegion = 0; xRegion < n; xRegion++) { for (int zRegion = 0; zRegion < n; zRegion++) { - try - { - xIndex = (xRegion + center.x) - halfWidth; - zIndex = (zRegion + center.z) - halfWidth; - regionPos = new RegionPos(xIndex, zIndex); - region = getRegion(regionPos); - region.getDataToGenerate(dataToGenerate, playerPosX, playerPosZ); + xIndex = (xRegion + center.x) - halfWidth; + zIndex = (zRegion + center.z) - halfWidth; + region = getRegion(xIndex, zIndex); + if (region != null) + region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ); - } catch (Exception e) - { - //e.printStackTrace(); - } } } + return posToGenerate; } /** @@ -514,33 +514,11 @@ public class LodDimension * * @return list of nodes */ - public void getDataToRender(ConcurrentMap dataToRender, RegionPos regionPos, int playerPosX, int playerPosZ) + public void getDataToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX, int playerPosZ) { - try - { - LodRegion region = getRegion(regionPos); - region.getDataToRender(dataToRender, playerPosX, playerPosZ); - } catch (NullPointerException e) - { - System.out.println(regionPos); - e.printStackTrace(); - } catch (Exception e) - { - //e.printStackTrace(); - } - } - - /** - * Get the LodNodeData at the given X and Z coordinates - * in this dimension. - *
- * Returns null if the LodChunk doesn't exist or - * is outside the loaded area. - */ - public short[] getData(ChunkPos chunkPos) - { - LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z); - return getData(levelPos); + LodRegion region = getRegion(regionPos.x, regionPos.z); + if (region != null) + region.getDataToRender(posToRender, playerPosX, playerPosZ); } /** @@ -550,26 +528,19 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public short[] getData(LevelPos levelPos) + public long getData(byte detailLevel, int posX, int posZ) { - if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL) - throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); + if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) + throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); - try + LodRegion region = getRegion(detailLevel, posX, posZ); + + if (region == null) { - LodRegion region = getRegion(levelPos); - - if (region == null) - { - return null; - } - - return region.getData(levelPos); - - } catch (Exception e) - { - return null; + return 0; } + + return region.getData(detailLevel, posX, posZ); } @@ -580,40 +551,34 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public void updateData(LevelPos levelPos) + public void updateData(byte detailLevel, int posX, int posZ) { - if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL) - throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); + if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) + throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); - LodRegion region = getRegion(levelPos); + LodRegion region = getRegion(detailLevel, posX, posZ); if (region == null) { return; } - region.updateArea(levelPos); + region.updateArea(detailLevel, posX, posZ); } /** * return true if and only if the node at that position exist */ - public boolean doesDataExist(LevelPos levelPos) + public boolean doesDataExist(byte detailLevel, int posX, int posZ) { - try - { - LodRegion region = getRegion(levelPos); + LodRegion region = getRegion(detailLevel, posX, posZ); - if (region == null) - { - return false; - } - - return region.doesDataExist(levelPos.clone()); - } catch (Exception e) + if (region == null) { return false; } + + return region.doesDataExist(detailLevel, posX, posZ); } /** @@ -716,7 +681,6 @@ public class LodDimension } stringBuilder.append("\n"); } - System.out.println(stringBuilder); return stringBuilder.toString(); } } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index af191362b..64e8a0cd4 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -1,14 +1,8 @@ package com.seibel.lod.objects; -import java.io.Serializable; -import java.util.concurrent.ConcurrentMap; - -import org.apache.commons.lang3.mutable.MutableBoolean; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.LevelPos.LevelPos; -import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodUtil; @@ -20,24 +14,19 @@ import com.seibel.lod.util.LodUtil; * 0 for x, 1 for y, 2 for z in 3D */ -public class LodRegion implements Serializable +public class LodRegion { //x coord, private byte minDetailLevel; private static final byte POSSIBLE_LOD = 10; - private int numberOfPoints; + //private int numberOfPoints; private DistanceGenerationMode generationMode; //For each of the following field the first slot is for the level of detail //Important: byte have a [-128, 127] range. When converting from or to int a 128 should be added or removed //If there is a bug with color then it's probably caused by this. //in the future other fields like transparency and light level could be added - private byte[][][][] colors; - private short[][][] height; - - private short[][][] depth; - - private boolean[][][] dataExistence; + private long[][][] data; public final int regionPosX; @@ -50,42 +39,18 @@ public class LodRegion implements Serializable this.regionPosZ = regionPos.z; this.minDetailLevel = levelContainer.detailLevel; - //Array of matrices of arrays - colors = new byte[POSSIBLE_LOD][][][]; - //Arrays of matrices - height = new short[POSSIBLE_LOD][][]; - depth = new short[POSSIBLE_LOD][][]; - dataExistence = new boolean[POSSIBLE_LOD][][]; + data = new long[POSSIBLE_LOD][][]; - colors[minDetailLevel] = levelContainer.colors; - height[minDetailLevel] = levelContainer.height; - depth[minDetailLevel] = levelContainer.depth; - dataExistence[minDetailLevel] = levelContainer.dataExistence; + data[minDetailLevel] = levelContainer.data; //Initialize all the different matrices for (byte lod = (byte) (minDetailLevel + 1); lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod); - colors[lod] = new byte[size][size][3]; - height[lod] = new short[size][size]; - depth[lod] = new short[size][size]; - dataExistence[lod] = new boolean[size][size]; - } - int width; - LevelPos levelPos = new LevelPos(); - for (byte tempLod = (byte) (minDetailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++) - { - width = 1 << (LodUtil.REGION_DETAIL_LEVEL - tempLod); - for (int x = 0; x < width; x++) - { - for (int z = 0; z < width; z++) - { - levelPos.changeParameters(tempLod, x, z); - update(levelPos); - } - } + data[lod] = new long[size][size]; } + updateArea(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ); } public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode) @@ -95,23 +60,14 @@ public class LodRegion implements Serializable this.regionPosX = regionPos.x; this.regionPosZ = regionPos.z; - //Array of matrices of arrays - colors = new byte[POSSIBLE_LOD][][][]; - - //Arrays of matrices - height = new short[POSSIBLE_LOD][][]; - depth = new short[POSSIBLE_LOD][][]; - dataExistence = new boolean[POSSIBLE_LOD][][]; + data = new long[POSSIBLE_LOD][][]; //Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod); - colors[lod] = new byte[size][size][3]; - height[lod] = new short[size][size]; - depth[lod] = new short[size][size]; - dataExistence[lod] = new boolean[size][size]; + data[lod] = new long[size][size]; } } @@ -119,26 +75,21 @@ public class LodRegion implements Serializable /** * This method can be used to insert data into the LodRegion * - * @param levelPos * @param dataPoint * @return */ - public boolean addData(LevelPos levelPos, short[] dataPoint, boolean serverQuality) + public boolean addData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality) { - levelPos.performRegionModule(); - if (!doesDataExist(levelPos) || serverQuality) + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + if (!doesDataExist(detailLevel, posX, posZ) || serverQuality) { //update the number of node present - if (this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ]) numberOfPoints++; + //if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++; //add the node data - this.height[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getHeight(dataPoint); - this.depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getDepth(dataPoint); - this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] = (byte) (DataPoint.getRed(dataPoint) - 128); - this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] = (byte) (DataPoint.getGreen(dataPoint) - 128); - this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] = (byte) (DataPoint.getBlue(dataPoint) - 128); - this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = true; + this.data[detailLevel][posX][posZ] = dataPoint; return true; } else { @@ -149,18 +100,13 @@ public class LodRegion implements Serializable /** * This method will return the data in the position relative to the level of detail * - * @param levelPos * @return the data at the relative pos and level */ - public short[] getData(LevelPos levelPos) + public long getData(byte detailLevel, int posX, int posZ) { - levelPos = levelPos.getRegionModuleLevelPos(); - return new short[]{height[levelPos.detailLevel][levelPos.posX][levelPos.posZ], - depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ], - (short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] + 128), - (short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] + 128), - (short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] + 128) - }; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return data[detailLevel][posX][posZ]; } /** @@ -168,25 +114,21 @@ public class LodRegion implements Serializable * * @return */ - public void getDataToGenerate(ConcurrentMap dataToGenerate, int playerPosX, int playerPosZ) + public void getDataToGenerate(PosToGenerateContainer posToGenerate, int playerPosX, int playerPosZ) { - LevelPos levelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, 0, 0); - getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ); + getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ); } - private void getDataToGenerate(ConcurrentMap dataToGenerate, LevelPos levelPos, int playerPosX, int playerPosZ) + private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) { - int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel); + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); //here i calculate the the LevelPos is in range //This is important to avoid any kind of hole in the generation - int minDistance = levelPos.minDistance(playerPosX, playerPosZ, regionPosX, regionPosZ); + //nt minDistance = LevelPosUtil.minDistance(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size, playerPosX, playerPosZ); + int maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); - - int posX = levelPos.posX; - int posZ = levelPos.posZ; - byte detailLevel = levelPos.detailLevel; byte childDetailLevel = (byte) (detailLevel - 1); int childPosX = posX * 2; int childPosZ = posZ * 2; @@ -194,21 +136,14 @@ public class LodRegion implements Serializable int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel); //we have reached the target detail level - if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) > detailLevel) + if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) > detailLevel) { return; - } else if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) == detailLevel) + } else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) == detailLevel) { - if (!doesDataExist(levelPos)) + if (!doesDataExist(detailLevel, posX, posZ)) { - levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - if (dataToGenerate.containsKey(levelPos)) - { - dataToGenerate.get(levelPos).setTrue(); - } else - { - dataToGenerate.put(levelPos.clone(), new MutableBoolean(true)); - } + posToGenerate.addPosToGenerate(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); } } else { @@ -221,19 +156,11 @@ public class LodRegion implements Serializable { for (int z = 0; z <= 1; z++) { - levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z); - if (!doesDataExist(levelPos)) + if (!doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) { num++; - levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize); - if (dataToGenerate.containsKey(levelPos)) - { - dataToGenerate.get(levelPos).setTrue(); - } else - { - dataToGenerate.put(levelPos.clone(), new MutableBoolean(true)); - } + posToGenerate.addPosToGenerate(childDetailLevel, childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize); } } } @@ -245,8 +172,7 @@ public class LodRegion implements Serializable { for (int z = 0; z <= 1; z++) { - levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z); - getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ); + getDataToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ); } } } @@ -255,21 +181,12 @@ public class LodRegion implements Serializable { if (DetailDistanceUtil.getLodGenDetail(childDetailLevel).detailLevel <= (childDetailLevel)) { - levelPos.changeParameters(detailLevel, posX, posZ); - levelPos.convert(childDetailLevel); - if (!doesDataExist(levelPos)) + if (!doesDataExist(childDetailLevel, childPosX, childPosZ)) { - levelPos.changeParameters(levelPos.detailLevel, levelPos.posX + regionPosX * childSize, levelPos.posZ + regionPosZ * childSize); - if (dataToGenerate.containsKey(levelPos)) - { - dataToGenerate.get(levelPos).setTrue(); - } else - { - dataToGenerate.put(levelPos.clone(), new MutableBoolean(true)); - } + posToGenerate.addPosToGenerate(childDetailLevel, childPosX + regionPosX * childSize, childPosZ + regionPosZ * childSize); } else { - getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ); + getDataToGenerate(posToGenerate, childDetailLevel, childPosX, childPosZ, playerPosX, playerPosZ); } } } @@ -280,60 +197,41 @@ public class LodRegion implements Serializable /** * @return */ - public void getDataToRender(ConcurrentMap dataToRender, int playerPosX, int playerPosZ) + public void getDataToRender(PosToRenderContainer posToRender, int playerPosX, int playerPosZ) { - LevelPos levelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, 0, 0); - getDataToRender(dataToRender, levelPos, playerPosX, playerPosZ); + getDataToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ); } /** * @return */ - private void getDataToRender(ConcurrentMap dataToRender, LevelPos levelPos, int playerPosX, int playerPosZ) + private void getDataToRender(PosToRenderContainer posToRender, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) { - int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel); - - int posX = levelPos.posX; - int posZ = levelPos.posZ; - byte detailLevel = levelPos.detailLevel; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); //here i calculate the the LevelPos is in range //This is important to avoid any kind of hole in the rendering - int maxDistance = levelPos.maxDistance(playerPosX, playerPosZ, regionPosX, regionPosZ); + int maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); byte supposedLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDistanceRenderingInverse(maxDistance)); if (supposedLevel > detailLevel) return; else if (supposedLevel == detailLevel) { - if (dataToRender.containsKey(levelPos)) - { - levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - try - { - dataToRender.get(levelPos).setTrue(); - }catch (Exception e){ - /*TODO Fix this exception*/ - // This seems to happen more often when using an elytra in an amplified world - // maybe it has something to do with the dimensions moving? - ClientProxy.LOGGER.error("getDataToRender had a error at " + levelPos.getRegionPos() + ". Exception: " + e.getMessage()); - dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true)); - } - } else - { - dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true)); - } + posToRender.addPosToRender(detailLevel, + posX + regionPosX * size, + posZ + regionPosZ * size); } else //case where (detailLevel > supposedLevel) { int childPosX = posX * 2; int childPosZ = posZ * 2; + byte childDetailLevel = (byte) (detailLevel - 1); int childrenCount = 0; for (int x = 0; x <= 1; x++) { for (int z = 0; z <= 1; z++) { - levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z); - if (doesDataExist(levelPos)) childrenCount++; + if (doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) childrenCount++; } } @@ -344,68 +242,50 @@ public class LodRegion implements Serializable { for (int z = 0; z <= 1; z++) { - levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z); - getDataToRender(dataToRender, levelPos, playerPosX, playerPosZ); + getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ); } } } else { - - levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - if (dataToRender.containsKey(levelPos)) - { - if (dataToRender.get(levelPos) == null) - dataToRender.replace(levelPos, new MutableBoolean()); - dataToRender.get(levelPos).setTrue(); - } else - { - dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true)); - } + posToRender.addPosToRender(detailLevel, + posX + regionPosX * size, + posZ + regionPosZ * size); } } } - /** - * @param levelPos */ - public void updateArea(LevelPos levelPos) + public void updateArea(byte detailLevel, int posX, int posZ) { int width; int startX; int startZ; - byte detailLevel = levelPos.detailLevel; - int posX = levelPos.posX; - int posZ = levelPos.posZ; for (byte bottom = (byte) (minDetailLevel + 1); bottom <= detailLevel; bottom++) { - levelPos.convert(bottom); - startX = levelPos.posX; - startZ = levelPos.posZ; + startX = LevelPosUtil.convert(detailLevel, posX, bottom); + startZ = LevelPosUtil.convert(detailLevel, posZ, bottom); width = 1 << (detailLevel - bottom); for (int x = 0; x < width; x++) { for (int z = 0; z < width; z++) { - levelPos.changeParameters(bottom, startX + x, startZ + z); - update(levelPos); + update(bottom, startX + x, startZ + z); } } - levelPos.changeParameters(detailLevel, posX, posZ); } - for (byte tempLod = (byte) (detailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++) + for (byte up = (byte) (detailLevel + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++) { - levelPos.convert(tempLod); - update(levelPos); + update(up, + LevelPosUtil.convert(detailLevel, posX, up), + LevelPosUtil.convert(detailLevel, posZ, up)); } } /** - * @param levelPos */ - private void update(LevelPos levelPos) + private void update(byte detailLevel, int posX, int posZ) { - levelPos.performRegionModule(); int numberOfChildren = 0; int numberOfVoidChildren = 0; @@ -414,32 +294,30 @@ public class LodRegion implements Serializable int tempBlue = 0; int tempHeight = 0; int tempDepth = 0; - int newPosX; - int newPosZ; - byte newDetailLevel; - int detailLevel = levelPos.detailLevel; - int posX = levelPos.posX; - int posZ = levelPos.posZ; + int childPosX; + int childPosZ; + byte childDetailLevel; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int x = 0; x <= 1; x++) { for (int z = 0; z <= 1; z++) { - newPosX = 2 * posX + x; - newPosZ = 2 * posZ + z; - newDetailLevel = (byte) (detailLevel - 1); - levelPos.changeParameters(newDetailLevel, newPosX, newPosZ); - if (doesDataExist(levelPos)) + childPosX = 2 * posX + x; + childPosZ = 2 * posZ + z; + childDetailLevel = (byte) (detailLevel - 1); + if (doesDataExist(childDetailLevel, childPosX, childPosZ)) { - if (height[newDetailLevel][newPosX][newPosZ] != LodBuilder.DEFAULT_HEIGHT - && depth[newDetailLevel][newPosX][newPosZ] != LodBuilder.DEFAULT_DEPTH) + if (DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) != LodBuilder.DEFAULT_HEIGHT + && DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) != LodBuilder.DEFAULT_DEPTH) { numberOfChildren++; - tempRed += colors[newDetailLevel][newPosX][newPosZ][0]; - tempGreen += colors[newDetailLevel][newPosX][newPosZ][1]; - tempBlue += colors[newDetailLevel][newPosX][newPosZ][2]; - tempHeight += height[newDetailLevel][newPosX][newPosZ]; - tempDepth += depth[newDetailLevel][newPosX][newPosZ]; + tempRed += DataPoint.getRed(data[childDetailLevel][childPosX][childPosZ]); + tempGreen += DataPoint.getGreen(data[childDetailLevel][childPosX][childPosZ]); + tempBlue += DataPoint.getBlue(data[childDetailLevel][childPosX][childPosZ]); + tempHeight += DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]); + tempDepth += DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]); } else { // void children have the default height (most likely -1) @@ -449,42 +327,34 @@ public class LodRegion implements Serializable } } } - if (numberOfChildren > 0) { - colors[detailLevel][posX][posZ][0] = (byte) (tempRed / numberOfChildren); - colors[detailLevel][posX][posZ][1] = (byte) (tempGreen / numberOfChildren); - colors[detailLevel][posX][posZ][2] = (byte) (tempBlue / numberOfChildren); - height[detailLevel][posX][posZ] = (short) (tempHeight / numberOfChildren); - depth[detailLevel][posX][posZ] = (short) (tempDepth / numberOfChildren); - dataExistence[detailLevel][posX][posZ] = true; + tempRed = tempRed / numberOfChildren; + tempGreen = tempGreen / numberOfChildren; + tempBlue = tempBlue / numberOfChildren; + tempHeight = tempHeight / numberOfChildren; + tempDepth = tempDepth / numberOfChildren; } else if (numberOfVoidChildren > 0) { - colors[detailLevel][posX][posZ][0] = (byte) 0; - colors[detailLevel][posX][posZ][1] = (byte) 0; - colors[detailLevel][posX][posZ][2] = (byte) 0; - - height[detailLevel][posX][posZ] = LodBuilder.DEFAULT_HEIGHT; - depth[detailLevel][posX][posZ] = LodBuilder.DEFAULT_DEPTH; - - dataExistence[detailLevel][posX][posZ] = true; + tempRed = (byte) 0; + tempGreen = (byte) 0; + tempBlue = (byte) 0; + tempHeight = LodBuilder.DEFAULT_HEIGHT; + tempDepth = LodBuilder.DEFAULT_DEPTH; } + data[detailLevel][posX][posZ] = DataPoint.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); } + /** - * @param levelPos * @return */ - public boolean doesDataExist(LevelPos levelPos) + public boolean doesDataExist(byte detailLevel, int posX, int posZ) { - try - { - levelPos = levelPos.getRegionModuleLevelPos(); - return dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ]; - } catch (NullPointerException e) - { - return false; - } + if(detailLevel < minDetailLevel) return false; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return DataPoint.doesItExist(data[detailLevel][posX][posZ]); } /** @@ -512,7 +382,7 @@ public class LodRegion implements Serializable { throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel); } - return new LevelContainer(detailLevel, colors[detailLevel], height[detailLevel], depth[detailLevel], dataExistence[detailLevel]); + return new LevelContainer(detailLevel, data[detailLevel]); } /** @@ -525,10 +395,7 @@ public class LodRegion implements Serializable throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 "); } if (levelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = levelContainer.detailLevel; - colors[levelContainer.detailLevel] = levelContainer.colors; - height[levelContainer.detailLevel] = levelContainer.height; - depth[levelContainer.detailLevel] = levelContainer.depth; - dataExistence[levelContainer.detailLevel] = levelContainer.dataExistence; + data[levelContainer.detailLevel] = levelContainer.data; } @@ -541,10 +408,7 @@ public class LodRegion implements Serializable { for (byte tempLod = 0; tempLod < detailLevel; tempLod++) { - colors[tempLod] = new byte[0][0][0]; - height[tempLod] = new short[0][0]; - depth[tempLod] = new short[0][0]; - dataExistence[tempLod] = new boolean[0][0]; + data[tempLod] = new long[0][0]; } minDetailLevel = detailLevel; } @@ -560,10 +424,7 @@ public class LodRegion implements Serializable for (byte tempLod = detailLevel; tempLod < minDetailLevel; tempLod++) { int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod); - colors[tempLod] = new byte[size][size][3]; - height[tempLod] = new short[size][size]; - depth[tempLod] = new short[size][size]; - dataExistence[tempLod] = new boolean[size][size]; + data[tempLod] = new long[size][size]; } minDetailLevel = detailLevel; } diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index f2d139166..00d5f50ae 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -1,7 +1,5 @@ package com.seibel.lod.objects; -import org.lwjgl.system.CallbackI; - public class PosToGenerateContainer { private int playerPosX; @@ -27,20 +25,10 @@ public class PosToGenerateContainer posToGenerate = new int[maxDataToGenerate][4]; } - public void addPosToGenerate(int[] levelPos) - { - addPosToGenerate(LevelPosUtil.getDetailLevel(levelPos), LevelPosUtil.getPosX(levelPos), LevelPosUtil.getPosZ(levelPos)); - } - public void addPosToGenerate(byte detailLevel, int posX, int posZ) { int distance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ); int index; - int[] tempPos = new int[]{ - detailLevel, - posX, - posZ, - distance}; if (detailLevel >= farMinDetail) {//We are introducing a position in the far array if (farSize < maxFarSize) @@ -53,26 +41,42 @@ public class PosToGenerateContainer maxNearSize--; } index = posToGenerate.length - farSize; - while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(tempPos, posToGenerate[index + 1]) <= 0) + while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(detailLevel, distance, (byte) posToGenerate[index + 1][0], posToGenerate[index + 1][3]) <= 0) { - posToGenerate[index] = posToGenerate[index + 1]; + posToGenerate[index][0] = posToGenerate[index + 1][0]; + posToGenerate[index][1] = posToGenerate[index + 1][1]; + posToGenerate[index][2] = posToGenerate[index + 1][2]; + posToGenerate[index][3] = posToGenerate[index + 1][3]; index++; } if (index <= posToGenerate.length - 1) - posToGenerate[index] = tempPos; + { + posToGenerate[index][0] = detailLevel + 1; + posToGenerate[index][1] = posX; + posToGenerate[index][2] = posZ; + posToGenerate[index][3] = distance; + } } else {//We are introducing a position in the near array if (nearSize < maxNearSize) nearSize++; index = nearSize - 1; - while (index > 0 && LevelPosUtil.compareDistance(tempPos, posToGenerate[index - 1]) <= 0) + while (index > 0 && LevelPosUtil.compareDistance(distance, posToGenerate[index - 1][3]) <= 0) { - posToGenerate[index] = posToGenerate[index - 1]; + posToGenerate[index][0] = posToGenerate[index - 1][0]; + posToGenerate[index][1] = posToGenerate[index - 1][1]; + posToGenerate[index][2] = posToGenerate[index - 1][2]; + posToGenerate[index][3] = posToGenerate[index - 1][3]; index--; } if (index >= 0) - posToGenerate[index] = tempPos; + { + posToGenerate[index][0] = detailLevel + 1; + posToGenerate[index][1] = posX; + posToGenerate[index][2] = posZ; + posToGenerate[index][3] = distance; + } } } @@ -84,6 +88,10 @@ public class PosToGenerateContainer public int[] getNthPos(int n) { + /*if(n < farSize) + return posToGenerate[maxSize - n - 1]; + else + return posToGenerate[n - farSize];*/ int index; if (n > farSize * 2) index = n - farSize; diff --git a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java index 7bf05c2b9..8e715fd6d 100644 --- a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java @@ -1,40 +1,75 @@ package com.seibel.lod.objects; import com.seibel.lod.util.LodUtil; - import java.util.Arrays; public class PosToRenderContainer { - private byte minDetail; + public byte minDetail; + private int regionPosX; + private int regionPosZ; private int numberOfPosToRender; private int[][] posToRender; /*TODO this population matrix could be converted to boolean to improve memory use*/ private byte[][] population; - public PosToRenderContainer(byte minDetail) + public PosToRenderContainer(byte minDetail, int regionPosX, int regionPosZ) { this.minDetail = minDetail; this.numberOfPosToRender = 0; - posToRender = new int[1][4]; + this.regionPosX = regionPosX; + this.regionPosZ = regionPosZ; int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); + posToRender = new int[size*size][3]; population = new byte[size][size]; } - public void addPosToRender(int[] levelPos) + public void addPosToRender(byte detailLevel, int posX, int posZ) { - if(numberOfPosToRender >= posToRender.length) - posToRender = Arrays.copyOf(posToRender, posToRender.length*2); - posToRender[numberOfPosToRender] = levelPos; + //if(numberOfPosToRender >= posToRender.length) + // posToRender = Arrays.copyOf(posToRender, posToRender.length*2); + posToRender[numberOfPosToRender][0] = detailLevel; + posToRender[numberOfPosToRender][1] = posX; + posToRender[numberOfPosToRender][2] = posZ; numberOfPosToRender++; - int[] newLevelPos = LevelPosUtil.getRegionModule(LevelPosUtil.convert(levelPos, minDetail)); - population[LevelPosUtil.getPosZ(newLevelPos)][LevelPosUtil.getPosZ(newLevelPos)] = (byte) (LevelPosUtil.getDetailLevel(levelPos) + 1); + population[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posX,minDetail))] + [LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posZ,minDetail))] = (byte) (detailLevel + 1); } - public boolean contains(int[] levelPos) + public boolean contains(byte detailLevel, int posX, int posZ) { - int[] newLevelPos = LevelPosUtil.convert(LevelPosUtil.getRegionModule(levelPos), minDetail); - return (population[LevelPosUtil.getPosZ(newLevelPos)][LevelPosUtil.getPosZ(newLevelPos)] == (LevelPosUtil.getDetailLevel(levelPos) + 1)); + if(LevelPosUtil.getRegion(detailLevel, posX) == regionPosX && LevelPosUtil.getRegion(detailLevel, posZ) == regionPosZ) + { + return (population[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posX,minDetail))] + [LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posZ,minDetail))] == (detailLevel + 1)); + }else + { + return false; + } + } + public void clear(byte minDetail, int regionPosX, int regionPosZ){ + this.numberOfPosToRender = 0; + this.regionPosX = regionPosX; + this.regionPosZ = regionPosZ; + if(this.minDetail == minDetail) + { + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); + for (int x = 0; x < size; x++) + { + for (int z = 0; z < size; z++) + { + posToRender[0][0] = 0; + posToRender[0][1] = 0; + posToRender[0][2] = 0; + population[x][z] = 0; + } + } + }else{ + this.minDetail = minDetail; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail); + posToRender = new int[size*size][3]; + population = new byte[size][size]; + } } public int getNumberOfPos() @@ -42,6 +77,19 @@ public class PosToRenderContainer return numberOfPosToRender; } + public byte getNthDetailLevel(int n) + { + return (byte) posToRender[n][0]; + } + public int getNthPosX(int n) + { + return posToRender[n][1]; + } + public int getNthPosZ(int n) + { + return posToRender[n][2]; + } + public int[] getNthPos(int n) { return posToRender[n]; @@ -51,6 +99,9 @@ public class PosToRenderContainer { StringBuilder builder = new StringBuilder(); + builder.append("To render "); + builder.append(numberOfPosToRender); + builder.append('\n'); for(int i = 0; i < numberOfPosToRender; i++) { builder.append(posToRender[i][0]); diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index a0e2c7e17..4e5f25015 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -41,7 +41,6 @@ import com.seibel.lod.handlers.ReflectionHandler; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.NearFarFogSettings; import com.seibel.lod.objects.RegionPos; -import com.seibel.lod.objects.LevelPos.LevelPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodUtil; @@ -127,7 +126,9 @@ public class LodRenderer /** * This is used to determine if the LODs should be regenerated */ - private LevelPos previousPos = new LevelPos((byte) 0, 0, 0); + private byte previousDetailLevel = 0; + private int previousChunkPosX = 0; + private int previousChunkPosZ = 0; private int prevRenderDistance = 0; private long prevPlayerPosTime = 0; private long prevVanillaChunkTime = 0; @@ -809,7 +810,8 @@ public class LodRenderer { DetailDistanceUtil.updateSettings(); fullRegen = true; - previousPos.changeParameters((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk); + previousChunkPosX = mc.getPlayer().xChunk; + previousChunkPosZ = mc.getPlayer().zChunk; prevFogDistance = LodConfig.CLIENT.graphics.fogDistance.get(); prevRenderDistance = mc.getRenderDistance(); //should use this when it's ready @@ -829,12 +831,12 @@ public class LodRenderer // check if the player has moved if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get()) { - if (previousPos.detailLevel == 0 - || mc.getPlayer().xChunk != previousPos.posX - || mc.getPlayer().zChunk != previousPos.posZ) + if (mc.getPlayer().xChunk != previousChunkPosX + || mc.getPlayer().zChunk != previousChunkPosZ) { fullRegen = true; - previousPos.changeParameters((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk); + previousChunkPosX = mc.getPlayer().xChunk; + previousChunkPosZ = mc.getPlayer().zChunk; //should use this when it's ready vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2]; } diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index 05d8476d0..027896f80 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -21,9 +21,9 @@ import java.awt.Color; import java.io.File; import java.util.HashSet; +import com.seibel.lod.objects.DataPoint; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.RegionPos; -import com.seibel.lod.objects.LevelPos.LevelPos; import com.seibel.lod.wrapper.MinecraftWrapper; import it.unimi.dsi.fastutil.objects.ObjectList; @@ -324,13 +324,13 @@ public class LodUtil { for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++) { - LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, x, z); - if (!lodDim.doesDataExist(levelPos.clone())) + if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) continue; - - short[] data = lodDim.getData(levelPos); - - short lodAverageHeight = data[0]; + + long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); + + short lodAverageHeight = DataPoint.getHeight(data); + if (playerPos.getY() <= lodAverageHeight) { // don't draw Lod's that are taller than the player From 94d994e761443302a0432a4239b44a444470f29f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 18:52:58 +0200 Subject: [PATCH 2/8] re-added the commit --- .../seibel/lod/builders/LodBufferBuilder.java | 17 +- .../lodTemplates/CubicLodTemplate.java | 17 +- .../lod/handlers/LodDimensionFileHandler.java | 2 +- .../com/seibel/lod/render/LodRenderer.java | 478 +++++++++--------- 4 files changed, 266 insertions(+), 248 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 676a3d275..4e78f3612 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -112,6 +112,8 @@ public class LodBufferBuilder private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0,0); private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0,0); + + public LodBufferBuilder() { @@ -146,8 +148,6 @@ public class LodBufferBuilder ChunkPos playerChunkPos = new ChunkPos(playerBlockPos); BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition(); - // this will be the center of the VBOs once they have been built - buildableCenterChunkPos = playerChunkPos; Thread thread = new Thread(() -> { @@ -180,7 +180,8 @@ public class LodBufferBuilder if (setsToRender.length != lodDim.regions.length) setsToRender = new Object[lodDim.regions.length][lodDim.regions.length]; - + // this will be the center of the VBOs once they have been built + buildableCenterChunkPos = playerChunkPos; for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++) { @@ -249,7 +250,6 @@ public class LodBufferBuilder // skip any chunks that Minecraft is going to render try { - boolean disableFix = false; if (lodDim.doesDataExist(detailLevel, posX, posZ)) { lodData = lodDim.getData(detailLevel, posX, posZ); @@ -263,20 +263,21 @@ public class LodBufferBuilder if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) { + if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] - && (posToRender.contains(detailLevel, xAdj, zAdj) || disableFix)) + && posToRender.contains(detailLevel, xAdj, zAdj)) { adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj); } } else { - if (posToRender.contains(detailLevel, xAdj, zAdj) || disableFix) + if (posToRender.contains(detailLevel, xAdj, zAdj)) { adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj); } } } - LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData, + LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, lodData, adjData, detailLevel, posX, posZ, renderer.previousDebugMode); } } catch (ArrayIndexOutOfBoundsException e) @@ -451,6 +452,8 @@ public class LodBufferBuilder } } + + /** * Get the newly created VBOs */ diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 147ea9982..234f6ba57 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -47,7 +47,7 @@ public class CubicLodTemplate extends AbstractLodTemplate } @Override - public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, long data, long[] adjData, + public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, byte detailLevel, int posX, int posZ,DebugMode debugging) { AxisAlignedBB bbox; @@ -60,7 +60,8 @@ public class CubicLodTemplate extends AbstractLodTemplate width, posX * width, 0, - posZ * width); + posZ * width, + bufferCenterBlockPos); int color = DataPoint.getColor(data); if (debugging != DebugMode.OFF) @@ -70,12 +71,12 @@ public class CubicLodTemplate extends AbstractLodTemplate if (bbox != null) { - addBoundingBoxToBuffer(buffer, bbox, color, playerBlockPos, adjData); + addBoundingBoxToBuffer(buffer, bbox, color, bufferCenterBlockPos, adjData); } } - private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset) + private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos) { // don't add an LOD if it is empty if (height == -1 && depth == -1) @@ -88,7 +89,13 @@ public class CubicLodTemplate extends AbstractLodTemplate height++; } - return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset); + // offset the AABB by it's x/z position in the world since + // it uses doubles to specify its location, unlike the model view matrix + // which only uses floats + double x = -bufferCenterBlockPos.getX(); + double z = -bufferCenterBlockPos.getZ(); + + return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset).move(x, 0, z); } private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, long[] adjData) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 8dfe98099..8a133fa2e 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -88,7 +88,7 @@ public class LodDimensionFileHandler * file handler, older versions (smaller numbers) will be deleted and overwritten, * newer versions (larger numbers) will be ignored and won't be read. */ - public static final int LOD_SAVE_FILE_VERSION = 4; + public static final int LOD_SAVE_FILE_VERSION = 5; /** * This is the string written before the file version diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 4e5f25015..98802c72e 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -23,6 +23,7 @@ import java.nio.FloatBuffer; import java.util.HashSet; import java.util.Iterator; +import com.seibel.lod.objects.LevelPosUtil; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.NVFogDistance; @@ -56,8 +57,8 @@ import net.minecraft.entity.Entity; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.profiler.IProfiler; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; @@ -69,7 +70,7 @@ import net.minecraft.util.math.vector.Vector3f; * This is where LODs are draw to the world. * * @author James Seibel - * @version 9-6-2021 + * @version 8-31-2021 */ public class LodRenderer { @@ -78,7 +79,7 @@ public class LodRenderer * it should be something different than what is used by Minecraft */ private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2; - + /** * 64 MB by default is the maximum amount of memory that * can be directly allocated.

@@ -91,80 +92,78 @@ public class LodRenderer * https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx */ public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024; - + /** * Does this computer's GPU support fancy fog? */ private static Boolean fancyFogAvailable = null; - - + + /** * If true the LODs colors will be replaced with * a checkerboard, this can be used for debugging. */ public DebugMode previousDebugMode = DebugMode.OFF; - + private MinecraftWrapper mc; private GameRenderer gameRender; private IProfiler profiler; private int farPlaneBlockDistance; private ReflectionHandler reflectionHandler; - - + + /** * This is used to generate the buildable buffers */ private LodBufferBuilder lodBufferBuilder; - + /** * Each VertexBuffer represents 1 region */ private VertexBuffer[][] vbos; public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR; private ChunkPos vbosCenter = new ChunkPos(0,0); - + /** * This is used to determine if the LODs should be regenerated */ - private byte previousDetailLevel = 0; - private int previousChunkPosX = 0; - private int previousChunkPosZ = 0; + private int[] previousPos = new int[]{0,0,0}; private int prevRenderDistance = 0; private long prevPlayerPosTime = 0; private long prevVanillaChunkTime = 0; private long prevChunkTime = 0; - - + + /** * This is used to determine if the LODs should be regenerated */ private FogDistance prevFogDistance = FogDistance.NEAR_AND_FAR; - + /** * if this is true the LOD buffers should be regenerated, * provided they aren't already being regenerated. */ private volatile boolean partialRegen = false; private volatile boolean fullRegen = true; - + /** * This HashSet contains every chunk that Vanilla Minecraft * is going to render */ public boolean[][] vanillaRenderedChunks; public boolean vanillaRenderedChunksChanged; - - + + public LodRenderer(LodBufferBuilder newLodNodeBufferBuilder) { mc = MinecraftWrapper.INSTANCE; gameRender = mc.getGameRenderer(); - + reflectionHandler = new ReflectionHandler(); lodBufferBuilder = newLodNodeBufferBuilder; } - - + + /** * Besides drawing the LODs this method also starts * the async process of generating the Buffers that hold those LODs. @@ -180,37 +179,37 @@ public class LodRenderer // don't try drawing anything return; } - - + + //===============// // initial setup // //===============// - + profiler = newProfiler; profiler.push("LOD setup"); - - + + // only check the GPU capability's once if (fancyFogAvailable == null) { // see if this GPU can run fancy fog fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance; - + if (!fancyFogAvailable) { ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available."); } } - - + + // TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead) // starting here... determineIfLodsShouldRegenerate(lodDim); - + //=================// // create the LODs // //=================// - + // only regenerate the LODs if: // 1. we want to regenerate LODs // 2. we aren't already regenerating the LODs @@ -220,78 +219,87 @@ public class LodRenderer { // generate the LODs on a separate thread to prevent stuttering or freezing lodBufferBuilder.generateLodBuffersAsync(this, lodDim, mc.getPlayer().blockPosition(), true); - + // the regen process has been started, // it will be done when lodBufferBuilder.newBuffersAvaliable() // is true fullRegen = false; partialRegen = false; } - + // TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead) // ...ending here - - - + + // replace the buffers used to draw and build, + // this is only done when the createLodBufferGenerationThread + // has finished executing on a parallel thread. + if (lodBufferBuilder.newBuffersAvaliable()) + { + swapBuffers(); + } + + + //===========================// // GL settings for rendering // //===========================// - + // set the required open GL settings - + if (LodConfig.CLIENT.debugging.debugMode.get() == DebugMode.SHOW_DETAIL_WIREFRAME) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); else GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); - + GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glEnable(GL11.GL_COLOR_MATERIAL); GL11.glEnable(GL11.GL_DEPTH_TEST); - + // disable the lights Minecraft uses GL11.glDisable(GL11.GL_LIGHT0); GL11.glDisable(GL11.GL_LIGHT1); - + // get the default projection matrix so we can // reset it after drawing the LODs float[] defaultProjMatrix = new float[16]; GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, defaultProjMatrix); - + Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks); - + // required for setupFog and setupProjectionMatrix farPlaneBlockDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH; - + setupProjectionMatrix(partialTicks); setupLighting(lodDim, partialTicks); - + NearFarFogSettings fogSettings = determineFogSettings(); - + // determine the current fog settings so they can be // reset after drawing the LODs float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START); float defaultFogEndDist = GL11.glGetFloat(GL11.GL_FOG_END); int defaultFogMode = GL11.glGetInteger(GL11.GL_FOG_MODE); int defaultFogDistance = GL11.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV); - - + + //===========// // rendering // //===========// profiler.popPush("LOD draw"); - + if (vbos != null) { Entity cameraEntity = mc.getCameraEntity(); Vector3d cameraDir = cameraEntity.getLookAngle().normalize(); cameraDir = mc.getOptions().getCameraType().isMirrored() ? cameraDir.reverse() : cameraDir; - - + + + // used to determine what type of fog to render int halfWidth = vbos.length / 2; int quarterWidth = vbos.length / 4; - + for (int i = 0; i < vbos.length; i++) { for (int j = 0; j < vbos.length; j++) @@ -303,21 +311,21 @@ public class LodRenderer setupFog(fogSettings.near.distance, fogSettings.near.quality); else setupFog(fogSettings.far.distance, fogSettings.far.quality); - - + + sendLodsToGpuAndDraw(vbos[i][j], modelViewMatrix); } } } } - - + + //=========// // cleanup // //=========// - + profiler.popPush("LOD cleanup"); - + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(LOD_GL_LIGHT_NUMBER); @@ -325,23 +333,23 @@ public class LodRenderer GL11.glEnable(GL11.GL_LIGHT0); GL11.glEnable(GL11.GL_LIGHT1); RenderSystem.disableLighting(); - + // reset the fog settings so the normal chunks // will be drawn correctly cleanupFog(fogSettings, defaultFogStartDist, defaultFogEndDist, defaultFogMode, defaultFogDistance); - + // reset the projection matrix so anything drawn after // the LODs will use the correct projection matrix Matrix4f mvm = new Matrix4f(defaultProjMatrix); mvm.transpose(); gameRender.resetProjectionMatrix(mvm); - + // clear the depth buffer so anything drawn is drawn // over the LODs GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); - - - + + + // replace the buffers used to draw and build, // this is only done when the createLodBufferGenerationThread // has finished executing on a parallel thread. @@ -351,13 +359,13 @@ public class LodRenderer // otherwise rubber banding may occur swapBuffers(); } - - + + // end of internal LOD profiling profiler.pop(); } - - + + /** * This is where the actual drawing happens. */ @@ -365,22 +373,22 @@ public class LodRenderer { if (vbo == null) return; - + vbo.bind(); // 0L is the starting pointer LOD_VERTEX_FORMAT.setupBufferState(0L); - + vbo.draw(modelViewMatrix, GL11.GL_QUADS); - + VertexBuffer.unbind(); LOD_VERTEX_FORMAT.clearBufferState(); } - - + + //=================// // Setup Functions // //=================// - + @SuppressWarnings("deprecation") private void setupFog(FogDistance fogDistance, FogQuality fogQuality) { @@ -390,12 +398,12 @@ public class LodRenderer RenderSystem.disableFog(); return; } - + if (fogDistance == FogDistance.NEAR_AND_FAR) { throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance."); } - + // determine the fog distance mode to use int glFogDistanceMode; if (fogQuality == FogQuality.FANCY) @@ -408,7 +416,7 @@ public class LodRenderer // fast fog (frustum distance based fog) glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV; } - + // the multipliers are percentages // of the regular view distance. if (fogDistance == FogDistance.FAR) @@ -417,7 +425,7 @@ public class LodRenderer // is because we are using fog backwards to how // it is normally used, with it hiding near objects // instead of far objects. - + if (fogQuality == FogQuality.FANCY) { // for more realistic fog when using FAR @@ -452,37 +460,37 @@ public class LodRenderer RenderSystem.fogStart(mc.getRenderDistance() * 16 * 1.5f); } } - + GL11.glEnable(GL11.GL_FOG); RenderSystem.enableFog(); RenderSystem.setupNvFogDistance(); RenderSystem.fogMode(GlStateManager.FogMode.LINEAR); GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, glFogDistanceMode); } - + /** * Revert any changes that were made to the fog. */ private void cleanupFog(NearFarFogSettings fogSettings, - float defaultFogStartDist, float defaultFogEndDist, - int defaultFogMode, int defaultFogDistance) + float defaultFogStartDist, float defaultFogEndDist, + int defaultFogMode, int defaultFogDistance) { RenderSystem.fogStart(defaultFogStartDist); RenderSystem.fogEnd(defaultFogEndDist); RenderSystem.fogMode(defaultFogMode); GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, defaultFogDistance); - + // disable fog if Minecraft wasn't rendering fog // but we were if (!fogSettings.vanillaIsRenderingFog && - (fogSettings.near.quality != FogQuality.OFF || - fogSettings.far.quality != FogQuality.OFF)) + (fogSettings.near.quality != FogQuality.OFF || + fogSettings.far.quality != FogQuality.OFF)) { GL11.glDisable(GL11.GL_FOG); } } - - + + /** * Create the model view matrix to move the LODs * from object space into world space. @@ -492,8 +500,8 @@ public class LodRenderer // get all relevant camera info ActiveRenderInfo renderInfo = mc.getGameRenderer().getMainCamera(); Vector3d projectedView = renderInfo.getPosition(); - - + + // generate the model view matrix MatrixStack matrixStack = new MatrixStack(); matrixStack.pushPose(); @@ -508,11 +516,11 @@ public class LodRenderer double xDiff = eyePos.x - bufferPos.getX(); double zDiff = eyePos.z - bufferPos.getZ(); matrixStack.translate(-xDiff, -projectedView.y, -zDiff); - + return matrixStack.last().pose(); } - - + + /** * create a new projection matrix and send it over to the GPU *

@@ -530,16 +538,16 @@ public class LodRenderer // Note: if the LOD objects don't distort correctly // compared to regular minecraft terrain, make sure // all the transformations in renderWorld are here too - + MatrixStack matrixStack = new MatrixStack(); matrixStack.pushPose(); - + gameRender.bobHurt(matrixStack, partialTicks); if (this.mc.getOptions().bobView) { gameRender.bobView(matrixStack, partialTicks); } - + // potion and nausea effects float f = MathHelper.lerp(partialTicks, this.mc.getPlayer().oPortalTime, this.mc.getPlayer().portalTime) * this.mc.getOptions().screenEffectScale * this.mc.getOptions().screenEffectScale; if (f > 0.0F) @@ -553,8 +561,8 @@ public class LodRenderer float f2 = -(gameRender.tick + partialTicks) * i; matrixStack.mulPose(vector3f.rotationDegrees(f2)); } - - + + // this projection matrix allows us to see past the normal // world render distance Matrix4f projectionMatrix = @@ -566,14 +574,14 @@ public class LodRenderer // terrain, so I don't think it is much of an issue. mc.getRenderDistance(), farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2); - + // add the screen space distortions projectionMatrix.multiply(matrixStack.last().pose()); gameRender.resetProjectionMatrix(projectionMatrix); return; } - - + + /** * setup the lighting to be used for the LODs */ @@ -594,27 +602,27 @@ public class LodRenderer } } } - - + + float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.getSkyDarken(partialTicks) : 0.2f; sunBrightness = playerHasNightVision ? 1.0f : sunBrightness; float gammaMultiplyer = (float) mc.getOptions().gamma - 0.5f; float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.3f); - + float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f}; - + // can be used for debugging // if (partialTicks < 0.005) // ClientProxy.LOGGER.debug(lightStrength); - + ByteBuffer temp = ByteBuffer.allocateDirect(16); temp.order(ByteOrder.nativeOrder()); GL11.glLightfv(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip()); GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting - + RenderSystem.enableLighting(); } - + /** * Create all buffers that will be used. */ @@ -622,24 +630,24 @@ public class LodRenderer { // calculate the max amount of memory needed (in bytes) int bufferMemory = RenderUtil.getBufferMemoryForRegion(); - + // if the required memory is greater than the // MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier // to fit. if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY) { ClientProxy.LOGGER.warn("setupBuffers tried to allocate too much memory for the BufferBuilders." - + " It tried to allocate \"" + bufferMemory + "\" bytes, when \"" + MAX_ALOCATEABLE_DIRECT_MEMORY + "\" is the max."); + + " It tried to allocate \"" + bufferMemory + "\" bytes, when \"" + MAX_ALOCATEABLE_DIRECT_MEMORY + "\" is the max."); } - + lodBufferBuilder.setupBuffers(numbRegionsWide, bufferMemory); } - - + + //======================// // Other Misc Functions // //======================// - + /** * If this is called then the next time "drawLODs" is called * the LODs will be regenerated; the same as if the player moved. @@ -648,12 +656,12 @@ public class LodRenderer { fullRegen = true; } - - + + /** * Replace the current Vertex Buffers with the newly * created buffers from the lodBufferBuilder.

- * + * * For some reason this has to be called after the frame has been rendered, * otherwise visual stuttering/rubber banding may happen. I'm not sure why... */ @@ -665,7 +673,7 @@ public class LodRenderer vbos = result.vbos; vbosCenter = result.drawableCenterChunkPos; } - + /** * Calls the BufferBuilder's destroyBuffers method. */ @@ -673,183 +681,183 @@ public class LodRenderer { lodBufferBuilder.destroyBuffers(); } - - + + private double getFov(float partialTicks, boolean useFovSetting) { return mc.getGameRenderer().getFov(mc.getGameRenderer().getMainCamera(), partialTicks, useFovSetting); } - - + + /** * Return what fog settings should be used when rendering. */ private NearFarFogSettings determineFogSettings() { NearFarFogSettings fogSettings = new NearFarFogSettings(); - - + + FogQuality quality = reflectionHandler.getFogQuality(); FogDrawOverride override = LodConfig.CLIENT.graphics.fogDrawOverride.get(); - - + + if (quality == FogQuality.OFF) fogSettings.vanillaIsRenderingFog = false; else fogSettings.vanillaIsRenderingFog = true; - - + + // use any fog overrides the user may have set switch (override) { - case ALWAYS_DRAW_FOG_FANCY: - quality = FogQuality.FANCY; - break; - - case NEVER_DRAW_FOG: - quality = FogQuality.OFF; - break; - - case ALWAYS_DRAW_FOG_FAST: - quality = FogQuality.FAST; - break; - - case USE_OPTIFINE_FOG_SETTING: - // don't override anything - break; + case ALWAYS_DRAW_FOG_FANCY: + quality = FogQuality.FANCY; + break; + + case NEVER_DRAW_FOG: + quality = FogQuality.OFF; + break; + + case ALWAYS_DRAW_FOG_FAST: + quality = FogQuality.FAST; + break; + + case USE_OPTIFINE_FOG_SETTING: + // don't override anything + break; } - - + + // only use fancy fog if the user's GPU can deliver if (!fancyFogAvailable && quality == FogQuality.FANCY) { quality = FogQuality.FAST; } - - + + // how different distances are drawn depends on the quality set switch (quality) { - case FANCY: - fogSettings.near.quality = FogQuality.FANCY; - fogSettings.far.quality = FogQuality.FANCY; - - switch (LodConfig.CLIENT.graphics.fogDistance.get()) - { - case NEAR_AND_FAR: - fogSettings.near.distance = FogDistance.NEAR; - fogSettings.far.distance = FogDistance.FAR; + case FANCY: + fogSettings.near.quality = FogQuality.FANCY; + fogSettings.far.quality = FogQuality.FANCY; + + switch (LodConfig.CLIENT.graphics.fogDistance.get()) + { + case NEAR_AND_FAR: + fogSettings.near.distance = FogDistance.NEAR; + fogSettings.far.distance = FogDistance.FAR; + break; + + case NEAR: + fogSettings.near.distance = FogDistance.NEAR; + fogSettings.far.distance = FogDistance.NEAR; + break; + + case FAR: + fogSettings.near.distance = FogDistance.FAR; + fogSettings.far.distance = FogDistance.FAR; + break; + } break; - - case NEAR: - fogSettings.near.distance = FogDistance.NEAR; - fogSettings.far.distance = FogDistance.NEAR; + + case FAST: + fogSettings.near.quality = FogQuality.FAST; + fogSettings.far.quality = FogQuality.FAST; + + // fast fog setting should only have one type of + // fog, since the LODs are separated into a near + // and far portion; and fast fog is rendered from the + // frustrum's perspective instead of the camera + switch (LodConfig.CLIENT.graphics.fogDistance.get()) + { + case NEAR_AND_FAR: + fogSettings.near.distance = FogDistance.NEAR; + fogSettings.far.distance = FogDistance.NEAR; + break; + + case NEAR: + fogSettings.near.distance = FogDistance.NEAR; + fogSettings.far.distance = FogDistance.NEAR; + break; + + case FAR: + fogSettings.near.distance = FogDistance.FAR; + fogSettings.far.distance = FogDistance.FAR; + break; + } break; - - case FAR: - fogSettings.near.distance = FogDistance.FAR; - fogSettings.far.distance = FogDistance.FAR; + + case OFF: + + fogSettings.near.quality = FogQuality.OFF; + fogSettings.far.quality = FogQuality.OFF; break; - } - break; - - case FAST: - fogSettings.near.quality = FogQuality.FAST; - fogSettings.far.quality = FogQuality.FAST; - - // fast fog setting should only have one type of - // fog, since the LODs are separated into a near - // and far portion; and fast fog is rendered from the - // frustrum's perspective instead of the camera - switch (LodConfig.CLIENT.graphics.fogDistance.get()) - { - case NEAR_AND_FAR: - fogSettings.near.distance = FogDistance.NEAR; - fogSettings.far.distance = FogDistance.NEAR; - break; - - case NEAR: - fogSettings.near.distance = FogDistance.NEAR; - fogSettings.far.distance = FogDistance.NEAR; - break; - - case FAR: - fogSettings.near.distance = FogDistance.FAR; - fogSettings.far.distance = FogDistance.FAR; - break; - } - break; - - case OFF: - - fogSettings.near.quality = FogQuality.OFF; - fogSettings.far.quality = FogQuality.OFF; - break; - + } - - + + return fogSettings; } - - + + /** * Determines if the LODs should have a fullRegen or partialRegen */ + @SuppressWarnings("unchecked") private void determineIfLodsShouldRegenerate(LodDimension lodDim) { - + fullRegen = true; short renderDistance = (short) mc.getRenderDistance(); //=============// // full regens // //=============// // check if the view distance changed if (ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() - || mc.getRenderDistance() != prevRenderDistance - || prevFogDistance != LodConfig.CLIENT.graphics.fogDistance.get()) + || mc.getRenderDistance() != prevRenderDistance + || prevFogDistance != LodConfig.CLIENT.graphics.fogDistance.get()) { DetailDistanceUtil.updateSettings(); fullRegen = true; - previousChunkPosX = mc.getPlayer().xChunk; - previousChunkPosZ = mc.getPlayer().zChunk; + previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk); prevFogDistance = LodConfig.CLIENT.graphics.fogDistance.get(); prevRenderDistance = mc.getRenderDistance(); //should use this when it's ready vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2]; } - + // did the user change the debug setting? if (LodConfig.CLIENT.debugging.debugMode.get() != previousDebugMode) { previousDebugMode = LodConfig.CLIENT.debugging.debugMode.get(); fullRegen = true; } - - +Bug + long newTime = System.currentTimeMillis(); - + // check if the player has moved if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get()) { - if (mc.getPlayer().xChunk != previousChunkPosX - || mc.getPlayer().zChunk != previousChunkPosZ) + if (LevelPosUtil.getDetailLevel(previousPos) == 0 + || mc.getPlayer().xChunk != LevelPosUtil.getPosX(previousPos) + || mc.getPlayer().zChunk != LevelPosUtil.getPosZ(previousPos)) { fullRegen = true; - previousChunkPosX = mc.getPlayer().xChunk; - previousChunkPosZ = mc.getPlayer().zChunk; + previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk); //should use this when it's ready vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2]; } prevPlayerPosTime = newTime; } - - - + + + //================// // partial regens // //================// - - + + // check if the vanilla rendered chunks changed if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.get()) { @@ -857,12 +865,12 @@ public class LodRenderer { partialRegen = true; vanillaRenderedChunksChanged = false; - + } prevVanillaChunkTime = newTime; } - - + + // check if there is any newly generated terrain to show if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.get()) { @@ -873,14 +881,14 @@ public class LodRenderer } prevChunkTime = newTime; } - - - - + + + + //==============// // LOD skipping // //==============// - + // determine which LODs should not be rendered close to the player HashSet chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, mc.getPlayer().blockPosition()); int chunkX; @@ -902,8 +910,8 @@ public class LodRenderer e.printStackTrace(); } } - - + + // if the player is high enough, draw all LODs if(chunkPosToSkip.isEmpty() && mc.getPlayer().position().y > 256) { @@ -911,5 +919,5 @@ public class LodRenderer vanillaRenderedChunksChanged = true; } } - -} \ No newline at end of file + +} From b096cc53aa6840c8179c5a7b767a67749d31541d Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 19:02:51 +0200 Subject: [PATCH 3/8] Working version --- src/main/java/com/seibel/lod/render/LodRenderer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 98802c72e..f78bd3030 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -807,7 +807,6 @@ public class LodRenderer @SuppressWarnings("unchecked") private void determineIfLodsShouldRegenerate(LodDimension lodDim) { - fullRegen = true; short renderDistance = (short) mc.getRenderDistance(); //=============// // full regens // @@ -832,7 +831,7 @@ public class LodRenderer previousDebugMode = LodConfig.CLIENT.debugging.debugMode.get(); fullRegen = true; } -Bug + long newTime = System.currentTimeMillis(); From aa5a8aa3b836ceb7a11f45be47a24a2df0e04a26 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 19:05:58 +0200 Subject: [PATCH 4/8] small change --- .../java/com/seibel/lod/util/DetailDistanceUtil.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index e9c0cfcc2..79fbeff37 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -19,7 +19,7 @@ public class DetailDistanceUtil private static int base = 2; private static double logBase = Math.log(2); - private static LodDetail[] lodDetails = { + private static LodDetail[] lodGenDetails = { LodDetail.FULL, LodDetail.HALF, LodDetail.QUAD, @@ -33,6 +33,7 @@ public class DetailDistanceUtil LodDetail.SINGLE}; + public static void updateSettings(){ minGenDetail = LodConfig.CLIENT.worldGenerator.maxGenerationDetail.get().detailLevel; minDrawDetail = Math.max(LodConfig.CLIENT.graphics.maxDrawDetail.get().detailLevel,LodConfig.CLIENT.worldGenerator.maxGenerationDetail.get().detailLevel); @@ -153,10 +154,10 @@ public class DetailDistanceUtil { if (detail < minGenDetail) { - return lodDetails[minGenDetail]; + return lodGenDetails[minGenDetail]; } else { - return lodDetails[detail]; + return lodGenDetails[detail]; } } @@ -165,13 +166,13 @@ public class DetailDistanceUtil { if (detail < minGenDetail) { - return lodDetails[minGenDetail].detailLevel; + return lodGenDetails[minGenDetail].detailLevel; } else if (detail == maxDetail) { return LodUtil.REGION_DETAIL_LEVEL; } else { - return lodDetails[detail].detailLevel; + return lodGenDetails[detail].detailLevel; } } From 849d5634250112daa61b5afad427db66aaccf3e1 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 20:07:39 +0200 Subject: [PATCH 5/8] Added box to replace AxisAlignedBB --- .../seibel/lod/builders/lodTemplates/Box.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/com/seibel/lod/builders/lodTemplates/Box.java diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java b/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java new file mode 100644 index 000000000..267e7dcec --- /dev/null +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java @@ -0,0 +1,64 @@ +package com.seibel.lod.builders.lodTemplates; + +public class Box +{ + public static final int DOWN = 0; + public static final int UP = 1; + public static final int EAST = 2; + public static final int WEST = 3; + public static final int SOUTH = 4; + public static final int NORTH = 5; + + public static final int OFFSET = 0; + public static final int WIDTH = 1; + + public static final int X = 0; + public static final int Y = 1; + public static final int Z = 2; + + public int[][] box; + + public Box(){ + box = new int[2][3]; + } + + public void set(int xWidth, int yWidth, int zWidth){ + box[OFFSET][X] = 0; + box[OFFSET][Y] = 0; + box[OFFSET][Z] = 0; + + box[WIDTH][X] = xWidth; + box[WIDTH][Y] = yWidth; + box[WIDTH][Z] = zWidth; + } + + public void move(int xOffset, int yOffset, int zOffset){ + box[NORTH][X] = xOffset; + box[NORTH][Y] = yOffset; + box[NORTH][Z] = zOffset; + } + + public int getMinX(){ + return box[OFFSET][X]; + } + + public int getMaxX(){ + return box[OFFSET][X] + box[WIDTH][X]; + } + + public int getMinY(){ + return box[OFFSET][Y]; + } + + public int getMaxY(){ + return box[OFFSET][Y] + box[WIDTH][Y]; + } + + public int getMinZ(){ + return box[OFFSET][Z]; + } + + public int getMaxZ(){ + return box[OFFSET][Z] + box[WIDTH][Z]; + } +} From 1e15d372c43b15c060d1baac1c38fccd4a679a62 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 21:22:12 +0200 Subject: [PATCH 6/8] Added box caching --- .../seibel/lod/builders/LodBufferBuilder.java | 21 +- .../lodTemplates/AbstractLodTemplate.java | 2 +- .../seibel/lod/builders/lodTemplates/Box.java | 6 +- .../lodTemplates/CubicLodTemplate.java | 250 +++++++++++------- .../lodTemplates/DynamicLodTemplate.java | 2 +- .../lodTemplates/TriangularLodTemplate.java | 2 +- 6 files changed, 172 insertions(+), 111 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 4e78f3612..f21345001 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -25,6 +25,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import com.seibel.lod.builders.lodTemplates.Box; import com.seibel.lod.objects.*; import org.lwjgl.opengl.GL11; @@ -104,7 +105,8 @@ public class LodBufferBuilder //in order -x, +x, -z, +z private static final int[][] ADJ_DIRECTION = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; - private volatile Object[][] setsToRender; + private volatile Box[][] boxCache; + private volatile PosToRenderContainer[][] setsToRender; private volatile RegionPos center; /** This is the ChunkPos the player was at the last time the buffers were built. @@ -175,10 +177,16 @@ public class LodBufferBuilder center = playerRegionPos; if (setsToRender == null) - setsToRender = new Object[lodDim.regions.length][lodDim.regions.length]; + setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length]; if (setsToRender.length != lodDim.regions.length) - setsToRender = new Object[lodDim.regions.length][lodDim.regions.length]; + setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length]; + + if (boxCache == null) + boxCache = new Box[lodDim.regions.length][lodDim.regions.length]; + + if (boxCache.length != lodDim.regions.length) + boxCache = new Box[lodDim.regions.length][lodDim.regions.length]; // this will be the center of the VBOs once they have been built buildableCenterChunkPos = playerChunkPos; @@ -213,6 +221,11 @@ public class LodBufferBuilder { setsToRender[xR][zR] = new PosToRenderContainer(minDetail, regionPos.x, regionPos.z); } + + if (boxCache[xR][zR] == null) + { + boxCache[xR][zR] = new Box(); + } PosToRenderContainer posToRender = (PosToRenderContainer) setsToRender[xR][zR]; posToRender.clear(minDetail, regionPos.x, regionPos.z); @@ -278,7 +291,7 @@ public class LodBufferBuilder } } LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, lodData, adjData, - detailLevel, posX, posZ, renderer.previousDebugMode); + detailLevel, posX, posZ, boxCache[xR][zR],renderer.previousDebugMode); } } catch (ArrayIndexOutOfBoundsException e) { diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index 7d9ca9d42..b44d75756 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -32,7 +32,7 @@ import net.minecraft.util.math.BlockPos; public abstract class AbstractLodTemplate { public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, - byte detailLevel, int posX, int posZ,DebugMode debugging); + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging); /** * add the given position and color to the buffer diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java b/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java index 267e7dcec..500e6bd16 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/Box.java @@ -33,9 +33,9 @@ public class Box } public void move(int xOffset, int yOffset, int zOffset){ - box[NORTH][X] = xOffset; - box[NORTH][Y] = yOffset; - box[NORTH][Z] = zOffset; + box[OFFSET][X] = xOffset; + box[OFFSET][Y] = yOffset; + box[OFFSET][Z] = zOffset; } public int getMinX(){ diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 234f6ba57..d23316599 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -21,14 +21,12 @@ import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.enums.ShadingMode; import com.seibel.lod.objects.DataPoint; -import com.seibel.lod.objects.LevelPosUtil; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.LodUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.Direction; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; /** @@ -48,13 +46,13 @@ public class CubicLodTemplate extends AbstractLodTemplate @Override public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, - byte detailLevel, int posX, int posZ,DebugMode debugging) + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging) { - AxisAlignedBB bbox; int width = 1 << detailLevel; // add each LOD for the detail level - bbox = generateBoundingBox( + generateBoundingBox( + box, DataPoint.getHeight(data), DataPoint.getDepth(data), width, @@ -69,18 +67,18 @@ public class CubicLodTemplate extends AbstractLodTemplate color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); } - if (bbox != null) + if (box != null) { - addBoundingBoxToBuffer(buffer, bbox, color, bufferCenterBlockPos, adjData); + addBoundingBoxToBuffer(buffer, box, color, bufferCenterBlockPos, adjData); } } - private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos) + private void generateBoundingBox(Box box, int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos) { // don't add an LOD if it is empty if (height == -1 && depth == -1) - return null; + return; if (depth == height) { @@ -93,12 +91,12 @@ public class CubicLodTemplate extends AbstractLodTemplate // it uses doubles to specify its location, unlike the model view matrix // which only uses floats double x = -bufferCenterBlockPos.getX(); - double z = -bufferCenterBlockPos.getZ(); - - return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset).move(x, 0, z); + double z = -bufferCenterBlockPos.getZ();; + box.set(width, height - depth, width); + box.move((int) (xOffset + x), (int) (yOffset + depth), (int) (zOffset + z)); } - private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, long[] adjData) + private void addBoundingBoxToBuffer(BufferBuilder buffer, Box box, int c, BlockPos playerBlockPos, long[] adjData) { int topColor = c; int bottomColor = c; @@ -136,9 +134,15 @@ public class CubicLodTemplate extends AbstractLodTemplate westColor = ColorUtil.applySaturationAndBrightnessMultipliers(westColor, saturationMultiplier, brightnessMultiplier); eastColor = ColorUtil.applySaturationAndBrightnessMultipliers(eastColor, saturationMultiplier, brightnessMultiplier); } + int minX; + int maxX; int minY; int maxY; + int minZ; + int maxZ; long data; + int tempMinY; + int tempMaxY; int red; int green; @@ -146,32 +150,44 @@ public class CubicLodTemplate extends AbstractLodTemplate int alpha; boolean disableCulling = true; /**TODO make all of this more automatic if possible*/ - if (playerBlockPos.getY() > bb.maxY - CULL_OFFSET || disableCulling) + if (playerBlockPos.getY() > box.getMaxY() - CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(topColor); green = ColorUtil.getGreen(topColor); blue = ColorUtil.getBlue(topColor); alpha = ColorUtil.getAlpha(topColor); // top (facing up) - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); } - if (playerBlockPos.getY() < bb.minY + CULL_OFFSET || disableCulling) + if (playerBlockPos.getY() < box.getMinY() + CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(bottomColor); green = ColorUtil.getGreen(bottomColor); blue = ColorUtil.getBlue(bottomColor); alpha = ColorUtil.getAlpha(bottomColor); // bottom (facing down) - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); } - if (playerBlockPos.getX() < bb.maxX + CULL_OFFSET || disableCulling) + if (playerBlockPos.getX() < box.getMaxX() + CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(westColor); green = ColorUtil.getGreen(westColor); @@ -179,37 +195,45 @@ public class CubicLodTemplate extends AbstractLodTemplate alpha = ColorUtil.getAlpha(westColor); // west (facing -X) data = adjData[0]; + + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); if (data == 0) { - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - } - else + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); + }else { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) + maxY = box.getMaxY(); + tempMaxY = DataPoint.getHeight(data); + if (tempMaxY < maxY) { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); + minY = Math.max(tempMaxY, minY); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) + tempMinY = DataPoint.getDepth(data); + minY = box.getMinY(); + if (tempMinY > minY) { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha); + maxY = Math.min(tempMinY, maxX); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); } } } - if (playerBlockPos.getX() > bb.minX - CULL_OFFSET || disableCulling) + if (playerBlockPos.getX() > box.getMinX() - CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(eastColor); green = ColorUtil.getGreen(eastColor); @@ -217,108 +241,132 @@ public class CubicLodTemplate extends AbstractLodTemplate alpha = ColorUtil.getAlpha(eastColor); // east (facing +X) data = adjData[1]; + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); if (data == 0) { - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } else { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) + maxY = box.getMaxY(); + tempMaxY = DataPoint.getHeight(data); + if (tempMaxY < maxY) { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha); + minY = Math.max(tempMaxY, minY); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) + tempMinY = DataPoint.getDepth(data); + minY = box.getMinY(); + if (tempMinY > minY) { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + maxY = Math.min(tempMinY, maxX); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } } } - if (playerBlockPos.getZ() > bb.minZ - CULL_OFFSET || disableCulling) + if (playerBlockPos.getZ() > box.getMinZ() - CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(northColor); green = ColorUtil.getGreen(northColor); blue = ColorUtil.getBlue(northColor); alpha = ColorUtil.getAlpha(northColor); data = adjData[3]; + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); // north (facing +Z) if (data == 0) { - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); } else { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) + maxY = box.getMaxY(); + tempMaxY = DataPoint.getHeight(data); + if (tempMaxY < maxY) { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha); + minY = Math.max(tempMaxY, minY); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) + tempMinY = DataPoint.getDepth(data); + minY = box.getMinY(); + if (tempMinY > minY) { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha); + maxY = Math.min(tempMinY, maxX); + addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); } } } - if (playerBlockPos.getZ() < bb.maxZ + CULL_OFFSET || disableCulling) + if (playerBlockPos.getZ() < box.getMaxZ() + CULL_OFFSET || disableCulling) { red = ColorUtil.getRed(southColor); green = ColorUtil.getGreen(southColor); blue = ColorUtil.getBlue(southColor); alpha = ColorUtil.getAlpha(southColor); data = adjData[2]; + minX = box.getMinX(); + maxX = box.getMaxX(); + minY = box.getMinY(); + maxY = box.getMaxY(); + minZ = box.getMinZ(); + maxZ = box.getMaxZ(); // south (facing -Z) if (data == 0) { - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } else { - maxY = DataPoint.getHeight(data); - if (maxY < bb.maxY) + maxY = box.getMaxY(); + tempMaxY = DataPoint.getHeight(data); + if (tempMaxY < maxY) { - minY = (int) Math.max(maxY, bb.minY); - addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha); + minY = Math.max(tempMaxY, minY); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } - minY = DataPoint.getDepth(data); - if (minY > bb.minY) + tempMinY = DataPoint.getDepth(data); + minY = box.getMinY(); + if (tempMinY > minY) { - maxY = (int) Math.min(minY, bb.maxY); - addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha); - addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha); + maxY = Math.min(tempMinY, maxX); + addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); + addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } } } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java index d5de6f7db..690b1b158 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java @@ -35,7 +35,7 @@ public class DynamicLodTemplate extends AbstractLodTemplate { @Override public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, - byte detailLevel, int posX, int posZ,DebugMode debugging) + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging) { System.err.println("DynamicLodTemplate not implemented!"); } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java index f8158c7da..5ef595bab 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java @@ -33,7 +33,7 @@ public class TriangularLodTemplate extends AbstractLodTemplate { @Override public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, - byte detailLevel, int posX, int posZ,DebugMode debugging) + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging) { System.err.println("DynamicLodTemplate not implemented!"); } From bd9e2acaf6e4df6e734656bb4712a4bd0fc81544 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 8 Sep 2021 00:23:44 +0200 Subject: [PATCH 7/8] Changed the default heigth and depth and small fix to the culling --- .../com/seibel/lod/builders/LodBufferBuilder.java | 11 ++++++----- src/main/java/com/seibel/lod/builders/LodBuilder.java | 4 ++-- src/main/java/com/seibel/lod/objects/LodRegion.java | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index f21345001..561760984 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -243,7 +243,7 @@ public class LodBufferBuilder int chunkXdist; int chunkZdist; short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1); - long lodData; + long dataPoint; long[] adjData; for (int index = 0; index < posToRender.getNumberOfPos(); index++) { @@ -265,18 +265,19 @@ public class LodBufferBuilder { if (lodDim.doesDataExist(detailLevel, posX, posZ)) { - lodData = lodDim.getData(detailLevel, posX, posZ); + dataPoint = lodDim.getData(detailLevel, posX, posZ); + if(DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH) + continue; adjData = new long[NUMBER_OF_DIRECTION]; for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) { xAdj = posX + ADJ_DIRECTION[direction][0]; zAdj = posZ + ADJ_DIRECTION[direction][1]; chunkXdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.x; - chunkZdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.z; + chunkZdist = LevelPosUtil.getChunkPos(detailLevel,zAdj) - playerChunkPos.z; if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) { - if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] && posToRender.contains(detailLevel, xAdj, zAdj)) { @@ -290,7 +291,7 @@ public class LodBufferBuilder } } } - LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, lodData, adjData, + LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData, detailLevel, posX, posZ, boxCache[xR][zR],renderer.previousDebugMode); } } catch (ArrayIndexOutOfBoundsException e) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 15f703113..b4c924c5d 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -67,11 +67,11 @@ public class LodBuilder /** * If no blocks are found in the area in determineBottomPointForArea return this */ - public static final short DEFAULT_DEPTH = -1; + public static final short DEFAULT_DEPTH = 0; /** * If no blocks are found in the area in determineHeightPointForArea return this */ - public static final short DEFAULT_HEIGHT = -1; + public static final short DEFAULT_HEIGHT = 0; /** * How wide LodDimensions should be in regions diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 64e8a0cd4..c0d4fbb18 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -308,8 +308,8 @@ public class LodRegion childDetailLevel = (byte) (detailLevel - 1); if (doesDataExist(childDetailLevel, childPosX, childPosZ)) { - if (DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) != LodBuilder.DEFAULT_HEIGHT - && DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) != LodBuilder.DEFAULT_DEPTH) + if (!(DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT + && DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) { numberOfChildren++; From e897c3edbaa487521a0173f073e3318f5a9bf54c Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 8 Sep 2021 00:51:39 +0200 Subject: [PATCH 8/8] fixed generation --- src/main/java/com/seibel/lod/objects/LevelPosUtil.java | 4 +++- .../java/com/seibel/lod/objects/PosToGenerateContainer.java | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java b/src/main/java/com/seibel/lod/objects/LevelPosUtil.java index fb7c10cef..fe30f5c40 100644 --- a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java +++ b/src/main/java/com/seibel/lod/objects/LevelPosUtil.java @@ -234,11 +234,13 @@ public class LevelPosUtil int compareResult = Integer.compare( secondDetail, firstDetail); + System.out.println("comparing level "+ firstDetail + " " + secondDetail + " " + compareResult); if (compareResult == 0) { - compareResult = Integer.compare( + compareResult = compareDistance( firstDistance, secondDistance); + System.out.println("Equal level "+ firstDistance + " " + secondDistance + " " + compareResult); } return compareResult; } diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index 00d5f50ae..405ee2b77 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -41,7 +41,7 @@ public class PosToGenerateContainer maxNearSize--; } index = posToGenerate.length - farSize; - while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(detailLevel, distance, (byte) posToGenerate[index + 1][0], posToGenerate[index + 1][3]) <= 0) + while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(detailLevel, distance, (byte) (posToGenerate[index + 1][0] - 1), posToGenerate[index + 1][3]) <= 0) { posToGenerate[index][0] = posToGenerate[index + 1][0]; posToGenerate[index][1] = posToGenerate[index + 1][1]; @@ -119,7 +119,7 @@ public class PosToGenerateContainer builder.append('\n'); for (int i = 0; i < nearSize; i++) { - builder.append(posToGenerate[i][0]); + builder.append(posToGenerate[i][0]-1); builder.append(" "); builder.append(posToGenerate[i][1]); builder.append(" "); @@ -133,7 +133,7 @@ public class PosToGenerateContainer builder.append('\n'); for (int i = maxSize - 1; i >= maxSize - farSize; i--) { - builder.append(posToGenerate[i][0]); + builder.append(posToGenerate[i][0]-1); builder.append(" "); builder.append(posToGenerate[i][1]); builder.append(" ");