Quick merge fix
This commit is contained in:
@@ -19,12 +19,10 @@
|
||||
|
||||
package com.seibel.lod.core.api.internal.a7;
|
||||
|
||||
import com.seibel.lod.core.Config;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodBufferBuilderFactory;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.RendererType;
|
||||
import com.seibel.lod.core.handlers.LodDimensionFinder;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
@@ -33,9 +31,7 @@ import com.seibel.lod.core.objects.a7.DHLevel;
|
||||
import com.seibel.lod.core.objects.a7.DHWorld;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.render.GLProxy;
|
||||
import com.seibel.lod.core.render.LodRenderer;
|
||||
import com.seibel.lod.core.render.RenderSystemTest;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
@@ -63,21 +59,15 @@ public class ClientApi
|
||||
public static boolean prefLoggerEnabled = false;
|
||||
|
||||
public static final ClientApi INSTANCE = new ClientApi();
|
||||
public static final LodBufferBuilderFactory lodBufferBuilderFactory = new LodBufferBuilderFactory();
|
||||
public static LodRenderer renderer = new LodRenderer(lodBufferBuilderFactory);
|
||||
public static RenderSystemTest testRenderer = new RenderSystemTest();
|
||||
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
|
||||
private static final ServerApi EVENT_API = ServerApi.INSTANCE;
|
||||
|
||||
public static final boolean ENABLE_LAG_SPIKE_LOGGING = false;
|
||||
public static final long LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(16, TimeUnit.MILLISECONDS);
|
||||
|
||||
public static final long SPAM_LOGGER_FLUSH_NS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
|
||||
|
||||
public static LodDimensionFinder DIMENSION_FINDER = new LodDimensionFinder();;
|
||||
|
||||
public static class LagSpikeCatcher {
|
||||
long timer = System.nanoTime();
|
||||
public LagSpikeCatcher() {}
|
||||
@@ -96,7 +86,6 @@ public class ClientApi
|
||||
*/
|
||||
private boolean firstTimeSetupComplete = false;
|
||||
private boolean configOverrideReminderPrinted = false;
|
||||
|
||||
public boolean rendererDisabledBecauseOfExceptions = false;
|
||||
private ClientApi()
|
||||
{
|
||||
|
||||
@@ -19,26 +19,12 @@
|
||||
|
||||
package com.seibel.lod.core.api.internal.a7;
|
||||
|
||||
import com.seibel.lod.core.api.internal.InternalApiShared;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.worldGeneration.BatchGenerator;
|
||||
import com.seibel.lod.core.enums.WorldType;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.objects.DHRegionPos;
|
||||
import com.seibel.lod.core.objects.a7.DHWorld;
|
||||
import com.seibel.lod.core.objects.a7.Server;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.render.GLProxy;
|
||||
import com.seibel.lod.core.render.LodRenderer;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
@@ -104,33 +104,4 @@ public class DHLevel extends LodQuadTree implements Closeable {
|
||||
dataFileHandler.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void viewDistanceChangedEvent()
|
||||
{
|
||||
// calculate how wide the dimension(s) should be in regions
|
||||
int chunksWide;
|
||||
if (MC.getWrappedClientWorld().getDimensionType().hasCeiling())
|
||||
chunksWide = Math.min(CONFIG.client().graphics().quality().getLodChunkRenderDistance(),
|
||||
LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * 2 + 1;
|
||||
else
|
||||
chunksWide = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 2 + 1;
|
||||
|
||||
int newWidth = (int) Math.ceil(chunksWide / (float) LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
// make sure we have an odd number of regions
|
||||
newWidth += (newWidth & 1) == 0 ? 1 : 0;
|
||||
|
||||
// do the dimensions need to change in size?
|
||||
if (InternalApiShared.lodBuilder.defaultDimensionWidthInRegions != newWidth || recalculateWidths)
|
||||
{
|
||||
// update the dimensions to fit the new width
|
||||
InternalApiShared.lodWorld.resizeDimensionRegionWidth(newWidth);
|
||||
InternalApiShared.lodBuilder.defaultDimensionWidthInRegions = newWidth;
|
||||
ClientApi.renderer.setupBuffers();
|
||||
|
||||
recalculateWidths = false;
|
||||
// LOGGER.info("new dimension width in regions: " + newWidth + "\t potential: "
|
||||
// + newWidth );
|
||||
}
|
||||
DetailDistanceUtil.updateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.seibel.lod.core.objects.a7;
|
||||
|
||||
import com.seibel.lod.core.Config;
|
||||
import com.seibel.lod.core.api.internal.InternalApiShared;
|
||||
import com.seibel.lod.core.api.internal.a7.ClientApi;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.objects.a7.io.DHFolderHandler;
|
||||
import com.seibel.lod.core.objects.a7.io.LevelToFileMatcher;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
|
||||
@@ -1,765 +0,0 @@
|
||||
package com.seibel.lod.core.objects.a7;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.LodDataView;
|
||||
import com.seibel.lod.core.objects.lod.LevelContainer;
|
||||
import com.seibel.lod.core.objects.lod.VerticalLevelContainer;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
@Deprecated // Please edit the ColumnDatatype instead.
|
||||
public class RenderDataContainer
|
||||
{
|
||||
public static final boolean DO_SAFETY_CHECKS = true;
|
||||
|
||||
private final short minHeight;
|
||||
public final byte detailLevel;
|
||||
public final int SECTION_SIZE = 128;
|
||||
public final int AIR_LODS_SIZE = 16;
|
||||
public final int AIR_SECTION_SIZE = SECTION_SIZE/AIR_LODS_SIZE;
|
||||
public final int verticalSize;
|
||||
|
||||
public final long[] dataContainer;
|
||||
public final int[] airDataContainer;
|
||||
|
||||
/**
|
||||
* Constructor of the RenderDataContainer
|
||||
* @param detailLevel
|
||||
*/
|
||||
public RenderDataContainer(byte detailLevel)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
verticalSize = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
|
||||
dataContainer = new long[SECTION_SIZE * SECTION_SIZE * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
|
||||
airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
|
||||
|
||||
minHeight = SingletonHandler.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
|
||||
}
|
||||
|
||||
public byte getDetailLevel()
|
||||
{
|
||||
return detailLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will clear all data at relative section position
|
||||
* @param posX
|
||||
* @param posZ
|
||||
*/
|
||||
public void clear(int posX, int posZ)
|
||||
{
|
||||
for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++)
|
||||
dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex] = DataPointUtil.EMPTY_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will add the data given in input at the relative position and vertical index
|
||||
* @param data
|
||||
* @param posX
|
||||
* @param posZ
|
||||
* @param verticalIndex
|
||||
* @return
|
||||
*/
|
||||
public boolean addData(long data, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex] = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This section will fill the data given in input at the given position
|
||||
* @param data
|
||||
* @param posX
|
||||
* @param posZ
|
||||
*/
|
||||
private void forceWriteVerticalData(long[] data, int posX, int posZ)
|
||||
{
|
||||
int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize;
|
||||
if (verticalSize >= 0) System.arraycopy(data, 0, dataContainer, index + 0, verticalSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods will add the data in the given position if certain condition are satisfied
|
||||
* @param data
|
||||
* @param posX
|
||||
* @param posZ
|
||||
* @param override if override is true we can override data created with same generation mode
|
||||
* @return
|
||||
*/
|
||||
public boolean addVerticalData(long[] data, int posX, int posZ, boolean override)
|
||||
{
|
||||
int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize;
|
||||
int compare = DataPointUtil.compareDatapointPriority(data[0], dataContainer[index]);
|
||||
if (override) {
|
||||
if (compare<0) return false;
|
||||
} else {
|
||||
if (compare<=0) return false;
|
||||
}
|
||||
forceWriteVerticalData(data, posX, posZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
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 >= SECTION_SIZE)
|
||||
throw new IllegalArgumentException("X position is out of bounds");
|
||||
if (posZ < 0 || posZ >= SECTION_SIZE)
|
||||
throw new IllegalArgumentException("Z position is out of bounds");
|
||||
}
|
||||
int index = posX * SECTION_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;
|
||||
}
|
||||
|
||||
public boolean addChunkOfData(long[] data, int posX, int posZ, int widthX, int widthZ, boolean override)
|
||||
{
|
||||
boolean anyChange = false;
|
||||
if (posX+widthX > SECTION_SIZE || posZ+widthZ > SECTION_SIZE)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData param not inside valid range");
|
||||
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");
|
||||
|
||||
for (int ox=0; ox<widthX; ox++) {
|
||||
anyChange = DataPointUtil.mergeTwoDataArray(
|
||||
dataContainer, ((ox+posX)* SECTION_SIZE +posZ) * verticalSize,
|
||||
data, ox*widthX*verticalSize,
|
||||
widthZ, verticalSize, override);
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
public boolean copyChunkOfData(LodDataView data, int posX, int posZ, int widthX, int widthZ, boolean override) {
|
||||
boolean anyChange = false;
|
||||
if (posX+widthX > SECTION_SIZE || posZ+widthZ > SECTION_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)* SECTION_SIZE +posZ) * verticalSize)
|
||||
.mergeWith(data, verticalSize, override);
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
public long getData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex];
|
||||
}
|
||||
|
||||
|
||||
public long getSingleData(int posX, int posZ)
|
||||
{
|
||||
return dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize];
|
||||
}
|
||||
|
||||
|
||||
public long[] getAllData(int posX, int posZ)
|
||||
{
|
||||
long[] result = new long[verticalSize];
|
||||
int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize;
|
||||
System.arraycopy(dataContainer, index, result, 0, verticalSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
public LodDataView getVerticalDataView(int posX, int posZ) {
|
||||
return new LodDataView(dataContainer, verticalSize, posX * SECTION_SIZE * verticalSize + posZ * verticalSize);
|
||||
}
|
||||
|
||||
public int getVerticalSize()
|
||||
{
|
||||
return verticalSize;
|
||||
}
|
||||
|
||||
public int getSECTION_SIZE()
|
||||
{
|
||||
return SECTION_SIZE;
|
||||
}
|
||||
|
||||
public boolean doesItExist(int posX, int posZ)
|
||||
{
|
||||
return DataPointUtil.doesItExist(getSingleData(posX, posZ));
|
||||
}
|
||||
|
||||
private long[] readDataVersion6(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
patchHeightAndDepth(result,-minHeight);
|
||||
return result;
|
||||
}
|
||||
private long[] readDataVersion7(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
patchHeightAndDepth(result, 64 - minHeight);
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] readDataVersion8(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
short tempMinHeight = Short.reverseBytes(inputData.readShort());
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
if (tempMinHeight != minHeight) {
|
||||
patchHeightAndDepth(result,tempMinHeight - minHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] readDataVersion9(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
short tempMinHeight = Short.reverseBytes(inputData.readShort());
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
if (tempMinHeight != minHeight) {
|
||||
patchHeightAndDepth(result,tempMinHeight - minHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void patchHeightAndDepth(long[] data, int offset) {
|
||||
for (int i=0; i<data.length; i++) {
|
||||
data[i] = DataPointUtil.shiftHeightAndDepth(data[i], (short)offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static void patchVersion9Reorder(long[] data) {
|
||||
for (int i=0; i<data.length; i++) {
|
||||
data[i] = DataPointUtil.version9Reorder(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public RenderDataContainer(DataInputStream inputData, int version, byte expectedDetailLevel) throws IOException {
|
||||
minHeight = SingletonHandler.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
|
||||
detailLevel = inputData.readByte();
|
||||
if (detailLevel != expectedDetailLevel)
|
||||
throw new IOException("Invalid Data: The expected detail level should be "+expectedDetailLevel+
|
||||
" but the data header say it's "+detailLevel);
|
||||
int fileMaxVerticalData = inputData.readByte() & 0b01111111;
|
||||
long[] tempDataContainer = null;
|
||||
|
||||
switch (version) {
|
||||
case 6:
|
||||
tempDataContainer = readDataVersion6(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 7:
|
||||
tempDataContainer = readDataVersion7(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 8:
|
||||
tempDataContainer = readDataVersion8(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 9:
|
||||
tempDataContainer = readDataVersion9(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
int targetMaxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
verticalSize = targetMaxVerticalData;
|
||||
dataContainer = DataPointUtil.changeMaxVertSize(tempDataContainer, fileMaxVerticalData, verticalSize);
|
||||
airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
|
||||
}
|
||||
|
||||
public LevelContainer expand()
|
||||
{
|
||||
return new VerticalLevelContainer((byte) (getDetailLevel() - 1));
|
||||
}
|
||||
|
||||
private static final ThreadLocal<long[][]> tLocalVerticalUpdateArrays = ThreadLocal.withInitial(() ->
|
||||
{
|
||||
return new long[LodUtil.DETAIL_OPTIONS - 1][];
|
||||
});
|
||||
|
||||
public void updateData(RenderDataContainer lowerRenderContainer, int posX, int posZ)
|
||||
{
|
||||
//We reset the array
|
||||
long[][] verticalUpdateArrays = tLocalVerticalUpdateArrays.get();
|
||||
long[] dataToMerge = verticalUpdateArrays[detailLevel-1];
|
||||
int arrayLength = DetailDistanceUtil.getMaxVerticalData(detailLevel-1) * 4;
|
||||
if (dataToMerge == null || dataToMerge.length != arrayLength) {
|
||||
dataToMerge = new long[arrayLength];
|
||||
verticalUpdateArrays[detailLevel-1] = dataToMerge;
|
||||
} else Arrays.fill(dataToMerge, 0);
|
||||
|
||||
//int lowerMaxVertical = dataToMerge.length / 4;
|
||||
int lowerSectionSize = lowerRenderContainer.getSECTION_SIZE();
|
||||
int childPosStartX = Math.floorMod(2 * posX, lowerSectionSize);
|
||||
int childPosEndX = Math.floorMod(2 * posX + 1, lowerSectionSize);
|
||||
int childPosStartZ = Math.floorMod(2 * posZ, lowerSectionSize);
|
||||
int childPosEndZ = Math.floorMod(2 * posZ + 1, lowerSectionSize);
|
||||
|
||||
long[] data;
|
||||
boolean anyDataExist = false;
|
||||
|
||||
mergeAndAddDataFromOtherContainer(posX, posZ, lowerRenderContainer, childPosStartX, childPosEndX, childPosStartZ, childPosEndZ);
|
||||
/*
|
||||
TODO remove this old code when we are sure that this works
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
if (lowerLevelContainer.doesItExist(childPosX, childPosZ)) anyDataExist = true;
|
||||
for (int verticalIndex = 0; verticalIndex < lowerMaxVertical; verticalIndex++)
|
||||
dataToMerge[(z * 2 + x) * lowerMaxVertical + verticalIndex] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex);
|
||||
}
|
||||
}
|
||||
if (!anyDataExist)
|
||||
throw new RuntimeException("Update data called but no child datapoint exist!");
|
||||
|
||||
if ((!DataPointUtil.doesItExist(data[0])) && anyDataExist)
|
||||
throw new RuntimeException("Update data called but higher level datapoint doesn't exist even though child data does exist!");
|
||||
|
||||
//FIXME: Disabled check if genMode for old data is already invalid due to having genMode 0.
|
||||
if (DataPointUtil.getGenerationMode(data[0]) != DataPointUtil.getGenerationMode(lowerLevelContainer.getSingleData(posX*2, posZ*2)))
|
||||
throw new RuntimeException("Update data called but higher level datapoint does not have the same GenerationMode as the top left corner child datapoint!");
|
||||
|
||||
forceWriteVerticalData(data, posX, posZ);*/
|
||||
}
|
||||
|
||||
public boolean writeData(DataOutputStream output) throws IOException {
|
||||
output.writeByte(detailLevel);
|
||||
output.writeByte((byte) verticalSize);
|
||||
output.writeByte((byte) (minHeight & 0xFF));
|
||||
output.writeByte((byte) ((minHeight >> 8) & 0xFF));
|
||||
boolean allGenerated = true;
|
||||
int x = SECTION_SIZE * SECTION_SIZE;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
for (int j = 0; j < verticalSize; j++)
|
||||
{
|
||||
long current = dataContainer[i * verticalSize + j];
|
||||
output.writeLong(Long.reverseBytes(current));
|
||||
}
|
||||
if (!DataPointUtil.doesItExist(dataContainer[i]))
|
||||
allGenerated = false;
|
||||
}
|
||||
return allGenerated;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String LINE_DELIMITER = "\n";
|
||||
String DATA_DELIMITER = " ";
|
||||
String SUBDATA_DELIMITER = ",";
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(LINE_DELIMITER);
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int y = 0; y < verticalSize; y++) {
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(getData(x,z,y)));
|
||||
if (y != verticalSize) stringBuilder.append(SUBDATA_DELIMITER);
|
||||
}
|
||||
if (x != size) stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
if (z != size) stringBuilder.append(LINE_DELIMITER);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public int getMaxNumberOfLods()
|
||||
{
|
||||
return SECTION_SIZE * SECTION_SIZE * getVerticalSize();
|
||||
}
|
||||
|
||||
public long getRoughRamUsage()
|
||||
{
|
||||
return dataContainer.length * Long.BYTES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final ThreadLocal<short[]> tLocalHeightAndDepth = new ThreadLocal<short[]>();
|
||||
private static final ThreadLocal<int[]> tDataIndexCache = new ThreadLocal<int[]>();
|
||||
/**
|
||||
*
|
||||
* This method merge column of multiple data together
|
||||
*/
|
||||
// TODO: Make this operate on a out param array, to allow skipping copy array on use
|
||||
public void mergeAndAddDataFromOtherContainer(int mergeInX, int mergeInZ, RenderDataContainer lowerDataContainer, int mergeFromX, int mergeToX, int mergeFromZ, int mergeToZ)
|
||||
{
|
||||
int outBaseIndex = mergeInX * SECTION_SIZE * verticalSize + mergeInZ*verticalSize;
|
||||
int inputVerticalSize = lowerDataContainer.verticalSize;
|
||||
int inputSectionSize = lowerDataContainer.SECTION_SIZE;
|
||||
int mergeFromToX;
|
||||
int xSize = (mergeFromX - mergeToX + 1);
|
||||
int zSize = (mergeFromZ - mergeToZ + 1);
|
||||
//size indicate how many position we are merging in one position
|
||||
|
||||
// We initialize the arrays that are going to be used
|
||||
int heightAndDepthLength = (DataPointUtil.MAX_WORLD_Y_SIZE / 2 + 16) * 2;
|
||||
short[] heightAndDepth = tLocalHeightAndDepth.get();
|
||||
if (heightAndDepth==null || heightAndDepth.length != heightAndDepthLength) {
|
||||
heightAndDepth = new short[heightAndDepthLength];
|
||||
tLocalHeightAndDepth.set(heightAndDepth);
|
||||
}
|
||||
int dataPointLength = verticalSize;
|
||||
|
||||
int firstIndex = mergeFromX*SECTION_SIZE*inputVerticalSize + mergeFromZ * inputVerticalSize;
|
||||
byte genMode = DataPointUtil.getGenerationMode(lowerDataContainer.dataContainer[firstIndex]);
|
||||
if (genMode == 0) genMode = 1; // FIXME: Hack to make the version 10 genMode never be 0.
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
boolean limited = false;
|
||||
boolean allDefault;
|
||||
long singleData;
|
||||
|
||||
|
||||
short depth;
|
||||
short height;
|
||||
int count = 0;
|
||||
int i;
|
||||
int ii;
|
||||
|
||||
//We collect the indexes of the data, ordered by the depth
|
||||
int dataIndex = 0;
|
||||
int x;
|
||||
int z;
|
||||
int y;
|
||||
for (x = mergeFromX; x <= mergeToX; x++)
|
||||
{
|
||||
for (z = mergeFromZ; z <= mergeToZ; z++)
|
||||
{
|
||||
if (x == mergeFromX && z == mergeFromZ)
|
||||
{
|
||||
for (y = 0; y < inputVerticalSize; y++)
|
||||
{
|
||||
dataIndex = x * inputSectionSize * inputVerticalSize + z * inputVerticalSize + y;
|
||||
singleData = lowerDataContainer.dataContainer[dataIndex];
|
||||
if (DataPointUtil.doesItExist(singleData))
|
||||
{
|
||||
//genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!DataPointUtil.isVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
count++;
|
||||
heightAndDepth[dataIndex * 2] = DataPointUtil.getHeight(singleData);
|
||||
heightAndDepth[dataIndex * 2 + 1] = DataPointUtil.getDepth(singleData);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < inputVerticalSize; y++)
|
||||
{
|
||||
dataIndex = x * inputSectionSize * inputVerticalSize + z * inputVerticalSize + y;
|
||||
singleData = lowerDataContainer.dataContainer[dataIndex];
|
||||
if (DataPointUtil.doesItExist(singleData))
|
||||
{
|
||||
//genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!DataPointUtil.isVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
depth = DataPointUtil.getDepth(singleData);
|
||||
height = DataPointUtil.getHeight(singleData);
|
||||
|
||||
int botPos = -1;
|
||||
int topPos = -1;
|
||||
//values fall in between and possibly require extension of array
|
||||
boolean botExtend = false;
|
||||
boolean topExtend = false;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (depth < heightAndDepth[i * 2] && depth >= heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
botPos = i;
|
||||
break;
|
||||
}
|
||||
else if (depth < heightAndDepth[i * 2 + 1] && ((i + 1 < count && depth >= heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
botPos = i;
|
||||
botExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (height <= heightAndDepth[i * 2] && height > heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
topPos = i;
|
||||
break;
|
||||
}
|
||||
else if (height <= heightAndDepth[i * 2 + 1] && ((i + 1 < count && height > heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
topPos = i;
|
||||
topExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topPos == -1)
|
||||
{
|
||||
if (botPos == -1)
|
||||
{
|
||||
//whole block falls above
|
||||
DataPointUtil.extendArray(heightAndDepth, 2, 0, 1, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count++;
|
||||
}
|
||||
else if (!botExtend)
|
||||
{
|
||||
//only top falls above extending it there, while bottom is inside existing
|
||||
DataPointUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
count -= botPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//top falls between some blocks, extending those as well
|
||||
DataPointUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count -= botPos;
|
||||
}
|
||||
}
|
||||
else if (!topExtend)
|
||||
{
|
||||
if (!botExtend)
|
||||
//both top and bottom are within some exiting blocks, possibly merging them
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
else
|
||||
//top falls between some blocks, extending it there
|
||||
heightAndDepth[topPos * 2 + 1] = depth;
|
||||
DataPointUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!botExtend)
|
||||
{
|
||||
//only top is within some exiting block, extending it
|
||||
topPos++; //to make it easier
|
||||
heightAndDepth[topPos * 2] = height;
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
DataPointUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//both top and bottom are outside existing blocks
|
||||
DataPointUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
DataPointUtil.extendArray(heightAndDepth, 2, topPos + 1, 1, count);
|
||||
count++;
|
||||
heightAndDepth[topPos * 2 + 2] = height;
|
||||
heightAndDepth[topPos * 2 + 3] = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//We check if there is any data that's not empty or void
|
||||
if (allEmpty)
|
||||
return;
|
||||
if (allVoid)
|
||||
{
|
||||
dataContainer[outBaseIndex] = DataPointUtil.createVoidDataPoint(genMode);
|
||||
return;
|
||||
}
|
||||
|
||||
//we limit the vertical portion to maxVerticalData
|
||||
int j = 0;
|
||||
while (count > verticalSize)
|
||||
{
|
||||
limited = true;
|
||||
ii = DataPointUtil.MAX_WORLD_Y_SIZE;
|
||||
for (i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii)
|
||||
{
|
||||
ii = heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2];
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1];
|
||||
for (i = j + 1; i < count - 1; i++)
|
||||
{
|
||||
heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2];
|
||||
heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1];
|
||||
}
|
||||
//System.arraycopy(heightAndDepth, j + 1, heightAndDepth, j, count - j - 1);
|
||||
count--;
|
||||
}
|
||||
int yOut;
|
||||
//As standard the vertical lods are ordered from top to bottom
|
||||
if (!limited && xSize*zSize == 1)
|
||||
{
|
||||
for (yOut = 0; yOut < count; yOut++)
|
||||
dataIndex = mergeFromX*inputSectionSize*inputVerticalSize + mergeFromZ*inputVerticalSize + yOut;
|
||||
dataContainer[outBaseIndex + yOut] = lowerDataContainer.dataContainer[dataIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//We want to efficiently memorize indexes
|
||||
int[] dataIndexesCache = tDataIndexCache.get();
|
||||
if (dataIndexesCache==null || dataIndexesCache.length != xSize*zSize) {
|
||||
dataIndexesCache = new int[xSize*zSize];
|
||||
tDataIndexCache.set(dataIndexesCache);
|
||||
}
|
||||
Arrays.fill(dataIndexesCache,0);
|
||||
|
||||
//For each lod height-depth value we have found we now want to generate the rest of the data
|
||||
//by merging all lods at lower level that are contained inside the new ones
|
||||
for (yOut = 0; yOut < count; yOut++)
|
||||
{
|
||||
//We firstly collect height and depth data
|
||||
//this will be added to each realtive long DataPoint
|
||||
height = heightAndDepth[yOut * 2];
|
||||
depth = heightAndDepth[yOut * 2 + 1];
|
||||
|
||||
//if both height and depth are at 0 then we finished
|
||||
if ((depth == 0 && height == 0) || yOut >= heightAndDepth.length / 2)
|
||||
break;
|
||||
|
||||
//We initialize data useful for the merge
|
||||
int numberOfChildren = 0;
|
||||
allEmpty = true;
|
||||
allVoid = true;
|
||||
|
||||
//We initialize all the new values that we are going to put in the dataPoint
|
||||
int tempAlpha = 0;
|
||||
int tempRed = 0;
|
||||
int tempGreen = 0;
|
||||
int tempBlue = 0;
|
||||
int tempLightBlock = 0;
|
||||
int tempLightSky = 0;
|
||||
long data = 0;
|
||||
|
||||
int index;
|
||||
|
||||
//For each position that we want to merge
|
||||
for(x = mergeFromX; x <= mergeToX; x++)
|
||||
{
|
||||
for (z = mergeFromZ; z <= mergeToZ; z++)
|
||||
{
|
||||
index = x * xSize + z;
|
||||
//we scan the lods in the position from top to bottom
|
||||
while (dataIndexesCache[index] < inputVerticalSize)
|
||||
{
|
||||
y = dataIndexesCache[index];
|
||||
dataIndex = x * inputSectionSize * inputVerticalSize + z * inputVerticalSize + y;
|
||||
|
||||
singleData = lowerDataContainer.dataContainer[dataIndex];
|
||||
if (DataPointUtil.doesItExist(singleData) && !DataPointUtil.isVoid(singleData))
|
||||
{
|
||||
dataIndexesCache[index]++;
|
||||
if ((depth <= DataPointUtil.getDepth(singleData) && DataPointUtil.getDepth(singleData) < height)
|
||||
|| (depth < DataPointUtil.getHeight(singleData) && DataPointUtil.getHeight(singleData) <= height))
|
||||
{
|
||||
data = singleData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!DataPointUtil.doesItExist(data))
|
||||
{
|
||||
data = DataPointUtil.createVoidDataPoint(genMode);
|
||||
}
|
||||
|
||||
if (DataPointUtil.doesItExist(data))
|
||||
{
|
||||
allEmpty = false;
|
||||
if (!DataPointUtil.isVoid(data))
|
||||
{
|
||||
numberOfChildren++;
|
||||
allVoid = false;
|
||||
tempAlpha = Math.max(DataPointUtil.getAlpha(data), tempAlpha);
|
||||
tempRed += DataPointUtil.getRed(data) * DataPointUtil.getRed(data);
|
||||
tempGreen += DataPointUtil.getGreen(data) * DataPointUtil.getGreen(data);
|
||||
tempBlue += DataPointUtil.getBlue(data) * DataPointUtil.getBlue(data);
|
||||
tempLightBlock += DataPointUtil.getLightBlock(data);
|
||||
tempLightSky += DataPointUtil.getLightSky(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allEmpty)
|
||||
//no child has been initialized
|
||||
dataContainer[outBaseIndex + yOut] = DataPointUtil.EMPTY_DATA;
|
||||
else if (allVoid)
|
||||
//all the children are void
|
||||
dataContainer[outBaseIndex + yOut] = DataPointUtil.createVoidDataPoint(genMode);
|
||||
else
|
||||
{
|
||||
//we have at least 1 child
|
||||
if (xSize*zSize != 1)
|
||||
{
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
}
|
||||
//data = createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault);
|
||||
//if (j > 0 && getColor(data) == getColor(dataPoint[j]))
|
||||
//{
|
||||
// add simplification at the end due to color
|
||||
//}
|
||||
dataContainer[outBaseIndex + yOut] = DataPointUtil.createDataPoint((int) Math.sqrt(tempAlpha), (int) Math.sqrt(tempRed), (int) Math.sqrt(tempGreen), (int) Math.sqrt(tempBlue), height, depth, tempLightSky, tempLightBlock, genMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public abstract class DataSourceLoader {
|
||||
return false;
|
||||
})) {
|
||||
throw new IllegalArgumentException("Loader for class " + clazz + " that supports one of the version in "
|
||||
+ loaderSupportedVersions " already registered!");
|
||||
+ loaderSupportedVersions + " already registered!");
|
||||
}
|
||||
datatypeIdRegistry.put(datatypeId, clazz);
|
||||
loaderRegistry.put(datatypeId, this);
|
||||
|
||||
@@ -19,12 +19,11 @@
|
||||
|
||||
package com.seibel.lod.core.render;
|
||||
|
||||
import com.seibel.lod.core.Config;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.api.internal.InternalApiShared;
|
||||
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodBufferBuilderFactory;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
@@ -44,7 +43,6 @@ import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.EdgeDistanceBooleanGrid;
|
||||
import com.seibel.lod.core.util.gridList.MovableGridRingList;
|
||||
import com.seibel.lod.core.util.gridList.PosArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
|
||||
Reference in New Issue
Block a user