From 031539bd31bef8d6d10b70cc555ba1577e187044 Mon Sep 17 00:00:00 2001 From: TomTheFurry Date: Sun, 1 May 2022 14:19:51 +0800 Subject: [PATCH] Added dataView system so no longer need to copy arrays around --- .../bufferBuilding/CubicLodTemplate.java | 5 +- .../seibel/lod/core/objects/LodDataView.java | 51 ++++++++++++++++ .../lod/core/objects/lod/LevelContainer.java | 23 ++++--- .../lod/core/objects/lod/LodRegion.java | 7 +++ .../objects/lod/VerticalLevelContainer.java | 60 ++++++++++++++++--- .../lod/core/objects/opengl/LodBox.java | 31 +++++----- .../lod/core/objects/opengl/RenderRegion.java | 30 +++++----- 7 files changed, 154 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/seibel/lod/core/objects/LodDataView.java diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/CubicLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/CubicLodTemplate.java index 99f50e0dd..8c68b69b6 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/CubicLodTemplate.java @@ -21,6 +21,7 @@ package com.seibel.lod.core.builders.lodBuilding.bufferBuilding; import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.objects.LodDataView; import com.seibel.lod.core.objects.opengl.LodBox; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.util.DataPointUtil; @@ -37,8 +38,8 @@ public class CubicLodTemplate { private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class); - public static void addLodToBuffer(long data, long topData, long botData, long[][][] adjData, - boolean[] adjFillBlack, byte detailLevel,int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) + public static void addLodToBuffer(long data, long topData, long botData, LodDataView[][] adjData, + boolean[] adjFillBlack, byte detailLevel, int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) { short width = (short) (1 << detailLevel); short x = (short) LevelPosUtil.convert(detailLevel, offsetPosX, LodUtil.BLOCK_DETAIL_LEVEL); diff --git a/src/main/java/com/seibel/lod/core/objects/LodDataView.java b/src/main/java/com/seibel/lod/core/objects/LodDataView.java new file mode 100644 index 000000000..e671143b9 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/objects/LodDataView.java @@ -0,0 +1,51 @@ +package com.seibel.lod.core.objects; + +import com.seibel.lod.core.util.DataPointUtil; + +public final class LodDataView { + private final long[] data; + private final int size; + private final int offset; + public LodDataView(long[] data, int size, int offset) { + this.data = data; + this.size = size; + this.offset = offset; + } + public long get(int index) { + return data[index + offset]; + } + public void set(int index, long value) { + data[index + offset] = value; + } + public int size() { + return size; + } + public void copyTo(long[] target, int offset) { + System.arraycopy(data, this.offset, target, offset, size); + } + public void copyTo(LodDataView target) { + System.arraycopy(data, this.offset, target.data, target.offset, size); + } + + public boolean mergeWith(LodDataView source, int verticalSize, boolean override) { + if (size != source.size) { + throw new IllegalArgumentException("Cannot merge views of different sizes"); + } + boolean anyChange = false; + for (int o=0; o<(source.size()*verticalSize); o+=verticalSize) { + if (override) { + if (DataPointUtil.compareDatapointPriority(source.get(o), get(o)) >= 0) { + anyChange = true; + System.arraycopy(source.data, source.offset+o, data, offset+o, verticalSize); + } + } else { + if (DataPointUtil.compareDatapointPriority(source.get(o), get(o)) > 0) { + anyChange = true; + System.arraycopy(source.data, source.offset+o, data, offset+o, verticalSize); + } + } + } + return anyChange; + + } +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java b/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java index e88b1985f..21c8bc1fd 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java @@ -19,6 +19,8 @@ package com.seibel.lod.core.objects.lod; +import com.seibel.lod.core.objects.LodDataView; + import java.io.DataOutputStream; import java.io.IOException; @@ -32,11 +34,11 @@ public interface LevelContainer * @param data actual data to add in an 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 + * @param index vertical position in the detail level * @return true if correctly added, false otherwise */ boolean addData(long data, int posX, int posZ, int index); - + /** * With this you can add data to the level container * @param data actual data to add in an array of long[] format. @@ -44,23 +46,18 @@ public interface LevelContainer * @param posZ z position in the detail level * @return true if correctly changed, false otherwise */ + @Deprecated boolean addVerticalData(long[] data, int posX, int posZ, boolean override); + boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override); /** * With this you can add a square of data to the level container * @return true if anything changed, false otherwise */ + @Deprecated boolean addChunkOfData(long[] data, int posX, int posZ, int widthX, int widthZ, boolean override); - - /** - * With this you can add data to the level container - * @param data actual data to add in an array of long format. - * @param posX x position in the detail level - * @param posZ z position in the detail level - * @return true if correctly added, false otherwise - */ - boolean addSingleData(long data, int posX, int posZ); - + boolean copyChunkOfData(LodDataView data, int posX, int posZ, int widthX, int widthZ, boolean override); + /** * With this you can get data from the level container * @param posX x position in the detail level @@ -75,7 +72,9 @@ public interface LevelContainer * @param posZ z position in the detail level * @return the data in long array format */ + @Deprecated long[] getAllData(int posX, int posZ); + LodDataView getVerticalDataView(int posX, int posZ); /** * With this you can get data from the level container diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java index d49181de4..c01b35f4d 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java @@ -28,6 +28,7 @@ import com.seibel.lod.core.enums.config.DropoffQuality; import com.seibel.lod.core.enums.config.GenerationPriority; import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.objects.LodDataView; import com.seibel.lod.core.objects.PosToGenerateContainer; import com.seibel.lod.core.objects.PosToRenderContainer; import com.seibel.lod.core.util.DataPointUtil; @@ -205,11 +206,17 @@ public class LodRegion { * @return the data at the relative pos and detail level, 0 if the data doesn't * exist. */ + @Deprecated public long[] getAllData(byte detailLevel, int posX, int posZ) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); return dataContainer[detailLevel].getAllData(posX, posZ); } + public LodDataView getDataView(byte detailLevel, int posX, int posZ) { + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return dataContainer[detailLevel].getVerticalDataView(posX, posZ); + } /** * Get the dataPoint at the given relative position. diff --git a/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java index 4ed18b733..ee775ad70 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java @@ -27,6 +27,7 @@ import java.nio.ByteOrder; import java.util.Arrays; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.objects.LodDataView; import com.seibel.lod.core.util.*; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -37,6 +38,8 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; */ public class VerticalLevelContainer implements LevelContainer { + public static final boolean DO_SAFETY_CHECKS = true; + private final short minHeight; public final byte detailLevel; public final int size; @@ -107,15 +110,36 @@ public class VerticalLevelContainer implements LevelContainer forceWriteVerticalData(data, posX, posZ); return true; } - + + @Override + public boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override) { + if (DO_SAFETY_CHECKS) { + if (data.size() != verticalSize) + throw new IllegalArgumentException("data size not the same as vertical size"); + if (posX < 0 || posX >= size) + throw new IllegalArgumentException("X position is out of bounds"); + if (posZ < 0 || posZ >= size) + throw new IllegalArgumentException("Z position is out of bounds"); + } + int index = posX * size * verticalSize + posZ * verticalSize; + int compare = DataPointUtil.compareDatapointPriority(data.get(0), dataContainer[index]); + if (override) { + if (compare<0) return false; + } else { + if (compare<=0) return false; + } + data.copyTo(dataContainer, index); + return true; + } + @Override public boolean addChunkOfData(long[] data, int posX, int posZ, int widthX, int widthZ, boolean override) { boolean anyChange = false; if (posX+widthX > size || posZ+widthZ > size) throw new IndexOutOfBoundsException("addChunkOfData param not inside valid range"); - if (widthX*widthZ*verticalSize > data.length) - throw new IndexOutOfBoundsException("addChunkOfData data array not long enough to contain the data to be copied"); + if (widthX*widthZ*verticalSize != data.length) + throw new IndexOutOfBoundsException("addChunkOfData data array not sized correctly to contain the data to be copied"); if (posX<0 || posZ<0 || widthX<0 || widthZ<0) throw new IndexOutOfBoundsException("addChunkOfData param is negative"); @@ -127,18 +151,31 @@ public class VerticalLevelContainer implements LevelContainer } return anyChange; } - + @Override - public boolean addSingleData(long data, int posX, int posZ) - { - return addData(data, posX, posZ, 0); + public boolean copyChunkOfData(LodDataView data, int posX, int posZ, int widthX, int widthZ, boolean override) { + boolean anyChange = false; + if (posX+widthX > size || posZ+widthZ > size) + throw new IndexOutOfBoundsException("addChunkOfData param not inside valid range"); + if (widthX*widthZ*verticalSize != data.size()) + throw new IndexOutOfBoundsException("addChunkOfData data array not sized correctly to contain the data to be copied"); + if (posX<0 || posZ<0 || widthX<0 || widthZ<0) + throw new IndexOutOfBoundsException("addChunkOfData param is negative"); + + for (int ox=0; ox> 24) & 0xFF) == 255; - for (i = 0; i < dataPoint.length && DataPointUtil.doesItExist(adjData[i]) - && !DataPointUtil.isVoid(adjData[i]); i++) + for (i = 0; i < dataPoint.size() && DataPointUtil.doesItExist(adjData.get(i)) + && !DataPointUtil.isVoid(adjData.get(i)); i++) { - long adjPoint = adjData[i]; + long adjPoint = adjData.get(i); // TODO transparency ocean floor fix // if (isOpaque && DataPointUtil.getAlpha(singleAdjDataPoint) != 255) @@ -291,8 +292,8 @@ public class LodBox previousDepth = depth; firstFace = false; nextSkyLight = upSkyLight; - if (i + 1 < adjData.length && DataPointUtil.doesItExist(adjData[i + 1])) - nextSkyLight = DataPointUtil.getLightSky(adjData[i + 1]); + if (i + 1 < adjData.size() && DataPointUtil.doesItExist(adjData.get(i + 1))) + nextSkyLight = DataPointUtil.getLightSky(adjData.get(i + 1)); } if (allAbove) diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java index 4f175060a..4eb63ef61 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java @@ -36,6 +36,7 @@ import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.enums.rendering.GLProxyContext; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.objects.BoolType; +import com.seibel.lod.core.objects.LodDataView; import com.seibel.lod.core.objects.PosToRenderContainer; import com.seibel.lod.core.objects.lod.LodDimension; import com.seibel.lod.core.objects.lod.LodRegion; @@ -294,13 +295,12 @@ public class RenderRegion implements AutoCloseable // skip any chunks that Minecraft is going to render if (chunkGrid != null && chunkGrid.get(chunkX, chunkZ) != null) continue; } - - long[] posData = region.getAllData(detailLevel, posX, posZ); - if (posData == null || posData.length == 0 || !DataPointUtil.doesItExist(posData[0]) - || DataPointUtil.isVoid(posData[0])) + LodDataView posData = region.getDataView(detailLevel, posX, posZ); + if (posData == null || posData.size() == 0 || !DataPointUtil.doesItExist(posData.get(0)) + || DataPointUtil.isVoid(posData.get(0))) continue; - - long[][][] adjData = new long[4][][]; + + LodDataView[][] adjData = new LodDataView[4][]; boolean[] adjUseBlack = new boolean[4]; // We extract the adj data in the four cardinal direction @@ -360,15 +360,15 @@ public class RenderRegion implements AutoCloseable } if (adjDetail == detailLevel || adjDetail > detailLevel) { - adjData[lodDirection.ordinal() - 2] = new long[1][]; - adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, + adjData[lodDirection.ordinal() - 2] = new LodDataView[1]; + adjData[lodDirection.ordinal() - 2][0] = adjRegion.getDataView(adjDetail, LevelPosUtil.convert(detailLevel, xAdj, adjDetail), LevelPosUtil.convert(detailLevel, zAdj, adjDetail)); } else { - adjData[lodDirection.ordinal() - 2] = new long[2][]; - adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, + adjData[lodDirection.ordinal() - 2] = new LodDataView[2]; + adjData[lodDirection.ordinal() - 2][0] = adjRegion.getDataView(adjDetail, childXAdj, childZAdj); - adjData[lodDirection.ordinal() - 2][1] = adjRegion.getAllData(adjDetail, + adjData[lodDirection.ordinal() - 2][1] = adjRegion.getDataView(adjDetail, childXAdj + (lodDirection.getAxis()==LodDirection.Axis.X ? 0 : 1), childZAdj + (lodDirection.getAxis()==LodDirection.Axis.Z ? 0 : 1)); } @@ -380,15 +380,15 @@ public class RenderRegion implements AutoCloseable // We render every vertical lod present in this position // We only stop when we find a block that is void or non-existing block - for (int i = 0; i < posData.length; i++) { - long data = posData[i]; + for (int i = 0; i < posData.size(); i++) { + long data = posData.get(i); // If the data is not renderable (Void or non-existing) we stop since there is // no data left in this position if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data)) break; - long adjDataTop = i - 1 >= 0 ? posData[i - 1] : DataPointUtil.EMPTY_DATA; - long adjDataBot = i + 1 < posData.length ? posData[i + 1] : DataPointUtil.EMPTY_DATA; + long adjDataTop = i - 1 >= 0 ? posData.get(i - 1) : DataPointUtil.EMPTY_DATA; + long adjDataBot = i + 1 < posData.size() ? posData.get(i + 1) : DataPointUtil.EMPTY_DATA; // We send the call to create the vertices CubicLodTemplate.addLodToBuffer(data, adjDataTop, adjDataBot, adjData, adjUseBlack, detailLevel,