Fixed the artifacts (was caused by wrong array initialisation) and added the reset to while changing dimension

This commit is contained in:
Leonardo
2021-09-22 19:38:04 +02:00
parent da413f594e
commit d65bfd408e
9 changed files with 127 additions and 89 deletions
@@ -18,7 +18,6 @@
package com.seibel.lod.builders;
import java.awt.Color;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@@ -42,13 +41,11 @@ import com.seibel.lod.util.LodUtil;
import com.seibel.lod.util.ThreadMapUtil;
import com.seibel.lod.wrappers.MinecraftWrapper;
import net.minecraft.block.AbstractPlantBlock;
import net.minecraft.block.Block;
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.material.MaterialColor;
import net.minecraft.client.renderer.model.BakedQuad;
@@ -69,8 +66,6 @@ import net.minecraft.world.gen.Heightmap;
import net.minecraftforge.client.extensions.IForgeBakedModel;
import net.minecraftforge.client.model.data.ModelDataMap;
import javax.xml.crypto.Data;
/**
* This object is in charge of creating Lod related objects. (specifically: Lod
* World, Dimension, and Region objects)
@@ -156,6 +151,7 @@ public class LodBuilder
if (lodWorld.getLodDimension(dim) == null)
{
lodDim = new LodDimension(dim, lodWorld, defaultDimensionWidthInRegions);
ThreadMapUtil.clearMaps();
lodWorld.addLodDimension(lodDim);
lodDim.treeGenerator(playerPosX, playerPosZ);
} else
@@ -238,7 +234,7 @@ public class LodBuilder
break;
case MULTI_LOD:
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT, DetailDistanceUtil.getMaxVerticalData(detailLevel));
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel));
//lodDim.clear(detailLevel, posX, posZ);
@@ -271,12 +267,19 @@ public class LodBuilder
private long[] createVerticalDataToMerge(HorizontalResolution detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
{
int size = 1 << detail.detailLevel;
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel];
Arrays.fill(dataToMerge, DataPointUtil.EMPTY_DATA);
int verticalData = DataPointUtil.WORLD_HEIGHT;
if (dataToMerge == null || dataToMerge.length != size*size*DataPointUtil.worldHeight + 1)
dataToMerge = new long[size*size*DataPointUtil.worldHeight + 1];
for (int i = 0; i < dataToMerge.length; i++)
dataToMerge[i] = DataPointUtil.EMPTY_DATA;
int verticalData = DataPointUtil.worldHeight;
ChunkPos chunkPos = chunk.getPos();
int size = 1 << detail.detailLevel;
int height;
int depth;
int color;
@@ -304,7 +307,7 @@ public class LodBuilder
zAbs = chunkPos.getMinBlockZ() + zRel;
//Calculate the height of the lod
yAbs = DataPointUtil.WORLD_HEIGHT+2;
yAbs = DataPointUtil.worldHeight +2;
int count = 0;
boolean topBlock = true;
while (yAbs > 0)
@@ -111,6 +111,10 @@ public class LodNodeGenWorker implements IWorker
newLodDimension, newServerWorld);
}
public static void resetGenerator(){
ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build());
}
@Override
public boolean doWork()
{
@@ -125,7 +125,7 @@ public class LodConfig
+ DetailDropOff.BY_BLOCK + " in chunks circles around the player (best quality option, may cause stuttering)\n"
+ DetailDropOff.BY_REGION_FANCY + " in regions circles around the player (quality option)\n"
+ DetailDropOff.BY_REGION_FAST + " in regions circles around the player (performance option)\n")
.defineEnum("detailDropOff", DetailDropOff.BY_REGION_FAST);
.defineEnum("detailDropOff", DetailDropOff.BY_BLOCK);
drawResolution = builder
.comment("\n\n"
@@ -28,11 +28,7 @@ import com.seibel.lod.enums.GenerationPriority;
import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.enums.VerticalQuality;
import com.seibel.lod.handlers.LodDimensionFileHandler;
import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.DetailDistanceUtil;
import com.seibel.lod.util.LevelPosUtil;
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;
@@ -535,23 +531,9 @@ public class LodDimension
int posX;
int posZ;
long data;
int numbChunksWide = (width) * 32;
//int circleLimit = Integer.MAX_VALUE;
int numbChunksWide = (width) * 32 * 2;
for (int i = 0; i < numbChunksWide * numbChunksWide; i++)
{
// use this for square generation
if (maxDataToGenerate <= 0)
{
break;
}
// use this for circular generation
/*if (circleLimit < Math.abs(x) && circleLimit < Math.abs(z))
break;
if (maxDataToGenerate == 0)
{
circleLimit = (int) (Math.abs(x) * 1.6f);
}*/
xChunkToCheck = x + playerChunkX;
@@ -568,8 +550,8 @@ public class LodDimension
if (DataPointUtil.getGenerationMode(data) < LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get().complexity)
{
posToGenerate.addPosToGenerate(detailLevel, posX, posZ);
if (maxDataToGenerate >= 0)
maxDataToGenerate--;
//if (maxDataToGenerate >= 0)
// maxDataToGenerate--;
}
if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
{
@@ -88,8 +88,7 @@ public class SingleLevelContainer implements LevelContainer
{
newData = 3;
index++;
}
else if (index + 7 >= inputData.length)
} else if (index + 7 >= inputData.length)
break;
else
{
@@ -126,7 +125,8 @@ public class SingleLevelContainer implements LevelContainer
addSingleData(data, posX, posZ);
}
public int getMaxVerticalData(){
public int getMaxVerticalData()
{
return 1;
}
@@ -142,7 +142,11 @@ public class SingleLevelContainer implements LevelContainer
{
int index = 0;
int tempIndex;
byte[] tempData = ThreadMapUtil.getSaveContainer(1 + (size * size * 8));
byte[] tempData = ThreadMapUtil.getSaveContainer();
if (tempData == null || tempData.length != (1 + (size * size * 8)))
tempData = new byte[1 + (size * size * 8)];
else
Arrays.fill(tempData, (byte) 0);
tempData[index] = detailLevel;
index++;
for (int x = 0; x < size; x++)
@@ -177,11 +181,13 @@ public class SingleLevelContainer implements LevelContainer
}
public int getMaxNumberOfLods(){
return size*size*getMaxVerticalData();
public int getMaxNumberOfLods()
{
return size * size * getMaxVerticalData();
}
public int getMaxMemoryUse(){
public int getMaxMemoryUse()
{
return getMaxNumberOfLods() * 2; //2 byte
}
}
@@ -133,9 +133,13 @@ public class VerticalLevelContainer implements LevelContainer
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
{
//We reset the array
int lowerMaxVerticalData = lowerLevelContainer.getMaxVerticalData();
long[] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(detailLevel);
Arrays.fill(dataToMerge, DataPointUtil.EMPTY_DATA);
long[] dataToMerge = ThreadMapUtil.getVerticalUpdateArray()[detailLevel];
if(dataToMerge == null || dataToMerge.length != 4*lowerLevelContainer.getMaxVerticalData())
dataToMerge = new long[4 * lowerLevelContainer.getMaxVerticalData()];
else
Arrays.fill(dataToMerge, DataPointUtil.EMPTY_DATA);
int lowerMaxVertical = dataToMerge.length/4;
int childPosX;
int childPosZ;
@@ -170,7 +174,12 @@ public class VerticalLevelContainer implements LevelContainer
byte last = -1;
int x = size * size * maxVerticalData;
int tempIndex;
byte[] tempData = ThreadMapUtil.getSaveContainer(2 + (x * 8));
byte[] tempData = ThreadMapUtil.getSaveContainer();
if(tempData == null || tempData.length != (2 + (x * 8)))
tempData = new byte[2 + (x * 8)];
else
Arrays.fill(tempData, (byte) 0);
tempData[index] = detailLevel;
index++;
tempData[index] = (byte) maxVerticalData;
@@ -17,6 +17,9 @@
*/
package com.seibel.lod.proxy;
import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.ThreadMapUtil;
import net.minecraft.world.DimensionType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
@@ -85,7 +88,7 @@ public class ClientProxy
* to the LOD view distance
*/
private boolean recalculateWidths = false;
private DimensionType currentDimension = null;
public ClientProxy()
{
@@ -112,9 +115,15 @@ public class ClientProxy
// only run the first time setup once
if (!firstTimeSetupComplete)
{
ThreadMapUtil.clearMaps();
firstFrameSetup();
}
if(mc.getCurrentDimension() != currentDimension)
{
currentDimension = mc.getCurrentDimension();
reset();
}
DetailDistanceUtil.updateSettings();
if (mc == null || mc.getPlayer() == null || !lodWorld.getIsWorldLoaded())
@@ -235,6 +244,7 @@ public class ClientProxy
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
DataPointUtil.worldHeight = event.getWorld().getHeight();
// the player just loaded a new world/dimension
lodWorld.selectWorld(LodUtil.getWorldID(event.getWorld()));
// make sure the correct LODs are being rendered
@@ -360,8 +370,15 @@ public class ClientProxy
firstTimeSetupComplete = true;
}
public static void reset()
{
lodBufferBuilder = new LodBufferBuilder();
renderer = new LodRenderer(lodBufferBuilder);
LodNodeGenWorker.resetGenerator();
ThreadMapUtil.clearMaps();
}
//================//
// public getters //
@@ -31,7 +31,7 @@ public class DataPointUtil
//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 static int worldHeight = 256;
public final static int ALPHA_DOWNSIZE_SHIFT = 4;
@@ -279,14 +279,32 @@ public class DataPointUtil
public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData)
{
int size = dataToMerge.length / inputVerticalData;
short[] projection = ThreadMapUtil.getProjectionShort((WORLD_HEIGHT) / 16 + 2);
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((WORLD_HEIGHT + 1) * 2);
long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(size);
long[] dataPoint = ThreadMapUtil.verticalDataArray(WORLD_HEIGHT + 1);
Arrays.fill(projection, (short) 0);
Arrays.fill(heightAndDepth, (short) 0);
Arrays.fill(singleDataToMerge, EMPTY_DATA);
Arrays.fill(dataPoint, EMPTY_DATA);
//We initialise the arrays that are going to be used
short[] projection = ThreadMapUtil.getProjectionShort();
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth();
long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge();
long[] dataPoint = ThreadMapUtil.verticalDataArray();
if (projection == null || projection.length != (worldHeight) / 16 + 1)
projection = new short[(worldHeight) / 16 + 1];
else
Arrays.fill(projection, (short) 0);
if (heightAndDepth == null || heightAndDepth.length != (worldHeight + 1) * 2)
heightAndDepth = new short[(worldHeight + 1) * 2];
else
Arrays.fill(heightAndDepth, (short) 0);
if (singleDataToMerge == null || singleDataToMerge.length != size)
singleDataToMerge = new long[size];
else
Arrays.fill(singleDataToMerge, EMPTY_DATA);
if (dataPoint == null || dataPoint.length != worldHeight + 1)
dataPoint = new long[worldHeight + 1];
else
Arrays.fill(dataPoint, EMPTY_DATA);
int genMode = DistanceGenerationMode.SERVER.complexity;
boolean allEmpty = true;
@@ -355,7 +373,7 @@ public class DataPointUtil
if (i == projection.length) //solid to WORLD_HEIGHT
{
heightAndDepth[count * 2] = depth;
heightAndDepth[count * 2 + 1] = WORLD_HEIGHT - 1;
heightAndDepth[count * 2 + 1] = (short) (worldHeight - 1);
break;
}
while ((((projection[i] >>> ii) & 1) == 1)) ii++;
@@ -370,7 +388,7 @@ public class DataPointUtil
int j = 0;
while (count > maxVerticalData)
{
ii = WORLD_HEIGHT;
ii = worldHeight;
for (i = 0; i < count - 1; i++)
{
if (heightAndDepth[(i + 1) * 2] - heightAndDepth[i * 2 + 1] < ii)
@@ -19,7 +19,7 @@ public class ThreadMapUtil
{
if (!threadSingleUpdateMap.containsKey(Thread.currentThread().getName()) || (threadSingleUpdateMap.get(Thread.currentThread().getName()) == null))
{
threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[4]);
threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[0]);
}
return threadSingleUpdateMap.get(Thread.currentThread().getName());
}
@@ -39,71 +39,70 @@ public class ThreadMapUtil
if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null))
{
long[][] array = new long[5][];
for(int i = 0; i < array.length; i++)
{
int size = 1 << i;
array[i] = new long[size * size * DataPointUtil.WORLD_HEIGHT];
}
threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
}
return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName());
}
public static long[] verticalDataArray(int count)
public static long[] verticalDataArray()
{
if (!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null))
{
threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[count]);
}
for(int i = 0; i < threadVerticalAddDataMap.get(Thread.currentThread().getName()).length ; i++)
{
threadVerticalAddDataMap.get(Thread.currentThread().getName())[i] = DataPointUtil.EMPTY_DATA;
threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[0]);
}
return threadVerticalAddDataMap.get(Thread.currentThread().getName());
}
public static short[] getProjectionShort(int size){
if(!projectionShortMap.containsKey(Thread.currentThread().getName()) || (projectionShortMap.get(Thread.currentThread().getName()) == null) || (projectionShortMap.get(Thread.currentThread().getName()).length != size))
public static short[] getProjectionShort(){
if(!projectionShortMap.containsKey(Thread.currentThread().getName()) || (projectionShortMap.get(Thread.currentThread().getName()) == null))
{
projectionShortMap.put(Thread.currentThread().getName(), new short[size]);
projectionShortMap.put(Thread.currentThread().getName(), new short[0]);
}
return projectionShortMap.get(Thread.currentThread().getName());
}
public static short[] getHeightAndDepth(int size){
if(!heightAndDepthMap.containsKey(Thread.currentThread().getName()) || (heightAndDepthMap.get(Thread.currentThread().getName()) == null) || (heightAndDepthMap.get(Thread.currentThread().getName()).length != size))
public static short[] getHeightAndDepth(){
if(!heightAndDepthMap.containsKey(Thread.currentThread().getName()) || (heightAndDepthMap.get(Thread.currentThread().getName()) == null))
{
heightAndDepthMap.put(Thread.currentThread().getName(), new short[size]);
heightAndDepthMap.put(Thread.currentThread().getName(), new short[0]);
}
return heightAndDepthMap.get(Thread.currentThread().getName());
}
public static byte[] getSaveContainer(int size){
if(!saveContainer.containsKey(Thread.currentThread().getName()) || (saveContainer.get(Thread.currentThread().getName()) == null) || (saveContainer.get(Thread.currentThread().getName()).length != size))
public static byte[] getSaveContainer(){
if(!saveContainer.containsKey(Thread.currentThread().getName()) || (saveContainer.get(Thread.currentThread().getName()) == null))
{
saveContainer.put(Thread.currentThread().getName(), new byte[size]);
saveContainer.put(Thread.currentThread().getName(), new byte[0]);
}
return saveContainer.get(Thread.currentThread().getName());
}
public static long[] getVerticalUpdateArray(byte detailLevel){
if(!verticalUpdate.containsKey(Thread.currentThread().getName()) || (verticalUpdate.get(Thread.currentThread().getName()) == null) || (verticalUpdate.get(Thread.currentThread().getName())[detailLevel].length != 4*DetailDistanceUtil.getMaxVerticalData(detailLevel)))
public static long[][] getVerticalUpdateArray(){
if(!verticalUpdate.containsKey(Thread.currentThread().getName()) || (verticalUpdate.get(Thread.currentThread().getName()) == null))
{
long[][] array = new long[10][];
for(int i = 0; i < array.length; i++)
{
array[i] = new long[4 * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
}
verticalUpdate.put(Thread.currentThread().getName(), array);
}
return verticalUpdate.get(Thread.currentThread().getName())[detailLevel];
return verticalUpdate.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))
public static long[] getSingleAddDataToMerge(){
if(!singleDataToMergeMap.containsKey(Thread.currentThread().getName()) || (singleDataToMergeMap.get(Thread.currentThread().getName()) == null))
{
singleDataToMergeMap.put(Thread.currentThread().getName(), new long[size]);
singleDataToMergeMap.put(Thread.currentThread().getName(), new long[0]);
}
return singleDataToMergeMap.get(Thread.currentThread().getName());
}
public static void clearMaps(){
threadSingleUpdateMap.clear();
threadBuilderArrayMap.clear();
threadBuilderVerticalArrayMap.clear();
threadVerticalAddDataMap.clear();
saveContainer.clear();
projectionShortMap.clear();
heightAndDepthMap.clear();
singleDataToMergeMap.clear();
verticalUpdate.clear();
}
}