Correctly removed LodDataPoint and optimized the LevelPos use
This commit is contained in:
@@ -2,7 +2,7 @@ package com.seibel.lod.builders;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class GenerationRequest
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
LevelPos chunkLevelPos = levelPos.convert(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
LevelPos chunkLevelPos = levelPos.getConvertedLevelPos(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return new ChunkPos(chunkLevelPos.posX, chunkLevelPos.posZ);
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,11 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
@@ -53,129 +53,141 @@ import net.minecraft.util.math.ChunkPos;
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
/** This holds the thread used to generate new LODs off the main thread. */
|
||||
private ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - main"));
|
||||
/** This holds the threads used to generate buffers. */
|
||||
private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder"));
|
||||
|
||||
/** The buffers that are used to create LODs using far fog */
|
||||
public volatile BufferBuilder[][] buildableBuffers;
|
||||
|
||||
/** Used when building new VBOs */
|
||||
public volatile VertexBuffer[][] buildableVbos;
|
||||
|
||||
/** VBOs that are sent over to the LodNodeRenderer */
|
||||
public volatile VertexBuffer[][] drawableVbos;
|
||||
|
||||
/**
|
||||
* if this is true the LOD buffers are currently being
|
||||
* regenerated.
|
||||
*/
|
||||
public boolean generatingBuffers = false;
|
||||
|
||||
/**
|
||||
* if this is true new LOD buffers have been generated
|
||||
* and are waiting to be swapped with the drawable buffers
|
||||
*/
|
||||
private boolean switchVbos = false;
|
||||
|
||||
|
||||
/** Size of the buffer builders in bytes last time we created them */
|
||||
public int previousBufferSize = 0;
|
||||
|
||||
/** Width of the dimension in regions last time we created the buffers */
|
||||
public int previousRegionWidth = 0;
|
||||
|
||||
/** this is used to prevent multiple threads creating, destroying, or using the buffers at the same time */
|
||||
private ReentrantLock bufferLock = new ReentrantLock();
|
||||
|
||||
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread to asynchronously generate LOD buffers
|
||||
* centered around the given camera X and Z.
|
||||
* <br>
|
||||
* This method will write to the drawable near and far buffers.
|
||||
* <br>
|
||||
* After the buildable buffers have been generated they must be
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
*/
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
BlockPos playerBlockPos, int numbChunksWide)
|
||||
{
|
||||
// only allow one generation process to happen at a time
|
||||
if (generatingBuffers)
|
||||
return;
|
||||
|
||||
if (buildableBuffers == null)
|
||||
throw new IllegalStateException("\"generateLodBuffersAsync\" was called before the \"setupBuffers\" method was called.");
|
||||
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
ChunkPos playerChunkPos = new ChunkPos(playerBlockPos);
|
||||
BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition();
|
||||
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
bufferLock.lock();
|
||||
/**
|
||||
* This holds the thread used to generate new LODs off the main thread.
|
||||
*/
|
||||
private ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - main"));
|
||||
/**
|
||||
* This holds the threads used to generate buffers.
|
||||
*/
|
||||
private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder"));
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
long treeStart = System.currentTimeMillis();
|
||||
long treeEnd = System.currentTimeMillis();
|
||||
/**
|
||||
* The buffers that are used to create LODs using far fog
|
||||
*/
|
||||
public volatile BufferBuilder[][] buildableBuffers;
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
ArrayList<Callable<Boolean>> builderThreads = new ArrayList<>(lodDim.regions.length * lodDim.regions.length);
|
||||
|
||||
startBuffers();
|
||||
/**
|
||||
* Used when building new VBOs
|
||||
*/
|
||||
public volatile VertexBuffer[][] buildableVbos;
|
||||
|
||||
// =====================//
|
||||
// RENDERING PART //
|
||||
// =====================//
|
||||
/**
|
||||
* VBOs that are sent over to the LodNodeRenderer
|
||||
*/
|
||||
public volatile VertexBuffer[][] drawableVbos;
|
||||
|
||||
for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++)
|
||||
{
|
||||
for (int zRegion = 0; zRegion < lodDim.regions.length; zRegion++)
|
||||
{
|
||||
RegionPos regionPos = new RegionPos(xRegion + lodDim.getCenterX() - lodDim.getWidth() / 2, zRegion + lodDim.getCenterZ() - lodDim.getWidth() / 2);
|
||||
/**
|
||||
* if this is true the LOD buffers are currently being
|
||||
* regenerated.
|
||||
*/
|
||||
public boolean generatingBuffers = false;
|
||||
|
||||
// local position in the vbo and bufferBuilder arrays
|
||||
BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion];
|
||||
|
||||
// make sure the buffers weren't
|
||||
// changed while we were running this method
|
||||
if (currentBuffer == null || (currentBuffer != null && !currentBuffer.building()))
|
||||
return;
|
||||
/**
|
||||
* if this is true new LOD buffers have been generated
|
||||
* and are waiting to be swapped with the drawable buffers
|
||||
*/
|
||||
private boolean switchVbos = false;
|
||||
|
||||
|
||||
byte detailLevel = LodConfig.CLIENT.maxGenerationDetail.get().detailLevel;
|
||||
/**
|
||||
* Size of the buffer builders in bytes last time we created them
|
||||
*/
|
||||
public int previousBufferSize = 0;
|
||||
|
||||
Callable<Boolean> bufferBuildingThread = () ->
|
||||
{
|
||||
byte detailToRender;
|
||||
boolean zFix;
|
||||
Set<LevelPos> setOfPosToRender = new HashSet<>();
|
||||
/**
|
||||
* Width of the dimension in regions last time we created the buffers
|
||||
*/
|
||||
public int previousRegionWidth = 0;
|
||||
|
||||
for (byte detail = detailLevel; detail <= LodUtil.REGION_DETAIL_LEVEL; detail++)
|
||||
{
|
||||
detailToRender = detail;
|
||||
zFix = true;
|
||||
/**
|
||||
* this is used to prevent multiple threads creating, destroying, or using the buffers at the same time
|
||||
*/
|
||||
private ReentrantLock bufferLock = new ReentrantLock();
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread to asynchronously generate LOD buffers
|
||||
* centered around the given camera X and Z.
|
||||
* <br>
|
||||
* This method will write to the drawable near and far buffers.
|
||||
* <br>
|
||||
* After the buildable buffers have been generated they must be
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
*/
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
BlockPos playerBlockPos, int numbChunksWide)
|
||||
{
|
||||
// only allow one generation process to happen at a time
|
||||
if (generatingBuffers)
|
||||
return;
|
||||
|
||||
if (buildableBuffers == null)
|
||||
throw new IllegalStateException("\"generateLodBuffersAsync\" was called before the \"setupBuffers\" method was called.");
|
||||
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
ChunkPos playerChunkPos = new ChunkPos(playerBlockPos);
|
||||
BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition();
|
||||
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
long treeStart = System.currentTimeMillis();
|
||||
long treeEnd = System.currentTimeMillis();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
ArrayList<Callable<Boolean>> builderThreads = new ArrayList<>(lodDim.regions.length * lodDim.regions.length);
|
||||
|
||||
startBuffers();
|
||||
|
||||
// =====================//
|
||||
// RENDERING PART //
|
||||
// =====================//
|
||||
|
||||
for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++)
|
||||
{
|
||||
for (int zRegion = 0; zRegion < lodDim.regions.length; zRegion++)
|
||||
{
|
||||
RegionPos regionPos = new RegionPos(xRegion + lodDim.getCenterX() - lodDim.getWidth() / 2, zRegion + lodDim.getCenterZ() - lodDim.getWidth() / 2);
|
||||
|
||||
// local position in the vbo and bufferBuilder arrays
|
||||
BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion];
|
||||
|
||||
// make sure the buffers weren't
|
||||
// changed while we were running this method
|
||||
if (currentBuffer == null || (currentBuffer != null && !currentBuffer.building()))
|
||||
return;
|
||||
|
||||
|
||||
byte detailLevel = LodConfig.CLIENT.maxGenerationDetail.get().detailLevel;
|
||||
|
||||
Callable<Boolean> bufferBuildingThread = () ->
|
||||
{
|
||||
byte detailToRender;
|
||||
boolean zFix;
|
||||
Set<LevelPos> setOfPosToRender = new HashSet<>();
|
||||
|
||||
for (byte detail = detailLevel; detail <= LodUtil.REGION_DETAIL_LEVEL; detail++)
|
||||
{
|
||||
detailToRender = detail;
|
||||
zFix = true;
|
||||
/*
|
||||
detailToRender = (byte) 4;
|
||||
if(detail > detailToRender){
|
||||
@@ -185,269 +197,256 @@ public class LodBufferBuilder
|
||||
zFix = true;
|
||||
}
|
||||
*/
|
||||
setOfPosToRender.addAll(lodDim.getDataToRender(
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ(),
|
||||
DetailDistanceUtil.getDistanceRendering(detail),
|
||||
DetailDistanceUtil.getDistanceRendering(detail + 1),
|
||||
detailToRender,
|
||||
zFix));
|
||||
}
|
||||
setOfPosToRender.addAll(lodDim.getDataToRender(
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ(),
|
||||
DetailDistanceUtil.getDistanceRendering(detail),
|
||||
DetailDistanceUtil.getDistanceRendering(detail + 1),
|
||||
detailToRender,
|
||||
zFix));
|
||||
}
|
||||
|
||||
|
||||
for (LevelPos posToRender : setOfPosToRender)
|
||||
{
|
||||
LevelPos chunkPos = posToRender.convert(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
// skip any chunks that Minecraft is going to render
|
||||
for (LevelPos posToRender : setOfPosToRender)
|
||||
{
|
||||
LevelPos chunkPos = posToRender.getConvertedLevelPos(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
// skip any chunks that Minecraft is going to render
|
||||
|
||||
if (renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkPos.posX, chunkPos.posZ)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkPos.posX, chunkPos.posZ)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lodDim.doesDataExist(posToRender))
|
||||
{
|
||||
try
|
||||
{
|
||||
LodDataPoint lodData = lodDim.getData(posToRender);
|
||||
if (lodDim.doesDataExist(posToRender))
|
||||
{
|
||||
try
|
||||
{
|
||||
ChunkPos adjChunkPos = new ChunkPos(0, 0);
|
||||
LevelPos adjPos = new LevelPos();
|
||||
if (lodDim.doesDataExist(posToRender))
|
||||
{
|
||||
short[] lodData = lodDim.getData(posToRender);
|
||||
short[][][] adjData = new short[2][2][];
|
||||
for (int x : new int[]{0, 1})
|
||||
{
|
||||
adjPos.changeParameters(posToRender.detailLevel, posToRender.posX + x * 2 - 1, posToRender.posZ);
|
||||
if (!renderer.vanillaRenderedChunks.contains(adjPos.getChunkPos())
|
||||
&& setOfPosToRender.contains(adjPos))
|
||||
adjData[0][x] = lodDim.getData(adjPos);
|
||||
}
|
||||
|
||||
if (lodData != null)
|
||||
{
|
||||
/*We check for adjacent data*/
|
||||
LodDataPoint[][] adjData = new LodDataPoint[2][2];
|
||||
LevelPos adjPos;
|
||||
for(int x : new int[]{0,1}){
|
||||
adjPos = new LevelPos(posToRender.detailLevel, posToRender.posX + x*2-1, posToRender.posZ);
|
||||
if (!renderer.vanillaRenderedChunks.contains(new ChunkPos(adjPos.convert(LodUtil.CHUNK_DETAIL_LEVEL).posX, adjPos.convert(LodUtil.CHUNK_DETAIL_LEVEL).posZ)));
|
||||
adjData[0][x] = lodDim.getData(adjPos);
|
||||
/*
|
||||
if(setOfPosToRender.contains(adjPos)){
|
||||
System.out.println("yup");
|
||||
adjData[0][x] = lodDim.getData(adjPos);
|
||||
}*/
|
||||
}
|
||||
for (int z : new int[]{0, 1})
|
||||
{
|
||||
adjPos.changeParameters(posToRender.detailLevel, posToRender.posX, posToRender.posZ + z * 2 - 1);
|
||||
if (!renderer.vanillaRenderedChunks.contains(adjPos.getChunkPos())
|
||||
&& setOfPosToRender.contains(adjPos))
|
||||
adjData[1][z] = lodDim.getData(adjPos);
|
||||
}
|
||||
|
||||
for(int z : new int[]{0,1}){
|
||||
adjPos = new LevelPos(posToRender.detailLevel, posToRender.posX, posToRender.posZ + z*2-1);
|
||||
if (!renderer.vanillaRenderedChunks.contains(new ChunkPos(adjPos.convert(LodUtil.CHUNK_DETAIL_LEVEL).posX, adjPos.convert(LodUtil.CHUNK_DETAIL_LEVEL).posZ)))
|
||||
adjData[1][z] = lodDim.getData(adjPos);
|
||||
/*
|
||||
if(setOfPosToRender.contains(adjPos)){
|
||||
System.out.println("yup2");
|
||||
adjData[1][z] = lodDim.getData(adjPos);
|
||||
}*/
|
||||
}
|
||||
LodConfig.CLIENT.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData,
|
||||
posToRender, renderer.debugging);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LodConfig.CLIENT.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData,
|
||||
posToRender, renderer.debugging);
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}// for pos to in list to render
|
||||
|
||||
}// for pos to in list to render
|
||||
|
||||
// the thread executed successfully
|
||||
return true;
|
||||
};// buffer builder worker thread
|
||||
// the thread executed successfully
|
||||
return true;
|
||||
};// buffer builder worker thread
|
||||
|
||||
|
||||
builderThreads.add(bufferBuildingThread);
|
||||
builderThreads.add(bufferBuildingThread);
|
||||
|
||||
}// region z
|
||||
}// region z
|
||||
}// region z
|
||||
}// region z
|
||||
|
||||
long renderStart = System.currentTimeMillis();
|
||||
// wait for all threads to finish
|
||||
List<Future<Boolean>> futures = bufferBuilderThreads.invokeAll(builderThreads);
|
||||
for(Future<Boolean> future : futures)
|
||||
{
|
||||
// the future will be false if its thread failed
|
||||
if (!future.get())
|
||||
{
|
||||
ClientProxy.LOGGER.warn("LodBufferBuilder ran into trouble and had to start over.");
|
||||
closeBuffers();
|
||||
return;
|
||||
}
|
||||
}
|
||||
long renderEnd = System.currentTimeMillis();
|
||||
|
||||
|
||||
// finish the buffer building
|
||||
closeBuffers();
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers();
|
||||
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
long buildTime = endTime - startTime;
|
||||
long renderStart = System.currentTimeMillis();
|
||||
// wait for all threads to finish
|
||||
List<Future<Boolean>> futures = bufferBuilderThreads.invokeAll(builderThreads);
|
||||
for (Future<Boolean> future : futures)
|
||||
{
|
||||
// the future will be false if its thread failed
|
||||
if (!future.get())
|
||||
{
|
||||
ClientProxy.LOGGER.warn("LodBufferBuilder ran into trouble and had to start over.");
|
||||
closeBuffers();
|
||||
return;
|
||||
}
|
||||
}
|
||||
long renderEnd = System.currentTimeMillis();
|
||||
|
||||
long treeTime = treeEnd - treeStart;
|
||||
|
||||
long renderingTime = renderEnd - renderStart;
|
||||
// finish the buffer building
|
||||
closeBuffers();
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers();
|
||||
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
long buildTime = endTime - startTime;
|
||||
|
||||
long treeTime = treeEnd - treeStart;
|
||||
|
||||
long renderingTime = renderEnd - renderStart;
|
||||
|
||||
ClientProxy.LOGGER.info("Buffer Build time: " + buildTime + " ms" + '\n' +
|
||||
"Tree cutting time: " + treeTime + " ms" + '\n' +
|
||||
"Rendering time: " + renderingTime + " ms");
|
||||
|
||||
// mark that the buildable buffers as ready to swap
|
||||
switchVbos = true;
|
||||
} catch (Exception e)
|
||||
{
|
||||
ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ");
|
||||
e.printStackTrace();
|
||||
} finally
|
||||
{
|
||||
// regardless of if we successfully created the buffers
|
||||
// we are done generating.
|
||||
generatingBuffers = false;
|
||||
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers();
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//===============================//
|
||||
// BufferBuilder related methods //
|
||||
//===============================//
|
||||
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders. <br><br>
|
||||
* <p>
|
||||
* May have to wait for the bufferLock to open.
|
||||
*/
|
||||
public void setupBuffers(int numbRegionsWide, int bufferMaxCapacity)
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
previousBufferSize = bufferMaxCapacity;
|
||||
|
||||
|
||||
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
{
|
||||
buildableBuffers[x][z] = new BufferBuilder(bufferMaxCapacity);
|
||||
buildableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
drawableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the buffers and Vbos to null, forcing them to be recreated. <br><br>
|
||||
* <p>
|
||||
* May have to wait for the bufferLock to open.
|
||||
*/
|
||||
public void destroyBuffers()
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
buildableBuffers = null;
|
||||
buildableVbos = null;
|
||||
drawableVbos = null;
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls begin on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void startBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
buildableBuffers[x][z].begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls end on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void closeBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building())
|
||||
buildableBuffers[x][z].end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders at the right size.
|
||||
*/
|
||||
private void uploadBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableVbos.length; x++)
|
||||
{
|
||||
for (int z = 0; z < buildableVbos.length; z++)
|
||||
{
|
||||
buildableVbos[x][z].upload(buildableBuffers[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the newly created VBOs
|
||||
*/
|
||||
public VertexBuffer[][] getVertexBuffers()
|
||||
{
|
||||
// don't wait for the lock to open
|
||||
// since this is called on the main render thread
|
||||
if (bufferLock.tryLock())
|
||||
{
|
||||
VertexBuffer[][] tmp = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmp;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
return drawableVbos;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is true the buildable near and far
|
||||
* buffers have been generated and are ready to be
|
||||
* sent to the LodRenderer.
|
||||
*/
|
||||
public boolean newBuffersAvaliable()
|
||||
{
|
||||
return switchVbos;
|
||||
}
|
||||
|
||||
|
||||
ClientProxy.LOGGER.info("Buffer Build time: " + buildTime + " ms" + '\n' +
|
||||
"Tree cutting time: " + treeTime + " ms" + '\n' +
|
||||
"Rendering time: " + renderingTime + " ms");
|
||||
|
||||
// mark that the buildable buffers as ready to swap
|
||||
switchVbos = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// regardless of if we successfully created the buffers
|
||||
// we are done generating.
|
||||
generatingBuffers = false;
|
||||
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers();
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================//
|
||||
// BufferBuilder related methods //
|
||||
//===============================//
|
||||
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders. <br><br>
|
||||
*
|
||||
* May have to wait for the bufferLock to open.
|
||||
*/
|
||||
public void setupBuffers(int numbRegionsWide, int bufferMaxCapacity)
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
previousBufferSize = bufferMaxCapacity;
|
||||
|
||||
|
||||
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
{
|
||||
buildableBuffers[x][z] = new BufferBuilder(bufferMaxCapacity);
|
||||
buildableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
drawableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the buffers and Vbos to null, forcing them to be recreated. <br><br>
|
||||
*
|
||||
* May have to wait for the bufferLock to open.
|
||||
*/
|
||||
public void destroyBuffers()
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
buildableBuffers = null;
|
||||
buildableVbos = null;
|
||||
drawableVbos = null;
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls begin on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void startBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
buildableBuffers[x][z].begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls end on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void closeBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building())
|
||||
buildableBuffers[x][z].end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders at the right size.
|
||||
*
|
||||
*/
|
||||
private void uploadBuffers()
|
||||
{
|
||||
for (int x = 0; x < buildableVbos.length; x++)
|
||||
{
|
||||
for (int z = 0; z < buildableVbos.length; z++)
|
||||
{
|
||||
buildableVbos[x][z].upload(buildableBuffers[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the newly created VBOs
|
||||
*/
|
||||
public VertexBuffer[][] getVertexBuffers()
|
||||
{
|
||||
// don't wait for the lock to open
|
||||
// since this is called on the main render thread
|
||||
if (bufferLock.tryLock())
|
||||
{
|
||||
VertexBuffer[][] tmp = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmp;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
return drawableVbos;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is true the buildable near and far
|
||||
* buffers have been generated and are ready to be
|
||||
* sent to the LodRenderer.
|
||||
*/
|
||||
public boolean newBuffersAvaliable()
|
||||
{
|
||||
return switchVbos;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -24,8 +24,7 @@ import java.util.concurrent.Executors;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
@@ -150,11 +149,11 @@ public class LodBuilder
|
||||
int startZ;
|
||||
int endX;
|
||||
int endZ;
|
||||
Color color;
|
||||
short[] color;
|
||||
short height;
|
||||
short depth;
|
||||
LevelPos levelPos;
|
||||
LodDataPoint data = null;
|
||||
LevelPos levelPos = new LevelPos();
|
||||
short[] data;
|
||||
|
||||
for (int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
|
||||
{
|
||||
@@ -175,14 +174,14 @@ public class LodBuilder
|
||||
startZ, endX, endZ);
|
||||
depth = 0;
|
||||
}
|
||||
levelPos = new LevelPos((byte) 0,
|
||||
levelPos.changeParameters((byte) 0,
|
||||
chunk.getPos().x * 16 + startX,
|
||||
chunk.getPos().z * 16 + startZ);
|
||||
data = new LodDataPoint(height, depth, color);
|
||||
lodDim.addData(levelPos.convert(detail.detailLevel),
|
||||
levelPos.convert(detail.detailLevel);
|
||||
data = new short[]{height, depth, color[0], color[1], color[2]};
|
||||
lodDim.addData(levelPos,
|
||||
data,
|
||||
config.distanceGenerationMode,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
lodDim.updateData(new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z));
|
||||
@@ -332,7 +331,7 @@ public class LodBuilder
|
||||
* otherwise only use the block's
|
||||
* material color
|
||||
*/
|
||||
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
|
||||
private short[] generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
|
||||
int endZ)
|
||||
{
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
@@ -386,11 +385,9 @@ public class LodBuilder
|
||||
colorInt = getColorForBlock(x, z, blockState, biome);
|
||||
}
|
||||
|
||||
Color c = LodUtil.intToColor(colorInt);
|
||||
|
||||
red += c.getRed();
|
||||
green += c.getGreen();
|
||||
blue += c.getBlue();
|
||||
red += (colorInt)&0xFF;;
|
||||
green += (colorInt>>8)&0xFF;
|
||||
blue += (colorInt>>16)&0xFF;
|
||||
|
||||
numbOfBlocks++;
|
||||
|
||||
@@ -410,7 +407,7 @@ public class LodBuilder
|
||||
green /= numbOfBlocks;
|
||||
blue /= numbOfBlocks;
|
||||
|
||||
return new Color(red, green, blue);
|
||||
return new short[]{(short) red, (short) green, (short) blue};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,8 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Set;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
@@ -38,8 +34,8 @@ import net.minecraft.util.math.BlockPos;
|
||||
*/
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, LodDataPoint data, LodDataPoint[][] adjData,
|
||||
LevelPos levelPos, boolean debugging);
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, boolean debugging);
|
||||
|
||||
/** add the given position and color to the buffer */
|
||||
protected void addPosAndColor(BufferBuilder buffer,
|
||||
|
||||
@@ -21,8 +21,8 @@ import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
@@ -45,23 +45,23 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, LodDataPoint data, LodDataPoint[][] adjData,
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, boolean debugging)
|
||||
{
|
||||
AxisAlignedBB bbox;
|
||||
|
||||
int width = (int) Math.pow(2, levelPos.detailLevel);
|
||||
int width = 1 << levelPos.detailLevel;
|
||||
|
||||
// add each LOD for the detail level
|
||||
bbox = generateBoundingBox(
|
||||
data.height,
|
||||
data.depth,
|
||||
DataPoint.getHeight(data),
|
||||
DataPoint.getDepth(data),
|
||||
width,
|
||||
levelPos.posX * width,
|
||||
0,
|
||||
levelPos.posZ * width);
|
||||
|
||||
Color color = data.color;
|
||||
Color color = new Color(DataPoint.getColor(data));
|
||||
if (LodConfig.CLIENT.debugMode.get())
|
||||
{
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[levelPos.detailLevel];
|
||||
@@ -105,7 +105,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset);
|
||||
}
|
||||
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color c, BlockPos playerBlockPos, LodDataPoint[][] adjData)
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color c, BlockPos playerBlockPos, short[][][] adjData)
|
||||
{
|
||||
Color topColor = c;
|
||||
Color northSouthColor = c;
|
||||
@@ -136,7 +136,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
bottomColor = applySaturationAndBrightnessMultipliers(bottomColor, saturationMultiplier, brightnessMultiplier);
|
||||
int minY;
|
||||
int maxY;
|
||||
LodDataPoint data;
|
||||
short[] data;
|
||||
/**TODO make all of this more automatic if possible*/
|
||||
if (playerBlockPos.getY() > bb.maxY - CULL_OFFSET)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
} else
|
||||
{
|
||||
maxY = data.height;
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
@@ -177,7 +177,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
}
|
||||
minY = data.depth;
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxX);
|
||||
@@ -201,7 +201,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
} else
|
||||
{
|
||||
maxY = data.height;
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
@@ -210,7 +210,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
}
|
||||
minY = data.depth;
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxX);
|
||||
@@ -234,7 +234,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
} else
|
||||
{
|
||||
maxY = data.height;
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
@@ -243,7 +243,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
}
|
||||
minY = data.depth;
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxX);
|
||||
@@ -267,7 +267,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
} else
|
||||
{
|
||||
maxY = data.height;
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
@@ -276,7 +276,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
}
|
||||
minY = data.depth;
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxX);
|
||||
|
||||
@@ -17,15 +17,11 @@
|
||||
*/
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* TODO DynamicLodTemplate
|
||||
* Chunks smoothly transition between
|
||||
@@ -38,7 +34,7 @@ import java.util.Set;
|
||||
public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, LodDataPoint data, LodDataPoint[][] adjData,
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, boolean debugging)
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
|
||||
@@ -17,15 +17,11 @@
|
||||
*/
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* TODO #21 TriangularLodTemplate
|
||||
* Builds each LOD chunk as a singular rectangular prism.
|
||||
@@ -36,7 +32,7 @@ import java.util.Set;
|
||||
public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, LodDataPoint data, LodDataPoint[][] adjData,
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, boolean debugging)
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.seibel.lod.builders.GenerationRequest;
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
@@ -131,14 +131,13 @@ public class LodWorldGenerator
|
||||
//=======================================//
|
||||
|
||||
// start by generating half-region sized blocks...
|
||||
int farRequesting = maxChunkGenRequests/2;
|
||||
int farRequesting = maxChunkGenRequests/4;
|
||||
|
||||
//we firstly make sure that the world is filled with half region wide block
|
||||
/*
|
||||
|
||||
for (byte detailGen = LodConfig.CLIENT.maxGenerationDetail.get().detailLevel; detailGen <= LodUtil.REGION_DETAIL_LEVEL; detailGen++)
|
||||
{
|
||||
if (farRequesting <= 0){
|
||||
farRequesting=0;
|
||||
break;
|
||||
}
|
||||
levelPosListToGen = lodDim.getDataToGenerate(
|
||||
@@ -147,20 +146,19 @@ public class LodWorldGenerator
|
||||
DetailDistanceUtil.getDistanceGeneration(detailGen),
|
||||
DetailDistanceUtil.getDistanceGeneration(detailGen + 1),
|
||||
DetailDistanceUtil.getDistanceGenerationMode(detailGen).complexity,
|
||||
(byte) 7,
|
||||
(byte) 8,
|
||||
farRequesting);
|
||||
for(LevelPos levelPos : levelPosListToGen){
|
||||
generationRequestList.add(new GenerationRequest(levelPos,DetailDistanceUtil.getDistanceGenerationMode(detailGen), DetailDistanceUtil.getLodDetail(detailGen)));
|
||||
}
|
||||
farRequesting = farRequesting - levelPosListToGen.size();
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
// ...then once the world is filled with half-region sized blocks
|
||||
// fill in the rest
|
||||
int t = generationRequestList.size();
|
||||
int nearRequesting = maxChunkGenRequests - maxChunkGenRequests/2 + farRequesting;
|
||||
System.out.println("clear slot " + nearRequesting);
|
||||
int nearRequesting = maxChunkGenRequests - maxChunkGenRequests/4 + farRequesting;
|
||||
//we then fill the world with the rest of the block
|
||||
for (byte detailGen = LodConfig.CLIENT.maxGenerationDetail.get().detailLevel; detailGen <= LodUtil.REGION_DETAIL_LEVEL; detailGen++)
|
||||
{
|
||||
@@ -177,9 +175,7 @@ public class LodWorldGenerator
|
||||
generationRequestList.add(new GenerationRequest(levelPos,DetailDistanceUtil.getDistanceGenerationMode(detailGen), DetailDistanceUtil.getLodDetail(detailGen)));
|
||||
}
|
||||
nearRequesting = nearRequesting - levelPosListToGen.size();
|
||||
System.out.println("adding " + levelPosListToGen.size());
|
||||
}
|
||||
System.out.println("generating " + generationRequestList.size() + " and " + t);
|
||||
|
||||
|
||||
//====================================//
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.seibel.lod.enums;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
/**
|
||||
@@ -63,10 +62,7 @@ public enum LodDetail
|
||||
|
||||
public final int[] endX;
|
||||
public final int[] endZ;
|
||||
|
||||
/** This is how many pieces of data should be expected
|
||||
* when creating a LodChunk with this detail level */
|
||||
public final int lodChunkStringDelimiterCount;
|
||||
|
||||
|
||||
/**
|
||||
* 1st dimension: LodDetail.detailLevel <br>
|
||||
@@ -106,9 +102,6 @@ public enum LodDetail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lodChunkStringDelimiterCount = 2 + (dataPointLengthCount * dataPointLengthCount * LodDataPoint.NUMBER_OF_DELIMITERS);
|
||||
|
||||
}// constructor
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
public class DataPoint
|
||||
{
|
||||
|
||||
public static short[] createDataPoint(int height, int depth, int red, int green, int blue){
|
||||
return new short[]{(short) height, (short) depth, (short) red, (short) green, (short) blue};
|
||||
}
|
||||
|
||||
public static short getHeight(short[] dataPoint){
|
||||
return dataPoint[0];
|
||||
}
|
||||
|
||||
public static short getDepth(short[] dataPoint){
|
||||
return dataPoint[1];
|
||||
}
|
||||
|
||||
public static short getRed(short[] dataPoint){
|
||||
return dataPoint[2];
|
||||
}
|
||||
|
||||
public static short getGreen(short[] dataPoint){
|
||||
return dataPoint[3];
|
||||
}
|
||||
|
||||
public static short getBlue(short[] dataPoint){
|
||||
return dataPoint[4];
|
||||
}
|
||||
|
||||
public static short[] getHeightDepth(short[] dataPoint){
|
||||
return new short[]{dataPoint[0], dataPoint[1]};
|
||||
}
|
||||
|
||||
public static int getColor(short[] dataPoint){
|
||||
int R = (dataPoint[2] << 16) & 0x00FF0000;
|
||||
int G = (dataPoint[3] << 8) & 0x0000FF00;
|
||||
int B = dataPoint[4] & 0x000000FF;
|
||||
return 0xFF000000 | R | G | B;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
public interface ImmutableLevelPos
|
||||
{
|
||||
public LevelPos getConvertedLevelPos(byte newDetailLevel);
|
||||
public LevelPos getRegionModuleLevelPos();
|
||||
}
|
||||
+113
-25
@@ -1,15 +1,23 @@
|
||||
package com.seibel.lod.objects;
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
|
||||
public class LevelPos implements Cloneable
|
||||
public class LevelPos implements Cloneable, ImmutableLevelPos, MutableLevelPos
|
||||
{
|
||||
public final byte detailLevel;
|
||||
public final int posX;
|
||||
public final int posZ;
|
||||
public byte detailLevel;
|
||||
public int posX;
|
||||
public int posZ;
|
||||
|
||||
|
||||
public LevelPos()
|
||||
{
|
||||
}
|
||||
|
||||
public LevelPos(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
@@ -18,46 +26,117 @@ public class LevelPos implements Cloneable
|
||||
this.detailLevel = detailLevel;
|
||||
}
|
||||
|
||||
public LevelPos convert(byte newDetailLevel)
|
||||
/**
|
||||
* this operation does not change the state
|
||||
*/
|
||||
public LevelPos getConvertedLevelPos(byte newDetailLevel)
|
||||
{
|
||||
if (newDetailLevel >= detailLevel)
|
||||
{
|
||||
int width = 1 << (newDetailLevel - detailLevel);
|
||||
return new LevelPos(
|
||||
newDetailLevel,
|
||||
Math.floorDiv(posX, (int) Math.pow(2, newDetailLevel - detailLevel)),
|
||||
Math.floorDiv(posZ, (int) Math.pow(2, newDetailLevel - detailLevel)));
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - newDetailLevel);
|
||||
return new LevelPos(
|
||||
newDetailLevel,
|
||||
posX * (int) Math.pow(2, detailLevel - newDetailLevel),
|
||||
posZ * (int) Math.pow(2, detailLevel - newDetailLevel));
|
||||
posX * width,
|
||||
posZ * width);
|
||||
}
|
||||
}
|
||||
|
||||
public LevelPos regionModule()
|
||||
/**
|
||||
* this operation does not change the state
|
||||
*/
|
||||
public LevelPos getRegionModuleLevelPos()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return new LevelPos(
|
||||
detailLevel,
|
||||
Math.floorMod(posX, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel)),
|
||||
Math.floorMod(posZ, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel)));
|
||||
Math.floorMod(posX, width),
|
||||
Math.floorMod(posZ, width));
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void convert(byte newDetailLevel)
|
||||
{
|
||||
if (newDetailLevel >= detailLevel)
|
||||
{
|
||||
int width = 1 << (newDetailLevel - detailLevel);
|
||||
detailLevel = newDetailLevel;
|
||||
posX = Math.floorDiv(posX, width);
|
||||
posZ = Math.floorDiv(posZ, width);
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - newDetailLevel);
|
||||
detailLevel = newDetailLevel;
|
||||
posX = posX * width;
|
||||
posZ = posZ * width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void performRegionModule()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
posX = Math.floorMod(posX, width);
|
||||
posX = Math.floorMod(posZ, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void applyOffset(int xOffset, int zOffset)
|
||||
{
|
||||
posX = posX + xOffset;
|
||||
posX = posZ + zOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ)
|
||||
{
|
||||
detailLevel = newDetailLevel;
|
||||
posX = newPosX;
|
||||
posX = newPosZ;
|
||||
}
|
||||
|
||||
public RegionPos getRegionPos()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return new RegionPos(
|
||||
Math.floorDiv(posX, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel)),
|
||||
Math.floorDiv(posZ, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel)));
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LevelPos clone()
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return new LevelPos(detailLevel, posX, posZ);
|
||||
if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel)
|
||||
{
|
||||
int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel);
|
||||
return new ChunkPos(
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return new ChunkPos(
|
||||
posX * width,
|
||||
posZ * width);
|
||||
}
|
||||
}
|
||||
|
||||
/**TODO fix the region disappearing for a second*/
|
||||
/**
|
||||
* TODO fix the region disappearing for a second
|
||||
*/
|
||||
|
||||
public int maxDistance(int playerPosX, int playerPosZ, int regionPosX, int regionPosZ)
|
||||
{
|
||||
@@ -192,7 +271,7 @@ public class LevelPos implements Cloneable
|
||||
@Override
|
||||
public int compare(Map.Entry<LevelPos, Integer> first, Map.Entry<LevelPos, Integer> second)
|
||||
{
|
||||
Integer compareResult = Integer.compare(first.getKey().detailLevel, second.getKey().detailLevel);
|
||||
int compareResult = Integer.compare(first.getKey().detailLevel, second.getKey().detailLevel);
|
||||
if (compareResult != 0)
|
||||
{
|
||||
compareResult = Integer.compare(first.getValue(), second.getValue());
|
||||
@@ -201,6 +280,14 @@ public class LevelPos implements Cloneable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LevelPos clone()
|
||||
{
|
||||
return new LevelPos(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
@@ -210,11 +297,12 @@ public class LevelPos implements Cloneable
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean equals(LevelPos other)
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return (this.detailLevel == other.detailLevel &&
|
||||
this.posX == other.posX &&
|
||||
this.posZ == other.posZ);
|
||||
return (this.detailLevel == ((LevelPos) other).detailLevel &&
|
||||
this.posX == ((LevelPos) other).posX &&
|
||||
this.posZ == ((LevelPos) other).posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
public interface MutableLevelPos
|
||||
{
|
||||
public void convert(byte newDetailLevel);
|
||||
|
||||
public void performRegionModule();
|
||||
|
||||
public void applyOffset(int xOffset, int zOffset);
|
||||
|
||||
public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
/**
|
||||
* This stores the height and color
|
||||
* for a specific area in a LodChunk.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-8-2021
|
||||
*/
|
||||
public class LodDataPoint implements Serializable
|
||||
{
|
||||
/**
|
||||
* This is what separates each piece of data in the toData method
|
||||
*/
|
||||
private static final char DATA_DELIMITER = LodDimensionFileHandler.DATA_DELIMITER;
|
||||
|
||||
/**
|
||||
* this is how many pieces of data are exported when toData is called
|
||||
*/
|
||||
public static final int NUMBER_OF_DELIMITERS = 5;
|
||||
|
||||
/**
|
||||
* a empty data point that can be used for comparisons
|
||||
*/
|
||||
public static final LodDataPoint EMPTY_DATA_POINT = new LodDataPoint();
|
||||
|
||||
|
||||
/**
|
||||
* highest point
|
||||
*/
|
||||
public short height;
|
||||
|
||||
/**
|
||||
* lowest point
|
||||
*/
|
||||
public short depth;
|
||||
|
||||
/**
|
||||
* The average color for the 6 cardinal directions
|
||||
*/
|
||||
public Color color;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an empty LodDataPoint
|
||||
*/
|
||||
public LodDataPoint()
|
||||
{
|
||||
height = -1;
|
||||
depth = -1;
|
||||
color = LodUtil.COLOR_INVISIBLE;
|
||||
}
|
||||
|
||||
|
||||
public LodDataPoint(short newHeight, short newDepth, Color newColor)
|
||||
{
|
||||
height = newHeight;
|
||||
depth = newDepth;
|
||||
color = newColor;
|
||||
}
|
||||
|
||||
public LodDataPoint(int newHeight, int newDepth, Color newColor)
|
||||
{
|
||||
height = (short) newHeight;
|
||||
depth = (short) newDepth;
|
||||
color = newColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(this.height, this.depth, this.color);
|
||||
}
|
||||
|
||||
public boolean equals(LodDataPoint other)
|
||||
{
|
||||
return (this.height == other.height
|
||||
&& this.depth == other.depth
|
||||
&& this.color == other.color);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.equals(EMPTY_DATA_POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs all data in a csv format
|
||||
* with the given delimiter.
|
||||
* <br>
|
||||
* Exports data in the form:
|
||||
* <br>
|
||||
* height, depth, rgb color data
|
||||
*
|
||||
* <br>
|
||||
* example output:
|
||||
* <br>
|
||||
* 4, 0, 255,255,255,
|
||||
*/
|
||||
public String toData()
|
||||
{
|
||||
String s = Short.toString(height) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(depth) + DATA_DELIMITER;
|
||||
|
||||
s += Integer.toString(color.getRed()) + DATA_DELIMITER + Integer.toString(color.getGreen()) + DATA_DELIMITER + Integer.toString(color.getBlue()) + DATA_DELIMITER;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = Short.toString(height) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(depth) + DATA_DELIMITER;
|
||||
|
||||
s += Integer.toString(color.getRed()) + DATA_DELIMITER + Integer.toString(color.getGreen()) + DATA_DELIMITER + Integer.toString(color.getBlue()) + DATA_DELIMITER;
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
@@ -400,7 +401,7 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinates it will be overwritten.
|
||||
*/
|
||||
public synchronized Boolean addData(LevelPos levelPos, LodDataPoint lodDataPoint, DistanceGenerationMode generationMode, boolean update, boolean dontSave)
|
||||
public synchronized Boolean addData(LevelPos levelPos, short[] lodDataPoint, DistanceGenerationMode generationMode, boolean dontSave)
|
||||
{
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
@@ -412,7 +413,7 @@ public class LodDimension
|
||||
|
||||
LodRegion region = getRegion(levelPos);
|
||||
|
||||
boolean nodeAdded = region.setData(levelPos, lodDataPoint, generationMode.complexity, true);
|
||||
boolean nodeAdded = region.setData(levelPos, lodDataPoint, generationMode.complexity);
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
{
|
||||
@@ -432,20 +433,6 @@ public class LodDimension
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the LodNodeData at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public LodDataPoint getData(ChunkPos chunkPos)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z);
|
||||
return getData(levelPos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method to get all the quadtree level that have to be generated based on the position of the player
|
||||
*
|
||||
@@ -474,7 +461,7 @@ public class LodDimension
|
||||
if (end >= regionLevelPos.minDistance(playerPosX, playerPosZ) &&
|
||||
start <= regionLevelPos.maxDistance(playerPosX, playerPosZ))
|
||||
{
|
||||
region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).convert(detailLevel));
|
||||
region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).getConvertedLevelPos(detailLevel));
|
||||
listOfData.addAll(region.getDataToGenerate(playerPosX, playerPosZ, start, end, generation, detailLevel, dataNumber));
|
||||
}
|
||||
}catch (Exception e){
|
||||
@@ -510,7 +497,7 @@ public class LodDimension
|
||||
if (end >= regionLevelPos.minDistance(playerPosX, playerPosZ) &&
|
||||
start <= regionLevelPos.maxDistance(playerPosX, playerPosZ))
|
||||
{
|
||||
LodRegion region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).convert(detailLevel));
|
||||
LodRegion region = getRegion(new LevelPos(LodUtil.REGION_DETAIL_LEVEL, regionPos.x, regionPos.z).getConvertedLevelPos(detailLevel));
|
||||
listOfData.addAll(region.getDataToRender(playerPosX, playerPosZ, start, end, detailLevel,zFix));
|
||||
}
|
||||
}catch (Exception e){
|
||||
@@ -522,6 +509,19 @@ public class LodDimension
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LodNodeData at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public short[] getData(ChunkPos chunkPos)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z);
|
||||
return getData(levelPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data point at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
@@ -529,7 +529,7 @@ public class LodDimension
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public LodDataPoint getData(LevelPos levelPos)
|
||||
public short[] getData(LevelPos levelPos)
|
||||
{
|
||||
if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* STANDARD TO FOLLOW
|
||||
@@ -128,12 +126,11 @@ public class LodRegion implements Serializable
|
||||
* @param levelPos
|
||||
* @param dataPoint
|
||||
* @param generationType
|
||||
* @param update
|
||||
* @return
|
||||
*/
|
||||
public boolean setData(LevelPos levelPos, LodDataPoint dataPoint, byte generationType, boolean update)
|
||||
public boolean setData(LevelPos levelPos, short[] dataPoint, byte generationType)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos.performRegionModule();
|
||||
if ((this.generationType[levelPos.detailLevel][levelPos.posX][levelPos.posZ] == 0) || (generationType >= this.generationType[levelPos.detailLevel][levelPos.posX][levelPos.posZ]))
|
||||
{
|
||||
|
||||
@@ -141,24 +138,13 @@ public class LodRegion implements Serializable
|
||||
if (this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ]) numberOfPoints++;
|
||||
|
||||
//add the node data
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] = (byte) (dataPoint.color.getRed() - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] = (byte) (dataPoint.color.getGreen() - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] = (byte) (dataPoint.color.getBlue() - 128);
|
||||
this.height[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = dataPoint.height;
|
||||
this.depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = dataPoint.depth;
|
||||
this.height[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = dataPoint[0];
|
||||
this.depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = dataPoint[1];
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] = (byte) (dataPoint[2] - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] = (byte) (dataPoint[3] - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] = (byte) (dataPoint[4] - 128);
|
||||
this.generationType[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = generationType;
|
||||
this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = true;
|
||||
|
||||
//update could be stopped and a single big update could be done at the end
|
||||
LevelPos tempLevelPos = levelPos;
|
||||
if (update)
|
||||
{
|
||||
for (byte tempLod = (byte) (levelPos.detailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++)
|
||||
{
|
||||
tempLevelPos = tempLevelPos.convert(tempLod);
|
||||
update(tempLevelPos);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
@@ -167,7 +153,7 @@ public class LodRegion implements Serializable
|
||||
}
|
||||
|
||||
|
||||
public LodDataPoint getData(ChunkPos chunkPos)
|
||||
public short[] getData(ChunkPos chunkPos)
|
||||
{
|
||||
return getData(new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z));
|
||||
}
|
||||
@@ -178,7 +164,7 @@ public class LodRegion implements Serializable
|
||||
* @param lod
|
||||
* @return the data at the relative pos and level
|
||||
*/
|
||||
public LodDataPoint getData(byte lod, BlockPos blockPos)
|
||||
public short[] getData(byte lod, BlockPos blockPos)
|
||||
{
|
||||
int posX = Math.floorMod(blockPos.getX(), (int) Math.pow(2, lod));
|
||||
int posZ = Math.floorMod(blockPos.getZ(), (int) Math.pow(2, lod));
|
||||
@@ -191,17 +177,15 @@ public class LodRegion implements Serializable
|
||||
* @param levelPos
|
||||
* @return the data at the relative pos and level
|
||||
*/
|
||||
public LodDataPoint getData(LevelPos levelPos)
|
||||
public short[] getData(LevelPos levelPos)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
return new LodDataPoint(
|
||||
height[levelPos.detailLevel][levelPos.posX][levelPos.posZ],
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
return new short[]{height[levelPos.detailLevel][levelPos.posX][levelPos.posZ],
|
||||
depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ],
|
||||
new Color(colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] + 128,
|
||||
colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] + 128,
|
||||
colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] + 128
|
||||
)
|
||||
);
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] + 128),
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] + 128),
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] + 128)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -296,8 +280,9 @@ public class LodRegion implements Serializable
|
||||
}
|
||||
}
|
||||
} else
|
||||
//now we keep exploring the top right child
|
||||
{
|
||||
childPos = levelPos.convert((byte) (levelPos.detailLevel - 1));
|
||||
childPos = levelPos.getConvertedLevelPos((byte) (levelPos.detailLevel - 1));
|
||||
if (generationType[childPos.detailLevel][childPos.posX][childPos.posZ] < generation)
|
||||
{
|
||||
minDistance = childPos.minDistance(playerPosX,playerPosZ,regionPosX,regionPosZ);
|
||||
@@ -403,7 +388,7 @@ public class LodRegion implements Serializable
|
||||
int startX;
|
||||
int startZ;
|
||||
for(byte bottom = (byte) (minDetailLevel + 1); bottom < levelPos.detailLevel ; bottom++){
|
||||
tempLevelPos = levelPos.convert(bottom);
|
||||
tempLevelPos = levelPos.getConvertedLevelPos(bottom);
|
||||
startX = tempLevelPos.posX;
|
||||
startZ = tempLevelPos.posZ;
|
||||
sizeDiff = (int) Math.pow(2, levelPos.detailLevel - bottom);
|
||||
@@ -415,7 +400,7 @@ public class LodRegion implements Serializable
|
||||
|
||||
}
|
||||
for (byte tempLod = levelPos.detailLevel; tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++) {
|
||||
tempLevelPos = levelPos.convert(tempLod);
|
||||
tempLevelPos = levelPos.getConvertedLevelPos(tempLod);
|
||||
update(tempLevelPos);
|
||||
}
|
||||
}
|
||||
@@ -426,7 +411,7 @@ public class LodRegion implements Serializable
|
||||
private void update(LevelPos levelPos)
|
||||
{
|
||||
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
int numberOfChildren = 0;
|
||||
|
||||
/**TODO add the ability to change how the heigth and depth are determinated (for example min or max)**/
|
||||
@@ -480,7 +465,7 @@ public class LodRegion implements Serializable
|
||||
*/
|
||||
private boolean[][] getChildren(LevelPos levelPos)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
boolean[][] children = new boolean[2][2];
|
||||
int numberOfChild = 0;
|
||||
if (minDetailLevel == levelPos.detailLevel)
|
||||
@@ -512,7 +497,7 @@ public class LodRegion implements Serializable
|
||||
*/
|
||||
public boolean doesDataExist(LevelPos levelPos)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
return dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ];
|
||||
}
|
||||
|
||||
@@ -522,7 +507,7 @@ public class LodRegion implements Serializable
|
||||
*/
|
||||
public DistanceGenerationMode getGenerationMode(LevelPos levelPos)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
DistanceGenerationMode generationMode = DistanceGenerationMode.NONE;
|
||||
switch (generationType[levelPos.detailLevel][levelPos.posX][levelPos.posZ])
|
||||
{
|
||||
@@ -558,7 +543,7 @@ public class LodRegion implements Serializable
|
||||
*/
|
||||
public boolean hasDataBeenGenerated(LevelPos levelPos)
|
||||
{
|
||||
levelPos = levelPos.regionModule();
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
return (generationType[levelPos.detailLevel][levelPos.posX][levelPos.posZ] != 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,9 +95,8 @@ public class ClientProxy
|
||||
{
|
||||
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
|
||||
return;
|
||||
|
||||
|
||||
applyConfigOverrides();
|
||||
|
||||
viewDistanceChangedEvent();
|
||||
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
|
||||
@@ -125,7 +124,9 @@ public class ClientProxy
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
profiler.push("terrain"); // restart "terrain"
|
||||
|
||||
|
||||
|
||||
applyConfigOverrides();
|
||||
|
||||
// these can't be set until after the buffers are built (in renderer.drawLODs)
|
||||
// otherwise the buffers may be set to the wrong size, or not changed at all
|
||||
@@ -156,10 +157,9 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.saturationMultiplier.set(1.0);
|
||||
|
||||
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
|
||||
LodConfig.CLIENT.lodChunkRenderDistance.set(256);
|
||||
LodConfig.CLIENT.lodChunkRenderDistance.set(128);
|
||||
LodConfig.CLIENT.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
|
||||
LodConfig.CLIENT.lodQuality.set(1);
|
||||
LodConfig.CLIENT.lodQuality.set(2);
|
||||
LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
|
||||
LodConfig.CLIENT.numberOfWorldGenerationThreads.set(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.objects.LevelPos;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
|
||||
@@ -325,11 +324,9 @@ public class LodUtil
|
||||
if (!lodDim.doesDataExist(levelPos))
|
||||
continue;
|
||||
|
||||
LodDataPoint data = lodDim.getData(levelPos);
|
||||
if (data == null)
|
||||
continue;
|
||||
short[] data = lodDim.getData(levelPos);
|
||||
|
||||
short lodAverageHeight = data.height;
|
||||
short lodAverageHeight = data[0];
|
||||
if (playerPos.getY() <= lodAverageHeight)
|
||||
{
|
||||
// don't draw Lod's that are taller than the player
|
||||
|
||||
Reference in New Issue
Block a user