Added dataView system so no longer need to copy arrays around

This commit is contained in:
TomTheFurry
2022-05-01 14:19:51 +08:00
parent be7a077367
commit 031539bd31
7 changed files with 154 additions and 53 deletions
@@ -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);
@@ -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;
}
}
@@ -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
@@ -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.
@@ -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<widthX; ox++) {
anyChange |= new LodDataView(dataContainer, widthX*verticalSize,
((ox+posX)*size+posZ) * verticalSize)
.mergeWith(data, verticalSize, override);
}
return anyChange;
}
@Override
public long getData(int posX, int posZ, int verticalIndex)
{
return dataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex];
}
public short getPositionData(int posX, int posZ)
{
@@ -194,7 +231,12 @@ public class VerticalLevelContainer implements LevelContainer
System.arraycopy(dataContainer, index, result, 0, verticalSize);
return result;
}
@Override
public LodDataView getVerticalDataView(int posX, int posZ) {
return new LodDataView(dataContainer, verticalSize, posX * size * verticalSize + posZ * verticalSize);
}
@Override
public int getVerticalSize()
{
@@ -22,6 +22,7 @@ package com.seibel.lod.core.objects.opengl;
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodQuadBuilder;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.objects.LodDataView;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.util.DataPointUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -31,8 +32,8 @@ public class LodBox
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
public static void addBoxQuadsToBuilder(LodQuadBuilder builder, short xSize, short ySize, short zSize, short x,
short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, long[][][] adjData,
boolean[] adjFillBlack)
short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, LodDataView[][] adjData,
boolean[] adjFillBlack)
{
short maxX = (short) (x + xSize);
short maxY = (short) (y + ySize);
@@ -57,7 +58,7 @@ public class LodBox
//NORTH face vertex creation
{
long[][] adjDataNorth = adjData[LodDirection.NORTH.ordinal() - 2];
LodDataView[] adjDataNorth = adjData[LodDirection.NORTH.ordinal() - 2];
int adjOverlapNorth = adjFillBlack[LodDirection.NORTH.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT;
if (adjDataNorth == null)
{
@@ -79,7 +80,7 @@ public class LodBox
//SOUTH face vertex creation
{
long[][] adjDataSouth = adjData[LodDirection.SOUTH.ordinal() - 2];
LodDataView[] adjDataSouth = adjData[LodDirection.SOUTH.ordinal() - 2];
int adjOverlapSouth = adjFillBlack[LodDirection.SOUTH.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT;
if (adjDataSouth == null)
{
@@ -102,7 +103,7 @@ public class LodBox
//WEST face vertex creation
{
long[][] adjDataWest = adjData[LodDirection.WEST.ordinal() - 2];
LodDataView[] adjDataWest = adjData[LodDirection.WEST.ordinal() - 2];
int adjOverlapWest = adjFillBlack[LodDirection.WEST.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT;
if (adjDataWest == null)
{
@@ -124,7 +125,7 @@ public class LodBox
//EAST face vertex creation
{
long[][] adjDataEast = adjData[LodDirection.EAST.ordinal() - 2];
LodDataView[] adjDataEast = adjData[LodDirection.EAST.ordinal() - 2];
int adjOverlapEast = adjFillBlack[LodDirection.EAST.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT;
if (adjData[LodDirection.EAST.ordinal() - 2] == null)
{
@@ -145,12 +146,12 @@ public class LodBox
}
}
private static void makeAdjQuads(LodQuadBuilder builder, long[] adjData, LodDirection direction, short x, short y,
short z, short w0, short wy, int color, int overlapColor, byte upSkyLight, byte blockLight)
private static void makeAdjQuads(LodQuadBuilder builder, LodDataView adjData, LodDirection direction, short x, short y,
short z, short w0, short wy, int color, int overlapColor, byte upSkyLight, byte blockLight)
{
color = ColorUtil.applyShade(color, MC.getShade(direction));
long[] dataPoint = adjData;
if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0]))
LodDataView dataPoint = adjData;
if (dataPoint == null || DataPointUtil.isVoid(dataPoint.get(0)))
{
builder.addQuadAdj(direction, x, y, z, w0, wy, color, (byte) 15, blockLight);
return;
@@ -164,10 +165,10 @@ public class LodBox
// TODO transparency ocean floor fix
// boolean isOpaque = ((colorMap[0] >> 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)
@@ -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,