diff --git a/src/main/java/com/backsun/lod/LodMain.java b/src/main/java/com/backsun/lod/LodMain.java
index 78411042c..61ceebbf8 100644
--- a/src/main/java/com/backsun/lod/LodMain.java
+++ b/src/main/java/com/backsun/lod/LodMain.java
@@ -16,6 +16,10 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
/**
+ * Initialize and setup the Mod.
+ *
+ * If you are looking for the real start of the mod
+ * check out the ClientProxy.
*
* @author James Seibel
* @version 02-07-2021
diff --git a/src/main/java/com/backsun/lod/builders/BuildBufferThread.java b/src/main/java/com/backsun/lod/builders/BuildBufferThread.java
index 809a3445f..df540e497 100644
--- a/src/main/java/com/backsun/lod/builders/BuildBufferThread.java
+++ b/src/main/java/com/backsun/lod/builders/BuildBufferThread.java
@@ -5,7 +5,6 @@ import java.util.concurrent.Callable;
import org.lwjgl.opengl.GL11;
import com.backsun.lod.objects.NearFarBuffer;
-import com.backsun.lod.renderer.RenderUtil;
import com.backsun.lod.util.enums.FogDistance;
import net.minecraft.client.renderer.BufferBuilder;
@@ -13,10 +12,12 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.AxisAlignedBB;
/**
- *
+ * This object is used to create NearFarBuffer objects
+ * in a thread independent way, so multiple of these objects can be
+ * created and executed in parallel to populate BufferBuilders.
*
* @author James Seibel
- * @version 02-21-2021
+ * @version 02-22-2021
*/
public class BuildBufferThread implements Callable
{
@@ -70,6 +71,9 @@ public class BuildBufferThread implements Callable
int blue;
int alpha;
+ // this is done if the FogDistance is either
+ // NEAR or FAR, if it is NEAR_AND_FAR
+ // the buffer is determined for each LOD
if (distanceMode == FogDistance.NEAR)
{
currentBuffer = nearBuffer;
@@ -97,10 +101,10 @@ public class BuildBufferThread implements Callable
blue = colors[i][j].getBlue();
alpha = colors[i][j].getAlpha();
- // choose which buffer to add these LODs too
+
if (distanceMode == FogDistance.NEAR_AND_FAR)
{
- if (RenderUtil.isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
+ if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
currentBuffer = nearBuffer;
else
currentBuffer = farBuffer;
@@ -193,6 +197,22 @@ public class BuildBufferThread implements Callable
{
buffer.pos(x, y, z).color(red, green, blue, alpha).endVertex();
}
-
+
+
+
+ /**
+ * Find the coordinates that are in the center half of the given
+ * 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
+ */
+ private static boolean isCoordinateInNearFogArea(int chunkX, int chunkZ, int lodRadius)
+ {
+ int halfRadius = lodRadius / 2;
+
+ return (chunkX >= lodRadius - halfRadius
+ && chunkX <= lodRadius + halfRadius)
+ &&
+ (chunkZ >= lodRadius - halfRadius
+ && chunkZ <= lodRadius + halfRadius);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/backsun/lod/builders/LodBuilder.java b/src/main/java/com/backsun/lod/builders/LodBuilder.java
index ac310ef32..57e720997 100644
--- a/src/main/java/com/backsun/lod/builders/LodBuilder.java
+++ b/src/main/java/com/backsun/lod/builders/LodBuilder.java
@@ -3,7 +3,7 @@ package com.backsun.lod.builders;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import com.backsun.lod.handlers.LodFileHandler;
+import com.backsun.lod.handlers.LodDimensionFileHandler;
import com.backsun.lod.objects.LodChunk;
import com.backsun.lod.objects.LodDimension;
import com.backsun.lod.objects.LodWorld;
@@ -20,12 +20,12 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
* (specifically: Lod World, Dimension, Region, and Chunk objects)
*
* @author James Seibel
- * @version 2-21-2021
+ * @version 2-22-2021
*/
public class LodBuilder
{
- private ExecutorService lodGenThreadPool = Executors.newFixedThreadPool(1);
- public LodWorld lodWorld;
+ private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor();
+ public volatile LodWorld lodWorld;
/** Default size of any LOD regions we use */
public int regionWidth = 5;
@@ -41,7 +41,7 @@ public class LodBuilder
* Returns LodWorld so that it can be passed
* to the LodRenderer.
*/
- public LodWorld generateLodChunk(Chunk chunk)
+ public LodWorld generateLodChunkAsync(Chunk chunk)
{
Minecraft mc = Minecraft.getMinecraft();
@@ -68,13 +68,13 @@ public class LodBuilder
if (lodWorld == null)
{
- lodWorld = new LodWorld(LodFileHandler.getWorldName());
+ lodWorld = new LodWorld(LodDimensionFileHandler.getWorldName());
}
else
{
// if we have a lodWorld make sure
// it is for this minecraft world
- if (!lodWorld.worldName.equals(LodFileHandler.getWorldName()))
+ if (!lodWorld.worldName.equals(LodDimensionFileHandler.getWorldName()))
{
// this lodWorld isn't for this minecraft world
// delete it so we can get a new one
@@ -106,7 +106,6 @@ public class LodBuilder
// they will throw errors as they try to access things that no longer
// exist.
}
-
});
lodGenThreadPool.execute(thread);
@@ -119,9 +118,9 @@ public class LodBuilder
*/
public boolean isValidChunk(Chunk chunk)
{
- ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
+ ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray();
- for(ExtendedBlockStorage e : data)
+ for(ExtendedBlockStorage e : blockStorage)
{
if(e != null && !e.isEmpty())
{
diff --git a/src/main/java/com/backsun/lod/handlers/LodFileHandler.java b/src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java
similarity index 74%
rename from src/main/java/com/backsun/lod/handlers/LodFileHandler.java
rename to src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java
index fe666080f..574a3a69c 100644
--- a/src/main/java/com/backsun/lod/handlers/LodFileHandler.java
+++ b/src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java
@@ -23,9 +23,9 @@ import net.minecraft.world.storage.ISaveHandler;
* @author James Seibel
* @version 01-30-2021
*/
-public class LodFileHandler
+public class LodDimensionFileHandler
{
- private LodDimension loadedRegion = null;
+ private LodDimension loadedDimension = null;
public long regionLastWriteTime[][];
// String s = Minecraft.getMinecraftDir().getCanonicalPath() + "/saves/" + world.getSaveHandler().getSaveDirectoryName() + "/data/AA/World" + world.provider.dimensionId + ".dat";
@@ -36,19 +36,17 @@ public class LodFileHandler
private final String FILE_EXTENSION = ".txt";
private ExecutorService fileWritingThreadPool = Executors.newFixedThreadPool(1);
- /** Is true if the readyToReadAndWrite is false */
- private boolean waitingToSaveRegions = false;
- public LodFileHandler(ISaveHandler newSaveHandler, LodDimension newLoadedRegion)
+ public LodDimensionFileHandler(ISaveHandler newSaveHandler, LodDimension newLoadedDimension)
{
saveHandler = newSaveHandler;
- loadedRegion = newLoadedRegion;
+ loadedDimension = newLoadedDimension;
// these two variable are used in sync with the LodDimension
- regionLastWriteTime = new long[loadedRegion.getWidth()][loadedRegion.getWidth()];
- for(int i = 0; i < loadedRegion.getWidth(); i++)
- for(int j = 0; j < loadedRegion.getWidth(); j++)
+ regionLastWriteTime = new long[loadedDimension.getWidth()][loadedDimension.getWidth()];
+ for(int i = 0; i < loadedDimension.getWidth(); i++)
+ for(int j = 0; j < loadedDimension.getWidth(); j++)
regionLastWriteTime[i][j] = -1;
if (saveHandler != null && saveHandler.getWorldDirectory() != null)
@@ -141,8 +139,10 @@ public class LodFileHandler
// Save to File //
//==============//
-
- public synchronized void saveDirtyRegionsToFile()
+ /**
+ * Save all dirty regions in this LodDimension to file.
+ */
+ public synchronized void saveDirtyRegionsToFileAsync()
{
// we don't currently support reading or writing
// files when connected to a server
@@ -150,64 +150,31 @@ public class LodFileHandler
return;
if (!readyToReadAndWrite())
- {
// we aren't ready to read and write yet
- if(!waitingToSaveRegions)
- {
- waitingToSaveRegions = true;
-
- // retry until we are able to read and write
- // then wake up the fileWritingThreadPool
- Thread retryReady = new Thread(() ->
- {
- try
- {
- // check once every so often so see
- // if anything has changed so we can
- // start reading and writing files
- while(!readyToReadAndWrite())
- {
- this.wait(1000);
- // get the save handler again, if for some
- // reason the original handler was null
- saveHandler = Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler();
- save_dir = getWorldSaveDirectory();
- }
-
- // we can start writing files now
- fileWritingThreadPool.execute(saveDirtyRegionsThread);
- waitingToSaveRegions = false;
- }
- catch (InterruptedException e)
- { /* should never be called */}
- });
-
- retryReady.run();
- }
-
return;
- }
fileWritingThreadPool.execute(saveDirtyRegionsThread);
}
private Thread saveDirtyRegionsThread = new Thread(() ->
{
- for(int i = 0; i < loadedRegion.getWidth(); i++)
+ for(int i = 0; i < loadedDimension.getWidth(); i++)
{
- for(int j = 0; j < loadedRegion.getWidth(); j++)
+ for(int j = 0; j < loadedDimension.getWidth(); j++)
{
- if(loadedRegion.isRegionDirty[i][j])
+ if(loadedDimension.isRegionDirty[i][j])
{
- saveRegionToDisk(loadedRegion.regions[i][j]);
- loadedRegion.isRegionDirty[i][j] = false;
+ saveRegionToDisk(loadedDimension.regions[i][j]);
+ loadedDimension.isRegionDirty[i][j] = false;
}
}
}
-
- waitingToSaveRegions = false;
});
-
+ /**
+ * Save a specific region to disk.
+ * Note: it will save to the LodDimension that this
+ * handler is associated with.
+ */
private void saveRegionToDisk(LodRegion region)
{
if (!readyToReadAndWrite() || region == null)
@@ -258,15 +225,13 @@ public class LodFileHandler
* Return the name of the file that should contain the
* region at the given x and z.
* Returns null if this object isn't ready to read and write.
- * @param regionX
- * @param regionZ
*/
private String getFileNameForRegion(int regionX, int regionZ)
{
if (!readyToReadAndWrite())
return null;
- return save_dir + "\\lod_data\\DIM" + loadedRegion.dimension.getId() + "\\" +
+ return save_dir + "\\lod_data\\DIM" + loadedDimension.dimension.getId() + "\\" +
FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION;
}
@@ -274,6 +239,8 @@ public class LodFileHandler
/**
* Returns if this FileHandler is ready to read
* and write files.
+ *
+ * This returns true when the world save directory is known.
*/
public boolean readyToReadAndWrite()
{
@@ -306,6 +273,8 @@ public class LodFileHandler
/**
+ * Gets the canonical path to the world save folder.
+ *
* Returns null if there was an IO Exception
*/
private String getWorldSaveDirectory()
diff --git a/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java b/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java
index 65a3d9788..12215fda5 100644
--- a/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java
+++ b/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java
@@ -11,7 +11,8 @@ import net.minecraft.client.Minecraft;
/**
* This object is used to get variables from methods
- * where they are private.
+ * where they are private. Specifically the fog setting
+ * in Optifine.
*
* @author James Seibel
* @version 09-21-2020
diff --git a/src/main/java/com/backsun/lod/objects/LodChunk.java b/src/main/java/com/backsun/lod/objects/LodChunk.java
index 0069d7403..2064fceb5 100644
--- a/src/main/java/com/backsun/lod/objects/LodChunk.java
+++ b/src/main/java/com/backsun/lod/objects/LodChunk.java
@@ -3,7 +3,7 @@ package com.backsun.lod.objects;
import java.awt.Color;
import com.backsun.lod.util.enums.ColorDirection;
-import com.backsun.lod.util.enums.LodLocation;
+import com.backsun.lod.util.enums.LodCorner;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
@@ -73,7 +73,7 @@ public class LodChunk
//==============//
/**
- * Create an empty LodChunk
+ * Create an empty invisible LodChunk at (0,0)
*/
public LodChunk()
{
@@ -145,7 +145,7 @@ public class LodChunk
// top
top = new short[4];
- for(LodLocation loc : LodLocation.values())
+ for(LodCorner loc : LodCorner.values())
{
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
@@ -156,7 +156,7 @@ public class LodChunk
// bottom
bottom = new short[4];
- for(LodLocation loc : LodLocation.values())
+ for(LodCorner loc : LodCorner.values())
{
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
@@ -202,11 +202,11 @@ public class LodChunk
}
/**
- * Illegal argument is thrown if either the
- * chunk or world is null. The reason the world
- * can't be null is because it's required to determine
- * a block's color.
- * @throws IllegalArgumentException
+ * Creates a LodChunk for a chunk in the given world.
+ * Note: The world is required to determine each block's color
+ *
+ * @throws IllegalArgumentException
+ * thrown if either the chunk or world is null.
*/
public LodChunk(Chunk chunk, World world) throws IllegalArgumentException
{
@@ -228,16 +228,16 @@ public class LodChunk
colors = new Color[6];
// generate the top and bottom points of this LOD
- for(LodLocation loc : LodLocation.values())
+ for(LodCorner loc : LodCorner.values())
{
- top[loc.value] = generateLodSection(chunk, true, loc);
- bottom[loc.value] = generateLodSection(chunk, false, loc);
+ top[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_TOP, loc);
+ bottom[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_BOTTOM, loc);
}
// determine the average color for each direction
for(ColorDirection dir : ColorDirection.values())
{
- colors[dir.value] = generateLodColorSection(chunk, world, dir);
+ colors[dir.value] = generateLodColor(chunk, world, dir);
}
}
@@ -253,15 +253,17 @@ public class LodChunk
/**
+ * Generate the height for the given LodLocation, either the top or bottom.
+ *
* If invalid/null/empty chunks are given
* crashes may occur.
*/
- public short generateLodSection(Chunk chunk, boolean getTopSection, LodLocation lodLoc)
+ private short generateLodCorner(Chunk chunk, SectionGenerationMode generationMode, LodCorner lodLoc)
{
// should have a length of 16
// (each storage is 16x16x16 and the
// world height is 256)
- ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
+ ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray();
@@ -313,21 +315,29 @@ public class LodChunk
}
- if(getTopSection)
- return determineTopPoint(data, startX, endX, startZ, endZ);
+ if(generationMode == SectionGenerationMode.GENERATE_TOP)
+ return determineTopPoint(blockStorage, startX, endX, startZ, endZ);
else
- return determineBottomPoint(data, startX, endX, startZ, endZ);
+ return determineBottomPoint(blockStorage, startX, endX, startZ, endZ);
+ }
+ /** GENERATE_TOP, GENERATE_BOTTOM */
+ private enum SectionGenerationMode
+ {
+ GENERATE_TOP,
+ GENERATE_BOTTOM;
}
- private short determineBottomPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ)
+ /**
+ * Find the lowest valid point from the bottom.
+ */
+ private short determineBottomPoint(ExtendedBlockStorage[] blockStorage, int startX, int endX, int startZ, int endZ)
{
// search from the bottom up
- for(int i = 0; i < data.length; i++)
+ for(int i = 0; i < blockStorage.length; i++)
{
for(int y = 0; y < CHUNK_DATA_HEIGHT; y++)
{
-
- if(isLayerValidLodPoint(data, startX, endX, startZ, endZ, i, y))
+ if(isLayerValidLodPoint(blockStorage, startX, endX, startZ, endZ, i, y))
{
// we found
// enough blocks in this
@@ -335,23 +345,24 @@ public class LodChunk
// LOD point
return (short) (y + (i * CHUNK_DATA_HEIGHT));
}
-
- } // y
- } // data
-
+ }
+ }
// we never found a valid LOD point
return -1;
}
- private short determineTopPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ)
+ /**
+ * Find the highest valid point from the Top
+ */
+ private short determineTopPoint(ExtendedBlockStorage[] blockStorage, int startX, int endX, int startZ, int endZ)
{
// search from the top down
- for(int i = data.length - 1; i >= 0; i--)
+ for(int i = blockStorage.length - 1; i >= 0; i--)
{
for(int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
{
- if(isLayerValidLodPoint(data, startX, endX, startZ, endZ, i, y))
+ if(isLayerValidLodPoint(blockStorage, startX, endX, startZ, endZ, i, y))
{
// we found
// enough blocks in this
@@ -359,10 +370,8 @@ public class LodChunk
// LOD point
return (short) (y + (i * CHUNK_DATA_HEIGHT));
}
- } // y
- } // data
-
-
+ }
+ }
// we never found a valid LOD point
return -1;
@@ -373,7 +382,7 @@ public class LodChunk
* values a valid LOD point?
*/
private boolean isLayerValidLodPoint(
- ExtendedBlockStorage[] data,
+ ExtendedBlockStorage[] blockStorage,
int startX, int endX,
int startZ, int endZ,
int dataIndex, int y)
@@ -385,7 +394,7 @@ public class LodChunk
{
for(int z = startZ; z < endZ; z++)
{
- if(data[dataIndex] == null)
+ if(blockStorage[dataIndex] == null)
{
// this section doesn't have any blocks,
// it is not a valid section
@@ -393,7 +402,7 @@ public class LodChunk
}
else
{
- if(data[dataIndex].get(x, y, z) != null && Block.getIdFromBlock(data[dataIndex].get(x, y, z).getBlock()) != airBlockId)
+ if(blockStorage[dataIndex].get(x, y, z) != null && Block.getIdFromBlock(blockStorage[dataIndex].get(x, y, z).getBlock()) != airBlockId)
{
// we found a valid block in
// in this layer
@@ -412,9 +421,11 @@ public class LodChunk
return false;
}
-
-
- private Color generateLodColorSection(Chunk chunk, World world, ColorDirection colorDir)
+ /**
+ * Generate the color of the given ColorDirection at the given chunk
+ * in the given world.
+ */
+ private Color generateLodColor(Chunk chunk, World world, ColorDirection colorDir)
{
Minecraft mc = Minecraft.getMinecraft();
BlockColors bc = mc.getBlockColors();
@@ -441,11 +452,18 @@ public class LodChunk
}
/**
- * Only accepts TOP and BOTTOM as ColorPositions
+ * Generates the color of the top or bottom of a given chunk in the given world.
+ *
+ * @throws IllegalArgumentException if given a ColorDirection other than TOP or BOTTOM
*/
private Color generateLodColorVertical(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
{
- ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
+ if(colorDir != ColorDirection.TOP && colorDir != ColorDirection.BOTTOM)
+ {
+ throw new IllegalArgumentException("generateLodColorVertical only accepts the ColorDirection TOP or BOTTOM");
+ }
+
+ ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray();
int numbOfBlocks = 0;
int red = 0;
@@ -456,8 +474,8 @@ public class LodChunk
// either go top down or bottom up
- int dataStart = goTopDown? data.length - 1 : 0;
- int dataMax = data.length;
+ int dataStart = goTopDown? blockStorage.length - 1 : 0;
+ int dataMax = blockStorage.length;
int dataMin = 0;
int dataIncrement = goTopDown? -1 : 1;
@@ -474,16 +492,16 @@ public class LodChunk
for(int di = dataStart; !foundBlock && di >= dataMin && di < dataMax; di += dataIncrement)
{
- if(!foundBlock && data[di] != null)
+ if(!foundBlock && blockStorage[di] != null)
{
for(int y = topStart; !foundBlock && y >= topMin && y < topMax; y += topIncrement)
{
int ci;
- if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId)
+ if(Block.getIdFromBlock(blockStorage[di].get(x, y, z).getBlock()) == waterBlockId)
// this is a special case since getColor on water generally returns white
ci = waterColor;
else
- ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z));
+ ci = bc.getColor(blockStorage[di].get(x, y, z), world, new BlockPos(x,y,z));
if(ci == 0)
{
@@ -519,10 +537,20 @@ public class LodChunk
return new Color(red, green, blue);
}
-
+
+ /**
+ * Generates the color of the side of a given chunk in the given world for the given ColorDirection.
+ *
+ * @throws IllegalArgumentException if given a ColorDirection other than N, S, W, E (North, South, East, West)
+ */
private Color generateLodColorHorizontal(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
{
- ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
+ if(colorDir != ColorDirection.N && colorDir != ColorDirection.S && colorDir != ColorDirection.E && colorDir != ColorDirection.W)
+ {
+ throw new IllegalArgumentException("generateLodColorHorizontal only accepts the ColorDirection N (North), S (South), E (East), or W (West)");
+ }
+
+ ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray();
int numbOfBlocks = 0;
int red = 0;
@@ -563,9 +591,9 @@ public class LodChunk
}
- for (int di = 0; di < data.length; di++)
+ for (int di = 0; di < blockStorage.length; di++)
{
- if (data[di] != null)
+ if (blockStorage[di] != null)
{
for (int y = 0; y < CHUNK_DATA_HEIGHT; y++)
{
@@ -607,11 +635,11 @@ public class LodChunk
}
int ci;
- if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId)
+ if(Block.getIdFromBlock(blockStorage[di].get(x, y, z).getBlock()) == waterBlockId)
// this is a special case since getColor on water generally returns white
ci = waterColor;
else
- ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z));
+ ci = bc.getColor(blockStorage[di].get(x, y, z), world, new BlockPos(x,y,z));
if (ci == 0) {
// skip air or invisible blocks
@@ -671,6 +699,30 @@ public class LodChunk
+ //================//
+ // misc functions //
+ //================//
+
+ /**
+ * If this LOD is either invisible from every
+ * direction or doesn't have a valid height
+ * it is empty.
+ */
+ public boolean isLodEmpty()
+ {
+ for(LodCorner corner : LodCorner.values())
+ if(top[corner.value] != -1 || bottom[corner.value] != -1)
+ // at least one corner is valid
+ return false;
+
+ Color invisible = new Color(0,0,0,0);
+ for(ColorDirection dir : ColorDirection.values())
+ if(!colors[dir.value].equals(invisible))
+ // at least one direction has a non-invisible color
+ return false;
+
+ return true;
+ }
@@ -681,7 +733,6 @@ public class LodChunk
//========//
-
/**
* Outputs all data in csv format
* with the given delimiter.
@@ -727,27 +778,6 @@ public class LodChunk
s += "x: " + x + " z: " + z + "\t";
-// s += "top: ";
-// for(int i = 0; i < top.length; i++)
-// {
-// s += top[i] + " ";
-// }
-// s += "\t";
-
-// s += "bottom: ";
-// for(int i = 0; i < bottom.length; i++)
-// {
-// s += bottom[i] + " ";
-// }
-// s += "\t";
-
-// s += "colors ";
-// for(int i = 0; i < colors.length; i++)
-// {
-// if(colors[i] != null)
-// s += "(" + colors[i].getRed() + ", " + colors[i].getGreen() + ", " + colors[i].getBlue() + "), ";
-// }
-
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + "), ";
return s;
diff --git a/src/main/java/com/backsun/lod/objects/LodDimension.java b/src/main/java/com/backsun/lod/objects/LodDimension.java
index e645da3a1..f6be82e56 100644
--- a/src/main/java/com/backsun/lod/objects/LodDimension.java
+++ b/src/main/java/com/backsun/lod/objects/LodDimension.java
@@ -1,6 +1,6 @@
package com.backsun.lod.objects;
-import com.backsun.lod.handlers.LodFileHandler;
+import com.backsun.lod.handlers.LodDimensionFileHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.world.DimensionType;
@@ -10,13 +10,13 @@ import net.minecraft.world.DimensionType;
* for a given dimension.
*
* @author James Seibel
- * @version 01-31-2021
+ * @version 02-23-2021
*/
public class LodDimension
{
public final DimensionType dimension;
- private volatile int width; // if this ever changes make sure to update the halfWidth too
+ private volatile int width;
private volatile int halfWidth;
public LodRegion regions[][];
@@ -25,7 +25,8 @@ public class LodDimension
private int centerX;
private int centerZ;
- private LodFileHandler rfHandler;
+ private LodDimensionFileHandler fileHandler;
+
public LodDimension(DimensionType newDimension, int newMaxWidth)
{
@@ -33,7 +34,7 @@ public class LodDimension
width = newMaxWidth;
// dimension 0 works here since we are just looking for the save handler anyway
- rfHandler = new LodFileHandler(Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(), this);
+ fileHandler = new LodDimensionFileHandler(Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(), this);
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
@@ -50,7 +51,10 @@ public class LodDimension
}
-
+ /**
+ * Move the center of this LodDimension and move all owned
+ * regions over by the given x and z offset.
+ */
public void move(int xOffset, int zOffset)
{
// if the x or z offset is equal to or greater than
@@ -144,22 +148,16 @@ public class LodDimension
}
- public int getCenterX()
- {
- return centerX;
- }
-
- public int getCenterZ()
- {
- return centerZ;
- }
-
-
-
+ /**
+ * Gets the region at the given X and Z
+ *
+ * Returns null if the region doesn't exist
+ * or is outside the loaded area.
+ */
public LodRegion getRegion(int regionX, int regionZ)
{
int xIndex = (regionX - centerX) + halfWidth;
@@ -201,7 +199,11 @@ public class LodDimension
-
+ /**
+ * Add the given LOD to this dimension at the coordinate
+ * stored in the LOD. If an LOD already exists at the given
+ * coordinates it will be overwritten.
+ */
public void addLod(LodChunk lod)
{
int regionX = (lod.x + centerX) / LodRegion.SIZE;
@@ -236,14 +238,15 @@ public class LodDimension
int xIndex = (regionX - centerX) + halfWidth;
int zIndex = (regionZ - centerZ) + halfWidth;
isRegionDirty[xIndex][zIndex] = true;
-
-
-
- rfHandler.saveDirtyRegionsToFile();
+ fileHandler.saveDirtyRegionsToFileAsync();
}
/**
- * Returns null if the LodChunk isn't loaded
+ * Get the LodChunk at the given X and Z coordinates
+ * in this dimension.
+ *
+ * Returns null if the LodChunk doesn't exist or
+ * is outside the loaded area.
*/
public LodChunk getLodFromCoordinates(int chunkX, int chunkZ)
{
@@ -271,11 +274,13 @@ public class LodDimension
}
-
-
+ /**
+ * Get the region at the given X and Z coordinates from the
+ * RegionFileHandler.
+ */
public LodRegion getRegionFromFile(int regionX, int regionZ)
{
- return rfHandler.loadRegionFromFile(regionX, regionZ);
+ return fileHandler.loadRegionFromFile(regionX, regionZ);
}
@@ -293,6 +298,22 @@ public class LodDimension
+
+
+
+
+ public int getCenterX()
+ {
+ return centerX;
+ }
+
+ public int getCenterZ()
+ {
+ return centerZ;
+ }
+
+
+
public int getWidth()
{
return width;
@@ -311,6 +332,18 @@ public class LodDimension
for(int j = 0; j < width; j++)
isRegionDirty[i][j] = false;
}
+
+
+ @Override
+ public String toString()
+ {
+ String s = "";
+
+ s += "dim: " + dimension.getName() + "\t";
+ s += "(" + centerX + "," + centerZ + ")";
+
+ return s;
+ }
}
diff --git a/src/main/java/com/backsun/lod/objects/LodRegion.java b/src/main/java/com/backsun/lod/objects/LodRegion.java
index 7e826ddec..88c7a9b90 100644
--- a/src/main/java/com/backsun/lod/objects/LodRegion.java
+++ b/src/main/java/com/backsun/lod/objects/LodRegion.java
@@ -7,7 +7,7 @@ package com.backsun.lod.objects;
* one file in the file system.
*
* @author James Seibel
- * @version 1-20-2021
+ * @version 1-22-2021
*/
public class LodRegion
{
@@ -31,6 +31,11 @@ public class LodRegion
}
+ /**
+ * Add the given LOD to this region at the coordinate
+ * stored in the LOD. If an LOD already exists at the given
+ * coordinates it will be overwritten.
+ */
public void addLod(LodChunk lod)
{
// we use ABS since LODs can be negative, but if they are
@@ -43,6 +48,13 @@ public class LodRegion
chunks[xIndex][zIndex] = lod;
}
+ /**
+ * Get the LodChunk at the given X and Z coordinates
+ * in this region.
+ *
+ * Returns null if the LodChunk doesn't exist or
+ * is outside the loaded area.
+ */
public LodChunk getLod(int chunkX, int chunkZ)
{
// since we add LOD's with ABS, we get them the same way
@@ -52,11 +64,16 @@ public class LodRegion
if(arrayX >= SIZE || arrayZ >= SIZE)
return null;
+ // TODO fix some LOD strips showing up in the wrong location
+ // issue #2
+ // maybe this has to do with ABS being used incorrectly?
return chunks[arrayX][arrayZ];
}
-
+ /**
+ * Returns all LodChunks in this region
+ */
public LodChunk[][] getAllLods()
{
return chunks;
diff --git a/src/main/java/com/backsun/lod/objects/LodWorld.java b/src/main/java/com/backsun/lod/objects/LodWorld.java
index d961388fd..f7bcfa52b 100644
--- a/src/main/java/com/backsun/lod/objects/LodWorld.java
+++ b/src/main/java/com/backsun/lod/objects/LodWorld.java
@@ -1,14 +1,13 @@
package com.backsun.lod.objects;
-import java.util.Dictionary;
-import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Map;
/**
* This stores all LODs for a given world.
*
* @author James Seibel
- * @version 01-31-2021
+ * @version 02-22-2021
*/
public class LodWorld
{
@@ -17,7 +16,7 @@ public class LodWorld
/**
* Key = Dimension id (as an int)
*/
- private Dictionary lodDimensions;
+ private Map lodDimensions;
public LodWorld(String newWorldName)
@@ -38,12 +37,27 @@ public class LodWorld
return lodDimensions.get(dimensionId);
}
-
+ /**
+ * Resizes the max width in regions that each LodDimension
+ * should use.
+ */
public void resizeDimensionRegionWidth(int newWidth)
{
- Enumeration keys = lodDimensions.keys();
+ for(Integer key : lodDimensions.keySet())
+ lodDimensions.get(key).setRegionWidth(newWidth);
+ }
+
+
+
+ @Override
+ public String toString()
+ {
+ String s = "";
- while(keys.hasMoreElements())
- lodDimensions.get(keys.nextElement()).setRegionWidth(newWidth);
+ s += worldName + "\t - dimensions: ";
+ for(Integer key : lodDimensions.keySet())
+ s += lodDimensions.get(key).dimension.getName() + ", ";
+
+ return s;
}
}
diff --git a/src/main/java/com/backsun/lod/proxy/ClientProxy.java b/src/main/java/com/backsun/lod/proxy/ClientProxy.java
index c52d66a4f..9785338f4 100644
--- a/src/main/java/com/backsun/lod/proxy/ClientProxy.java
+++ b/src/main/java/com/backsun/lod/proxy/ClientProxy.java
@@ -22,10 +22,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
// Minecraft.getMinecraft().getIntegratedServer()
/**
- * This is used by the client.
+ * This handles all events sent to the client,
+ * and is the starting point for most of this program.
*
* @author James_Seibel
- * @version 02-21-2021
+ * @version 02-23-2021
*/
public class ClientProxy extends CommonProxy
{
@@ -57,6 +58,10 @@ public class ClientProxy extends CommonProxy
GL11.glDisable(GL11.GL_STENCIL_TEST);
}
+ /**
+ * Do any setup that is required to draw LODs
+ * and then tell the LodRenderer to draw.
+ */
public void renderLods(float partialTicks)
{
int newWidth = Math.max(4, (Minecraft.getMinecraft().gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
@@ -116,7 +121,7 @@ public class ClientProxy extends CommonProxy
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent event)
{
- lodWorld = lodBuilder.generateLodChunk(event.getChunk());
+ lodWorld = lodBuilder.generateLodChunkAsync(event.getChunk());
}
/**
@@ -132,7 +137,7 @@ public class ClientProxy extends CommonProxy
if(world != null)
{
- lodWorld = lodBuilder.generateLodChunk(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ()));
+ lodWorld = lodBuilder.generateLodChunkAsync(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ()));
}
}
}
diff --git a/src/main/java/com/backsun/lod/proxy/CommonProxy.java b/src/main/java/com/backsun/lod/proxy/CommonProxy.java
index 0b0498ad5..5362c2e93 100644
--- a/src/main/java/com/backsun/lod/proxy/CommonProxy.java
+++ b/src/main/java/com/backsun/lod/proxy/CommonProxy.java
@@ -1,7 +1,7 @@
package com.backsun.lod.proxy;
/**
- * This is used by the server.
+ * This handles any events sent to the server.
*
* @author James_Seibel
* @version 08-31-2020
diff --git a/src/main/java/com/backsun/lod/renderer/LodRenderer.java b/src/main/java/com/backsun/lod/renderer/LodRenderer.java
index e3e5bbb85..10a559da2 100644
--- a/src/main/java/com/backsun/lod/renderer/LodRenderer.java
+++ b/src/main/java/com/backsun/lod/renderer/LodRenderer.java
@@ -24,7 +24,7 @@ import com.backsun.lod.util.LodConfig;
import com.backsun.lod.util.enums.ColorDirection;
import com.backsun.lod.util.enums.FogDistance;
import com.backsun.lod.util.enums.FogQuality;
-import com.backsun.lod.util.enums.LodLocation;
+import com.backsun.lod.util.enums.LodCorner;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
@@ -41,6 +41,10 @@ import net.minecraft.util.math.MathHelper;
*/
public class LodRenderer
{
+ /** this is the light used when rendering the LODs,
+ * it should be something different than what is used by Minecraft */
+ private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
+
/** If true the LODs colors will be replaced with
* a checkerboard, this can be used for debugging. */
public boolean debugging = false;
@@ -98,23 +102,22 @@ public class LodRenderer
mc = Minecraft.getMinecraft();
// for some reason "Tessellator.getInstance()" won't work here, we have to create a new one
- tessellator = new Tessellator(2097152);
+ tessellator = new Tessellator(2097152); // the number here is what is used by the default Tessellator
bufferBuilder = tessellator.getBuffer();
reflectionHandler = new ReflectionHandler();
}
-
+ /**
+ * Besides drawing the LODs this method also starts
+ * the async process of generating the Buffers that hold those LODs.
+ *
+ * @param newDimension The dimension to draw, if null doesn't replace the current dimension.
+ * @param partialTicks how far into the current tick this method was called.
+ */
public void drawLODs(LodDimension newDimension, float partialTicks)
{
- if (reflectionHandler.fovMethod == null)
- {
- // don't continue if we can't get the
- // user's FOV
- return;
- }
-
if (reflectionHandler.fovMethod == null)
{
// we aren't able to get the user's
@@ -131,6 +134,19 @@ public class LodRenderer
+
+
+ //===============//
+ // initial setup //
+ //===============//
+
+
+ // used for debugging and viewing how long different processes take
+ mc.mcProfiler.endSection();
+ mc.mcProfiler.startSection("LOD");
+ mc.mcProfiler.startSection("LOD setup");
+
+
// should LODs be regenerated?
if ((int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH != prevChunkX ||
(int)Minecraft.getMinecraft().player.posZ / LodChunk.WIDTH != prevChunkZ ||
@@ -138,6 +154,7 @@ public class LodRenderer
prevFogDistance != LodConfig.fogDistance ||
lodDimension != newDimension)
{
+ // yes
regen = true;
prevChunkX = (int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH;
@@ -152,17 +169,9 @@ public class LodRenderer
regen = false;
}
- lodDimension = newDimension;
+ if (newDimension != null)
+ lodDimension = newDimension;
-
-
-
-
-
- // used for debugging and viewing how long different processes take
- mc.mcProfiler.endSection();
- mc.mcProfiler.startSection("LOD");
- mc.mcProfiler.startSection("LOD setup");
if (LodConfig.drawCheckerBoard)
{
if (debugging != LodConfig.drawCheckerBoard)
@@ -183,9 +192,6 @@ public class LodRenderer
double cameraX = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;
double cameraY = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;
double cameraZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;
-
-
-
// determine how far the game's render distance is currently set
int renderDistWidth = mc.gameSettings.renderDistanceChunks;
@@ -204,29 +210,32 @@ public class LodRenderer
// create the LODs //
//=================//
- // only regenerate LODs if:
+ // only regenerate the LODs if:
// 1. we want to regenerate LODs
- // 2. we aren't already regenerating LODs
+ // 2. we aren't already regenerating the LODs
// 3. we aren't waiting for the build and draw buffers to swap
+ // (this is to prevent thread conflicts)
if (regen && !regenerating && !switchBuffers)
{
mc.mcProfiler.endStartSection("LOD generation");
regenerating = true;
-
+ // this will only be called once, unless the numbBufferThreads changes
if (numbBufferThreads != bufferThreads.size())
setupBufferThreads();
+ // this will mainly happen when the view distance is changed
if (drawableNearBuffers == null || drawableFarBuffers == null ||
previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks)
setupBuffers(numbChunksWide);
-
+ // generate the LODs on a separate thread to prevent stuttering or freezing
genThread.execute(createLodBufferGenerationThread(cameraX, cameraZ, numbChunksWide));
}
// replace the buffers used to draw and build,
- // this is done to keep everything thread safe
+ // this is only done when the createLodBufferGenerationThread
+ // has finished executing on a parallel thread.
if (switchBuffers)
{
swapBuffers();
@@ -242,13 +251,13 @@ public class LodRenderer
//===========================//
// set the required open GL settings
+ GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLineWidth(2.0f);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_CULL_FACE);
- GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
-
+ // move the LODs so they are in the correct place relative to the camera
GlStateManager.translate(-cameraX, -cameraY, -cameraZ);
setProjectionMatrix(partialTicks);
@@ -266,21 +275,26 @@ public class LodRenderer
switch(LodConfig.fogDistance)
{
case NEAR_AND_FAR:
- mc.mcProfiler.endStartSection("LOD draw setup");
+ // when drawing NEAR_AND_FAR fog we need 2 draw
+ // calls since fog can only go in one direction at a time
+
+ mc.mcProfiler.endStartSection("LOD draw");
setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality());
sendLodsToGpuAndDraw(drawableNearBuffers);
- mc.mcProfiler.endStartSection("LOD draw setup");
+ mc.mcProfiler.endStartSection("LOD draw");
setupFog(FogDistance.FAR, reflectionHandler.getFogQuality());
sendLodsToGpuAndDraw(drawableFarBuffers);
break;
+
case NEAR:
- mc.mcProfiler.endStartSection("LOD draw setup");
+ mc.mcProfiler.endStartSection("LOD draw");
setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality());
sendLodsToGpuAndDraw(drawableNearBuffers);
break;
+
case FAR:
- mc.mcProfiler.endStartSection("LOD draw setup");
+ mc.mcProfiler.endStartSection("LOD draw");
setupFog(FogDistance.FAR, reflectionHandler.getFogQuality());
sendLodsToGpuAndDraw(drawableFarBuffers);
break;
@@ -302,7 +316,7 @@ public class LodRenderer
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
GL11.glEnable(GL11.GL_TEXTURE_2D);
- GL11.glDisable(GL11.GL_LIGHT2);
+ GL11.glDisable(LOD_GL_LIGHT_NUMBER);
GL11.glDisable(GL11.GL_COLOR_MATERIAL);
// change the perspective matrix back to prevent incompatibilities
@@ -319,49 +333,11 @@ public class LodRenderer
}
-
-
-
/**
- * draw an array of cubes (or squares) with the given colors.
- * @param lods bounding boxes to draw
- * @param colors color of each box to draw
+ * This is where the actual drawing happens.
+ *
+ * @param buffers the buffers sent to the GPU to draw
*/
- private void generateLodBuffers(AxisAlignedBB[][] lods, Color[][] colors, FogDistance fogDistance)
- {
- List> bufferFutures = new ArrayList<>();
-
- for(int i = 0; i < numbBufferThreads; i++)
- {
- bufferThreads.get(i).setNewData(buildableNearBuffers[i], buildableFarBuffers[i], fogDistance, lods, colors, i, numbBufferThreads);
- }
-
- try
- {
- bufferFutures = bufferThreadPool.invokeAll(bufferThreads);
- }
- catch (InterruptedException e)
- {
- // this should never happen, but just in case
- e.printStackTrace();
- }
-
- for(int i = 0; i < numbBufferThreads; i++)
- {
- try
- {
- buildableNearBuffers[i] = bufferFutures.get(i).get().nearBuffer;
- buildableFarBuffers[i] = bufferFutures.get(i).get().farBuffer;
- }
- catch(CancellationException | ExecutionException| InterruptedException e)
- {
- // this should never happen, but just in case
- e.printStackTrace();
- }
- }
-
- }
-
private void sendLodsToGpuAndDraw(BufferBuilder[] buffers)
{
for(int i = 0; i < numbBufferThreads; i++)
@@ -371,11 +347,10 @@ public class LodRenderer
bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.getByteBuffer().clear();
+ // replace the data in bufferBuilder with the data from the given buffer
bufferBuilder.putBulkData(buffers[i].getByteBuffer());
- mc.mcProfiler.endStartSection("LOD draw");
tessellator.draw();
- mc.mcProfiler.endStartSection("LOD draw setup");
bufferBuilder.getByteBuffer().clear(); // this is required otherwise nothing is drawn
}
@@ -451,7 +426,6 @@ public class LodRenderer
/**
* create a new projection matrix and send it over to the GPU
* @param partialTicks how many ticks into the frame we are
- * @return true if the matrix was successfully created and sent to the GPU, false otherwise
*/
private void setProjectionMatrix(float partialTicks)
{
@@ -483,16 +457,18 @@ public class LodRenderer
float gammaMultiplyer = (mc.gameSettings.gammaSetting * 0.5f + 0.5f);
float lightStrength = sunBrightness * skyHasLight * gammaMultiplyer;
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
-
+
ByteBuffer temp = ByteBuffer.allocateDirect(16);
temp.order(ByteOrder.nativeOrder());
- GL11.glLight(GL11.GL_LIGHT2, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
- GL11.glEnable(GL11.GL_LIGHT2); // Enable the above lighting
+ GL11.glLight(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
+ GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
GlStateManager.enableLighting();
}
-
+ /**
+ * create the BuildBufferThreads
+ */
private void setupBufferThreads()
{
bufferThreads.clear();
@@ -501,7 +477,7 @@ public class LodRenderer
}
/**
- *
+ * Create all buffers that will be used.
*/
private void setupBuffers(int numbChunksWide)
{
@@ -540,17 +516,17 @@ public class LodRenderer
/**
- * Returns -1 if there are no valid points
+ * @Returns -1 if there are no valid points
*/
- private int getHighestPointInLod(short[] heightPoints)
+ private int getValidHeightPoint(short[] heightPoints)
{
- if (heightPoints[LodLocation.NE.value] != -1)
- return heightPoints[LodLocation.NE.value];
- if (heightPoints[LodLocation.NW.value] != -1)
- return heightPoints[LodLocation.NW.value];
- if (heightPoints[LodLocation.SE.value] != -1)
- return heightPoints[LodLocation.NE.value];
- return heightPoints[LodLocation.NE.value];
+ if (heightPoints[LodCorner.NE.value] != -1)
+ return heightPoints[LodCorner.NE.value];
+ if (heightPoints[LodCorner.NW.value] != -1)
+ return heightPoints[LodCorner.NW.value];
+ if (heightPoints[LodCorner.SE.value] != -1)
+ return heightPoints[LodCorner.NE.value];
+ return heightPoints[LodCorner.NE.value];
}
@@ -603,7 +579,7 @@ public class LodRenderer
// this is just how chunk loading/unloading works. This can hopefully
// be hidden with careful use of fog)
int middle = (numbChunksWide / 2);
- if (RenderUtil.isCoordinateInLoadedArea(i, j, middle))
+ if (isCoordInCenterArea(i, j, middle))
{
continue;
}
@@ -660,8 +636,8 @@ public class LodRenderer
// add the new box to the array
- int topPoint = getHighestPointInLod(lod.top);
- int bottomPoint = getHighestPointInLod(lod.bottom);
+ int topPoint = getValidHeightPoint(lod.top);
+ int bottomPoint = getValidHeightPoint(lod.bottom);
// don't draw an LOD if it is empty
if (topPoint == -1 && bottomPoint == -1)
@@ -679,6 +655,54 @@ public class LodRenderer
return t;
}
+ /**
+ * draw an array of boxes with the given colors.
+ *
+ * Currently only one color per box is supported.
+ *
+ * @param lods bounding boxes to draw
+ * @param colors color of each box to draw
+ */
+ private void generateLodBuffers(AxisAlignedBB[][] lods, Color[][] colors, FogDistance fogDistance)
+ {
+ List> bufferFutures = new ArrayList<>();
+
+ // update the information that the bufferThreads are using
+ for(int i = 0; i < numbBufferThreads; i++)
+ {
+ bufferThreads.get(i).setNewData(buildableNearBuffers[i], buildableFarBuffers[i], fogDistance, lods, colors, i, numbBufferThreads);
+ }
+
+ // run all the bufferThreads and get their results
+ try
+ {
+ bufferFutures = bufferThreadPool.invokeAll(bufferThreads);
+ }
+ catch (InterruptedException e)
+ {
+ // this should never happen, but just in case
+ e.printStackTrace();
+ }
+
+ // update our buildable buffers
+ for(int i = 0; i < numbBufferThreads; i++)
+ {
+ try
+ {
+ buildableNearBuffers[i] = bufferFutures.get(i).get().nearBuffer;
+ buildableFarBuffers[i] = bufferFutures.get(i).get().farBuffer;
+ }
+ catch(CancellationException | ExecutionException| InterruptedException e)
+ {
+ // this should never happen, but just in case
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+
+
/**
* Swap buildable and drawable buffers.
*/
@@ -705,4 +729,16 @@ public class LodRenderer
+ /**
+ * Returns if the given coordinate is in the loaded area of the world.
+ * @param centerCoordinate the center of the loaded world
+ */
+ private boolean isCoordInCenterArea(int i, int j, int centerCoordinate)
+ {
+ return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks
+ && i <= centerCoordinate + mc.gameSettings.renderDistanceChunks)
+ &&
+ (j >= centerCoordinate - mc.gameSettings.renderDistanceChunks
+ && j <= centerCoordinate + mc.gameSettings.renderDistanceChunks);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/backsun/lod/renderer/RenderUtil.java b/src/main/java/com/backsun/lod/renderer/RenderUtil.java
deleted file mode 100644
index 8a9950c39..000000000
--- a/src/main/java/com/backsun/lod/renderer/RenderUtil.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.backsun.lod.renderer;
-
-import net.minecraft.client.Minecraft;
-
-/**
- * This holds miscellaneous helper code
- * to be used in the rendering process.
- *
- * @author James Seibel
- * @version 2-13-2021
- */
-public class RenderUtil
-{
- /**
- * Returns if the given coordinate is in the loaded area of the world.
- * @param centerCoordinate the center of the loaded world
- */
- public static boolean isCoordinateInLoadedArea(int i, int j, int centerCoordinate)
- {
- Minecraft mc = Minecraft.getMinecraft();
-
- return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks
- && i <= centerCoordinate + mc.gameSettings.renderDistanceChunks)
- &&
- (j >= centerCoordinate - mc.gameSettings.renderDistanceChunks
- && j <= centerCoordinate + mc.gameSettings.renderDistanceChunks);
- }
-
-
- /**
- * Find the coordinates that are in the center half of the given
- * 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
- */
- public static boolean isCoordinateInNearFogArea(int i, int j, int lodRadius)
- {
- int halfRadius = lodRadius / 2;
-
- return (i >= lodRadius - halfRadius
- && i <= lodRadius + halfRadius)
- &&
- (j >= lodRadius - halfRadius
- && j <= lodRadius + halfRadius);
- }
-
-}
diff --git a/src/main/java/com/backsun/lod/util/LodConfig.java b/src/main/java/com/backsun/lod/util/LodConfig.java
index 3cc12cbcb..4f5c02f86 100644
--- a/src/main/java/com/backsun/lod/util/LodConfig.java
+++ b/src/main/java/com/backsun/lod/util/LodConfig.java
@@ -9,6 +9,7 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
/**
+ * This is linked to Forge's mod config GUI.
*
* @author James Seibel
* @version 02-14-2021
diff --git a/src/main/java/com/backsun/lod/util/Reference.java b/src/main/java/com/backsun/lod/util/Reference.java
index fdb79e37b..f0bb4024c 100644
--- a/src/main/java/com/backsun/lod/util/Reference.java
+++ b/src/main/java/com/backsun/lod/util/Reference.java
@@ -1,6 +1,7 @@
package com.backsun.lod.util;
/**
+ * This holds meta information about the mod.
*
* @author James Seibel
* @version 04-16-2020
diff --git a/src/main/java/com/backsun/lod/util/enums/ColorDirection.java b/src/main/java/com/backsun/lod/util/enums/ColorDirection.java
index 49a188951..9d4aa782f 100644
--- a/src/main/java/com/backsun/lod/util/enums/ColorDirection.java
+++ b/src/main/java/com/backsun/lod/util/enums/ColorDirection.java
@@ -1,10 +1,10 @@
package com.backsun.lod.util.enums;
/**
+ * TOP, N, S, E, W, BOTTOM
+ *
* @author James Seibel
* @version 10-17-2020
- *
- * TOP, N, S, E, W, BOTTOM
*/
public enum ColorDirection
{
diff --git a/src/main/java/com/backsun/lod/util/enums/DrawMode.java b/src/main/java/com/backsun/lod/util/enums/DrawMode.java
deleted file mode 100644
index aee54e7d2..000000000
--- a/src/main/java/com/backsun/lod/util/enums/DrawMode.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.backsun.lod.util.enums;
-
-/**
- * @author James Seibel
- * @version 1-23-2021
- */
-public enum DrawMode
-{
- /** Draw the LOD objects in groups.
- *
- *
- * Fancy fog: render the center and outside LOD
- * objects in 2 different groups.
- *
- * Fast fog: render all LOD objects at one time.
- */
- BATCH(0),
-
- /** Draw each LOD objects separately.
- *
- *
- * Not suggested normally since draw calls are GPU expensive.
- */
- INDIVIDUAL(5);
-
- public final int value;
-
- private DrawMode(int newValue)
- {
- value = newValue;
- }
-}
diff --git a/src/main/java/com/backsun/lod/util/enums/FogDistance.java b/src/main/java/com/backsun/lod/util/enums/FogDistance.java
index a3046993d..87dd8c3f0 100644
--- a/src/main/java/com/backsun/lod/util/enums/FogDistance.java
+++ b/src/main/java/com/backsun/lod/util/enums/FogDistance.java
@@ -8,9 +8,9 @@ package com.backsun.lod.util.enums;
*/
public enum FogDistance
{
- /** valid for both fast and fancy fog qualities. */
+ /** good for fast or fancy fog qualities. */
NEAR,
- /** valid for both fast and fancy fog qualities. */
+ /** good for fast or fancy fog qualities. */
FAR,
/** only looks good if the fog quality is set to Fancy. */
NEAR_AND_FAR;
diff --git a/src/main/java/com/backsun/lod/util/enums/LodLocation.java b/src/main/java/com/backsun/lod/util/enums/LodCorner.java
similarity index 82%
rename from src/main/java/com/backsun/lod/util/enums/LodLocation.java
rename to src/main/java/com/backsun/lod/util/enums/LodCorner.java
index 47b03fc98..ac686f31f 100644
--- a/src/main/java/com/backsun/lod/util/enums/LodLocation.java
+++ b/src/main/java/com/backsun/lod/util/enums/LodCorner.java
@@ -1,13 +1,12 @@
package com.backsun.lod.util.enums;
/**
+ * NE, SE, SW, NW
*
* @author James Seibel
* @version 1-20-2020
- *
- * NE, SE, SW, NW
*/
-public enum LodLocation
+public enum LodCorner
{
// used for position
@@ -22,7 +21,7 @@ public enum LodLocation
public final int value;
- private LodLocation(int newValue)
+ private LodCorner(int newValue)
{
value = newValue;
}
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
index a18922536..9b62a4086 100644
--- a/src/main/resources/mcmod.info
+++ b/src/main/resources/mcmod.info
@@ -3,7 +3,7 @@
"modid": "lod",
"name": "Level Of Details",
"description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.",
- "version": "0.1",
+ "version": "1.0",
"mcversion": "1.12.2",
"url": "",
"updateUrl": "",