From ebe2c22a28552fbf060601c95a27bf7ee105951b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sun, 19 Sep 2021 20:48:07 +0200 Subject: [PATCH] Changed how the VerticalLevelContainer contains the data --- .../seibel/lod/builders/LodBufferBuilder.java | 65 +++++++------- .../com/seibel/lod/builders/LodBuilder.java | 39 +++++---- .../seibel/lod/objects/LevelContainer.java | 11 ++- .../com/seibel/lod/objects/LodDimension.java | 53 ++++++++--- .../com/seibel/lod/objects/LodRegion.java | 27 +++--- .../lod/objects/SingleLevelContainer.java | 87 +++++++++++-------- .../lod/objects/VerticalLevelContainer.java | 76 ++++++++++------ .../com/seibel/lod/util/DataPointUtil.java | 27 +++--- .../com/seibel/lod/util/ThreadMapUtil.java | 6 +- 9 files changed, 243 insertions(+), 148 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 6f595a3f1..f94cc3981 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -28,6 +28,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import com.seibel.lod.util.*; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL15C; @@ -43,10 +44,6 @@ import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.proxy.GlProxy; import com.seibel.lod.proxy.GlProxy.GlProxyContext; import com.seibel.lod.render.LodRenderer; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.vertex.VertexBuffer; @@ -224,13 +221,18 @@ public class LodBufferBuilder Callable dataToRenderThread = () -> { Map adjData = new HashMap<>(); + int maxVerticalData; if (LodConfig.CLIENT.worldGenerator.lodQualityMode.get() == LodQualityMode.HEIGHTMAP) { - adjData.put(Direction.WEST, new long[1]); - adjData.put(Direction.EAST, new long[1]); - adjData.put(Direction.SOUTH, new long[1]); - adjData.put(Direction.NORTH, new long[1]); + maxVerticalData = 1; + }else{ + maxVerticalData = DetailDistanceUtil.getMaxVerticalData(0); } + + adjData.put(Direction.WEST, new long[maxVerticalData]); + adjData.put(Direction.EAST, new long[maxVerticalData]); + adjData.put(Direction.SOUTH, new long[maxVerticalData]); + adjData.put(Direction.NORTH, new long[maxVerticalData]); //previous setToRender chache if (setsToRender[xR][zR] == null) { @@ -257,12 +259,12 @@ public class LodBufferBuilder int zAdj; int chunkXdist; int chunkZdist; - + // keep a local version so we don't have to worry about indexOutOfBounds Exceptions // if it changes in the LodRenderer while we are working here - boolean[][] vanillaRenderedChunks = renderer.vanillaRenderedChunks; + boolean[][] vanillaRenderedChunks = renderer.vanillaRenderedChunks; short gameChunkRenderDistance = (short) (vanillaRenderedChunks.length / 2 - 1); - + for (int index = 0; index < posToRender.getNumberOfPos(); index++) { detailLevel = posToRender.getNthDetailLevel(index); @@ -283,6 +285,7 @@ public class LodBufferBuilder { for (Direction direction : Box.ADJ_DIRECTIONS) { + xAdj = posX + direction.getNormal().getX(); zAdj = posZ + direction.getNormal().getZ(); chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.x; @@ -297,7 +300,8 @@ public class LodBufferBuilder adjData.get(direction)[0] = lodDim.getSingleData(detailLevel, xAdj, zAdj); } else { - adjData.put(direction, lodDim.getData(detailLevel, xAdj, zAdj)); + for(int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++) + adjData.get(direction)[verticalIndex] = lodDim.getData(detailLevel, xAdj, zAdj,verticalIndex); } } else @@ -319,7 +323,8 @@ public class LodBufferBuilder adjData.get(direction)[0] = lodDim.getSingleData(detailLevel, xAdj, zAdj); } else { - adjData.put(direction, lodDim.getData(detailLevel, xAdj, zAdj)); + for(int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++) + adjData.get(direction)[verticalIndex] = lodDim.getData(detailLevel, xAdj, zAdj,verticalIndex); } } else { @@ -346,13 +351,13 @@ public class LodBufferBuilder } else if (region.getLodQualityMode() == LodQualityMode.MULTI_LOD) { - for (long dataPoint : lodDim.getData(detailLevel, posX, posZ)) + int verticalIndex = 0; + long data = lodDim.getData(detailLevel, posX, posZ, verticalIndex); + while(!(DataPointUtil.isItVoid(data) || DataPointUtil.doesItExist(data))) { - if (!DataPointUtil.isItVoid(dataPoint) && DataPointUtil.doesItExist(dataPoint)) - { - LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData, - detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode, renderer.lightMap); - } + LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, data, adjData, + detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode, renderer.lightMap); + verticalIndex++; } } @@ -512,14 +517,14 @@ public class LodBufferBuilder private void uploadBuffers(boolean fullRegen, LodDimension lodDim) { GlProxy glProxy = GlProxy.getInstance(); - + try { // make sure we are uploading to a different OpenGL context, // to prevent interference (IE stuttering) with the Minecraft context. glProxy.setGlContext(GlProxyContext.LOD_BUILDER); - - + + for (int x = 0; x < buildableVbos.length; x++) { for (int z = 0; z < buildableVbos.length; z++) @@ -532,25 +537,23 @@ public class LodBufferBuilder } } } - - + + // make sure all the buffers have been uploaded. // this probably is necessary, but it makes me feel good :) GL11.glFlush(); - } - catch (IllegalStateException e) + } catch (IllegalStateException e) { ClientProxy.LOGGER.error(LodBufferBuilder.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage()); e.printStackTrace(); - } - finally + } finally { // make sure no buffer is bound if (glProxy.getGlContext() == GlProxyContext.LOD_BUILDER) { GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } - + // make sure the context is disabled glProxy.setGlContext(GlProxyContext.NONE); } @@ -579,8 +582,8 @@ public class LodBufferBuilder // is faster for transferring data. They must put the data in different memory // or something. GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer); - - + + GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } } diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 26f97eddd..7fdf912b1 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -239,17 +239,22 @@ public class LodBuilder isServer); break; case MULTI_LOD: - long[][] dataToMergeVertical; + long[] dataToMergeVertical; dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - data = DataPointUtil.mergeMultiData(dataToMergeVertical); + data = DataPointUtil.mergeMultiData(dataToMergeVertical, detailLevel); if (data.length == 0 || data == null) data = new long[]{DataPointUtil.EMPTY_DATA}; - lodDim.addData(detailLevel, - posX, - posZ, - data, - false, - isServer); + lodDim.clear(detailLevel, posX, posZ); + for(int verticalIndex = 0; (verticalIndex < data.length) && (verticalIndex < lodDim.getMaxVerticalData(detailLevel,posX,posZ)); verticalIndex++) + { + lodDim.addData(detailLevel, + posX, + posZ, + verticalIndex, + data[verticalIndex], + false, + isServer); + } break; } @@ -263,11 +268,12 @@ public class LodBuilder } - private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) + private long[] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) { - long[][] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel]; - ChunkPos chunkPos = chunk.getPos(); + long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel]; + int verticalData = DataPointUtil.WORLD_HEIGHT; + ChunkPos chunkPos = chunk.getPos(); int size = 1 << detail.detailLevel; int height = 0; int depth = 0; @@ -286,17 +292,18 @@ public class LodBuilder BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); int index = 0; + if (dataToMerge == null) { - dataToMerge = new long[size * size][DataPointUtil.WORLD_HEIGHT]; + dataToMerge = new long[size * size * DataPointUtil.WORLD_HEIGHT]; } //dataToMerge = new long[size * size][1024]; for (index = 0; index < size * size; index++) { - for (int i = 0; i < dataToMerge[index].length; i++) + for (int verticalIndex = 0; verticalIndex < verticalData; verticalIndex++) { - dataToMerge[index][i] = 0; + dataToMerge[index * verticalData + verticalIndex] = DataPointUtil.EMPTY_DATA; } xRel = Math.floorMod(index, size) + startX; zRel = Math.floorDiv(index, size) + startZ; @@ -314,7 +321,7 @@ public class LodBuilder //If the lod is at default, then we set this as void data if (height == DEFAULT_HEIGHT) { - dataToMerge[index][0] = DataPointUtil.createVoidDataPoint(generation); + dataToMerge[index*verticalData + 0] = DataPointUtil.createVoidDataPoint(generation); break; } @@ -344,7 +351,7 @@ public class LodBuilder topBlock = false; - dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, lightSky, lightBlock, generation); + dataToMerge[index * verticalData + count] = DataPointUtil.createDataPoint(height, depth, color, lightSky, lightBlock, generation); yAbs = depth - 1; count++; } diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index b03a293e7..a60bef3d2 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -4,14 +4,16 @@ public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; public static final char DATA_DELIMITER = ' '; + /**With this you can add data to the level container * * @param data actual data to add in a array of long format. * @param posX x position in the detail level * @param posZ z position in the detail level + * @param index z position in the detail level * @return true if correctly added, false otherwise */ - public boolean addData(long[] data, int posX, int posZ); + public boolean addData(long data, int posX, int posZ, int index); /**With this you can add data to the level container * @@ -28,7 +30,7 @@ public interface LevelContainer * @param posZ z position in the detail level * @return the data in long array format */ - public long[] getData(int posX, int posZ); + public long getData(int posX, int posZ, int index); /**With this you can get data from the level container * @@ -50,6 +52,11 @@ public interface LevelContainer */ public byte getDetailLevel(); + + public int getMaxVerticalData(); + + public void clear(int posX, int posZ); + /**This return a level container with detail level lower than the current level. * The new level container may use information of this level. * @return the new level container diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index c8d4353dc..da96d4f95 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -444,23 +444,23 @@ public class LodDimension cutAndGenThreads.execute(thread); } } - + /** * Add the given LOD to this dimension at the coordinate * stored in the LOD. If an LOD already exists at the given * coordinates it will be overwritten. */ - public Boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean dontSave, boolean serverQuality) + public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean dontSave, boolean serverQuality) { - + // don't continue if the region can't be saved int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); - + LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataPoint, serverQuality); + boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data, serverQuality); // only save valid LODs to disk if (!dontSave && fileHandler != null) { @@ -565,7 +565,22 @@ public class LodDimension if (region != null) region.getDataToRender(posToRender, playerPosX, playerPosZ); } - + + public int getMaxVerticalData(byte detailLevel, int posX, int posZ) + { + 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(detailLevel, posX, posZ); + + if (region == null) + { + return 0; + } + + return region.getMaxVerticalData(detailLevel); + } + /** * Get the data point at the given X and Z coordinates * in this dimension. @@ -573,7 +588,7 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public long[] getData(byte detailLevel, int posX, int posZ) + public long getData(byte detailLevel, int posX, int posZ, int verticalIndex) { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); @@ -582,12 +597,13 @@ public class LodDimension if (region == null) { - return new long[]{DataPointUtil.EMPTY_DATA}; + return DataPointUtil.EMPTY_DATA; } - return region.getData(detailLevel, posX, posZ); + return region.getData(detailLevel, posX, posZ, verticalIndex); } - + + /** * Get the data point at the given X and Z coordinates * in this dimension. @@ -609,7 +625,21 @@ public class LodDimension return region.getSingleData(detailLevel, posX, posZ); } - + + public void clear(byte detailLevel, int posX, int posZ) + { + 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(detailLevel, posX, posZ); + + if (region == null) + { + return; + } + + region.clear(detailLevel, posX, posZ); + } public boolean getRegenByArrayIndex(int xIndex, int zIndex) { @@ -761,4 +791,5 @@ public class LodDimension } 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 ddadfb905..08dde130b 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -79,13 +79,17 @@ public class LodRegion return generationMode; } + public int getMaxVerticalData(byte detailLevel) + { + return dataContainer[detailLevel].getMaxVerticalData(); + } + /** * This method can be used to insert data into the LodRegion * - * @param dataPoint * @return if the data was added successfully */ - public boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean serverQuality) + public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean serverQuality) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); @@ -97,12 +101,12 @@ public class LodRegion try { //add the node data - this.dataContainer[detailLevel].addData(dataPoint, posX, posZ); + this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); return true; } catch (NullPointerException e) { - String detailMessage = "pos: [" + posX + "," + posZ + "] dataPoint: [" + dataPoint + "] serverQuality: [" + serverQuality + "] dataContainer"; + String detailMessage = "pos: [" + posX + "," + posZ + "] dataPoint: [" + data + "] serverQuality: [" + serverQuality + "] dataContainer"; detailMessage += this.dataContainer != null ? ": [NULL]" : " at detailLevel: [" + dataContainer[detailLevel] + "]"; ClientProxy.LOGGER.error("addSingleData: " + e.getMessage() + "\t" + detailMessage); @@ -156,11 +160,9 @@ public class LodRegion * * @return the data at the relative pos and level */ - public long[] getData(byte detailLevel, int posX, int posZ) + public long getData(byte detailLevel, int posX, int posZ, int verticalIndex) { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return dataContainer[detailLevel].getData(posX, posZ); + return dataContainer[detailLevel].getData(posX, posZ,verticalIndex); } /** @@ -170,12 +172,13 @@ public class LodRegion */ public long getSingleData(byte detailLevel, int posX, int posZ) { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); return dataContainer[detailLevel].getSingleData(posX, posZ); } - + public void clear(byte detailLevel, int posX, int posZ) + { + dataContainer[detailLevel].clear(posX, posZ); + } /** * This method will return all the levelPos that are renderable according to the requisite given in input * @@ -378,7 +381,7 @@ public class LodRegion if(dataContainer[detailLevel].doesItExist(posX,posZ)) { //We take the bottom information always - return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getData(posX,posZ)[0]); + return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX,posZ)); }else { return DistanceGenerationMode.NONE.complexity; diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index 9fc1a2390..b76ac228d 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -1,6 +1,8 @@ package com.seibel.lod.objects; import com.seibel.lod.util.*; + +import javax.xml.crypto.Data; import java.util.Arrays; public class SingleLevelContainer implements LevelContainer @@ -8,51 +10,61 @@ public class SingleLevelContainer implements LevelContainer public final byte detailLevel; public final int size; - public final long[][] data; + public final long[][] dataContainer; public SingleLevelContainer(byte detailLevel) { this.detailLevel = detailLevel; size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - data = new long[size][size]; + dataContainer = new long[size][size]; } - public boolean addData(long[] newData, int posX, int posZ){ - + public void clear(int posX, int posZ) + { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - data[posX][posZ] = newData[0]; + dataContainer[posX][posZ] = DataPointUtil.EMPTY_DATA; + } + + public boolean addData(long data, int posX, int posZ, int index) + { + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + dataContainer[posX][posZ] = data; return true; } - public boolean addSingleData(long newData, int posX, int posZ){ + public boolean addSingleData(long newData, int posX, int posZ) + { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - data[posX][posZ] = newData; + dataContainer[posX][posZ] = newData; return true; } - public long[] getData(int posX, int posZ){ - long[] dataArray = ThreadMapUtil.getSingleGetDataArray(); + public long getData(int posX, int posZ, int index) + { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] - dataArray[0] = data[posX][posZ]; - return dataArray; + return dataContainer[posX][posZ]; } - public long getSingleData(int posX, int posZ){ + public long getSingleData(int posX, int posZ) + { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] - return data[posX][posZ]; + return dataContainer[posX][posZ]; } - public byte getDetailLevel(){ + public byte getDetailLevel() + { return detailLevel; } - public LevelContainer expand(){ + public LevelContainer expand() + { return new SingleLevelContainer((byte) (getDetailLevel() - 1)); } @@ -64,22 +76,23 @@ public class SingleLevelContainer implements LevelContainer detailLevel = inputData[index]; index++; size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.data = new long[size][size]; + this.dataContainer = new long[size][size]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { newData = 0; - if(inputData[index] == 0) + if (inputData[index] == 0) index++; - else if(index + 7 >= inputData.length) - break; - else { - for (tempIndex = 0; tempIndex < 8; tempIndex++) - newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex); - index = index + 8; - } - data[x][z] = newData; + else if (index + 7 >= inputData.length) + break; + else + { + for (tempIndex = 0; tempIndex < 8; tempIndex++) + newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex); + index = index + 8; + } + dataContainer[x][z] = newData; } } @@ -101,15 +114,19 @@ public class SingleLevelContainer implements LevelContainer { childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; - dataToMerge[2*x + z] = ((SingleLevelContainer) lowerLevelContainer).getSingleData(childPosX, childPosZ); + dataToMerge[2 * x + z] = ((SingleLevelContainer) lowerLevelContainer).getSingleData(childPosX, childPosZ); } } data = DataPointUtil.mergeSingleData(dataToMerge); - addSingleData(data,posX,posZ); + addSingleData(data, posX, posZ); } + public int getMaxVerticalData(){ + return 1; + } - public boolean doesItExist(int posX, int posZ){ + public boolean doesItExist(int posX, int posZ) + { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] @@ -127,14 +144,16 @@ public class SingleLevelContainer implements LevelContainer { for (int z = 0; z < size; z++) { - if(data[x][z] == 0){ + if (dataContainer[x][z] == 0) + { tempData[index] = 0; index++; - } else { - for (tempIndex = 0; tempIndex < 8; tempIndex++) - tempData[index + tempIndex] = (byte) (data[x][z] >>> (8 * tempIndex)); - index += 8; - } + } else + { + for (tempIndex = 0; tempIndex < 8; tempIndex++) + tempData[index + tempIndex] = (byte) (dataContainer[x][z] >>> (8 * tempIndex)); + index += 8; + } } } return Arrays.copyOfRange(tempData, 0, index); diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 6e88cd484..3bfda7c5e 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -1,9 +1,6 @@ package com.seibel.lod.objects; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodUtil; -import com.seibel.lod.util.ThreadMapUtil; +import com.seibel.lod.util.*; import java.security.InvalidParameterException; @@ -11,14 +8,17 @@ public class VerticalLevelContainer implements LevelContainer { public final byte detailLevel; + public final int size; + public final int maxVerticalData; - public final long[][][] dataContainer; + public final long[] dataContainer; public VerticalLevelContainer(byte detailLevel) { this.detailLevel = detailLevel; - int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - dataContainer = new long[size][size][1]; + size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); + maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel); + dataContainer = new long[size * size * DetailDistanceUtil.getMaxVerticalData(detailLevel)]; } @Override @@ -27,38 +27,49 @@ public class VerticalLevelContainer implements LevelContainer return detailLevel; } - public boolean addData(long[] newData, int posX, int posZ){ + public void clear(int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX][posZ] = newData; + int index = 0; + for(int i = 0; i < maxVerticalData; i++){ + index = posX*size*maxVerticalData + posZ*maxVerticalData + i; + dataContainer[index] = DataPointUtil.EMPTY_DATA; + } + } + + public boolean addData(long data, int posX, int posZ, int verticalIndex){ + + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + dataContainer[posX*size*maxVerticalData + posZ*maxVerticalData + verticalIndex] = data; return true; } - public boolean addSingleData(long newData, int posX, int posZ){ - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX][posZ][0] = newData; - return true; + public boolean addSingleData(long data, int posX, int posZ){ + return addData(data, posX, posZ, 0); } - public long[] getData(int posX, int posZ){ + public long getData(int posX, int posZ, int verticalIndex){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return dataContainer[posX][posZ]; + return dataContainer[posX*size*maxVerticalData + posZ*maxVerticalData + verticalIndex]; } public long getSingleData(int posX, int posZ){ - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - //Improve this using a thread map to long[] - return dataContainer[posX][posZ][0]; + return getData(posX,posZ,0); + } + + public int getMaxVerticalData(){ + return maxVerticalData; + } + + public int getSize(){ + return size; } public boolean doesItExist(int posX, int posZ){ - long[] data = getData(posX,posZ); - if(data == null) - return false; - return DataPointUtil.doesItExist(data[0]); + return DataPointUtil.doesItExist(getSingleData(posX,posZ)); } public VerticalLevelContainer(String inputString) @@ -94,7 +105,8 @@ public class VerticalLevelContainer implements LevelContainer public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { //We reset the array - long[][] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(); + //long[] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(); + long[] dataToMerge = new long[4*maxVerticalData]; int childPosX; int childPosZ; @@ -107,11 +119,19 @@ public class VerticalLevelContainer implements LevelContainer { childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; - dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ); + for(int y = 0; y < maxVerticalData; y++) + dataToMerge[(z*2+x)*maxVerticalData + y] = lowerLevelContainer.getData(childPosX, childPosZ, y); } } - data = DataPointUtil.mergeMultiData(dataToMerge); - addData(data,posX,posZ); + data = DataPointUtil.mergeMultiData(dataToMerge, lowerLevelContainer.getDetailLevel()); + + for(int verticalIndex = 0; (verticalIndex < data.length) && (verticalIndex < maxVerticalData); verticalIndex++) + { + addData(data[verticalIndex], + posX, + posZ, + verticalIndex); + } } public byte[] toDataString() diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 09826b5a8..3b27ddbf1 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -4,6 +4,9 @@ import com.seibel.lod.enums.DistanceGenerationMode; import net.minecraft.client.renderer.texture.NativeImage; +import java.lang.reflect.Array; +import java.util.Arrays; + public class DataPointUtil { /* @@ -276,11 +279,13 @@ public class DataPointUtil } } - public static long[] mergeMultiData(long[][] dataToMerge) + public static long[] mergeMultiData(long[] dataToMerge, byte detailLevel) { + int verticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel); + int size = dataToMerge.length/verticalData; short[] projection = ThreadMapUtil.getProjectionShort((WORLD_HEIGHT + 1) / 16); short[][] heightAndDepth = ThreadMapUtil.getHeightAndDepth((WORLD_HEIGHT / 2) + 1); - long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(dataToMerge.length); + long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(size); int genMode = DistanceGenerationMode.SERVER.complexity; boolean allEmpty = true; boolean allVoid = true; @@ -292,11 +297,11 @@ public class DataPointUtil short depth = 0; short height = 0; //We collect the indexes of the data, ordered by the depth - for (int index = 0; index < dataToMerge.length; index++) + for (int index = 0; index < size; index++) { - for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) + for (int verticalIndex = 0; verticalIndex < verticalData; verticalIndex++) { - singleData = dataToMerge[index][dataIndex]; + singleData = dataToMerge[index * verticalData + verticalIndex]; if (doesItExist(singleData)) { genMode = Math.min(genMode, getGenerationMode(singleData)); @@ -362,14 +367,14 @@ public class DataPointUtil { depth = heightAndDepth[j][0]; height = heightAndDepth[j][1]; - for(int k = 0; k < dataToMerge.length; k++){ + for(int k = 0; k < size; k++){ singleDataToMerge[k] = 0; } - for (int index = 0; index < dataToMerge.length; index++) + for (int index = 0; index < size; index++) { - for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) + for (int verticalIndex = 0; verticalIndex < verticalData; verticalIndex++) { - singleData = dataToMerge[index][dataIndex]; + singleData = dataToMerge[index * verticalData + verticalIndex]; if (doesItExist(singleData) && !isItVoid(singleData)) { if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) @@ -386,8 +391,8 @@ public class DataPointUtil long data = mergeSingleData(singleDataToMerge); dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data)); } - - return dataPoint; + verticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel+1); + return Arrays.copyOf(dataPoint, verticalData); } public static long[] compress(long[] data, byte detailLevel) diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index d5219b749..d94c5527e 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -11,7 +11,7 @@ public class ThreadMapUtil public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap<>(); public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap<>(); public static final ConcurrentMap threadBuilderArrayMap = new ConcurrentHashMap<>(); - public static final ConcurrentMap threadBuilderVerticalArrayMap = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadBuilderVerticalArrayMap = new ConcurrentHashMap<>(); public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap<>(); public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap<>(); public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap<>(); @@ -62,11 +62,11 @@ public class ThreadMapUtil return threadBuilderArrayMap.get(Thread.currentThread().getName()); } - public static long[][][] getBuilderVerticalArray() + public static long[][] getBuilderVerticalArray() { if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null)) { - long[][][] array = new long[5][][]; + long[][] array = new long[5][]; threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array); } return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName());