From f76fa17e25a29253a48a1af59c29ebef57a8dee9 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 7 Sep 2021 17:23:22 +0200 Subject: [PATCH] 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