diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
index 80f1607aa..a4f7031e2 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
@@ -1,5 +1,6 @@
package com.seibel.lod.builders.lodTemplates;
+import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
@@ -10,7 +11,7 @@ import net.minecraft.client.renderer.BufferBuilder;
* BufferBuilders.
*
* @author James Seibel
- * @version 06-12-2021
+ * @version 06-16-2021
*/
public abstract class AbstractLodTemplate
{
@@ -27,7 +28,9 @@ public abstract class AbstractLodTemplate
buffer.pos(x, y, z).color(red, green, blue, alpha).endVertex();
}
-
+ /** Returns in bytes how much buffer memory is required
+ * for one LOD object */
+ public abstract int getBufferMemoryForSingleLod(LodDetail detail);
diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
index 832f1ed77..8ac0c8ae4 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
@@ -15,7 +15,7 @@ import net.minecraft.util.math.AxisAlignedBB;
* Builds LODs as rectangular prisms.
*
* @author James Seibel
- * @version 06-13-2021
+ * @version 06-16-2021
*/
public class CubicLodTemplate extends AbstractLodTemplate
{
@@ -159,6 +159,14 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
}
+
+
+ @Override
+ public int getBufferMemoryForSingleLod(LodDetail detail)
+ {
+ // (sidesOnACube * pointsInASquare * (positionPoints + colorPoints))) * howManyPointsPerLodChunk
+ return (6 * 4 * (3 + 4)) * detail.lengthCount * detail.lengthCount;
+ }
diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java
index 0a66fdf9b..7203aa273 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java
@@ -1,5 +1,6 @@
package com.seibel.lod.builders.lodTemplates;
+import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
@@ -12,7 +13,7 @@ import net.minecraft.client.renderer.BufferBuilder;
* is at a significantly different height.
*
* @author James Seibel
- * @version 05-07-2021
+ * @version 06-16-2021
*/
public class DynamicLodTemplate extends AbstractLodTemplate
{
@@ -24,4 +25,10 @@ public class DynamicLodTemplate extends AbstractLodTemplate
{
System.err.println("DynamicLodTemplate not implemented!");
}
+
+ @Override
+ public int getBufferMemoryForSingleLod(LodDetail detail) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
}
diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java
index 66c9e9288..d1188f6ba 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java
@@ -1,5 +1,6 @@
package com.seibel.lod.builders.lodTemplates;
+import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
@@ -10,7 +11,7 @@ import net.minecraft.client.renderer.BufferBuilder;
* Builds each LOD chunk as a singular rectangular prism.
*
* @author James Seibel
- * @version 05-07-2021
+ * @version 06-16-2021
*/
public class TriangularLodTemplate extends AbstractLodTemplate
{
@@ -22,4 +23,10 @@ public class TriangularLodTemplate extends AbstractLodTemplate
{
System.err.println("DynamicLodTemplate not implemented!");
}
+
+ @Override
+ public int getBufferMemoryForSingleLod(LodDetail detail) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
}
diff --git a/src/main/java/com/seibel/lod/enums/LodTemplate.java b/src/main/java/com/seibel/lod/enums/LodTemplate.java
index 71aaa0fa4..f9dc4e867 100644
--- a/src/main/java/com/seibel/lod/enums/LodTemplate.java
+++ b/src/main/java/com/seibel/lod/enums/LodTemplate.java
@@ -9,7 +9,7 @@ import com.seibel.lod.builders.lodTemplates.TriangularLodTemplate;
* Cubic, Triangular, Dynamic
*
* @author James Seibel
- * @version 05-07-2021
+ * @version 06-16-2021
*/
public enum LodTemplate
{
@@ -35,4 +35,10 @@ public enum LodTemplate
{
template = newTemplate;
}
+
+
+ public int getBufferMemoryForSingleLod(LodDetail detail)
+ {
+ return template.getBufferMemoryForSingleLod(detail);
+ }
}
diff --git a/src/main/java/com/seibel/lod/render/LodRender.java b/src/main/java/com/seibel/lod/render/LodRender.java
index da6c879c0..96c84d693 100644
--- a/src/main/java/com/seibel/lod/render/LodRender.java
+++ b/src/main/java/com/seibel/lod/render/LodRender.java
@@ -13,11 +13,14 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.builders.LodBufferBuilder;
import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogQuality;
+import com.seibel.lod.enums.LodDetail;
+import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.handlers.ReflectionHandler;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.NearFarBuffer;
import com.seibel.lod.objects.NearFarFogSetting;
+import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.util.LodConfig;
import net.minecraft.client.Minecraft;
@@ -45,14 +48,28 @@ import net.minecraft.util.math.vector.Vector3f;
* This is where LODs are draw to the world.
*
* @author James Seibel
- * @version 05-08-2021
+ * @version 06-17-2021
*/
public class LodRender
{
/** 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;
-
+
+ /**
+ * 64 MB by default is the maximum amount of memory that
+ * can be directly allocated.
+ *
+ * I know there are commands to change that amount
+ * (specifically "-XX:MaxDirectMemorySize"), but
+ * I have no idea how to access that amount.
+ * So I guess this will be the hard limit for now.
+ *
+ * https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
+ */
+ public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
+
+
/** If true the LODs colors will be replaced with
* a checkerboard, this can be used for debugging. */
public boolean debugging = false;
@@ -114,7 +131,6 @@ public class LodRender
* @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.
*/
- @SuppressWarnings("deprecation")
public void drawLODs(LodDimension lodDim, float partialTicks, IProfiler newProfiler)
{
if (lodDim == null)
@@ -493,7 +509,6 @@ public class LodRender
/**
* setup the lighting to be used for the LODs
*/
- @SuppressWarnings("deprecation")
private void setupLighting(LodDimension lodDimension, float partialTicks)
{
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
@@ -510,28 +525,63 @@ public class LodRender
RenderSystem.enableLighting();
}
-
/**
* Create all buffers that will be used.
*/
private void setupBuffers(int numbChunksWide)
{
- // calculate the max amount of storage needed (in bytes)
- int bufferMaxCapacity = (numbChunksWide * numbChunksWide * (6 * 4 * (3 + 4)));
- // (numbChunksWide * numbChunksWide *
- // (sidesOnACube * pointsInASquare * (positionPoints + colorPoints)))
+ // calculate the max amount of memory needed (in bytes)
+ int bufferMemory = getBufferMemoryForRadiusMultiplier(LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
- // TODO complain or do something when memory is too low
- // currently the VM will just crash and complain there is no more memory
- // issue #4
- drawableNearBuffer = new BufferBuilder(bufferMaxCapacity);
- drawableFarBuffer = new BufferBuilder(bufferMaxCapacity);
+ // if the required memory is greater than the
+ // MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier
+ // to fit.
+ if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY)
+ {
+ int maxRadiusMultiplier = getMaxRadiusMultiplierWithAvaliableMemory(LodConfig.CLIENT.lodTemplate.get(), LodConfig.CLIENT.lodDetail.get());
+
+ ClientProxy.LOGGER.warn("The lodChunkRadiusMultiplier was set too high "
+ + "and had to be lowered to fit memory constraints "
+ + "from " + LodConfig.CLIENT.lodChunkRadiusMultiplier.get() + " "
+ + "to " + maxRadiusMultiplier);
+
+ LodConfig.CLIENT.lodChunkRadiusMultiplier.set(
+ maxRadiusMultiplier);
+
+ bufferMemory = getBufferMemoryForRadiusMultiplier(maxRadiusMultiplier);
+ }
- lodBufferBuilder.setupBuffers(bufferMaxCapacity);
+ drawableNearBuffer = new BufferBuilder(bufferMemory);
+ drawableFarBuffer = new BufferBuilder(bufferMemory);
+
+ lodBufferBuilder.setupBuffers(bufferMemory);
}
+ /**
+ * Get how much buffer memory would be required for the given radius multiplier
+ */
+ public int getBufferMemoryForRadiusMultiplier(int radiusMultiplier)
+ {
+ int numbChunksWide = mc.gameSettings.renderDistanceChunks *
+ radiusMultiplier * 2;
+
+ // calculate the max amount of buffer memory needed (in bytes)
+ return numbChunksWide * numbChunksWide *
+ LodConfig.CLIENT.lodTemplate.get().
+ getBufferMemoryForSingleLod(LodConfig.CLIENT.lodDetail.get());
+ }
-
+ /**
+ * Returns the maxViewDistanceMultiplier for the given LodTemplate
+ * at the given LodDetail level.
+ */
+ public int getMaxRadiusMultiplierWithAvaliableMemory(LodTemplate lodTemplate, LodDetail lodDetail)
+ {
+ int maxNumberOfLods = MAX_ALOCATEABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod(lodDetail);
+ int numbLodsWide = (int) Math.sqrt(maxNumberOfLods);
+
+ return numbLodsWide / (2 * mc.gameSettings.renderDistanceChunks);
+ }
diff --git a/src/main/java/com/seibel/lod/util/LodConfig.java b/src/main/java/com/seibel/lod/util/LodConfig.java
index 6d6bb4d08..c0fb26fac 100644
--- a/src/main/java/com/seibel/lod/util/LodConfig.java
+++ b/src/main/java/com/seibel/lod/util/LodConfig.java
@@ -21,7 +21,7 @@ import net.minecraftforge.fml.config.ModConfig;
/**
*
* @author James Seibel
- * @version 6-13-2021
+ * @version 6-17-2021
*/
@Mod.EventBusSubscriber
public class LodConfig
@@ -89,8 +89,8 @@ public class LodConfig
+ " This is multiplied by the default view distance \n"
+ " to determine how far out to generate/render LODs. \n"
+ " A value of 2 means that there is 1 render distance worth \n"
- + " of LODs in each cardinal direction.")
- .defineInRange("lodChunkRadiusMultiplier", 6, 2, 1023);
+ + " of LODs in each cardinal direction. ")
+ .defineInRange("lodChunkRadiusMultiplier", 6, 2, 32);
builder.pop();
}