Fix many stuff. See list below:

1. Fixed seeing previous dim's lod after going though a portal
2. Fixed changing VertQual live causes many issues (now force a reload)
3. Fixed loading old lod files with smaller than expected vert data
   causing the data container to be incorrectly sized
4. Improved BufferBuilder to use less RAM and cleanup
5. Shink BufferBuilder on calling end()
This commit is contained in:
tom lee
2022-02-10 14:50:33 +08:00
parent c70d2a27f2
commit 07d4050502
8 changed files with 94 additions and 428 deletions
@@ -21,6 +21,7 @@ package com.seibel.lod.core.api;
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.objects.lod.LodWorld;
/**
@@ -42,6 +43,7 @@ public class ApiShared
public static int previousChunkRenderDistance = 0;
/** Used to determine if the LODs should be regenerated */
public static int previousLodRenderDistance = 0;
public static VerticalQuality previousVertQual = null;
/** Signal whether a world is shutting down */
public static volatile boolean isShuttingDown = false;
@@ -33,6 +33,7 @@ import org.lwjgl.glfw.GLFW;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.GLProxy;
@@ -143,7 +144,13 @@ public class ClientApi
lastFlush = System.nanoTime();
flushSpamLoggersState();
}
if (ApiShared.previousVertQual != CONFIG.client().graphics().quality().getVerticalQuality()) {
ApiShared.previousVertQual = CONFIG.client().graphics().quality().getVerticalQuality();
EventApi.INSTANCE.worldUnloadEvent(MC.getWrappedServerWorld());
EventApi.INSTANCE.worldLoadEvent(MC.getWrappedClientWorld());
return;
}
// only run the first time setup once
if (!firstTimeSetupComplete)
@@ -26,6 +26,7 @@ import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.worldGeneration.BatchGenerator;
import com.seibel.lod.core.builders.worldGeneration.LodWorldGenerator;
import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.objects.lod.RegionPos;
import com.seibel.lod.core.render.GLProxy;
@@ -136,6 +137,7 @@ public class EventApi {
// make sure the correct LODs are being rendered
// (if this isn't done the previous world's LODs may be drawn)
ClientApi.renderer.regenerateLODsNextFrame();
ApiShared.previousVertQual = CONFIG.client().graphics().quality().getVerticalQuality();
}
/** This is also called when the user disconnects from a server+ */
@@ -174,6 +176,7 @@ public class EventApi {
ClientApi.renderer.requestCleanup();
GLProxy.ensureAllGLJobCompleted();
recalculateWidths = true;
ApiShared.previousVertQual = null;
// TODO: Check if after the refactoring, is this still needed
ClientApi.renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
@@ -206,7 +209,7 @@ public class EventApi {
// "\t center: " + lodDim.getCenterX() + "," + lodDim.getCenterZ());
}
}
/** Re-sizes all LodDimensions if they need to be. */
public void viewDistanceChangedEvent() {
// calculate how wide the dimension(s) should be in regions
@@ -116,7 +116,7 @@ public class LodBufferBuilderFactory
* This size will be too small, more than likely. The buffers will be expanded
* when need be to fit the larger sizes.
*/
public static final int DEFAULT_MEMORY_ALLOCATION = 128;
public static final int DEFAULT_MEMORY_ALLOCATION = (LodUtil.LOD_VERTEX_FORMAT.getByteSize()*3)*8;
public static final int MAX_TRIANGLES_PER_BUFFER = (1024*1024*1) / (LodUtil.LOD_VERTEX_FORMAT.getByteSize()*3);
@@ -166,6 +166,9 @@ public class LodBufferBuilderFactory
* and are waiting to be swapped with the drawable buffers
*/
private boolean switchVbos = false;
// The hideFrontBuffer is for when switching dimensions
private volatile boolean hideFrontBuffer = false;
private volatile boolean hideBackBuffer = false;
/** Size of the buffer builders in bytes last time we created them */
public int previousBufferSize = 0;
@@ -321,7 +324,7 @@ public class LodBufferBuilderFactory
if (builder == null) {
builder = buildableBuffers.setAndGet(regionX, regionZ, new LodBufferBuilder(DEFAULT_MEMORY_ALLOCATION));
} else {
builder.discard();
builder.reset();
}
builder.begin(GL32.GL_QUADS, LodUtil.LOD_VERTEX_FORMAT);
byte minDetail = region.getMinDetailLevel();
@@ -380,6 +383,7 @@ public class LodBufferBuilderFactory
} catch (Exception e) {
ClientApi.LOGGER.error("\"LodNodeBufferBuilder\" was unable to close buildable buffer: " + e.getMessage());
e.printStackTrace();
buildableBuffers.set(regPos.x, regPos.z, null);
}
}
@@ -558,6 +562,7 @@ public class LodBufferBuilderFactory
} // for pos to in list to render
// the thread executed successfully
currentBuffer.end();
return true;
}
@@ -716,8 +721,8 @@ public class LodBufferBuilderFactory
int maxLength = MAX_TRIANGLES_PER_BUFFER*(LodUtil.LOD_VERTEX_FORMAT.getByteSize()*3);
LagSpikeCatcher vboSetup = new LagSpikeCatcher();
LodVertexBuffer[] vbos = buildableVbos.get(p.x, p.z);
int requiredFullBuffers = Math.floorDiv(uploadBuffer.capacity(),maxLength);
int additionalBuffer = Math.floorMod(uploadBuffer.capacity(),maxLength);
int requiredFullBuffers = Math.floorDiv(uploadBuffer.limit(),maxLength);
int additionalBuffer = Math.floorMod(uploadBuffer.limit(),maxLength);
if (vbos == null) {
vbos = new LodVertexBuffer[requiredFullBuffers+1];
buildableVbos.set(p.x, p.z, vbos);
@@ -929,6 +934,8 @@ public class LodBufferBuilderFactory
shouldRegenBuff = frontBufferRequireReset || allBuffersRequireReset;
frontBufferRequireReset = allBuffersRequireReset;
allBuffersRequireReset = false;
hideFrontBuffer = hideBackBuffer;
hideBackBuffer = false;
}
catch (Exception e)
{
@@ -946,7 +953,7 @@ public class LodBufferBuilderFactory
/** Get the newly created VBOs */
public MovableGridList<LodVertexBuffer[]> getFrontBuffers()
{
return drawableVbos;
return shouldDrawFrontBuffer() ? drawableVbos : null;
}
public int getFrontBuffersCenterX()
{
@@ -956,4 +963,13 @@ public class LodBufferBuilderFactory
{
return drawableCenterBlockZ;
}
public void triggerReset() {
allBuffersRequireReset = true;
hideBackBuffer = true;
hideFrontBuffer = true;
}
public boolean shouldDrawFrontBuffer() {
return !hideFrontBuffer;
}
}
@@ -240,19 +240,6 @@ public class VerticalLevelContainer implements LevelContainer
return result;
}
private static long[] downgradeVerticalSize(int oldVertSize, int newVertSize, long[] data) {
int size = data.length/oldVertSize;
long[] dataToMerge = new long[oldVertSize];
long[] newData = new long[size * newVertSize];
for (int i = 0; i < size; i++)
{
System.arraycopy(data, i * oldVertSize, dataToMerge, 0, oldVertSize);
long[] tempBuffer = DataPointUtil.mergeMultiData(dataToMerge, oldVertSize, newVertSize);
System.arraycopy(tempBuffer, 0, newData, i * newVertSize, newVertSize);
}
return newData;
}
private static void patchHeightAndDepth(long[] data, int offset) {
for (int i=0; i<data.length; i++) {
data[i] = DataPointUtil.shiftHeightAndDepth(data[i], (short)offset);
@@ -285,146 +272,10 @@ public class VerticalLevelContainer implements LevelContainer
}
int targetMaxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
if (fileMaxVerticalData > targetMaxVerticalData)
{
verticalSize = targetMaxVerticalData;
this.dataContainer = downgradeVerticalSize(fileMaxVerticalData, targetMaxVerticalData, tempDataContainer);
}
else
{
verticalSize = fileMaxVerticalData;
this.dataContainer = tempDataContainer;
}
verticalSize = targetMaxVerticalData;
dataContainer = DataPointUtil.changeMaxVertSize(tempDataContainer, fileMaxVerticalData, verticalSize);
}
// Deprecated. Please use the DataInputStream version.
@Deprecated
public VerticalLevelContainer(byte[] inputData, int version)
{
minHeight = SingletonHandler.get(IMinecraftWrapper.class).getWrappedClientWorld().getMinHeight();
int tempMaxVerticalData;
int tempIndex;
int index = 0;
long newData;
detailLevel = inputData[index];
index++;
tempMaxVerticalData = inputData[index] & 0b01111111;
index++;
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
int x = size * size * tempMaxVerticalData;
long[] tempDataContainer = new long[x];
if (version == 6)
{
for (int i = 0; i < x; i++)
{
newData = 0;
for (tempIndex = 0; tempIndex < 8; tempIndex++)
newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
index += 8;
newData = DataPointUtil.createDataPoint(
DataPointUtil.getAlpha(newData),
DataPointUtil.getRed(newData),
DataPointUtil.getGreen(newData),
DataPointUtil.getBlue(newData),
DataPointUtil.getHeight(newData) - minHeight,
DataPointUtil.getDepth(newData) - minHeight,
DataPointUtil.getLightSky(newData),
DataPointUtil.getLightBlock(newData),
DataPointUtil.getGenerationMode(newData),
DataPointUtil.getFlag(newData));
tempDataContainer[i] = newData;
}
}
else if (version == 7)
{
for (int i = 0; i < x; i++)
{
newData = 0;
for (tempIndex = 0; tempIndex < 8; tempIndex++)
newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
index += 8;
newData = DataPointUtil.createDataPoint(
DataPointUtil.getAlpha(newData),
DataPointUtil.getRed(newData),
DataPointUtil.getGreen(newData),
DataPointUtil.getBlue(newData),
DataPointUtil.getHeight(newData) - 64 - minHeight,
DataPointUtil.getDepth(newData) - 64 - minHeight,
DataPointUtil.getLightSky(newData),
DataPointUtil.getLightBlock(newData),
DataPointUtil.getGenerationMode(newData),
DataPointUtil.getFlag(newData));
tempDataContainer[i] = newData;
}
}
else //if (version == 8)
{
short tempMinHeight = inputData[index];
index++;
tempMinHeight |= (((short) inputData[index]) & 0xff) << 8;
index++;
if (tempMinHeight != minHeight)
{
for (int i = 0; i < x; i++)
{
newData = 0;
for (tempIndex = 0; tempIndex < 8; tempIndex++)
newData |= (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
index += 8;
newData = DataPointUtil.createDataPoint(
DataPointUtil.getAlpha(newData),
DataPointUtil.getRed(newData),
DataPointUtil.getGreen(newData),
DataPointUtil.getBlue(newData),
DataPointUtil.getHeight(newData) + tempMinHeight - minHeight,
DataPointUtil.getDepth(newData) + tempMinHeight - minHeight,
DataPointUtil.getLightSky(newData),
DataPointUtil.getLightBlock(newData),
DataPointUtil.getGenerationMode(newData),
DataPointUtil.getFlag(newData));
tempDataContainer[i] = newData;
}
}
else
{
for (int i = 0; i < x; i++)
{
newData = 0;
for (tempIndex = 0; tempIndex < 8; tempIndex++)
newData |= (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
index += 8;
tempDataContainer[i] = newData;
}
}
}
if (tempMaxVerticalData > DetailDistanceUtil.getMaxVerticalData(detailLevel))
{
int tempMaxVerticalData2 = DetailDistanceUtil.getMaxVerticalData(detailLevel);
long[] dataToMerge = new long[tempMaxVerticalData];
long[] tempDataContainer2 = new long[size * size * tempMaxVerticalData2];
for (int i = 0; i < size * size; i++)
{
System.arraycopy(tempDataContainer, i * tempMaxVerticalData, dataToMerge, 0, tempMaxVerticalData);
dataToMerge = DataPointUtil.mergeMultiData(dataToMerge, tempMaxVerticalData, tempMaxVerticalData2);
System.arraycopy(dataToMerge, 0, tempDataContainer2, i * tempMaxVerticalData2, tempMaxVerticalData2);
}
verticalSize = tempMaxVerticalData2;
this.dataContainer = tempDataContainer2;
}
else
{
verticalSize = tempMaxVerticalData;
this.dataContainer = tempDataContainer;
}
}
/**
* This method merge column of multiple data together
* @return one column of correctly parsed data
@@ -21,14 +21,8 @@ package com.seibel.lod.core.objects.opengl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.List;
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
@@ -41,46 +35,28 @@ import com.google.common.collect.Lists;
*/
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;
private LodVertexFormatElement currentElement;
private int elementIndex;
private int mode;
private LodVertexFormat format;
private boolean building;
public LodBufferBuilder(int bufferSizeInBytes)
{
this.buffer = allocateByteBuffer(bufferSizeInBytes * 4);
this.buffer = allocateByteBuffer(bufferSizeInBytes);
}
public int getMemUsage() {return buffer.capacity();}
/** originally from MC's GLAllocation class */
private ByteBuffer allocateByteBuffer(int bufferSizeInBytes)
{
return ByteBuffer.allocateDirect(bufferSizeInBytes).order(ByteOrder.nativeOrder());
}
/** originally from MC's GLAllocation class */
@SuppressWarnings("unused")
private FloatBuffer allocateFloatBuffer(int bufferSizeInBytes)
{
return allocateByteBuffer(bufferSizeInBytes).asFloatBuffer();
}
/** make sure the buffer doesn't overflow when inserting new elements */
private void ensureVertexCapacity()
@@ -92,7 +68,7 @@ public class LodBufferBuilder
if (this.nextElementByte + vertexSizeInBytes > this.buffer.capacity())
{
int i = this.buffer.capacity();
int j = i + roundUp(vertexSizeInBytes);
int j = roundUp((int) ((i + vertexSizeInBytes)*2));
//LOGGER.debug("Needed to grow BufferBuilder buffer: Old size {} bytes, new size {} bytes.", i, j);
ByteBuffer bytebuffer = allocateByteBuffer(j);
this.buffer.position(0);
@@ -101,9 +77,23 @@ public class LodBufferBuilder
this.buffer = bytebuffer;
}
}
private void packBuffer() {
int cap = this.buffer.capacity();
int filled = this.format.getByteSize() * this.vertices;
this.buffer.position(0);
this.buffer.limit(filled);
if (cap - filled > 4096) {
ByteBuffer bytebuffer = allocateByteBuffer(filled);
bytebuffer.put(this.buffer);
bytebuffer.rewind();
this.buffer = bytebuffer;
}
}
private static int roundUp(int vertexSizeInBytes)
{
int i = 2097152; // 2 ^ 21
int i = 4096; // 4 KB (1 page)
if (vertexSizeInBytes == 0)
{
return i;
@@ -119,127 +109,6 @@ public class LodBufferBuilder
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)
{
@@ -266,11 +135,11 @@ public class LodBufferBuilder
else
{
this.building = true;
this.mode = openGlLodVertexFormat;
this.switchFormat(LodVertexFormat);
this.currentElement = LodVertexFormat.getElements().get(0);
this.elementIndex = 0;
this.buffer.clear();
this.vertices = 0;
}
}
@@ -278,16 +147,12 @@ public class LodBufferBuilder
{
if (!this.building)
{
throw new IllegalStateException("Not building!");
}
else
{
return;
} else {
this.building = false;
this.vertexCounts.add(new LodBufferBuilder.DrawState(this.format, this.vertices, this.mode));
this.totalRenderedBytes += this.vertices * this.format.getByteSize();
this.vertices = 0;
this.currentElement = null;
this.elementIndex = 0;
packBuffer();
}
}
@@ -386,103 +251,16 @@ public class LodBufferBuilder
}
}
/* 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++);
this.buffer.position(this.totalUploadedBytes);
this.totalUploadedBytes += bufferbuilder$drawstate.vertexCount() * bufferbuilder$drawstate.format().getByteSize();
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
this.buffer.clear();
return bytebuffer; // the original method also returned bufferbuilder$drawstate
return this.buffer;
}
public void clear()
public void reset()
{
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;
this.vertices = 0;
this.buffer.clear();
}
public LodVertexFormatElement currentElement()
@@ -502,15 +280,10 @@ public class LodBufferBuilder
return this.building;
}
//==================//
// internal classes //
//==================//
public static final class DrawState
{
private final LodVertexFormat format;
@@ -540,18 +313,6 @@ public class LodBufferBuilder
}
}
// Forge added methods
public void putBulkData(ByteBuffer buffer)
{
ensureCapacity(buffer.limit() + this.format.getByteSize());
this.buffer.position(this.vertices * this.format.getByteSize());
this.buffer.put(buffer);
this.vertices += buffer.limit() / this.format.getByteSize();
this.nextElementByte += buffer.limit();
}
public LodVertexFormat getLodVertexFormat()
{
return this.format;
@@ -220,10 +220,8 @@ public class LodRenderer
int vbosCenterX = lodBufferBuilderFactory.getFrontBuffersCenterX();
int vbosCenterZ = lodBufferBuilderFactory.getFrontBuffersCenterZ();
// @Unused
if (vbos == null) {
// There is still no vbos, which means nothing needs to be drawn. So no rendering needed
// (Vbos should be setup by now)
// There is no vbos, which means nothing needs to be drawn. So skip rendering
return;
}
@@ -403,7 +401,7 @@ public class LodRenderer
/** Create all buffers that will be used. */
public void setupBuffers()
{
lodBufferBuilderFactory.allBuffersRequireReset = true;
lodBufferBuilderFactory.triggerReset();
}
private Color getFogColor(float partialTicks)
@@ -326,6 +326,33 @@ public class DataPointUtil
}
return out;
}
// Extract a section of data from the 2D data array
// WARN: if sourceVertSize == targetVertSize, it will return the source array!!! Be careful about this!
public static long[] changeMaxVertSize(long[] source, int sourceVertSize, int targetVertSize) {
if (source.length%sourceVertSize != 0)
throw new ArrayIndexOutOfBoundsException("\"source\" array invalid vertical size or length");
if (sourceVertSize == targetVertSize) return source;
if (sourceVertSize > targetVertSize) {
int size = source.length/sourceVertSize;
long[] dataToMerge = new long[sourceVertSize];
long[] newData = new long[size * targetVertSize];
for (int i = 0; i < size; i++)
{
System.arraycopy(source, i * sourceVertSize, dataToMerge, 0, sourceVertSize);
long[] tempBuffer = DataPointUtil.mergeMultiData(dataToMerge, sourceVertSize, targetVertSize);
System.arraycopy(tempBuffer, 0, newData, i * targetVertSize, targetVertSize);
}
return newData;
} else {
int size = source.length/sourceVertSize;
long[] newData = new long[size * targetVertSize];
for (int i = 0; i < size; i++) {
System.arraycopy(source, i * sourceVertSize, newData, i * targetVertSize, sourceVertSize);
}
return newData;
}
}
private static final ThreadLocal<short[]> tLocalHeightAndDepth = new ThreadLocal<short[]>();
private static final ThreadLocal<long[]> tMaxVerticalData = new ThreadLocal<long[]>();
@@ -336,6 +363,7 @@ public class DataPointUtil
* @param maxVerticalData max vertical size of the merged data
* @return one column of correctly parsed data
*/
// TODO: Make this operate on a out param array, to allow skipping copy array on use
public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData)
{
int size = dataToMerge.length / inputVerticalData;