Create LodBufferBuilder and rename the old LodBufferBuilder to LodBufferBuilderFactory

This commit is contained in:
James Seibel
2021-11-13 13:34:07 -06:00
parent 342261d78a
commit f70c4f74ac
16 changed files with 1077 additions and 55 deletions
@@ -47,6 +47,7 @@ import com.seibel.lod.objects.PosToRenderContainer;
import com.seibel.lod.objects.lod.LodDimension;
import com.seibel.lod.objects.lod.LodRegion;
import com.seibel.lod.objects.lod.RegionPos;
import com.seibel.lod.objects.opengl.LodBufferBuilder;
import com.seibel.lod.proxy.GlProxy;
import com.seibel.lod.render.LodRenderer;
import com.seibel.lod.util.DataPointUtil;
@@ -59,20 +60,22 @@ import com.seibel.lod.wrappers.MinecraftWrapper;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import com.seibel.lod.wrappers.Chunk.ChunkPosWrapper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.util.Direction;
/**
* This object is used to create NearFarBuffer objects.
* This object creates the geometry that is
* rendered by the LodRenderer.
*
* @author James Seibel
* @version 11-8-2021
* @version 11-13-2021
*/
public class LodBufferBuilder
public class LodBufferBuilderFactory
{
/** The thread used to generate new LODs off the main thread. */
public static final ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(LodBufferBuilder.class.getSimpleName() + " - main"));
public static final ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(LodBufferBuilderFactory.class.getSimpleName() + " - main"));
/** The threads used to generate buffers. */
public static final ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.advancedModOptions.threading.numberOfBufferBuilderThreads.get(), new ThreadFactoryBuilder().setNameFormat("Buffer-Builder-%d").build());
@@ -100,7 +103,7 @@ public class LodBufferBuilder
public volatile int[][] numberOfBuffersPerRegion;
/** Stores the vertices when building the VBOs */
public volatile BufferBuilder[][][] buildableBuffers;
public volatile LodBufferBuilder[][][] buildableBuffers;
/** The OpenGL IDs of the storage buffers used by the buildableVbos */
public int[][][] buildableStorageBufferIds;
@@ -149,7 +152,7 @@ public class LodBufferBuilder
public LodBufferBuilder()
public LodBufferBuilderFactory()
{
}
@@ -242,7 +245,7 @@ public class LodBufferBuilder
zRegion + lodDim.getCenterRegionPosZ() - lodDim.getWidth() / 2);
// local position in the vbo and bufferBuilder arrays
BufferBuilder[] currentBuffers = buildableBuffers[xRegion][zRegion];
LodBufferBuilder[] currentBuffers = buildableBuffers[xRegion][zRegion];
LodRegion region = lodDim.getRegion(regionPos.x, regionPos.z);
if (region == null)
@@ -527,7 +530,7 @@ public class LodBufferBuilder
previousRegionWidth = numbRegionsWide;
numberOfBuffersPerRegion = new int[numbRegionsWide][numbRegionsWide];
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide][];
buildableBuffers = new LodBufferBuilder[numbRegionsWide][numbRegionsWide][];
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
@@ -554,7 +557,7 @@ public class LodBufferBuilder
// always allocating the max memory is a bit expensive isn't it?
regionMemoryRequired = LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY;
numberOfBuffersPerRegion[x][z] = numberOfBuffers;
buildableBuffers[x][z] = new BufferBuilder[numberOfBuffers];
buildableBuffers[x][z] = new LodBufferBuilder[numberOfBuffers];
buildableVbos[x][z] = new VertexBuffer[numberOfBuffers];
drawableVbos[x][z] = new VertexBuffer[numberOfBuffers];
@@ -568,7 +571,7 @@ public class LodBufferBuilder
{
// we only need one buffer for this region
numberOfBuffersPerRegion[x][z] = 1;
buildableBuffers[x][z] = new BufferBuilder[1];
buildableBuffers[x][z] = new LodBufferBuilder[1];
buildableVbos[x][z] = new VertexBuffer[1];
drawableVbos[x][z] = new VertexBuffer[1];
@@ -582,10 +585,10 @@ public class LodBufferBuilder
for (int i = 0; i < numberOfBuffersPerRegion[x][z]; i++)
{
buildableBuffers[x][z][i] = new BufferBuilder((int) regionMemoryRequired);
buildableBuffers[x][z][i] = new LodBufferBuilder((int) regionMemoryRequired);
buildableVbos[x][z][i] = new VertexBuffer(LodUtil.LOD_VERTEX_FORMAT);
drawableVbos[x][z][i] = new VertexBuffer(LodUtil.LOD_VERTEX_FORMAT);
buildableVbos[x][z][i] = new VertexBuffer(DefaultVertexFormats.POSITION_COLOR); //LodUtil.LOD_VERTEX_FORMAT);
drawableVbos[x][z][i] = new VertexBuffer(DefaultVertexFormats.POSITION_COLOR); //(LodUtil.LOD_VERTEX_FORMAT);
// create the initial mapped buffers (system memory)
@@ -777,7 +780,7 @@ public class LodBufferBuilder
{
for (int i = 0; i < buildableBuffers[x][z].length; i++)
{
ByteBuffer uploadBuffer = buildableBuffers[x][z][i].popNextBuffer().getSecond();
ByteBuffer uploadBuffer = buildableBuffers[x][z][i].getCleanedByteBuffer();
int storageBufferId = 0;
if (buildableStorageBufferIds != null)
storageBufferId = buildableStorageBufferIds[x][z][i];
@@ -792,7 +795,7 @@ public class LodBufferBuilder
catch (Exception e)
{
// this doesn't appear to be necessary anymore, but just in case.
ClientApi.LOGGER.error(LodBufferBuilder.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage());
ClientApi.LOGGER.error(LodBufferBuilderFactory.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage());
e.printStackTrace();
}
finally
@@ -22,28 +22,28 @@ package com.seibel.lod.builders.bufferBuilding.lodTemplates;
import java.util.Map;
import com.seibel.lod.enums.rendering.DebugMode;
import com.seibel.lod.objects.opengl.LodBufferBuilder;
import com.seibel.lod.util.ColorUtil;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
/**
* This is the abstract class used to create different
* BufferBuilders.
* @author James Seibel
* @version 10-10-2021
* @version 11-13-2021
*/
public abstract class AbstractLodTemplate
{
/** Uploads the given LOD to the buffer. */
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
public abstract void addLodToBuffer(LodBufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled);
/** add the given position and color to the buffer */
protected void addPosAndColor(BufferBuilder buffer,
double x, double y, double z,
protected void addPosAndColor(LodBufferBuilder buffer,
float x, float y, float z,
int color)
{
// TODO re-add transparency by replacing the 255 with "ColorUtil.getAlpha(color)"
@@ -22,13 +22,12 @@ package com.seibel.lod.builders.bufferBuilding.lodTemplates;
import java.util.Map;
import com.seibel.lod.enums.rendering.DebugMode;
import com.seibel.lod.objects.opengl.LodBufferBuilder;
import com.seibel.lod.util.ColorUtil;
import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.LodUtil;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
/**
@@ -45,7 +44,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
}
@Override
public void addLodToBuffer(BufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
public void addLodToBuffer(LodBufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
{
if (box == null)
@@ -110,7 +109,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
box.setAdjData(adjData);
}
private void addBoundingBoxToBuffer(BufferBuilder buffer, Box box)
private void addBoundingBoxToBuffer(LodBufferBuilder buffer, Box box)
{
int color;
int skyLight;
@@ -23,8 +23,9 @@ import java.util.Map;
import com.seibel.lod.enums.rendering.DebugMode;
import com.seibel.lod.lodApi.ClientApi;
import com.seibel.lod.objects.opengl.LodBufferBuilder;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
/**
@@ -38,7 +39,7 @@ import net.minecraft.util.Direction;
public class DynamicLodTemplate extends AbstractLodTemplate
{
@Override
public void addLodToBuffer(BufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
public void addLodToBuffer(LodBufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
{
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
@@ -23,8 +23,9 @@ import java.util.Map;
import com.seibel.lod.enums.rendering.DebugMode;
import com.seibel.lod.lodApi.ClientApi;
import com.seibel.lod.objects.opengl.LodBufferBuilder;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
/**
@@ -36,7 +37,7 @@ import net.minecraft.util.Direction;
public class TriangularLodTemplate extends AbstractLodTemplate
{
@Override
public void addLodToBuffer(BufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
public void addLodToBuffer(LodBufferBuilder buffer, BlockPosWrapper bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
{
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
@@ -19,7 +19,7 @@
package com.seibel.lod.lodApi;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilder;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilderFactory;
import com.seibel.lod.builders.lodBuilding.LodBuilder;
import com.seibel.lod.objects.lod.LodWorld;
@@ -34,7 +34,7 @@ public class ApiShared
{
public ApiShared INSTANCE = new ApiShared();
public static final LodBufferBuilder lodBufferBuilder = new LodBufferBuilder();
public static final LodBufferBuilderFactory lodBufferBuilderFactory = new LodBufferBuilderFactory();
public static final LodWorld lodWorld = new LodWorld();
public static final LodBuilder lodBuilder = new LodBuilder();
@@ -48,7 +48,7 @@ public class ClientApi
public static final ClientApi INSTANCE = new ClientApi();
public static final Logger LOGGER = LogManager.getLogger("LOD");
public static LodRenderer renderer = new LodRenderer(ApiShared.lodBufferBuilder);
public static LodRenderer renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
private final MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
@@ -138,7 +138,7 @@ public class EventApi
// breaking when changing worlds.
ClientApi.renderer.destroyBuffers();
recalculateWidths = true;
ClientApi.renderer = new LodRenderer(ApiShared.lodBufferBuilder);
ClientApi.renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
// make sure the nulled objects are freed.
@@ -0,0 +1,29 @@
package com.seibel.lod.objects.opengl;
import com.google.common.collect.ImmutableList;
/**
* A (almost) exact copy of MC's
* DefaultVertexFormats class.
*
* @author James Seibel
* @version 11-13-2021
*/
public class DefaultLodVertexFormats
{
public static final LodVertexFormatElement ELEMENT_POSITION = new LodVertexFormatElement(0, LodVertexFormatElement.Type.FLOAT, 3);
public static final LodVertexFormatElement ELEMENT_COLOR = new LodVertexFormatElement(0, LodVertexFormatElement.Type.UBYTE, 4);
public static final LodVertexFormatElement ELEMENT_UV = new LodVertexFormatElement(0, LodVertexFormatElement.Type.FLOAT, 2);
public static final LodVertexFormatElement ELEMENT_LIGHT_MAP_UV = new LodVertexFormatElement(1, LodVertexFormatElement.Type.SHORT, 2);
public static final LodVertexFormatElement ELEMENT_NORMAL = new LodVertexFormatElement(0, LodVertexFormatElement.Type.BYTE, 3);
public static final LodVertexFormatElement ELEMENT_PADDING = new LodVertexFormatElement(0, LodVertexFormatElement.Type.BYTE, 1);
public static final LodVertexFormat POSITION = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).build());
public static final LodVertexFormat POSITION_COLOR = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).build());
public static final LodVertexFormat POSITION_COLOR_LIGHTMAP = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_LIGHT_MAP_UV).build());
public static final LodVertexFormat POSITION_TEX = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_UV).build());
public static final LodVertexFormat POSITION_COLOR_TEX = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).build());
public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).add(ELEMENT_LIGHT_MAP_UV).build());
}
@@ -0,0 +1,565 @@
package com.seibel.lod.objects.opengl;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.List;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
* A (almost) exact copy of Minecraft's
* BufferBuilder object.
*
* @author James Seibel
* @version 11-13-2021
*/
public class LodBufferBuilder
{
private static final Logger LOGGER = LogManager.getLogger();
public ByteBuffer buffer;
private final List<LodBufferBuilder.DrawState> vertexCounts = Lists.newArrayList();
private int lastRenderedCountIndex = 0;
private int totalRenderedBytes = 0;
private int nextElementByte = 0;
private int totalUploadedBytes = 0;
private int vertices;
@Nullable
private LodVertexFormatElement currentElement;
private int elementIndex;
private int mode;
private LodVertexFormat format;
private boolean building;
private boolean defaultColorSet = false;
private int defaultR = 255;
private int defaultG = 255;
private int defaultB = 255;
private int defaultA = 255;
public LodBufferBuilder(int bufferSizeInBytes)
{
this.buffer = allocateByteBuffer(bufferSizeInBytes * 4);
}
// Part of MC BufferBuilder's parent DefaultColorVertexBuilder
public void defaultColor(int red, int green, int blue, int alpha)
{
this.defaultR = red;
this.defaultG = green;
this.defaultB = blue;
this.defaultA = alpha;
this.defaultColorSet = true;
}
/** originally from MC's GLAllocation class */
private ByteBuffer allocateByteBuffer(int bufferSizeInBytes)
{
return ByteBuffer.allocateDirect(bufferSizeInBytes).order(ByteOrder.nativeOrder());
}
/** originally from MC's GLAllocation class */
private FloatBuffer allocateFloatBuffer(int bufferSizeInBytes)
{
return allocateByteBuffer(bufferSizeInBytes).asFloatBuffer();
}
/** make sure the buffer doesn't overflow when inserting new elements */
private void ensureVertexCapacity()
{
this.ensureCapacity(this.format.getVertexSize());
}
private void ensureCapacity(int vertexSizeInBytes)
{
if (this.nextElementByte + vertexSizeInBytes > this.buffer.capacity())
{
int i = this.buffer.capacity();
int j = i + roundUp(vertexSizeInBytes);
//LOGGER.debug("Needed to grow BufferBuilder buffer: Old size {} bytes, new size {} bytes.", i, j);
ByteBuffer bytebuffer = allocateByteBuffer(j);
((Buffer) this.buffer).position(0);
bytebuffer.put(this.buffer);
((Buffer) bytebuffer).rewind();
this.buffer = bytebuffer;
}
}
private static int roundUp(int vertexSizeInBytes)
{
int i = 2097152; // 2 ^ 21
if (vertexSizeInBytes == 0)
{
return i;
}
else
{
if (vertexSizeInBytes < 0)
{
i *= -1;
}
int j = vertexSizeInBytes % i;
return j == 0 ? vertexSizeInBytes : vertexSizeInBytes + i - j;
}
}
/* not currently needed sortQuads()
// the x,y,z location is a blockPos
public void sortQuads(float x, float y, float z)
{
((Buffer) this.buffer).clear();
FloatBuffer floatbuffer = this.buffer.asFloatBuffer();
int i = this.vertices / 4;
float[] afloat = new float[i];
for (int j = 0; j < i; ++j)
{
afloat[j] = getQuadDistanceFromPlayer(floatbuffer, x, y, z, this.format.getIntegerSize(), this.totalRenderedBytes / 4 + j * this.format.getVertexSize());
}
int[] aint = new int[i];
for (int k = 0; k < aint.length; aint[k] = k++)
{
}
IntArrays.mergeSort(aint, (p_227830_1_, p_227830_2_) ->
{
return Floats.compare(afloat[p_227830_2_], afloat[p_227830_1_]);
});
BitSet bitset = new BitSet();
FloatBuffer floatbuffer1 = allocateFloatBuffer(this.format.getIntegerSize() * 4);
for (int l = bitset.nextClearBit(0); l < aint.length; l = bitset.nextClearBit(l + 1))
{
int i1 = aint[l];
if (i1 != l)
{
this.limitToVertex(floatbuffer, i1);
((Buffer) floatbuffer1).clear();
floatbuffer1.put(floatbuffer);
int j1 = i1;
for (int k1 = aint[i1]; j1 != l; k1 = aint[k1])
{
this.limitToVertex(floatbuffer, k1);
FloatBuffer floatbuffer2 = floatbuffer.slice();
this.limitToVertex(floatbuffer, j1);
floatbuffer.put(floatbuffer2);
bitset.set(j1);
j1 = k1;
}
this.limitToVertex(floatbuffer, l);
((Buffer) floatbuffer1).flip();
floatbuffer.put(floatbuffer1);
}
bitset.set(l);
}
}
private void limitToVertex(FloatBuffer p_227829_1_, int p_227829_2_)
{
int i = this.format.getIntegerSize() * 4;
((Buffer) p_227829_1_).limit(this.totalRenderedBytes / 4 + (p_227829_2_ + 1) * i);
((Buffer) p_227829_1_).position(this.totalRenderedBytes / 4 + p_227829_2_ * i);
}
*/
/* not curerntly needed getState()
public LodBufferBuilder.State getState()
{
((Buffer) this.buffer).limit(this.nextElementByte);
((Buffer) this.buffer).position(this.totalRenderedBytes);
ByteBuffer bytebuffer = ByteBuffer.allocate(this.vertices * this.format.getVertexSize());
bytebuffer.put(this.buffer);
((Buffer) this.buffer).clear();
return new LodBufferBuilder.State(bytebuffer, this.format);
}
*/
/* not currently needed getQuadDistanceFromPlayer()
private static float getQuadDistanceFromPlayer(FloatBuffer floatBuffer, float x, float y, float z, int p_181665_4_, int p_181665_5_)
{
float f = floatBuffer.get(p_181665_5_ + p_181665_4_ * 0 + 0);
float f1 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 0 + 1);
float f2 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 0 + 2);
float f3 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 1 + 0);
float f4 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 1 + 1);
float f5 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 1 + 2);
float f6 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 2 + 0);
float f7 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 2 + 1);
float f8 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 2 + 2);
float f9 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 3 + 0);
float f10 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 3 + 1);
float f11 = floatBuffer.get(p_181665_5_ + p_181665_4_ * 3 + 2);
float f12 = (f + f3 + f6 + f9) * 0.25F - x;
float f13 = (f1 + f4 + f7 + f10) * 0.25F - y;
float f14 = (f2 + f5 + f8 + f11) * 0.25F - z;
return f12 * f12 + f13 * f13 + f14 * f14;
}
*/
/* not currently needed restoreState()
public void restoreState(LodBufferBuilder.State bufferState)
{
((Buffer) bufferState.data).clear();
int i = bufferState.data.capacity();
this.ensureCapacity(i);
((Buffer) this.buffer).limit(this.buffer.capacity());
((Buffer) this.buffer).position(this.totalRenderedBytes);
this.buffer.put(bufferState.data);
((Buffer) this.buffer).clear();
LodVertexFormat LodVertexFormat = bufferState.format;
this.switchFormat(LodVertexFormat);
this.vertices = i / LodVertexFormat.getVertexSize();
this.nextElementByte = this.totalRenderedBytes + this.vertices * LodVertexFormat.getVertexSize();
}
*/
private void switchFormat(LodVertexFormat newFormat)
{
format = newFormat;
}
//========================================//
// methods for actually building a buffer //
//========================================//
/**
* @param openGlLodVertexFormat GL11.GL_QUADS, GL11.GL_TRIANGLES, etc.
* @param LodVertexFormat
*/
public void begin(int openGlLodVertexFormat, LodVertexFormat LodVertexFormat)
{
if (this.building)
{
throw new IllegalStateException("Already building!");
}
else
{
this.building = true;
this.mode = openGlLodVertexFormat;
this.switchFormat(LodVertexFormat);
this.currentElement = LodVertexFormat.getElements().get(0);
this.elementIndex = 0;
((Buffer) this.buffer).clear();
}
}
public void end()
{
if (!this.building)
{
throw new IllegalStateException("Not building!");
}
else
{
this.building = false;
this.vertexCounts.add(new LodBufferBuilder.DrawState(this.format, this.vertices, this.mode));
this.totalRenderedBytes += this.vertices * this.format.getVertexSize();
this.vertices = 0;
this.currentElement = null;
this.elementIndex = 0;
}
}
public void putByte(int index, byte newByte)
{
this.buffer.put(this.nextElementByte + index, newByte);
}
public void putShort(int index, short newShort)
{
this.buffer.putShort(this.nextElementByte + index, newShort);
}
public void putFloat(int index, float newFloat)
{
this.buffer.putFloat(this.nextElementByte + index, newFloat);
}
public void endVertex()
{
if (this.elementIndex != 0)
{
throw new IllegalStateException("Not filled all elements of the vertex");
}
else
{
++this.vertices;
this.ensureVertexCapacity();
}
}
public void nextElement()
{
ImmutableList<LodVertexFormatElement> immutablelist = this.format.getElements();
this.elementIndex = (this.elementIndex + 1) % immutablelist.size();
this.nextElementByte += this.currentElement.getByteSize();
LodVertexFormatElement LodVertexFormatelement = immutablelist.get(this.elementIndex);
this.currentElement = LodVertexFormatelement;
// if (LodVertexFormatelement.getUsage() == LodVertexFormatElement.Usage.PADDING)
// {
// this.nextElement();
// }
// if (this.defaultColorSet && this.currentElement.getUsage() == LodVertexFormatElement.Usage.COLOR)
// {
// color(this.defaultR, this.defaultG, this.defaultB, this.defaultA);
// }
}
public LodBufferBuilder color(int red, int green, int blue, int alpha)
{
if (this.defaultColorSet)
{
throw new IllegalStateException();
}
else
{
LodVertexFormatElement LodVertexFormatelement = this.currentElement();
// if (LodVertexFormatelement.getUsage() != LodVertexFormatElement.Usage.COLOR)
// {
// return this;
// }
// else if (LodVertexFormatelement.getType() != LodVertexFormatElement.Type.UBYTE)
// {
// throw new IllegalStateException();
// }
// else
// {
this.putByte(0, (byte) red);
this.putByte(1, (byte) green);
this.putByte(2, (byte) blue);
this.putByte(3, (byte) alpha);
this.nextElement();
return this;
// }
}
}
public LodBufferBuilder vertex(float x, float y, float z)
{
if (this.currentElement().getType() != LodVertexFormatElement.Type.FLOAT)
{
throw new IllegalStateException();
}
else
{
this.putFloat(0, x);
this.putFloat(4, y);
this.putFloat(8, z);
this.nextElement();
return this;
}
}
/* not currently needed fullVertex()
* TODO James isn't sure about these names
public void vertex(float blockPosX, float blockPosY, float blockPosZ,
float red, float green, float blue, float alpha,
float textureU, float textureV,
int p_225588_10_, int p_225588_11_,
float p_225588_12_, float p_225588_13_, float p_225588_14_)
{
if (this.defaultColorSet)
{
throw new IllegalStateException();
}
else if (this.fastFormat)
{
this.putFloat(0, blockPosX);
this.putFloat(4, blockPosY);
this.putFloat(8, blockPosZ);
this.putByte(12, (byte) ((int) (red * 255.0F)));
this.putByte(13, (byte) ((int) (green * 255.0F)));
this.putByte(14, (byte) ((int) (blue * 255.0F)));
this.putByte(15, (byte) ((int) (alpha * 255.0F)));
this.putFloat(16, textureU);
this.putFloat(20, textureV);
int i;
if (this.fullFormat)
{
this.putShort(24, (short) (p_225588_10_ & '\uffff'));
this.putShort(26, (short) (p_225588_10_ >> 16 & '\uffff'));
i = 28;
}
else
{
i = 24;
}
this.putShort(i + 0, (short) (p_225588_11_ & '\uffff'));
this.putShort(i + 2, (short) (p_225588_11_ >> 16 & '\uffff'));
this.putByte(i + 4, IVertexConsumer.normalIntValue(p_225588_12_));
this.putByte(i + 5, IVertexConsumer.normalIntValue(p_225588_13_));
this.putByte(i + 6, IVertexConsumer.normalIntValue(p_225588_14_));
this.nextElementByte += i + 8;
this.endVertex();
}
else
{
super.vertex(blockPosX, blockPosY, blockPosZ, red, green, blue, alpha, textureU, textureV, p_225588_10_, p_225588_11_, p_225588_12_, p_225588_13_, p_225588_14_);
}
}
*/
/**
* James isn't sure what the difference between
* using this method and just directly getting the buffer would be.
* But this was what was being used before, so it will stay for now.
*
* If anyone figures out what is special about this, please replace this comment.
*/
public ByteBuffer getCleanedByteBuffer()
{
LodBufferBuilder.DrawState bufferbuilder$drawstate = this.vertexCounts.get(this.lastRenderedCountIndex++);
((Buffer) this.buffer).position(this.totalUploadedBytes);
this.totalUploadedBytes += bufferbuilder$drawstate.vertexCount() * bufferbuilder$drawstate.format().getVertexSize();
((Buffer) this.buffer).limit(this.totalUploadedBytes);
if (this.lastRenderedCountIndex == this.vertexCounts.size() && this.vertices == 0)
{
this.clear();
}
ByteBuffer bytebuffer = this.buffer.slice();
bytebuffer.order(this.buffer.order()); // FORGE: Fix incorrect byte order
((Buffer) this.buffer).clear();
return bytebuffer; // the original method also returned bufferbuilder$drawstate
}
public void clear()
{
if (this.totalRenderedBytes != this.totalUploadedBytes)
{
LOGGER.warn("Bytes mismatch " + this.totalRenderedBytes + " " + this.totalUploadedBytes);
}
this.discard();
}
public void discard()
{
this.totalRenderedBytes = 0;
this.totalUploadedBytes = 0;
this.nextElementByte = 0;
this.vertexCounts.clear();
this.lastRenderedCountIndex = 0;
}
public LodVertexFormatElement currentElement()
{
if (this.currentElement == null)
{
throw new IllegalStateException("BufferBuilder not started");
}
else
{
return this.currentElement;
}
}
public boolean building()
{
return this.building;
}
//==================//
// internal classes //
//==================//
public static final class DrawState
{
private final LodVertexFormat format;
private final int vertexCount;
private final int mode;
private DrawState(LodVertexFormat p_i225905_1_, int p_i225905_2_, int p_i225905_3_)
{
this.format = p_i225905_1_;
this.vertexCount = p_i225905_2_;
this.mode = p_i225905_3_;
}
public LodVertexFormat format()
{
return this.format;
}
public int vertexCount()
{
return this.vertexCount;
}
public int mode()
{
return this.mode;
}
}
public static class State
{
private final ByteBuffer data;
private final LodVertexFormat format;
private State(ByteBuffer newByteBuffer, LodVertexFormat newLodVertexFormat)
{
data = newByteBuffer;
format = newLodVertexFormat;
}
}
// Forge added methods
public void putBulkData(ByteBuffer buffer)
{
ensureCapacity(buffer.limit() + this.format.getVertexSize());
((Buffer) this.buffer).position(this.vertices * this.format.getVertexSize());
this.buffer.put(buffer);
this.vertices += buffer.limit() / this.format.getVertexSize();
this.nextElementByte += buffer.limit();
}
public LodVertexFormat getLodVertexFormat()
{
return this.format;
}
}
@@ -0,0 +1,164 @@
package com.seibel.lod.objects.opengl;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
/**
* A (almost) exact copy of Minecraft's
* VertexFormat class, several methods
* were commented out since we didn't need them.
*
* @author James Seibel
* @version 11-13-2021
*/
public class LodVertexFormat
{
private final ImmutableList<LodVertexFormatElement> elements;
private final IntList offsets = new IntArrayList();
private final int vertexSize;
public LodVertexFormat(ImmutableList<LodVertexFormatElement> elementList)
{
this.elements = elementList;
int i = 0;
for (LodVertexFormatElement LodVertexFormatElement : elementList)
{
this.offsets.add(i);
i += LodVertexFormatElement.getByteSize();
}
this.vertexSize = i;
}
public int getIntegerSize()
{
return this.getVertexSize() / 4;
}
public int getVertexSize()
{
return this.vertexSize;
}
public ImmutableList<LodVertexFormatElement> getElements()
{
return this.elements;
}
// Forge added method
public int getOffset(int index)
{
return offsets.getInt(index);
}
@Override
public String toString()
{
return "format: " + this.elements.size() + " elements: " + this.elements.stream().map(Object::toString).collect(Collectors.joining(" "));
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
LodVertexFormat vertexformat = (LodVertexFormat) obj;
return this.vertexSize != vertexformat.vertexSize ? false : this.elements.equals(vertexformat.elements);
}
else
{
return false;
}
}
@Override
public int hashCode()
{
return this.elements.hashCode();
}
/* not currently needed setupBufferState()
public void setupBufferState(long p_227892_1_)
{
if (!RenderSystem.isOnRenderThread())
{
RenderSystem.recordRenderCall(() ->
{
this.setupBufferState(p_227892_1_);
});
}
else
{
int i = this.getVertexSize();
List<LodVertexFormatElement> list = this.getElements();
for (int j = 0; j < list.size(); ++j)
{
list.get(j).setupBufferState(p_227892_1_ + this.offsets.getInt(j), i);
}
}
}
*/
/* not currently needed clearBufferState()
public void clearBufferState()
{
if (!RenderSystem.isOnRenderThread())
{
RenderSystem.recordRenderCall(this::clearBufferState);
}
else
{
for (LodVertexFormatElement LodVertexFormatElement : this.getElements())
{
LodVertexFormatElement.clearBufferState();
}
}
}
*/
/* not currently needed has Position/Normal/Color/UV
public boolean hasPosition()
{
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.POSITION);
}
public boolean hasNormal()
{
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.NORMAL);
}
public boolean hasColor()
{
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.COLOR);
}
public boolean hasUV(int which)
{
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.UV && e.getIndex() == which);
}
*/
}
@@ -0,0 +1,257 @@
package com.seibel.lod.objects.opengl;
import org.lwjgl.opengl.GL11;
/**
* A (almost) exact copy of Minecraft's
* VertexFormatElement class.
* A number of things were removed from the original
* object since we didn't need them, specifically "usage".
*
* @author James Seibel
* @version 11-13-2021
*/
public class LodVertexFormatElement
{
// private static final Logger LOGGER = LogManager.getLogger();
private final LodVertexFormatElement.Type type;
// private final LodVertexFormatElement.Usage usage;
private final int index;
private final int count;
private final int byteSize;
// public LodVertexFormatElement(int p_i46096_1_, LodVertexFormatElement.Type p_i46096_2_, LodVertexFormatElement.Usage p_i46096_3_, int p_i46096_4_)
public LodVertexFormatElement(int newIndex, LodVertexFormatElement.Type newType, int newCount)
{
// if (this.supportsUsage(p_i46096_1_, p_i46096_3_))
// {
// this.usage = p_i46096_3_;
// }
// else
// {
// LOGGER.warn("Multiple vertex elements of the same type other than UVs are not supported. Forcing type to UV.");
// this.usage = LodVertexFormatElement.Usage.UV;
// }
this.type = newType;
this.index = newIndex;
this.count = newCount;
this.byteSize = newType.getSize() * this.count;
}
// private boolean supportsUsage(int p_177372_1_, LodVertexFormatElement.Usage p_177372_2_)
// {
// return p_177372_1_ == 0 || p_177372_2_ == LodVertexFormatElement.Usage.UV;
// }
public final LodVertexFormatElement.Type getType()
{
return this.type;
}
// public final LodVertexFormatElement.Usage getUsage()
// {
// return this.usage;
// }
public final int getIndex()
{
return this.index;
}
@Override
public String toString()
{
// return this.count + "," + this.usage.getName() + "," + this.type.getName();
return this.count + "," + this.type.getName();
}
public final int getByteSize()
{
return this.byteSize;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
LodVertexFormatElement LodVertexFormatElement = (LodVertexFormatElement) obj;
if (this.count != LodVertexFormatElement.count)
{
return false;
}
else if (this.index != LodVertexFormatElement.index)
{
return false;
}
else if (this.type != LodVertexFormatElement.type)
{
return false;
}
else
{
// return this.usage == LodVertexFormatElement.usage;
return false;
}
}
else
{
return false;
}
}
@Override
public int hashCode()
{
int i = this.type.hashCode();
// i = 31 * i + this.usage.hashCode();
i = 31 * i + this.index;
return 31 * i + this.count;
}
// public void setupBufferState(long p_227897_1_, int p_227897_3_)
// {
// this.usage.setupBufferState(this.count, this.type.getGlType(), p_227897_3_, p_227897_1_, this.index);
// }
// public void clearBufferState()
// {
// this.usage.clearBufferState(this.index);
// }
//Forge Start
public int getElementCount()
{
return count;
}
//Forge End
public static enum Type
{
FLOAT(4, "Float", GL11.GL_FLOAT),
UBYTE(1, "Unsigned Byte", GL11.GL_UNSIGNED_BYTE),
BYTE(1, "Byte", GL11.GL_BYTE),
USHORT(2, "Unsigned Short", GL11.GL_UNSIGNED_SHORT),
SHORT(2, "Short", GL11.GL_SHORT),
UINT(4, "Unsigned Int", GL11.GL_UNSIGNED_INT),
INT(4, "Int", GL11.GL_INT);
private final int size;
private final String name;
private final int glType;
private Type(int sizeInBytes, String newName, int openGlDataType)
{
this.size = sizeInBytes;
this.name = newName;
this.glType = openGlDataType;
}
public int getSize()
{
return this.size;
}
public String getName()
{
return this.name;
}
public int getGlType()
{
return this.glType;
}
}
// public static enum Usage
// {
// POSITION("Position", (p_227914_0_, p_227914_1_, p_227914_2_, p_227914_3_, p_227914_5_) ->
// {
// GlStateManager._vertexPointer(p_227914_0_, p_227914_1_, p_227914_2_, p_227914_3_);
// GlStateManager._enableClientState(32884);
// }, (p_227912_0_) ->
// {
// GlStateManager._disableClientState(32884);
// }),
// NORMAL("Normal", (p_227913_0_, p_227913_1_, p_227913_2_, p_227913_3_, p_227913_5_) ->
// {
// GlStateManager._normalPointer(p_227913_1_, p_227913_2_, p_227913_3_);
// GlStateManager._enableClientState(32885);
// }, (p_227910_0_) ->
// {
// GlStateManager._disableClientState(32885);
// }),
// COLOR("Vertex Color", (p_227911_0_, p_227911_1_, p_227911_2_, p_227911_3_, p_227911_5_) ->
// {
// GlStateManager._colorPointer(p_227911_0_, p_227911_1_, p_227911_2_, p_227911_3_);
// GlStateManager._enableClientState(32886);
// }, (p_227908_0_) ->
// {
// GlStateManager._disableClientState(32886);
// GlStateManager._clearCurrentColor();
// }),
// UV("UV", (p_227909_0_, p_227909_1_, p_227909_2_, p_227909_3_, p_227909_5_) ->
// {
// GlStateManager._glClientActiveTexture('\u84c0' + p_227909_5_);
// GlStateManager._texCoordPointer(p_227909_0_, p_227909_1_, p_227909_2_, p_227909_3_);
// GlStateManager._enableClientState(32888);
// GlStateManager._glClientActiveTexture(33984);
// }, (p_227906_0_) ->
// {
// GlStateManager._glClientActiveTexture('\u84c0' + p_227906_0_);
// GlStateManager._disableClientState(32888);
// GlStateManager._glClientActiveTexture(33984);
// }),
// PADDING("Padding", (p_227907_0_, p_227907_1_, p_227907_2_, p_227907_3_, p_227907_5_) ->
// {
// }, (p_227904_0_) ->
// {
// }),
// GENERIC("Generic", (p_227905_0_, p_227905_1_, p_227905_2_, p_227905_3_, p_227905_5_) ->
// {
// GlStateManager._enableVertexAttribArray(p_227905_5_);
// GlStateManager._vertexAttribPointer(p_227905_5_, p_227905_0_, p_227905_1_, false, p_227905_2_, p_227905_3_);
// }, GlStateManager::_disableVertexAttribArray);
//
// private final String name;
// private final LodVertexFormatElement.Usage.ISetupState setupState;
// private final IntConsumer clearState;
//
// private Usage(String p_i225912_3_, LodVertexFormatElement.Usage.ISetupState p_i225912_4_, IntConsumer p_i225912_5_)
// {
// this.name = p_i225912_3_;
// this.setupState = p_i225912_4_;
// this.clearState = p_i225912_5_;
// }
//
// private void setupBufferState(int p_227902_1_, int p_227902_2_, int p_227902_3_, long p_227902_4_, int p_227902_6_)
// {
// this.setupState.setupBufferState(p_227902_1_, p_227902_2_, p_227902_3_, p_227902_4_, p_227902_6_);
// }
//
// public void clearBufferState(int p_227901_1_)
// {
// this.clearState.accept(p_227901_1_);
// }
//
// public String getName()
// {
// return this.name;
// }
//
// @OnlyIn(Dist.CLIENT)
// interface ISetupState
// {
// void setupBufferState(int p_setupBufferState_1_, int p_setupBufferState_2_, int p_setupBufferState_3_, long p_setupBufferState_4_, int p_setupBufferState_6_);
// }
// }
}
@@ -26,8 +26,8 @@ import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.NVFogDistance;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilder;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilder.VertexBuffersAndOffset;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilderFactory;
import com.seibel.lod.builders.bufferBuilding.LodBufferBuilderFactory.VertexBuffersAndOffset;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.enums.config.GpuUploadMethod;
import com.seibel.lod.enums.rendering.DebugMode;
@@ -87,7 +87,7 @@ public class LodRenderer
/** This is used to generate the buildable buffers */
private final LodBufferBuilder lodBufferBuilder;
private final LodBufferBuilderFactory lodBufferBuilderFactory;
/** Each VertexBuffer represents 1 region */
private VertexBuffer[][][] vbos;
@@ -135,12 +135,12 @@ public class LodRenderer
public LodRenderer(LodBufferBuilder newLodNodeBufferBuilder)
public LodRenderer(LodBufferBuilderFactory newLodNodeBufferBuilder)
{
mc = MinecraftWrapper.INSTANCE;
gameRender = mc.getGameRenderer();
lodBufferBuilder = newLodNodeBufferBuilder;
lodBufferBuilderFactory = newLodNodeBufferBuilder;
}
@@ -195,10 +195,10 @@ public class LodRenderer
// 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 ((partialRegen || fullRegen) && !lodBufferBuilder.generatingBuffers && !lodBufferBuilder.newBuffersAvailable())
if ((partialRegen || fullRegen) && !lodBufferBuilderFactory.generatingBuffers && !lodBufferBuilderFactory.newBuffersAvailable())
{
// generate the LODs on a separate thread to prevent stuttering or freezing
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, mc.getPlayerBlockPos(), true);
lodBufferBuilderFactory.generateLodBuffersAsync(this, lodDim, mc.getPlayerBlockPos(), true);
// the regen process has been started,
// it will be done when lodBufferBuilder.newBuffersAvailable()
@@ -210,7 +210,7 @@ public class LodRenderer
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
// ...ending here
if (lodBufferBuilder.newBuffersAvailable())
if (lodBufferBuilderFactory.newBuffersAvailable())
{
swapBuffers();
}
@@ -644,7 +644,7 @@ public class LodRenderer
/** Create all buffers that will be used. */
public void setupBuffers(LodDimension lodDim)
{
lodBufferBuilder.setupBuffers(lodDim);
lodBufferBuilderFactory.setupBuffers(lodDim);
}
@@ -673,7 +673,7 @@ public class LodRenderer
{
// replace the drawable buffers with
// the newly created buffers from the lodBufferBuilder
VertexBuffersAndOffset result = lodBufferBuilder.getVertexBuffers();
VertexBuffersAndOffset result = lodBufferBuilderFactory.getVertexBuffers();
vbos = result.vbos;
storageBufferIds = result.storageBufferIds;
vbosCenter = result.drawableCenterChunkPos;
@@ -682,7 +682,7 @@ public class LodRenderer
/** Calls the BufferBuilder's destroyBuffers method. */
public void destroyBuffers()
{
lodBufferBuilder.destroyBuffers();
lodBufferBuilderFactory.destroyBuffers();
}
// TODO move this into the MC wrapper
@@ -27,7 +27,7 @@ import com.seibel.lod.wrappers.MinecraftWrapper;
*
* @author Cola
* @author Leonardo Amato
* @version ??
* @version 11-13-2021
*/
public class ColorUtil
{
@@ -41,21 +41,25 @@ public class ColorUtil
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
/** Returns a value between 0 and 255 */
public static int getAlpha(int color)
{
return (color >> 24) & 0xFF;
}
/** Returns a value between 0 and 255 */
public static int getRed(int color)
{
return (color >> 16) & 0xFF;
}
/** Returns a value between 0 and 255 */
public static int getGreen(int color)
{
return (color >> 8) & 0xFF;
}
/** Returns a value between 0 and 255 */
public static int getBlue(int color)
{
return color & 0xFF;
@@ -19,7 +19,7 @@
package com.seibel.lod.util;
import static com.seibel.lod.builders.bufferBuilding.LodBufferBuilder.skyLightPlayer;
import static com.seibel.lod.builders.bufferBuilding.LodBufferBuilderFactory.skyLightPlayer;
import com.seibel.lod.enums.config.DistanceGenerationMode;
@@ -29,18 +29,17 @@ import com.seibel.lod.enums.config.HorizontalResolution;
import com.seibel.lod.enums.config.VanillaOverdraw;
import com.seibel.lod.objects.lod.LodDimension;
import com.seibel.lod.objects.lod.RegionPos;
import com.seibel.lod.objects.opengl.DefaultLodVertexFormats;
import com.seibel.lod.objects.opengl.LodVertexFormat;
import com.seibel.lod.wrappers.MinecraftWrapper;
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
import com.seibel.lod.wrappers.Chunk.ChunkPosWrapper;
import com.seibel.lod.wrappers.World.DimensionTypeWrapper;
import com.seibel.lod.wrappers.World.WorldWrapper;
import com.seibel.lod.wrappers.World.WorldWrapper;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@@ -54,7 +53,7 @@ import net.minecraft.world.server.ServerWorld;
* This class holds methods and constants that may be used in multiple places.
*
* @author James Seibel
* @version 10-20-2021
* @version 11-13-2021
*/
public class LodUtil
{
@@ -142,17 +141,17 @@ public class LodUtil
* 64 MB by default is the maximum amount of memory that
* can be directly allocated. <br><br>
* <p>
* I know there are commands to change that amount
* James knows there are commands to change that amount
* (specifically "-XX:MaxDirectMemorySize"), but
* I have no idea how to access that amount. <br>
* So I guess this will be the hard limit for now. <br><br>
* He has no idea how to access that amount. <br>
* So for now this will be the hard limit. <br><br>
* <p>
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
*/
public static final int MAX_ALLOCATABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
/** the format of data stored in the GPU buffers */
public static final LodVertexFormat LOD_VERTEX_FORMAT = DefaultLodVertexFormats.POSITION_COLOR;