diff --git a/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java
index 80fa33013..8f7928525 100644
--- a/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java
+++ b/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java
@@ -50,32 +50,32 @@ import net.minecraftforge.common.WorldWorkerManager;
public class LodNodeBufferBuilder
{
private Minecraft mc;
-
+
/** This holds the thread used to generate new LODs off the main thread. */
private ExecutorService genThread = Executors.newSingleThreadExecutor();
-
+
private LodNodeBuilder LodQuadTreeNodeBuilder;
-
+
/** The buffers that are used to create LODs using near fog */
public volatile BufferBuilder buildableNearBuffer;
/** The buffers that are used to create LODs using far fog */
public volatile BufferBuilder buildableFarBuffer;
-
+
/** if this is true the LOD buffers are currently being
* regenerated. */
public volatile boolean generatingBuffers = false;
-
+
/** if this is true new LOD buffers have been generated
* and are waiting to be swapped with the drawable buffers*/
private volatile boolean switchBuffers = false;
-
+
/** This keeps track of how many chunk generation requests are on going.
* This is to prevent chunks from being generated for a long time in an area
* the player is no longer in. */
public volatile AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0);
-
+
/** how many chunks to generate outside of the player's
* view distance at one time. (or more specifically how
* many requests to make at one time).
@@ -83,8 +83,8 @@ public class LodNodeBufferBuilder
* to make sure the CPU is always busy and we can generate LODs as quickly as
* possible. */
public int maxChunkGenRequests = LodConfig.CLIENT.numberOfWorldGenerationThreads.get() * 8;
-
-
+
+
public LodNodeBufferBuilder(LodNodeBuilder newLodBuilder)
{
mc = Minecraft.getInstance();
@@ -95,7 +95,7 @@ public class LodNodeBufferBuilder
private BiomeContainer biomeContainer = null;
private LodQuadTreeDimension previousDimension = null;
-
+
/**
* Create a thread to asynchronously generate LOD buffers
* centered around the given camera X and Z.
@@ -106,7 +106,7 @@ public class LodNodeBufferBuilder
* swapped with the drawable buffers in the LodRenderer to be drawn.
*/
public void generateLodBuffersAsync(LodNodeRenderer renderer, LodQuadTreeDimension lodDim,
- double playerX, double playerZ, int numbChunksWide)
+ double playerX, double playerZ, int numbChunksWide)
{
// only allow one generation process to happen at a time
if (generatingBuffers)
@@ -137,7 +137,7 @@ public class LodNodeBufferBuilder
int startZ = (-LodQuadTreeNode.CHUNK_WIDTH * (numbChunksWide / 2)) + playerZChunkOffset;
- Thread thread = new Thread(()->
+ Thread thread = new Thread(() ->
{
// index of the chunk currently being added to the
// generation list
@@ -154,7 +154,7 @@ public class LodNodeBufferBuilder
// generate our new buildable buffers
buildableNearBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT);
buildableFarBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT);
-
+
// x axis
for (int i = 0; i < numbChunksWide; i++)
{
@@ -162,29 +162,28 @@ public class LodNodeBufferBuilder
for (int j = 0; j < numbChunksWide; j++) {
int chunkX = i + Math.floorDiv(startX, LodQuadTreeNode.CHUNK_WIDTH);
int chunkZ = j + Math.floorDiv(startZ, LodQuadTreeNode.CHUNK_WIDTH);
-
+
// skip any chunks that Minecraft is going to render
if (isCoordInCenterArea(i, j, (numbChunksWide / 2))
&& renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ))) {
continue;
}
-
-
+
+
// set where this square will be drawn in the world
double xOffset = (LodQuadTreeNode.CHUNK_WIDTH * i) + // offset by the number of LOD blocks
startX;
- // 8 works for LODs the size of chunks
double yOffset = 0;
double zOffset = (LodQuadTreeNode.CHUNK_WIDTH * j) + startZ;
-
+
LodQuadTreeNode lod = lodDim.getLodFromCoordinates(new ChunkPos(chunkX, chunkZ), LodQuadTreeNode.CHUNK_LEVEL);
-
+
if (lod == null || lod.complexity == DistanceGenerationMode.NONE) {
// generate a new chunk if no chunk currently exists
// and we aren't waiting on any other chunks to generate
if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) {
ChunkPos pos = new ChunkPos(chunkX, chunkZ);
-
+
// alternate determining logic that
// can be used for debugging
// if (chunksToGen == null)
@@ -198,12 +197,12 @@ public class LodNodeBufferBuilder
// chunksToGen[chunkGenIndex] = pos;
// chunkGenIndex++;
// }
-
-
+
+
// determine if this position is closer to the player
// than the previous
int newDistance = playerChunkPos.getChessboardDistance(pos);
-
+
// issue #40
// TODO optimize this code,
// using the purely optimized code above we can achieve close to
@@ -214,7 +213,7 @@ public class LodNodeBufferBuilder
// this chunk is closer, clear any previous
// positions and update the new minimum distance
minChunkDist = newDistance;
-
+
// move all the old chunks into the reserve
ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests];
int oldToGenIndex = 0;
@@ -223,7 +222,7 @@ public class LodNodeBufferBuilder
// we don't check if the boundaries are good since
// the tmp array will always be the same length
// as chunksToGen and chunksToGenReserve
-
+
if (chunksToGen[oldToGenIndex] != null) {
// add all the closest chunks...
newReserve[tmpIndex] = chunksToGen[oldToGenIndex];
@@ -240,8 +239,8 @@ public class LodNodeBufferBuilder
}
}
chunksToGenReserve = newReserve;
-
-
+
+
chunkGenIndex = 0;
chunksToGen = new ChunkPos[maxChunkGenRequests];
chunksToGen[chunkGenIndex] = pos;
@@ -256,58 +255,51 @@ public class LodNodeBufferBuilder
chunkGenIndex++;
}
}
-
+
} // lod null and can generate more chunks
-
+
// don't render this null/empty chunk
continue;
-
+
} // lod null or empty
-
-
+
+
+ // should we draw near or far fog?
BufferBuilder currentBuffer = null;
if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
currentBuffer = buildableNearBuffer;
else
currentBuffer = buildableFarBuffer;
-
- // get the desired LodTemplate and
- // add this LOD to the buffer
+
+
+ // what detail level should this LOD be drawn at?
int distance = (int) Math.sqrt(Math.pow((mc.player.getX() - lod.startBlockPos.getX()),2) + Math.pow((mc.player.getZ() - lod.startBlockPos.getZ()),2));
LodDetail detail;
- if(distance < 200){
+ if(distance < (numbChunksWide / 2) * 16 * 0.2)
+ {
detail = LodDetail.HALF;
- }else if(distance < 400){
+ }
+ else if(distance < (numbChunksWide / 2) * 16 * 0.5)
+ {
detail = LodDetail.QUAD;
- }else if(distance < 600){
+ }
+ else if(distance < (numbChunksWide / 2) * 16 * 0.75)
+ {
detail = LodDetail.DOUBLE;
- }else{
+ }
+ else
+ {
detail = LodDetail.SINGLE;
}
+
+ // get the desired LodTemplate and
+ // add this LOD to the buffer
LodConfig.CLIENT.lodTemplate.get().
- template.addLodToBuffer(currentBuffer, lodDim, lod,
+ template.addLodToBuffer(currentBuffer, lodDim, lod,
xOffset , yOffset, zOffset, renderer.debugging, detail);
- /*
- LodDetail detail = LodConfig.CLIENT.lodDetail.get();
- for(int x = 0; x < detail.dataPointLengthCount; x++){
- for(int z = 0; z < detail.dataPointLengthCount; z++) {
- int posX = LodUtil.convertLevelPos(lod.startBlockPos.getX() + (x*detail.dataPointWidth), 0, detail.detailLevel);
- int posZ = LodUtil.convertLevelPos(lod.startBlockPos.getZ() + (z*detail.dataPointWidth), 0, detail.detailLevel);
- LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX, posZ, detail.detailLevel);
- System.out.print("printing ");
- System.out.println(newLod);
- if(newLod != null) {
- LodConfig.CLIENT.lodTemplate.get().
- template.addLodToBuffer(currentBuffer, lodDim, newLod,
- xOffset + (x*detail.dataPointWidth), yOffset, zOffset + (z*detail.dataPointWidth), renderer.debugging);
- }
- }
- }
- */
}
}
- //ClientProxy.LOGGER.info(numberOfChunksWaitingToGenerate.get());
// issue #19
// TODO add a way for a server side mod to generate chunks requested here
@@ -323,7 +315,7 @@ public class LodNodeBufferBuilder
chunksToGen[i] = chunksToGenReserve[j];
}
}
-
+
// start chunk generation
for(ChunkPos chunkPos : chunksToGen)
{
@@ -340,7 +332,7 @@ public class LodNodeBufferBuilder
WorldWorkerManager.addWorker(genWorker);
}
}
-
+
// finish the buffer building
buildableNearBuffer.end();
buildableFarBuffer.end();
diff --git a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java
index 67d18f0da..9d9804ec9 100644
--- a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java
@@ -21,11 +21,10 @@ import java.awt.Color;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.enums.ShadingMode;
import com.seibel.lod.handlers.LodConfig;
-import com.seibel.lod.objects.LodQuadTree;
import com.seibel.lod.objects.LodQuadTreeDimension;
import com.seibel.lod.objects.LodQuadTreeNode;
-
import com.seibel.lod.util.LodUtil;
+
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.AxisAlignedBB;
@@ -34,7 +33,7 @@ import net.minecraft.util.math.AxisAlignedBB;
* Builds LODs as rectangular prisms.
*
* @author James Seibel
- * @version 8-8-2021
+ * @version 8-10-2021
*/
public class CubicLodNodeTemplate extends AbstractLodNodeTemplate
{
@@ -47,35 +46,24 @@ public class CubicLodNodeTemplate extends AbstractLodNodeTemplate
public void addLodToBuffer(BufferBuilder buffer,
LodQuadTreeDimension lodDim, LodQuadTreeNode lod,
double xOffset, double yOffset, double zOffset,
- boolean debugging, LodDetail detail) {
+ boolean debugging, LodDetail detail)
+ {
AxisAlignedBB bbox;
-
- // Add this LOD to the BufferBuilder
- int halfWidth = LodQuadTreeNode.CHUNK_WIDTH / 2;
- //LodDetail detail = LodConfig.CLIENT.lodDetail.get();
-/*
- bbox = generateBoundingBox(
- lod.getLodDataPoint().height,
- lod.getLodDataPoint().depth,
- lod.width,
- xOffset - halfWidth,
- yOffset,
- zOffset - halfWidth);
-
- if (bbox != null) {
- addBoundingBoxToBuffer(buffer, bbox, lod.getLodDataPoint().color);
- }
-
- */
- LodQuadTree chunkTree = lodDim.getLevelFromPos(lod.posX, lod.posZ, lod.detailLevel);
- for(int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++) {
+
+ // add each LOD for the detail level
+ for(int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
+ {
+ // how much to offset this LOD by
int startX = detail.startX[i];
int startZ = detail.startZ[i];
- int posX = LodUtil.convertLevelPos((int) xOffset+startX,0, detail.detailLevel);
- int posZ = LodUtil.convertLevelPos((int) zOffset+startZ,0, detail.detailLevel);;
- //LodQuadTreeNode newLod = chunkTree.getNodeAtPos(posX ,posZ ,detail.detailLevel);
- LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX ,posZ ,detail.detailLevel);
- if(newLod != null) {
+
+ // get the QuadTree location of this LOD
+ int posX = LodUtil.convertLevelPos((int) xOffset + startX, 0, detail.detailLevel);
+ int posZ = LodUtil.convertLevelPos((int) zOffset + startZ, 0, detail.detailLevel);
+
+ LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX, posZ, detail.detailLevel);
+ if(newLod != null)
+ {
bbox = generateBoundingBox(
newLod.getLodDataPoint().height,
newLod.getLodDataPoint().depth,
@@ -83,9 +71,17 @@ public class CubicLodNodeTemplate extends AbstractLodNodeTemplate
xOffset + startX,
yOffset,
zOffset + startZ);
-
- if (bbox != null) {
- addBoundingBoxToBuffer(buffer, bbox, newLod.getLodDataPoint().color);
+
+
+ Color color = newLod.getLodDataPoint().color;
+ if (LodConfig.CLIENT.debugMode.get())
+ {
+ color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detail.detailLevel];
+ }
+
+ if (bbox != null)
+ {
+ addBoundingBoxToBuffer(buffer, bbox, color);
}
}
}
diff --git a/src/main/java/com/seibel/lod/handlers/LodConfig.java b/src/main/java/com/seibel/lod/handlers/LodConfig.java
index 87e3f984d..c30e2f3f1 100644
--- a/src/main/java/com/seibel/lod/handlers/LodConfig.java
+++ b/src/main/java/com/seibel/lod/handlers/LodConfig.java
@@ -39,9 +39,10 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
/**
+ * This handles any configuration the user has access to.
*
* @author James Seibel
- * @version 7-25-2021
+ * @version 8-10-2021
*/
@Mod.EventBusSubscriber
public class LodConfig
@@ -106,11 +107,10 @@ public class LodConfig
debugMode = builder
.comment("\n\n"
- + " If false the LODs will draw with their normal world colors. \n"
- + " If true they will draw as a black and white checkerboard. \n"
- + " This can be used for debugging or imagining you are playing a \n"
- + " giant game of chess ;) \n")
- .define("drawCheckerBoard", false);
+ + " If false the LODs will draw with their normal colors. \n"
+ + " If true LODs colors will be based on their detail \n"
+ + " level. \n")
+ .define("debugMode", false);
lodTemplate = builder
.comment("\n\n"
diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java
index a6b3309f9..726f977ac 100644
--- a/src/main/java/com/seibel/lod/util/LodUtil.java
+++ b/src/main/java/com/seibel/lod/util/LodUtil.java
@@ -21,8 +21,8 @@ import java.awt.Color;
import java.io.File;
import com.seibel.lod.objects.LodQuadTreeNode;
-
import com.seibel.lod.objects.RegionPos;
+
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.server.integrated.IntegratedServer;
@@ -37,7 +37,7 @@ import net.minecraft.world.server.ServerWorld;
* This class holds methods and constants that may be used in multiple places.
*
* @author James Seibel
- * @version 8-8-2021
+ * @version 8-10-2021
*/
public class LodUtil
{
@@ -50,6 +50,14 @@ public class LodUtil
public static final Color COLOR_DEBUG_WHITE = new Color(255, 255, 255, DEBUG_ALPHA);
public static final Color COLOR_INVISIBLE = new Color(0,0,0,0);
+ /**
+ * In order of nearest to farthest:
+ * Orange, Yellow, Green, Blue, Magenta, Red
+ *
+ * Black is included in index 0, but it shouldn't be used normally.
+ */
+ public static final Color DEBUG_DETAIL_LEVEL_COLORS[] = new Color[] { Color.BLACK, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA, Color.RED};
+
/**
* Gets the first valid ServerWorld.