Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5 # Conflicts: # src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
This commit is contained in:
+1
-1
@@ -31,7 +31,7 @@ compileJava {
|
||||
// release 8 is needed because otherwise FloatBuffer.flip() will crash
|
||||
// on some machines
|
||||
// example thread: https://github.com/eclipse/jetty.project/issues/3244
|
||||
options.compilerArgs.addAll(['--release', '8', '-Xlint:unchecked', '-Xlint:deprecation'])
|
||||
options.compilerArgs.addAll(['-Xlint:unchecked', '-Xlint:deprecation'])
|
||||
}
|
||||
|
||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.seibel.lod;
|
||||
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
import com.seibel.lod.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
|
||||
import javax.xml.crypto.Data;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Main
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
/*
|
||||
try
|
||||
{
|
||||
long[][] dataToMerge = new long[][]{
|
||||
{DataPointUtil.createDataPoint(10, 5, 0, 0, 0)},
|
||||
{DataPointUtil.createDataPoint(15, 5, 0, 0, 0)},
|
||||
{DataPointUtil.createDataPoint(40, 20, 0, 0, 0)},
|
||||
{DataPointUtil.createDataPoint(1, 0, 0, 0, 0)}};
|
||||
long[] data = DataPointUtil.mergeVerticalData(dataToMerge);
|
||||
for (long dataPoint : data)
|
||||
{
|
||||
System.out.println("depth " + DataPointUtil.getDepth(dataPoint));
|
||||
System.out.println("height " + DataPointUtil.getHeight(dataPoint));
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,6 @@ import org.lwjgl.opengl.GL15C;
|
||||
|
||||
import com.seibel.lod.builders.lodTemplates.Box;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
import com.seibel.lod.objects.LevelPosUtil;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.PosToRenderContainer;
|
||||
@@ -42,10 +40,13 @@ 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.LightTexture;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -117,8 +118,10 @@ public class LodBufferBuilder
|
||||
private volatile PosToRenderContainer[][] setsToRender;
|
||||
private volatile RegionPos center;
|
||||
|
||||
/** This is the ChunkPos the player was at the last time the buffers were built.
|
||||
* IE the center of the buffers last time they were built */
|
||||
/**
|
||||
* This is the ChunkPos the player was at the last time the buffers were built.
|
||||
* IE the center of the buffers last time they were built
|
||||
*/
|
||||
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0, 0);
|
||||
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0, 0);
|
||||
|
||||
@@ -142,6 +145,20 @@ public class LodBufferBuilder
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
BlockPos playerBlockPos, boolean fullRegen)
|
||||
{
|
||||
|
||||
|
||||
for(int i = 0; i<16; i++)
|
||||
{
|
||||
for(int j = 0; j<16; j++)
|
||||
{
|
||||
int lightTint = LightTexture.pack(i,j);
|
||||
//System.out.print(ColorUtil.getRed(lightTint) + " " + ColorUtil.getGreen(lightTint) + " " + ColorUtil.getBlue(lightTint) + " ");
|
||||
System.out.print(Integer.toHexString(lightTint) + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
// only allow one generation process to happen at a time
|
||||
if (generatingBuffers)
|
||||
return;
|
||||
@@ -246,8 +263,9 @@ public class LodBufferBuilder
|
||||
int chunkXdist;
|
||||
int chunkZdist;
|
||||
short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1);
|
||||
long dataPoint;
|
||||
long[] adjData;
|
||||
//long dataPoint;
|
||||
long[] adjData = new long[NUMBER_OF_DIRECTION];
|
||||
|
||||
for (int index = 0; index < posToRender.getNumberOfPos(); index++)
|
||||
{
|
||||
detailLevel = posToRender.getNthDetailLevel(index);
|
||||
@@ -266,12 +284,13 @@ public class LodBufferBuilder
|
||||
// skip any chunks that Minecraft is going to render
|
||||
try
|
||||
{
|
||||
if (lodDim.doesDataExist(detailLevel, posX, posZ))
|
||||
//dataPoint = lodDim.getData(detailLevel, posX, posZ)[0];
|
||||
for(long dataPoint : lodDim.getData(detailLevel, posX, posZ))
|
||||
{
|
||||
dataPoint = lodDim.getData(detailLevel, posX, posZ);
|
||||
if (DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH)
|
||||
continue;
|
||||
adjData = new long[NUMBER_OF_DIRECTION];
|
||||
|
||||
if (!DataPointUtil.isItVoid(dataPoint) && DataPointUtil.doesItExist(dataPoint))
|
||||
{
|
||||
/*
|
||||
for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++)
|
||||
{
|
||||
xAdj = posX + ADJ_DIRECTION[direction][0];
|
||||
@@ -284,22 +303,27 @@ public class LodBufferBuilder
|
||||
if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
|
||||
&& posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0];
|
||||
} else
|
||||
{
|
||||
adjData[direction] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
if (posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0];
|
||||
} else
|
||||
{
|
||||
adjData[direction] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData,
|
||||
detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode);
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
|
||||
@@ -23,27 +23,21 @@ import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
import com.seibel.lod.objects.LevelPosUtil;
|
||||
import com.seibel.lod.util.*;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.block.AbstractPlantBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.BushBlock;
|
||||
import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
@@ -169,9 +163,9 @@ public class LodBuilder
|
||||
int endX;
|
||||
int endZ;
|
||||
int color;
|
||||
byte light;
|
||||
short height;
|
||||
short depth;
|
||||
long data;
|
||||
try
|
||||
{
|
||||
LodDetail detail;
|
||||
@@ -191,28 +185,31 @@ public class LodBuilder
|
||||
endX = detail.endX[i];
|
||||
endZ = detail.endZ[i];
|
||||
|
||||
color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ);
|
||||
|
||||
if (!config.useHeightmap)
|
||||
{
|
||||
height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
} else
|
||||
{
|
||||
height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP), startX,
|
||||
startZ, endX, endZ);
|
||||
depth = 0;
|
||||
}
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
|
||||
long[] data;
|
||||
long[][] dataToMerge;
|
||||
//data = ThreadMapUtil.getSingleAddDataArray();
|
||||
//dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
|
||||
/*long[][] dataToMerge2 = new long[dataToMerge.length][];
|
||||
for (int index = 0; index < dataToMerge.length; index++)
|
||||
{
|
||||
dataToMerge2[index] = new long[]{dataToMerge[index]};
|
||||
}*/
|
||||
//data[0] = DataPointUtil.mergeSingleData(dataToMerge);
|
||||
|
||||
dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
|
||||
data = DataPointUtil.mergeVerticalData(dataToMerge);
|
||||
if (data.length == 0 || data == null)
|
||||
data = new long[]{DataPointUtil.EMPTY_DATA};
|
||||
boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER;
|
||||
data = DataPoint.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color));
|
||||
lodDim.addData(detailLevel,
|
||||
posX,
|
||||
posZ,
|
||||
data,
|
||||
false,
|
||||
isServer);
|
||||
|
||||
}
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
} catch (Exception e)
|
||||
@@ -222,7 +219,199 @@ public class LodBuilder
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
int size = 1 << detail.detailLevel;
|
||||
int height = 0;
|
||||
int depth = 0;
|
||||
int color = 0;
|
||||
int light = 0;
|
||||
int generation = config.distanceGenerationMode.complexity;
|
||||
|
||||
int xRel;
|
||||
int zRel;
|
||||
int xAbs;
|
||||
int yAbs;
|
||||
int zAbs;
|
||||
|
||||
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][1024];
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
for(int i = 0; i < dataToMerge[index].length; i++)
|
||||
{
|
||||
dataToMerge[index][i] = 0;
|
||||
}
|
||||
xRel = Math.floorMod(index, size) + startX;
|
||||
zRel = Math.floorDiv(index, size) + startZ;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
|
||||
//Calculate the height of the lod
|
||||
yAbs = 255;
|
||||
int count = 0;
|
||||
while (yAbs > 0)
|
||||
{
|
||||
height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
|
||||
|
||||
//If the lod is at default, then we set this as void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
{
|
||||
dataToMerge[index][0] = DataPointUtil.createVoidDataPoint(generation);
|
||||
break;
|
||||
}
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel);
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
|
||||
blockPos.set(xAbs, yAbs + 1, zAbs);
|
||||
light = getLightValue(chunk, blockPos);
|
||||
|
||||
//System.out.println(dataToMerge.length + " " + index +" " + count + " " + yAbs);
|
||||
//System.out.println(dataToMerge.length + " " + dataToMerge[index].length);
|
||||
dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation);
|
||||
yAbs = depth - 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return dataToMerge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
*/
|
||||
private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
|
||||
{
|
||||
short depth = DEFAULT_DEPTH;
|
||||
if (config.useHeightmap)
|
||||
{
|
||||
depth = 0;
|
||||
} else
|
||||
{
|
||||
boolean voidData = true;
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
|
||||
{
|
||||
for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
|
||||
{
|
||||
if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs)
|
||||
continue;
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel);
|
||||
if (!isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
|
||||
voidData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!voidData)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the highest valid point from the Top
|
||||
*/
|
||||
private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
|
||||
{
|
||||
short height = DEFAULT_HEIGHT;
|
||||
if (config.useHeightmap)
|
||||
{
|
||||
height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
} else
|
||||
{
|
||||
boolean voidData = true;
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
|
||||
{
|
||||
for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
|
||||
{
|
||||
if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs)
|
||||
continue;
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel);
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
|
||||
voidData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!voidData)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
private long[] createSingleDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
|
||||
{
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderArray()[detail.detailLevel];
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
|
||||
int size = 1 << detail.detailLevel;
|
||||
int height = 0;
|
||||
int depth = 0;
|
||||
int color = 0;
|
||||
int light = 0;
|
||||
int generation = config.distanceGenerationMode.complexity;
|
||||
|
||||
int xRel;
|
||||
int zRel;
|
||||
int xAbs;
|
||||
int yAbs;
|
||||
int zAbs;
|
||||
|
||||
BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0);
|
||||
int index = 0;
|
||||
if (dataToMerge == null)
|
||||
{
|
||||
dataToMerge = new long[size * size];
|
||||
}
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
xRel = Math.floorMod(index, size) + startX;
|
||||
zRel = Math.floorDiv(index, size) + startZ;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
|
||||
//Calculate the height of the lod
|
||||
height = determineHeightPoint(chunk, config, xRel, zRel, blockPos);
|
||||
|
||||
//If the lod is at default, then we set this as void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
{
|
||||
dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation);
|
||||
continue;
|
||||
}
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel);
|
||||
depth = determineBottomPoint(chunk, config, xRel, zRel, blockPos);
|
||||
|
||||
blockPos.set(xAbs, yAbs + 1, zAbs);
|
||||
light = getLightValue(chunk, blockPos);
|
||||
|
||||
dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation);
|
||||
}
|
||||
return dataToMerge;
|
||||
}
|
||||
// =====================//
|
||||
// constructor helpers //
|
||||
// =====================//
|
||||
@@ -230,208 +419,118 @@ public class LodBuilder
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
*/
|
||||
private short determineBottomPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ)
|
||||
private short determineBottomPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos)
|
||||
{
|
||||
int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2);
|
||||
|
||||
// search from the bottom up
|
||||
for (int section = 0; section < CHUNK_DATA_WIDTH; section++)
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
short depth = DEFAULT_DEPTH;
|
||||
if (config.useHeightmap)
|
||||
{
|
||||
for (int y = 0; y < CHUNK_SECTION_HEIGHT; y++)
|
||||
depth = 0;
|
||||
} else
|
||||
{
|
||||
boolean found = false;
|
||||
for (int sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++)
|
||||
{
|
||||
int numberOfBlocksFound = 0;
|
||||
|
||||
for (int x = startX; x < endX; x++)
|
||||
for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++)
|
||||
{
|
||||
for (int z = startZ; z < endZ; z++)
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
if (isLayerValidLodPoint(chunkSections, section, y, x, z))
|
||||
{
|
||||
numberOfBlocksFound++;
|
||||
|
||||
if (numberOfBlocksFound >= numberOfBlocksRequired)
|
||||
{
|
||||
// we found
|
||||
// enough blocks in this
|
||||
// layer to count as an
|
||||
// LOD point
|
||||
return (short) (y + (section * CHUNK_SECTION_HEIGHT));
|
||||
}
|
||||
}
|
||||
depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we never found a valid LOD point
|
||||
return DEFAULT_DEPTH;
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private short determineBottomPoint(Heightmap heightmap)
|
||||
{
|
||||
// the heightmap only shows how high the blocks go, it
|
||||
// doesn't have any info about how low they go
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the highest valid point from the Top
|
||||
*/
|
||||
private short determineHeightPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ)
|
||||
private short determineHeightPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos)
|
||||
{
|
||||
int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2);
|
||||
// search from the top down
|
||||
for (int section = chunkSections.length - 1; section >= 0; section--)
|
||||
short height = DEFAULT_HEIGHT;
|
||||
if (config.useHeightmap)
|
||||
{
|
||||
for (int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
|
||||
height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
} else
|
||||
{
|
||||
boolean voidData = true;
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
|
||||
{
|
||||
int numberOfBlocksFound = 0;
|
||||
|
||||
for (int x = startX; x < endX; x++)
|
||||
for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
|
||||
{
|
||||
for (int z = startZ; z < endZ; z++)
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
if (isLayerValidLodPoint(chunkSections, section, y, x, z))
|
||||
{
|
||||
numberOfBlocksFound++;
|
||||
|
||||
if (numberOfBlocksFound >= numberOfBlocksRequired)
|
||||
{
|
||||
// we found
|
||||
// enough blocks in this
|
||||
// layer to count as an
|
||||
// LOD point
|
||||
return (short) (y + 1 + (section * CHUNK_SECTION_HEIGHT));
|
||||
}
|
||||
}
|
||||
height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
|
||||
voidData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!voidData)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we never found a valid LOD point
|
||||
return DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the highest point from the Top
|
||||
*/
|
||||
private short determineHeightPoint(Heightmap heightmap, int startX, int startZ, int endX, int endZ)
|
||||
{
|
||||
short highest = 0;
|
||||
for (int x = startX; x < endX; x++)
|
||||
{
|
||||
for (int z = startZ; z < endZ; z++)
|
||||
{
|
||||
short newHeight = (short) heightmap.getFirstAvailable(x, z);
|
||||
if (newHeight > highest)
|
||||
highest = newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return highest;
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the color for the given chunk using biome water color, foliage
|
||||
* color, and grass color.
|
||||
*
|
||||
* @param config_useSolidBlocksInColorGen <br>
|
||||
* If true we look down from the top of
|
||||
* the <br>
|
||||
* chunk until we find a non-invisible
|
||||
* block, and then use <br>
|
||||
* its color. If false we generate the
|
||||
* color immediately for <br>
|
||||
* each x and z.
|
||||
* @param config_useBiomeColors <br>
|
||||
* If true use biome foliage, water, and
|
||||
* grass colors, <br>
|
||||
* otherwise only use the block's
|
||||
* material color
|
||||
*/
|
||||
private int generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
|
||||
int endZ)
|
||||
private int generateLodColor(IChunk chunk, LodBuilderConfig config, int xRel, int yAbs, int zRel)
|
||||
{
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
int numbOfBlocks = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
for (int x = startX; x < endX; x++)
|
||||
int colorInt = 0;
|
||||
if (config.useBiomeColors)
|
||||
{
|
||||
for (int z = startZ; z < endZ; z++)
|
||||
// I have no idea why I need to bit shift to the right, but
|
||||
// if I don't the biomes don't show up correctly.
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2);
|
||||
colorInt = getColorForBiome(xRel, zRel, biome);
|
||||
} else
|
||||
{
|
||||
int sectionIndex = Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT);
|
||||
int yRel = Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT);
|
||||
if (chunkSections[sectionIndex] != null)
|
||||
{
|
||||
boolean foundBlock = false;
|
||||
BlockState blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel);
|
||||
|
||||
// go top down
|
||||
for (int i = chunkSections.length - 1; !foundBlock && i >= 0; i--)
|
||||
{
|
||||
if (!foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen))
|
||||
{
|
||||
for (int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--)
|
||||
{
|
||||
int colorInt = 0;
|
||||
BlockState blockState = null;
|
||||
// the bit shift is equivalent to dividing by 4
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2);
|
||||
|
||||
if (chunkSections[i] != null)
|
||||
{
|
||||
blockState = chunkSections[i].getBlockState(x, y, z);
|
||||
colorInt = blockState.materialColor.col;
|
||||
}
|
||||
|
||||
if (colorInt == 0 && config.useSolidBlocksInColorGen)
|
||||
{
|
||||
// skip air or invisible blocks
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.useBiomeColors)
|
||||
{
|
||||
// I have no idea why I need to bit shift to the right, but
|
||||
// if I don't the biomes don't show up correctly.
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + 1 * chunkSections.length >> 2,
|
||||
z >> 2);
|
||||
colorInt = getColorForBiome(x, z, biome);
|
||||
} else
|
||||
{
|
||||
|
||||
// the bit shift is equivalent to dividing by 4
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2,
|
||||
z >> 2);
|
||||
colorInt = getColorForBlock(x, z, blockState, biome);
|
||||
}
|
||||
|
||||
red += ColorUtil.getRed(colorInt);
|
||||
green += ColorUtil.getGreen(colorInt);
|
||||
blue += ColorUtil.getBlue(colorInt);
|
||||
|
||||
numbOfBlocks++;
|
||||
|
||||
// we found a valid block, skip to the
|
||||
// next x and z
|
||||
foundBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
colorInt = getColorForBlock(xRel, zRel, blockState, biome);
|
||||
}
|
||||
if (colorInt == 0 && yAbs > 0)
|
||||
{
|
||||
//invisible case
|
||||
colorInt = generateLodColor(chunk, config, xRel, yAbs - 1, zRel);
|
||||
}
|
||||
}
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
if (numbOfBlocks == 0)
|
||||
numbOfBlocks = 1;
|
||||
private int getLightValue(IChunk chunk, BlockPos.Mutable blockPos)
|
||||
{
|
||||
int light;
|
||||
|
||||
red /= numbOfBlocks;
|
||||
green /= numbOfBlocks;
|
||||
blue /= numbOfBlocks;
|
||||
return ColorUtil.rgbToInt(red,green,blue);
|
||||
//*TODO choose the best one between those options*/
|
||||
//lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos);
|
||||
//lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos);
|
||||
light = MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos);
|
||||
light += MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.SKY, blockPos) << 4;
|
||||
//BlockState blockState = chunk.getBlockState(blockPos);
|
||||
//lightBlock = (byte) blockState.getLightBlock(chunk, blockPos);
|
||||
return light;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,9 +541,9 @@ public class LodBuilder
|
||||
int colorInt = 0;
|
||||
|
||||
// block special cases
|
||||
if (blockState == Blocks.AIR.defaultBlockState()
|
||||
|| blockState == Blocks.CAVE_AIR.defaultBlockState()
|
||||
|| blockState == Blocks.BARRIER.defaultBlockState())
|
||||
if (blockState == Blocks.AIR.defaultBlockState()
|
||||
|| blockState == Blocks.CAVE_AIR.defaultBlockState()
|
||||
|| blockState == Blocks.BARRIER.defaultBlockState())
|
||||
{
|
||||
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
|
||||
tmp = tmp.darker();
|
||||
@@ -452,11 +551,36 @@ public class LodBuilder
|
||||
} else if (blockState == Blocks.STONE.defaultBlockState())
|
||||
{
|
||||
colorInt = LodUtil.STONE_COLOR_INT;
|
||||
} else if (blockState == Blocks.NETHERRACK.defaultBlockState())
|
||||
{
|
||||
colorInt = LodUtil.NETHERRACK_COLOR_INT;
|
||||
} else if (blockState == Blocks.WARPED_NYLIUM.defaultBlockState())
|
||||
{
|
||||
colorInt = LodUtil.WARPED_NYLIUM_COLOR_INT;
|
||||
} else if (blockState == Blocks.CRIMSON_NYLIUM.defaultBlockState())
|
||||
{
|
||||
colorInt = LodUtil.CRIMSON_NYLIUM_COLOR_INT;
|
||||
} else if (blockState == Blocks.BEDROCK.defaultBlockState())
|
||||
{
|
||||
colorInt = getColorForBiome(x, z, biome);
|
||||
} else if (blockState == Blocks.MYCELIUM.defaultBlockState())
|
||||
{
|
||||
colorInt = LodUtil.MYCELIUM_COLOR_INT;
|
||||
} else if (blockState == Blocks.SOUL_TORCH.defaultBlockState()
|
||||
|| blockState == Blocks.SOUL_WALL_TORCH.defaultBlockState())
|
||||
{
|
||||
colorInt = Blocks.WARPED_PLANKS.defaultMaterialColor().col;
|
||||
} else if (blockState == Blocks.TORCH.defaultBlockState()
|
||||
|| blockState == Blocks.WALL_TORCH.defaultBlockState())
|
||||
{
|
||||
colorInt = Blocks.OAK_PLANKS.defaultMaterialColor().col;
|
||||
} else if (blockState == Blocks.REDSTONE_TORCH.defaultBlockState()
|
||||
|| blockState == Blocks.REDSTONE_WALL_TORCH.defaultBlockState())
|
||||
{
|
||||
colorInt = Blocks.CRIMSON_PLANKS.defaultMaterialColor().col;
|
||||
}
|
||||
|
||||
|
||||
// plant life
|
||||
else if (blockState.getBlock() instanceof LeavesBlock || blockState.getBlock() == Blocks.VINE)
|
||||
{
|
||||
@@ -481,7 +605,7 @@ public class LodBuilder
|
||||
// everything else
|
||||
else
|
||||
{
|
||||
colorInt = blockState.materialColor.col;
|
||||
colorInt = blockState.getBlock().defaultMaterialColor().col;
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
@@ -498,7 +622,7 @@ public class LodBuilder
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = Blocks.BEDROCK.defaultBlockState().materialColor.col;
|
||||
colorInt = LodUtil.NETHERRACK_COLOR_INT;
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
@@ -552,19 +676,34 @@ public class LodBuilder
|
||||
/**
|
||||
* Is the layer between the given X, Z, and dataIndex values a valid LOD point?
|
||||
*/
|
||||
private boolean isLayerValidLodPoint(ChunkSection[] chunkSections, int sectionIndex, int y, int x, int z)
|
||||
private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos)
|
||||
{
|
||||
if (chunkSections[sectionIndex] == null)
|
||||
|
||||
BlockState blockState = chunk.getBlockState(blockPos);
|
||||
if (blockState != null)
|
||||
{
|
||||
// this section doesn't have any blocks,
|
||||
// it is not a valid section
|
||||
return false;
|
||||
} else
|
||||
{
|
||||
if (chunkSections[sectionIndex].getBlockState(x, y, z) != null
|
||||
&& chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.AIR
|
||||
&& chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.CAVE_AIR
|
||||
&& chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.BARRIER)
|
||||
if (!blockState.getFluidState().isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
VoxelShape voxelShape = blockState.getShape(chunk, blockPos);
|
||||
if (!voxelShape.isEmpty())
|
||||
{
|
||||
AxisAlignedBB bbox = voxelShape.bounds();
|
||||
int xWidth = (int) (bbox.maxX - bbox.minX);
|
||||
int yWidth = (int) (bbox.maxY - bbox.minY);
|
||||
int zWidth = (int) (bbox.maxZ - bbox.minZ);
|
||||
if (xWidth < 0.7 && zWidth < 0.7 && yWidth < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (blockState.getBlock() != Blocks.AIR
|
||||
&& blockState.getBlock() != Blocks.CAVE_AIR
|
||||
&& blockState.getBlock() != Blocks.BARRIER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.seibel.lod.builders.lodTemplates;
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -31,6 +32,8 @@ import net.minecraft.util.math.BlockPos;
|
||||
*/
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
|
||||
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging);
|
||||
|
||||
@@ -41,6 +44,7 @@ public abstract class AbstractLodTemplate
|
||||
double x, double y, double z,
|
||||
int red, int green, int blue, int alpha)
|
||||
{
|
||||
|
||||
buffer.vertex(x, y, z).color(red, green, blue, alpha).endVertex();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,11 @@ package com.seibel.lod.builders.lodTemplates;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.Direction;
|
||||
@@ -53,21 +54,29 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
// add each LOD for the detail level
|
||||
generateBoundingBox(
|
||||
box,
|
||||
DataPoint.getHeight(data),
|
||||
DataPoint.getDepth(data),
|
||||
DataPointUtil.getHeight(data),
|
||||
DataPointUtil.getDepth(data),
|
||||
width,
|
||||
posX * width,
|
||||
0,
|
||||
posZ * width,
|
||||
bufferCenterBlockPos);
|
||||
int color;
|
||||
boolean hasSkyLight = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight();
|
||||
boolean hasRoof = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight();
|
||||
int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000);
|
||||
boolean isDay = time < 0;
|
||||
//USE THIS IN THE boolean hasCeiling = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasCeiling();
|
||||
color = DataPointUtil.getLightColor(data, (hasRoof & hasSkyLight), isDay);
|
||||
|
||||
int color = DataPoint.getColor(data);
|
||||
if (debugging != DebugMode.OFF)
|
||||
|
||||
{
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
|
||||
}
|
||||
|
||||
if (box != null)
|
||||
|
||||
{
|
||||
addBoundingBoxToBuffer(buffer, box, color, bufferCenterBlockPos, adjData);
|
||||
}
|
||||
@@ -208,10 +217,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
|
||||
}else
|
||||
} else
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
tempMaxY = DataPointUtil.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
@@ -220,7 +229,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
tempMinY = DataPointUtil.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
@@ -253,11 +262,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
tempMaxY = DataPointUtil.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
@@ -266,7 +274,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
tempMinY = DataPointUtil.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
@@ -299,11 +307,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
tempMaxY = DataPointUtil.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
@@ -312,7 +319,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
tempMinY = DataPointUtil.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
@@ -345,11 +352,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
tempMaxY = DataPointUtil.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
@@ -358,7 +364,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
tempMinY = DataPointUtil.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
|
||||
@@ -24,8 +24,10 @@ import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.builders.LodBuilderConfig;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
@@ -72,7 +74,8 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
|
||||
*/
|
||||
public class LodNodeGenWorker implements IWorker
|
||||
{
|
||||
public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName()));
|
||||
public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build());
|
||||
//public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName()));
|
||||
|
||||
private boolean threadStarted = false;
|
||||
private LodChunkGenThread thread;
|
||||
@@ -126,7 +129,7 @@ public class LodNodeGenWorker implements IWorker
|
||||
// Every other method can
|
||||
// be done asynchronously
|
||||
Thread newThread = new Thread(thread);
|
||||
newThread.setPriority(3);
|
||||
newThread.setPriority(5);
|
||||
genThreads.execute(newThread);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.objects.LevelPosUtil;
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
|
||||
@@ -28,10 +28,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.objects.LevelContainer;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.objects.*;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
@@ -46,11 +43,6 @@ import com.seibel.lod.util.LodUtil;
|
||||
*/
|
||||
public class LodDimensionFileHandler
|
||||
{
|
||||
/**
|
||||
* This is what separates each piece of data
|
||||
*/
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
|
||||
|
||||
private LodDimension loadedDimension = null;
|
||||
public long regionLastWriteTime[][];
|
||||
@@ -84,7 +76,7 @@ public class LodDimensionFileHandler
|
||||
* file handler, older versions (smaller numbers) will be deleted and overwritten,
|
||||
* newer versions (larger numbers) will be ignored and won't be read.
|
||||
*/
|
||||
public static final int LOD_SAVE_FILE_VERSION = 5;
|
||||
public static final int LOD_SAVE_FILE_VERSION = 6;
|
||||
|
||||
/**
|
||||
* This is the string written before the file version
|
||||
@@ -200,7 +192,8 @@ public class LodDimensionFileHandler
|
||||
data = bufferedReader.readLine();
|
||||
|
||||
bufferedReader.close();
|
||||
region.addLevel(new LevelContainer(data));
|
||||
//region.addLevel(new SingleLevelContainer(data));
|
||||
region.addLevel(new VerticalLevelContainer(data));
|
||||
} catch (Exception e)
|
||||
{
|
||||
// the buffered reader encountered a
|
||||
@@ -331,7 +324,7 @@ public class LodDimensionFileHandler
|
||||
fw.write(LOD_FILE_VERSION_PREFIX + " " + LOD_SAVE_FILE_VERSION + "\n");
|
||||
|
||||
// add each LodChunk to the file
|
||||
fw.write(region.getLevel(detailLevel).toString());
|
||||
fw.write(region.getLevel(detailLevel).toDataString());
|
||||
fw.close();
|
||||
|
||||
// overwrite the old file with the new one
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
public class DataPoint
|
||||
{
|
||||
public final static int HEIGHT_SHIFT = 54;
|
||||
public final static int DEPTH_SHIFT = 44;
|
||||
public final static int RED_SHIFT = 36;
|
||||
public final static int GREEN_SHIFT = 28;
|
||||
public final static int BLUE_SHIFT = 20;
|
||||
public final static int GEN_TYPE_SHIFT = 17;
|
||||
public final static int LIGHT_SHIFT = 13;
|
||||
public final static int EXISTENCE_SHIFT = 0;
|
||||
|
||||
public final static long HEIGHT_MASK = Long.parseUnsignedLong("1111111111", 2);
|
||||
public final static long DEPTH_MASK = Long.parseUnsignedLong("1111111111", 2);
|
||||
public final static long RED_MASK = Long.parseUnsignedLong("11111111", 2);
|
||||
public final static long GREEN_MASK = Long.parseUnsignedLong("11111111", 2);
|
||||
public final static long BLUE_MASK = Long.parseUnsignedLong("11111111", 2);
|
||||
public final static long GEN_TYPE_MASK = Long.parseUnsignedLong("111", 2);
|
||||
public final static long LIGHT_MASK = Long.parseUnsignedLong("1111", 2);
|
||||
public final static long EXISTENCE_MASK = 1;
|
||||
|
||||
public static long createDataPoint(int height, int depth, int color)
|
||||
{
|
||||
int red = (getRed(color) << 16) & 0x00FF0000;
|
||||
int green = (getGreen(color) << 8) & 0x0000FF00;
|
||||
int blue = getBlue(color)& 0x000000FF;
|
||||
return createDataPoint(height, depth, red, green, blue);
|
||||
}
|
||||
public static long createDataPoint(int height, int depth, int red, int green, int blue)
|
||||
{
|
||||
long dataPoint = 0;
|
||||
dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
dataPoint += (red & RED_MASK) << RED_SHIFT;
|
||||
dataPoint += (green & GREEN_MASK) << GREEN_SHIFT;
|
||||
dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT;
|
||||
dataPoint += 1;
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
public static short getHeight(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(long dataPoint)
|
||||
{
|
||||
|
||||
return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static short getRed(long dataPoint)
|
||||
{
|
||||
|
||||
return (short) ((dataPoint >> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
|
||||
public static boolean doesItExist(long dataPoint)
|
||||
{
|
||||
return ((dataPoint & EXISTENCE_MASK) == 1);
|
||||
}
|
||||
|
||||
public static int getColor(long dataPoint)
|
||||
{
|
||||
int R = (getRed(dataPoint) << 16) & 0x00FF0000;
|
||||
int G = (getGreen(dataPoint) << 8) & 0x0000FF00;
|
||||
int B = getBlue(dataPoint)& 0x000000FF;
|
||||
return 0xFF000000 | R | G | B;
|
||||
}
|
||||
|
||||
public static String toString(long dataPoint)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(getHeight(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getDepth(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getRed(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getBlue(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getGreen(dataPoint));
|
||||
s.append('\n');
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,61 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
public class LevelContainer implements Serializable
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
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
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
public boolean addData(long[] data, int posX, int posZ);
|
||||
|
||||
/** This is here so that Eclipse doesn't complain */
|
||||
private static final long serialVersionUID = -4930855068717998385L;
|
||||
/**With this you can get data from the level container
|
||||
*
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
public long[] getData(int posX, int posZ);
|
||||
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
/**
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return true only if the data exist
|
||||
*/
|
||||
public boolean doesItExist(int posX, int posZ);
|
||||
|
||||
public final byte detailLevel;
|
||||
/**
|
||||
* @return return the deatilLevel of this level container
|
||||
*/
|
||||
public byte getDetailLevel();
|
||||
|
||||
public final long[][] data;
|
||||
/**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
|
||||
*/
|
||||
public LevelContainer expand();
|
||||
|
||||
public LevelContainer(byte detailLevel, long[][] data)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
this.data = data;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param lowerLevelContainer lower level where we extract the data
|
||||
* @param posX x position in the detail level to update
|
||||
* @param posZ z position in the detail level to update
|
||||
*/
|
||||
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ);
|
||||
|
||||
public LevelContainer(String inputString)
|
||||
{
|
||||
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
index = inputString.indexOf(DATA_DELIMITER, 0);
|
||||
this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index));
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
this.data = new long[size][size];
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(data[x][z]));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
/**
|
||||
* This will give the data to save in the file
|
||||
* @return data as a String
|
||||
*/
|
||||
public String toDataString();
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ import java.util.concurrent.Executors;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.util.*;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -435,7 +433,7 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinates it will be overwritten.
|
||||
*/
|
||||
public synchronized Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality)
|
||||
public Boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean dontSave, boolean serverQuality)
|
||||
{
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
@@ -445,7 +443,7 @@ public class LodDimension
|
||||
LodRegion region = getRegion(regionPosX, regionPosZ);
|
||||
if (region == null)
|
||||
return false;
|
||||
boolean nodeAdded = region.addData(detailLevel, posX, posZ, lodDataPoint, serverQuality);
|
||||
boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataPoint, serverQuality);
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
{
|
||||
@@ -520,7 +518,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)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
@@ -529,7 +527,7 @@ public class LodDimension
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
return 0;
|
||||
return new long[]{DataPointUtil.EMPTY_DATA};
|
||||
}
|
||||
|
||||
return region.getData(detailLevel, posX, posZ);
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
/**
|
||||
@@ -20,65 +22,61 @@ public class LodRegion
|
||||
private byte minDetailLevel;
|
||||
private static final byte POSSIBLE_LOD = 10;
|
||||
//private int numberOfPoints;
|
||||
private DistanceGenerationMode generationMode;
|
||||
//For each of the following field the first slot is for the level of detail
|
||||
//Important: byte have a [-128, 127] range. When converting from or to int a 128 should be added or removed
|
||||
//If there is a bug with color then it's probably caused by this.
|
||||
//in the future other fields like transparency and light level could be added
|
||||
|
||||
private long[][][] data;
|
||||
private LevelContainer[] dataContainer;
|
||||
|
||||
|
||||
private DistanceGenerationMode generationMode;
|
||||
|
||||
public final int regionPosX;
|
||||
public final int regionPosZ;
|
||||
|
||||
public LodRegion(LevelContainer levelContainer, RegionPos regionPos, DistanceGenerationMode generationMode)
|
||||
public LodRegion(RegionPos regionPos)
|
||||
{
|
||||
this.generationMode = generationMode;
|
||||
this.minDetailLevel = LodUtil.REGION_DETAIL_LEVEL;
|
||||
this.regionPosX = regionPos.x;
|
||||
this.regionPosZ = regionPos.z;
|
||||
this.minDetailLevel = levelContainer.detailLevel;
|
||||
|
||||
//Arrays of matrices
|
||||
data = new long[POSSIBLE_LOD][][];
|
||||
|
||||
data[minDetailLevel] = levelContainer.data;
|
||||
|
||||
//Initialize all the different matrices
|
||||
for (byte lod = (byte) (minDetailLevel + 1); lod <= LodUtil.REGION_DETAIL_LEVEL; lod++)
|
||||
{
|
||||
int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod);
|
||||
data[lod] = new long[size][size];
|
||||
}
|
||||
updateArea(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ);
|
||||
dataContainer = new LevelContainer[POSSIBLE_LOD];
|
||||
}
|
||||
|
||||
public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode)
|
||||
{
|
||||
this.generationMode = generationMode;
|
||||
this.minDetailLevel = minDetailLevel;
|
||||
this.regionPosX = regionPos.x;
|
||||
this.regionPosZ = regionPos.z;
|
||||
|
||||
data = new long[POSSIBLE_LOD][][];
|
||||
this.generationMode = generationMode;
|
||||
dataContainer = new LevelContainer[POSSIBLE_LOD];
|
||||
|
||||
|
||||
//Initialize all the different matrices
|
||||
for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++)
|
||||
{
|
||||
int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod);
|
||||
data[lod] = new long[size][size];
|
||||
|
||||
//dataContainer[lod] = new SingleLevelContainer(lod);
|
||||
dataContainer[lod] = new VerticalLevelContainer(lod);
|
||||
/*if(twoDimension){
|
||||
dataContainer[lod] = new SingleLevelContainer(lod);
|
||||
}else{
|
||||
dataContainer[lod] = new VerticalLevelContainer.java(lod);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public DistanceGenerationMode getGenerationMode()
|
||||
{
|
||||
return generationMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can be used to insert data into the LodRegion
|
||||
*
|
||||
* @param dataPoint
|
||||
* @return
|
||||
*/
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality)
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean serverQuality)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
@@ -89,7 +87,7 @@ public class LodRegion
|
||||
//if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++;
|
||||
|
||||
//add the node data
|
||||
this.data[detailLevel][posX][posZ] = dataPoint;
|
||||
this.dataContainer[detailLevel].addData(dataPoint, posX, posZ);
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
@@ -102,11 +100,11 @@ 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)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return data[detailLevel][posX][posZ];
|
||||
return dataContainer[detailLevel].getData(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,11 +133,11 @@ public class LodRegion
|
||||
|
||||
int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel);
|
||||
//we have reached the target detail level
|
||||
|
||||
if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) > detailLevel)
|
||||
byte targetDetailLevel = DetailDistanceUtil.getLodGenDetail(DetailDistanceUtil.getDistanceGenerationInverse(maxDistance)).detailLevel;
|
||||
if (targetDetailLevel > detailLevel)
|
||||
{
|
||||
return;
|
||||
} else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) == detailLevel)
|
||||
} else if (targetDetailLevel == detailLevel)
|
||||
{
|
||||
if (!doesDataExist(detailLevel, posX, posZ))
|
||||
{
|
||||
@@ -286,63 +284,7 @@ public class LodRegion
|
||||
*/
|
||||
private void update(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
int numberOfChildren = 0;
|
||||
int numberOfVoidChildren = 0;
|
||||
|
||||
int tempRed = 0;
|
||||
int tempGreen = 0;
|
||||
int tempBlue = 0;
|
||||
int tempHeight = 0;
|
||||
int tempDepth = 0;
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
byte childDetailLevel;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
childDetailLevel = (byte) (detailLevel - 1);
|
||||
if (doesDataExist(childDetailLevel, childPosX, childPosZ))
|
||||
{
|
||||
if (!(DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT
|
||||
&& DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH))
|
||||
{
|
||||
numberOfChildren++;
|
||||
|
||||
tempRed += DataPoint.getRed(data[childDetailLevel][childPosX][childPosZ]);
|
||||
tempGreen += DataPoint.getGreen(data[childDetailLevel][childPosX][childPosZ]);
|
||||
tempBlue += DataPoint.getBlue(data[childDetailLevel][childPosX][childPosZ]);
|
||||
tempHeight += DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]);
|
||||
tempDepth += DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]);
|
||||
} else
|
||||
{
|
||||
// void children have the default height (most likely -1)
|
||||
// and represent a LOD with no blocks in it
|
||||
numberOfVoidChildren++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numberOfChildren > 0)
|
||||
{
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempHeight = tempHeight / numberOfChildren;
|
||||
tempDepth = tempDepth / numberOfChildren;
|
||||
} else if (numberOfVoidChildren > 0)
|
||||
{
|
||||
tempRed = (byte) 0;
|
||||
tempGreen = (byte) 0;
|
||||
tempBlue = (byte) 0;
|
||||
tempHeight = LodBuilder.DEFAULT_HEIGHT;
|
||||
tempDepth = LodBuilder.DEFAULT_DEPTH;
|
||||
}
|
||||
data[detailLevel][posX][posZ] = DataPoint.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue);
|
||||
dataContainer[detailLevel].updateData(dataContainer[detailLevel - 1], posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -354,15 +296,24 @@ public class LodRegion
|
||||
if(detailLevel < minDetailLevel) return false;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return DataPoint.doesItExist(data[detailLevel][posX][posZ]);
|
||||
if(dataContainer == null || dataContainer[detailLevel] == null)
|
||||
return false;
|
||||
return dataContainer[detailLevel].doesItExist(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public DistanceGenerationMode getGenerationMode()
|
||||
public byte getGenerationMode(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
return generationMode;
|
||||
if(dataContainer[detailLevel].doesItExist(posX,posZ))
|
||||
{
|
||||
//We take the bottom information always
|
||||
return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getData(posX,posZ)[0]);
|
||||
}else
|
||||
{
|
||||
return DistanceGenerationMode.NONE.complexity;
|
||||
}
|
||||
}
|
||||
|
||||
public byte getMinDetailLevel()
|
||||
@@ -382,7 +333,7 @@ public class LodRegion
|
||||
{
|
||||
throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel);
|
||||
}
|
||||
return new LevelContainer(detailLevel, data[detailLevel]);
|
||||
return dataContainer[detailLevel];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,12 +341,12 @@ public class LodRegion
|
||||
*/
|
||||
public void addLevel(LevelContainer levelContainer)
|
||||
{
|
||||
if (levelContainer.detailLevel < minDetailLevel - 1)
|
||||
if (levelContainer.getDetailLevel() < minDetailLevel - 1)
|
||||
{
|
||||
throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 ");
|
||||
}
|
||||
if (levelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = levelContainer.detailLevel;
|
||||
data[levelContainer.detailLevel] = levelContainer.data;
|
||||
if (levelContainer.getDetailLevel() == minDetailLevel - 1) minDetailLevel = levelContainer.getDetailLevel();
|
||||
dataContainer[levelContainer.getDetailLevel()] = levelContainer;
|
||||
|
||||
}
|
||||
|
||||
@@ -408,7 +359,7 @@ public class LodRegion
|
||||
{
|
||||
for (byte tempLod = 0; tempLod < detailLevel; tempLod++)
|
||||
{
|
||||
data[tempLod] = new long[0][0];
|
||||
dataContainer[tempLod] = null;
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
@@ -421,10 +372,13 @@ public class LodRegion
|
||||
{
|
||||
if (detailLevel < minDetailLevel)
|
||||
{
|
||||
for (byte tempLod = detailLevel; tempLod < minDetailLevel; tempLod++)
|
||||
for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel ; tempLod--)
|
||||
{
|
||||
int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod);
|
||||
data[tempLod] = new long[size][size];
|
||||
if(dataContainer[tempLod + 1] == null)
|
||||
{
|
||||
dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1));
|
||||
}
|
||||
dataContainer[tempLod] = dataContainer[tempLod+1].expand();
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
|
||||
public class PosToGenerateContainer
|
||||
{
|
||||
private int playerPosX;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
public class PosToRenderContainer
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.util.*;
|
||||
|
||||
public class SingleLevelContainer implements LevelContainer
|
||||
{
|
||||
public final byte detailLevel;
|
||||
public final int size;
|
||||
|
||||
public final long[][] data;
|
||||
|
||||
public SingleLevelContainer(byte detailLevel)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
data = new long[size][size];
|
||||
}
|
||||
|
||||
public boolean addData(long[] newData, int posX, int posZ){
|
||||
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
data[posX][posZ] = newData[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean addSingleData(long newData, int posX, int posZ){
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
data[posX][posZ] = newData;
|
||||
return true;
|
||||
}
|
||||
|
||||
public long[] getData(int posX, int posZ){
|
||||
long[] dataArray = ThreadMapUtil.getSingleGetDataArray();
|
||||
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;
|
||||
}
|
||||
|
||||
private 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];
|
||||
}
|
||||
|
||||
public byte getDetailLevel(){
|
||||
return detailLevel;
|
||||
}
|
||||
|
||||
public LevelContainer expand(){
|
||||
return new SingleLevelContainer((byte) (getDetailLevel() - 1));
|
||||
}
|
||||
|
||||
public SingleLevelContainer(String inputString)
|
||||
{
|
||||
int tempIndex;
|
||||
int shift = 0;
|
||||
int index = 0;
|
||||
int digit;
|
||||
char currentChar;
|
||||
long newData;
|
||||
currentChar = inputString.charAt(index);
|
||||
digit = Character.digit(currentChar,16);
|
||||
detailLevel = (byte) digit;
|
||||
size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
this.data = new long[size][size];
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
newData = 0;
|
||||
for(tempIndex = 0; tempIndex < 16; tempIndex++)
|
||||
{
|
||||
if(index+tempIndex >= inputString.length())
|
||||
break;
|
||||
currentChar = inputString.charAt(index+tempIndex);
|
||||
if(currentChar == DATA_DELIMITER){
|
||||
break;
|
||||
}
|
||||
shift = (15-tempIndex)*4;
|
||||
digit = Character.digit(currentChar,16);
|
||||
newData += ((((long) digit & 0xf)) << shift);
|
||||
}
|
||||
newData = newData >>> (shift);
|
||||
data[x][z] = newData;
|
||||
index = index + tempIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
|
||||
{
|
||||
//We reset the array
|
||||
long[] dataToMerge = ThreadMapUtil.getSingleUpdateArray();
|
||||
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
long data = 0;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
dataToMerge[2*x + z] = ((SingleLevelContainer) lowerLevelContainer).getSingleData(childPosX, childPosZ);
|
||||
}
|
||||
}
|
||||
data = DataPointUtil.mergeSingleData(dataToMerge);
|
||||
addSingleData(data,posX,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[]
|
||||
return DataPointUtil.doesItExist(getSingleData(posX, posZ));
|
||||
}
|
||||
|
||||
public String toDataString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(data[x][z]));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(detailLevel);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
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 java.security.InvalidParameterException;
|
||||
|
||||
public class VerticalLevelContainer implements LevelContainer
|
||||
{
|
||||
|
||||
public final byte detailLevel;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getDetailLevel()
|
||||
{
|
||||
return detailLevel;
|
||||
}
|
||||
|
||||
public boolean addData(long[] newData, int posX, int posZ){
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
dataContainer[posX][posZ] = newData;
|
||||
return true;
|
||||
}
|
||||
|
||||
public long[] getData(int posX, int posZ){
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[posX][posZ];
|
||||
}
|
||||
|
||||
public boolean doesItExist(int posX, int posZ){
|
||||
long[] data = getData(posX,posZ);
|
||||
if(data == null)
|
||||
return false;
|
||||
return DataPointUtil.doesItExist(data[0]);
|
||||
}
|
||||
|
||||
public VerticalLevelContainer(String inputString)
|
||||
{
|
||||
|
||||
throw new InvalidParameterException("loading not yet implemented");
|
||||
|
||||
/*
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
index = inputString.indexOf(DATA_DELIMITER, 0);
|
||||
this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index));
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
this.dataContainer = new long[size][size][1];
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
dataContainer[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public LevelContainer expand(){
|
||||
return new VerticalLevelContainer((byte) (getDetailLevel() - 1));
|
||||
}
|
||||
|
||||
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
|
||||
{
|
||||
//We reset the array
|
||||
long[][] dataToMerge = ThreadMapUtil.getVerticalUpdateArray();
|
||||
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
long[] data;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ);
|
||||
}
|
||||
}
|
||||
data = DataPointUtil.mergeVerticalData(dataToMerge);
|
||||
addData(data,posX,posZ);
|
||||
}
|
||||
|
||||
public String toDataString()
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
/*
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(dataContainer[x][z][0]));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
*/
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ public class ClientProxy
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
// only run the first time setup once
|
||||
if (firstTimeSetupComplete)
|
||||
if (!firstTimeSetupComplete)
|
||||
{
|
||||
firstFrameSetup();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.FogQuality;
|
||||
import com.seibel.lod.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.objects.LevelPosUtil;
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.NearFarFogSettings;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
@@ -551,7 +551,7 @@ public class LodRenderer
|
||||
// it is possible to see the near clip plane, but
|
||||
// you have to be flying quickly in spectator mode through ungenerated
|
||||
// terrain, so I don't think it is much of an issue.
|
||||
mc.getRenderDistance(),
|
||||
mc.getRenderDistance()/2,
|
||||
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2);
|
||||
|
||||
// add the screen space distortions
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
package com.seibel.lod.util;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
|
||||
public class DataPointUtil
|
||||
{
|
||||
/*
|
||||
|a |a |a |a |r |r |r |r |
|
||||
|
||||
|r |r |r |r |g |g |g |g |
|
||||
|
||||
|g |g |g |g |b |b |b |b |
|
||||
|
||||
|b |b |b |b |h |h |h |h |
|
||||
|
||||
|h |h |h |h |h |h |d |d |
|
||||
|
||||
|d |d |d |d |d |d |d |d |
|
||||
|
||||
|bl |bl |bl |bl |sl |sl |sl |sl |
|
||||
|
||||
|l |l |f |g |g |g |v |e |
|
||||
|
||||
|
||||
*/
|
||||
//To be used in the future for negative value
|
||||
//public final static int MIN_DEPTH = -64;
|
||||
//public final static int MIN_HEIGHT = -64;
|
||||
public final static int EMPTY_DATA = 0;
|
||||
public final static int WORLD_HEIGHT = 256;
|
||||
|
||||
public final static int ALPHA_DOWNSIZE_SHIFT = 4;
|
||||
|
||||
public final static int BLUE_COLOR_SHIFT = 0;
|
||||
public final static int GREEN_COLOR_SHIFT = 8;
|
||||
public final static int RED_COLOR_SHIFT = 16;
|
||||
public final static int ALPHA_COLOR_SHIFT = 24;
|
||||
|
||||
public final static int BLUE_SHIFT = 36;
|
||||
public final static int GREEN_SHIFT = BLUE_SHIFT + 8;
|
||||
public final static int RED_SHIFT = BLUE_SHIFT + 16 ;
|
||||
public final static int ALPHA_SHIFT = BLUE_SHIFT + 24;
|
||||
|
||||
public final static int COLOR_SHIFT = 36;
|
||||
|
||||
public final static int HEIGHT_SHIFT = 26;
|
||||
public final static int DEPTH_SHIFT = 16;
|
||||
public final static int BLOCK_LIGHT_SHIFT = 12;
|
||||
public final static int SKY_LIGHT_SHIFT = 8;
|
||||
public final static int LIGHTS_SHIFT = SKY_LIGHT_SHIFT;
|
||||
public final static int VERTICAL_INDEX_SHIFT = 6;
|
||||
public final static int FLAG_SHIFT = 5;
|
||||
public final static int GEN_TYPE_SHIFT = 2;
|
||||
public final static int VOID_SHIFT = 1;
|
||||
public final static int EXISTENCE_SHIFT = 0;
|
||||
|
||||
public final static long ALPHA_MASK = 0b1111;
|
||||
public final static long RED_MASK = 0b1111_1111;
|
||||
public final static long GREEN_MASK = 0b1111_1111;
|
||||
public final static long BLUE_MASK = 0b1111_1111;
|
||||
public final static long COLOR_MASK = 0b11111111_11111111_11111111;
|
||||
public final static long HEIGHT_MASK = 0b11_1111_1111;
|
||||
public final static long DEPTH_MASK = 0b11_1111_1111;
|
||||
public final static long LIGHTS_MASK = 0b1111_1111;
|
||||
public final static long BLOCK_LIGHT_MASK = 0b1111;
|
||||
public final static long SKY_LIGHT_MASK = 0b1111;
|
||||
public final static long VERTICAL_INDEX_MASK = 0b11;
|
||||
public final static long FLAG_MASK = 0b1;
|
||||
public final static long GEN_TYPE_MASK = 0b111;
|
||||
public final static long VOID_MASK = 1;
|
||||
public final static long EXISTENCE_MASK = 1;
|
||||
|
||||
|
||||
public static long createVoidDataPoint(int generationMode)
|
||||
{
|
||||
long dataPoint = 0;
|
||||
dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
dataPoint += VOID_MASK << VOID_SHIFT;
|
||||
dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode)
|
||||
{
|
||||
return createDataPoint(
|
||||
ColorUtil.getAlpha(color),
|
||||
ColorUtil.getRed(color),
|
||||
ColorUtil.getGreen(color),
|
||||
ColorUtil.getBlue(color),
|
||||
height, depth, lightSky, lightBlock, generationMode);
|
||||
}
|
||||
|
||||
public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode)
|
||||
{
|
||||
long dataPoint = 0;
|
||||
dataPoint += ((alpha & ALPHA_MASK) >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT;
|
||||
dataPoint += (red & RED_MASK) << RED_SHIFT;
|
||||
dataPoint += (green & GREEN_MASK) << GREEN_SHIFT;
|
||||
dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT;
|
||||
dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
dataPoint += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT;
|
||||
dataPoint += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT;
|
||||
dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
public static short getHeight(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(long dataPoint)
|
||||
{
|
||||
|
||||
return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static short getAlpha(long dataPoint)
|
||||
{
|
||||
return (short) (((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT);
|
||||
}
|
||||
|
||||
public static short getRed(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
|
||||
public static int getLightSky(long dataPoint)
|
||||
{
|
||||
return (int) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static int getLightBlock(long dataPoint)
|
||||
{
|
||||
return (int) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static byte getGenerationMode(long dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isItVoid(long dataPoint)
|
||||
{
|
||||
return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1);
|
||||
}
|
||||
|
||||
public static boolean doesItExist(long dataPoint)
|
||||
{
|
||||
return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1);
|
||||
}
|
||||
|
||||
public static int getColor(long dataPoint)
|
||||
{
|
||||
int color = getBlue(dataPoint) << BLUE_COLOR_SHIFT;
|
||||
color += getRed(dataPoint) << BLUE_COLOR_SHIFT;
|
||||
return (int) (dataPoint >>> COLOR_SHIFT);
|
||||
}
|
||||
|
||||
public static int getLightColor(long dataPoint, boolean roof, boolean day)
|
||||
{
|
||||
int lightBlock = getLightBlock(dataPoint);
|
||||
int lightSky = getLightSky(dataPoint);
|
||||
int lightTint = LightTexture.pack(lightSky,lightBlock);
|
||||
|
||||
int red = (ColorUtil.getRed(lightTint) + getRed(dataPoint))/2;
|
||||
int green = (ColorUtil.getGreen(lightTint) + getGreen(dataPoint))/2;
|
||||
int blue = (ColorUtil.getBlue(lightTint) + getBlue(dataPoint))/2;
|
||||
/*
|
||||
red = LodUtil.clamp(0, getRed(dataPoint) + red, 255);
|
||||
green = LodUtil.clamp(0, getGreen(dataPoint) + green, 255);
|
||||
blue = LodUtil.clamp(0, getBlue(dataPoint) + blue, 255);*/
|
||||
|
||||
return ColorUtil.rgbToInt(red, green, blue);
|
||||
}
|
||||
|
||||
public static String toString(long dataPoint)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(getHeight(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getDepth(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getAlpha(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getRed(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getBlue(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getGreen(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getLightBlock(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getLightSky(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(getGenerationMode(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(isItVoid(dataPoint));
|
||||
s.append(" ");
|
||||
s.append(doesItExist(dataPoint));
|
||||
s.append('\n');
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
public static long mergeSingleData(long[] dataToMerge)
|
||||
{
|
||||
int numberOfChildren = 0;
|
||||
int numberOfVoidChildren = 0;
|
||||
|
||||
int tempAlpha = 0;
|
||||
int tempRed = 0;
|
||||
int tempGreen = 0;
|
||||
int tempBlue = 0;
|
||||
int tempHeight = 0;
|
||||
int tempDepth = 0;
|
||||
int tempLightBlock = 0;
|
||||
int tempLightSky = 0;
|
||||
byte tempGenMode = DistanceGenerationMode.SERVER.complexity;
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
for (long data : dataToMerge)
|
||||
{
|
||||
if (DataPointUtil.doesItExist(data))
|
||||
{
|
||||
allEmpty = false;
|
||||
if (!(DataPointUtil.isItVoid(data)))
|
||||
{
|
||||
numberOfChildren++;
|
||||
allVoid = false;
|
||||
tempAlpha += DataPointUtil.getAlpha(data);
|
||||
tempRed += DataPointUtil.getRed(data);
|
||||
tempGreen += DataPointUtil.getGreen(data);
|
||||
tempBlue += DataPointUtil.getBlue(data);
|
||||
tempHeight += DataPointUtil.getHeight(data);
|
||||
tempDepth += DataPointUtil.getDepth(data);
|
||||
tempLightBlock += DataPointUtil.getLightBlock(data);
|
||||
tempLightSky += DataPointUtil.getLightSky(data);
|
||||
}
|
||||
tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data));
|
||||
} else
|
||||
{
|
||||
tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity);
|
||||
}
|
||||
}
|
||||
|
||||
if (allEmpty)
|
||||
{
|
||||
//no child has been initialized
|
||||
return DataPointUtil.EMPTY_DATA;
|
||||
} else if (allVoid)
|
||||
{
|
||||
//all the children are void
|
||||
return DataPointUtil.createVoidDataPoint(tempGenMode);
|
||||
} else
|
||||
{
|
||||
//we have at least 1 child
|
||||
tempAlpha = tempAlpha / numberOfChildren;
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempHeight = tempHeight / numberOfChildren;
|
||||
tempDepth = tempDepth / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLightSky, tempLightBlock, tempGenMode);
|
||||
}
|
||||
}
|
||||
|
||||
public static long[] mergeVerticalData(long[][] dataToMerge)
|
||||
{
|
||||
boolean[] projection = ThreadMapUtil.getProjection(WORLD_HEIGHT + 1);
|
||||
int[][] heightAndDepth = ThreadMapUtil.getHeightAndDepth(WORLD_HEIGHT + 1);
|
||||
long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(dataToMerge.length);
|
||||
int genMode = DistanceGenerationMode.SERVER.complexity;
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
long singleData;
|
||||
|
||||
for(int k=0; k < projection.length; k++)
|
||||
projection[k] = false;
|
||||
int depth = 0;
|
||||
int height = 0;
|
||||
//We collect the indexes of the data, ordered by the depth
|
||||
for (int index = 0; index < dataToMerge.length; index++)
|
||||
{
|
||||
for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index][dataIndex];
|
||||
if (doesItExist(singleData))
|
||||
{
|
||||
genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!isItVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
depth = getDepth(singleData);
|
||||
height = getHeight(singleData);
|
||||
for (int y = depth; y <= height; y++)
|
||||
{
|
||||
projection[y] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//We check if there is any data that's not empty or void
|
||||
if (allEmpty)
|
||||
{
|
||||
return new long[]{EMPTY_DATA};
|
||||
}
|
||||
if (allVoid)
|
||||
{
|
||||
return new long[]{createVoidDataPoint(genMode)};
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
while (i < projection.length)
|
||||
{
|
||||
while (i < projection.length && !projection[i])
|
||||
{
|
||||
i++;
|
||||
}
|
||||
depth = i;
|
||||
while (i < projection.length && projection[i])
|
||||
{
|
||||
height = i;
|
||||
i++;
|
||||
}
|
||||
if(!(i < projection.length))
|
||||
break;
|
||||
heightAndDepth[count][0] = depth;
|
||||
heightAndDepth[count][1] = height;
|
||||
count++;
|
||||
}
|
||||
//As standard the vertical lods are ordered from top to bottom
|
||||
long[] dataPoint = new long[count];
|
||||
for (int j = count - 1; j >= 0; j--)
|
||||
{
|
||||
depth = heightAndDepth[j][0];
|
||||
height = heightAndDepth[j][1];
|
||||
for(int k = 0; k < dataToMerge.length; k++){
|
||||
singleDataToMerge[k] = 0;
|
||||
}
|
||||
for (int index = 0; index < dataToMerge.length; index++)
|
||||
{
|
||||
for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index][dataIndex];
|
||||
if (doesItExist(singleData) && !isItVoid(singleData))
|
||||
{
|
||||
if ((depth <= getDepth(singleData) && getDepth(singleData) <= height)
|
||||
|| (depth <= getHeight(singleData) && getHeight(singleData) <= height))
|
||||
{
|
||||
if(getHeight(singleData) > getHeight(singleDataToMerge[index]))
|
||||
{
|
||||
singleDataToMerge[index] = singleData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
long data = mergeSingleData(singleDataToMerge);
|
||||
dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data));
|
||||
}
|
||||
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
public static long[] compress(long[] data, byte detailLevel)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,19 @@ public class DetailDistanceUtil
|
||||
private static int base = 2;
|
||||
private static double logBase = Math.log(2);
|
||||
|
||||
private static int[] maxVerticalData = {
|
||||
8,
|
||||
4,
|
||||
4,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,};
|
||||
|
||||
private static LodDetail[] lodGenDetails = {
|
||||
LodDetail.FULL,
|
||||
LodDetail.HALF,
|
||||
@@ -147,7 +160,13 @@ public class DetailDistanceUtil
|
||||
|
||||
public static byte getLodDrawDetail(int detail)
|
||||
{
|
||||
return (byte) Math.max(detail, minDrawDetail);
|
||||
if (detail < minGenDetail)
|
||||
{
|
||||
return lodGenDetails[minGenDetail].detailLevel;
|
||||
} else
|
||||
{
|
||||
return lodGenDetails[detail].detailLevel;
|
||||
}
|
||||
}
|
||||
|
||||
public static LodDetail getLodGenDetail(int detail)
|
||||
@@ -176,6 +195,10 @@ public class DetailDistanceUtil
|
||||
}
|
||||
}
|
||||
|
||||
public static int getMaxVerticalData(int detail)
|
||||
{
|
||||
return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)];
|
||||
}
|
||||
|
||||
public static boolean regionInView(int playerPosX, int playerPosY, int playerPosZ, int xRot, int yRot, int fov, RegionPos regionPos)
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.seibel.lod.objects;
|
||||
package com.seibel.lod.util;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
@@ -64,7 +63,10 @@ public class LodUtil
|
||||
* and/or add a method to generate colors based on texture
|
||||
* issue #64 */
|
||||
public static final int STONE_COLOR_INT = LodUtil.colorToInt(new Color(150, 150, 150));
|
||||
|
||||
public static final int NETHERRACK_COLOR_INT = LodUtil.colorToInt(new Color(95, 38, 38));
|
||||
public static final int WARPED_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(34, 94, 85));
|
||||
public static final int CRIMSON_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(126, 27, 27));
|
||||
|
||||
/**
|
||||
* In order of nearest to farthest: <br>
|
||||
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black
|
||||
@@ -337,17 +339,19 @@ public class LodUtil
|
||||
{
|
||||
if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z))
|
||||
continue;
|
||||
/*
|
||||
long[] dataVertical = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
|
||||
long data = dataVertical[dataVertical.length - 1];
|
||||
|
||||
long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
|
||||
|
||||
short lodAverageHeight = DataPoint.getHeight(data);
|
||||
short lodAverageHeight = DataPointUtil.getHeight(data);
|
||||
|
||||
if (playerPos.getY() <= lodAverageHeight)
|
||||
{
|
||||
// don't draw Lod's that are taller than the player
|
||||
// to prevent LODs being drawn on top of the player
|
||||
posToSkip.add(new ChunkPos(x, z));
|
||||
}
|
||||
}*/
|
||||
posToSkip.add(new ChunkPos(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.seibel.lod.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class ThreadMapUtil
|
||||
{
|
||||
public static final ConcurrentMap<String,long[]> threadSingleAddDataMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[]> threadSingleGetDataMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[]> threadSingleUpdateMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[][]> threadBuilderArrayMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[][][]> threadBuilderVerticalArrayMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[]> threadVerticalAddDataMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[]> threadVerticalGetDataMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[][]> threadVerticalUpdateMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,int[]> threadVerticalIndexesMap = new ConcurrentHashMap();
|
||||
|
||||
|
||||
public static final ConcurrentMap<String,boolean[]> projectionMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,int[][]> heightAndDepthMap = new ConcurrentHashMap();
|
||||
public static final ConcurrentMap<String,long[]> singleDataToMergeMap = new ConcurrentHashMap();
|
||||
|
||||
|
||||
public static long[] getSingleAddDataArray(){
|
||||
if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadSingleAddDataMap.put(Thread.currentThread().getName(), new long[1]);
|
||||
}
|
||||
return threadSingleAddDataMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[] getSingleGetDataArray(){
|
||||
if(!threadSingleGetDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleGetDataMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadSingleGetDataMap.put(Thread.currentThread().getName(), new long[1]);
|
||||
}
|
||||
return threadSingleGetDataMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[] getSingleUpdateArray(){
|
||||
if(!threadSingleUpdateMap.containsKey(Thread.currentThread().getName()) || (threadSingleUpdateMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[4]);
|
||||
}
|
||||
return threadSingleUpdateMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[][] getBuilderArray(){
|
||||
if(!threadBuilderArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderArrayMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
long[][] array = new long[5][];
|
||||
threadBuilderArrayMap.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
return threadBuilderArrayMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[][][] getBuilderVerticalArray(){
|
||||
if(!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
long[][][] array = new long[5][][];
|
||||
threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[] addVerticalDataArray(){
|
||||
if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[16]);
|
||||
}
|
||||
return threadVerticalAddDataMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[] getVerticalGetDataArray(){
|
||||
if(!threadVerticalGetDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalGetDataMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadVerticalGetDataMap.put(Thread.currentThread().getName(), new long[16]);
|
||||
}
|
||||
return threadVerticalGetDataMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[][] getVerticalUpdateArray(){
|
||||
if(!threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][]);
|
||||
}
|
||||
return threadVerticalUpdateMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static int[] getVerticalIndexesArray(){
|
||||
if(!threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadVerticalIndexesMap.put(Thread.currentThread().getName(), new int[4]);
|
||||
}
|
||||
return threadVerticalIndexesMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static boolean[] getProjection(int size){
|
||||
if(!projectionMap.containsKey(Thread.currentThread().getName()) || (projectionMap.get(Thread.currentThread().getName()) == null) || (projectionMap.get(Thread.currentThread().getName()).length != size))
|
||||
{
|
||||
projectionMap.put(Thread.currentThread().getName(), new boolean[size]);
|
||||
}
|
||||
return projectionMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static int[][] getHeightAndDepth(int size){
|
||||
if(!heightAndDepthMap.containsKey(Thread.currentThread().getName()) || (heightAndDepthMap.get(Thread.currentThread().getName()) == null) || (heightAndDepthMap.get(Thread.currentThread().getName()).length != size))
|
||||
{
|
||||
heightAndDepthMap.put(Thread.currentThread().getName(), new int[size][2]);
|
||||
}
|
||||
return heightAndDepthMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static long[] getSingleAddDataToMerge(int size){
|
||||
if(!singleDataToMergeMap.containsKey(Thread.currentThread().getName()) || (singleDataToMergeMap.get(Thread.currentThread().getName()) == null) || (singleDataToMergeMap.get(Thread.currentThread().getName()).length != size))
|
||||
{
|
||||
singleDataToMergeMap.put(Thread.currentThread().getName(), new long[size]);
|
||||
}
|
||||
return singleDataToMergeMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user