Added different LodDetail support
This commit is contained in:
@@ -21,6 +21,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker;
|
||||
@@ -158,15 +159,13 @@ public class LodNodeBufferBuilder
|
||||
for (int i = 0; i < numbChunksWide; i++)
|
||||
{
|
||||
// z axis
|
||||
for (int j = 0; j < numbChunksWide; j++)
|
||||
{
|
||||
int chunkX = i + Math.floorDiv(startX , LodQuadTreeNode.CHUNK_WIDTH);
|
||||
int chunkZ = j + Math.floorDiv(startZ , LodQuadTreeNode.CHUNK_WIDTH);
|
||||
for (int j = 0; j < numbChunksWide; j++) {
|
||||
int chunkX = i + Math.floorDiv(startX, LodQuadTreeNode.CHUNK_WIDTH);
|
||||
int chunkZ = j + Math.floorDiv(startZ, LodQuadTreeNode.CHUNK_WIDTH);
|
||||
|
||||
// skip any chunks that Minecraft is going to render
|
||||
if(isCoordInCenterArea(i, j, (numbChunksWide / 2))
|
||||
&& renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ)))
|
||||
{
|
||||
if (isCoordInCenterArea(i, j, (numbChunksWide / 2))
|
||||
&& renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -175,20 +174,18 @@ public class LodNodeBufferBuilder
|
||||
double xOffset = (LodQuadTreeNode.CHUNK_WIDTH * i) + // offset by the number of LOD blocks
|
||||
startX + // offset so the center LOD block is centered underneath the player
|
||||
8; // I'm not sure what this is correcting exactly but with it the chunks line up.
|
||||
// 8 works for LODs the size of chunks
|
||||
// 8 works for LODs the size of chunks
|
||||
double yOffset = 0;
|
||||
double zOffset = (LodQuadTreeNode.CHUNK_WIDTH * j) + startZ + 8;
|
||||
|
||||
|
||||
LodQuadTreeNode lod = lodDim.getLodFromCoordinates(new ChunkPos(chunkX, chunkZ), LodQuadTreeNode.CHUNK_LEVEL);
|
||||
|
||||
if (lod == null || lod.complexity == DistanceGenerationMode.NONE)
|
||||
{
|
||||
if (lod == null || lod.complexity == DistanceGenerationMode.NONE) {
|
||||
// generate a new chunk if no chunk currently exists
|
||||
// and we aren't waiting on any other chunks to generate
|
||||
if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests)
|
||||
{
|
||||
if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) {
|
||||
ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
|
||||
|
||||
// alternate determining logic that
|
||||
// can be used for debugging
|
||||
// if (chunksToGen == null)
|
||||
@@ -202,10 +199,8 @@ public class LodNodeBufferBuilder
|
||||
// chunksToGen[chunkGenIndex] = pos;
|
||||
// chunkGenIndex++;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// determine if this position is closer to the player
|
||||
// than the previous
|
||||
int newDistance = playerChunkPos.getChessboardDistance(pos);
|
||||
@@ -216,69 +211,58 @@ public class LodNodeBufferBuilder
|
||||
// 100% CPU utilization, this code generally achieves 40 - 50%
|
||||
// after a certain point; and I'm sure there is a better data
|
||||
// structure for this.
|
||||
if (newDistance < minChunkDist)
|
||||
{
|
||||
if (newDistance < minChunkDist) {
|
||||
// this chunk is closer, clear any previous
|
||||
// positions and update the new minimum distance
|
||||
minChunkDist = newDistance;
|
||||
|
||||
|
||||
// move all the old chunks into the reserve
|
||||
ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests];
|
||||
int oldToGenIndex = 0;
|
||||
int oldReserveIndex = 0;
|
||||
for(int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++)
|
||||
{
|
||||
for (int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++) {
|
||||
// we don't check if the boundaries are good since
|
||||
// the tmp array will always be the same length
|
||||
// as chunksToGen and chunksToGenReserve
|
||||
|
||||
if (chunksToGen[oldToGenIndex] != null)
|
||||
{
|
||||
|
||||
if (chunksToGen[oldToGenIndex] != null) {
|
||||
// add all the closest chunks...
|
||||
newReserve[tmpIndex] = chunksToGen[oldToGenIndex];
|
||||
oldToGenIndex++;
|
||||
}
|
||||
else if (chunksToGenReserve[oldReserveIndex] != null)
|
||||
{
|
||||
} else if (chunksToGenReserve[oldReserveIndex] != null) {
|
||||
// ...then add all the previous reserve chunks
|
||||
// (which are farther away)
|
||||
newReserve[tmpIndex] = chunksToGenReserve[oldToGenIndex];
|
||||
oldReserveIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// we have moved all the items from
|
||||
// the old chunksToGen and reserve
|
||||
break;
|
||||
}
|
||||
}
|
||||
chunksToGenReserve = newReserve;
|
||||
|
||||
|
||||
|
||||
|
||||
chunkGenIndex = 0;
|
||||
chunksToGen = new ChunkPos[maxChunkGenRequests];
|
||||
chunksToGen[chunkGenIndex] = pos;
|
||||
chunkGenIndex++;
|
||||
}
|
||||
else if (newDistance <= minChunkDist)
|
||||
{
|
||||
} else if (newDistance <= minChunkDist) {
|
||||
// this chunk position is as close or closers than the
|
||||
// minimum distance
|
||||
if(chunkGenIndex < maxChunkGenRequests)
|
||||
{
|
||||
if (chunkGenIndex < maxChunkGenRequests) {
|
||||
// we are still under the number of chunks to generate
|
||||
// add this position to the list
|
||||
chunksToGen[chunkGenIndex] = pos;
|
||||
chunkGenIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // lod null and can generate more chunks
|
||||
|
||||
// don't render this null/empty chunk
|
||||
continue;
|
||||
|
||||
|
||||
} // lod null or empty
|
||||
|
||||
|
||||
@@ -290,9 +274,27 @@ public class LodNodeBufferBuilder
|
||||
|
||||
// get the desired LodTemplate and
|
||||
// add this LOD to the buffer
|
||||
|
||||
LodConfig.CLIENT.lodTemplate.get().
|
||||
template.addLodToBuffer(currentBuffer, lodDim, lod,
|
||||
xOffset, yOffset, zOffset, renderer.debugging);
|
||||
xOffset , yOffset, zOffset, renderer.debugging);
|
||||
/*
|
||||
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
|
||||
for(int x = 0; x < detail.dataPointLengthCount; x++){
|
||||
for(int z = 0; z < detail.dataPointLengthCount; z++) {
|
||||
int posX = LodUtil.convertLevelPos(lod.startBlockPos.getX() + (x*detail.dataPointWidth), 0, detail.detailLevel);
|
||||
int posZ = LodUtil.convertLevelPos(lod.startBlockPos.getZ() + (z*detail.dataPointWidth), 0, detail.detailLevel);
|
||||
LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX, posZ, detail.detailLevel);
|
||||
System.out.print("printing ");
|
||||
System.out.println(newLod);
|
||||
if(newLod != null) {
|
||||
LodConfig.CLIENT.lodTemplate.get().
|
||||
template.addLodToBuffer(currentBuffer, lodDim, newLod,
|
||||
xOffset + (x*detail.dataPointWidth), yOffset, zOffset + (z*detail.dataPointWidth), renderer.debugging);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public class LodNodeBuilder {
|
||||
try {
|
||||
DimensionType dim = world.dimensionType();
|
||||
|
||||
List<LodQuadTreeNode> nodeList = generateLodNodeFromChunk(chunk);
|
||||
List<LodQuadTreeNode> nodeList = generateLodNodeFromChunk(chunk);
|
||||
|
||||
LodQuadTreeDimension lodDim;
|
||||
|
||||
@@ -98,8 +98,9 @@ public class LodNodeBuilder {
|
||||
} else {
|
||||
lodDim = lodWorld.getLodDimension(dim);
|
||||
}
|
||||
for(LodQuadTreeNode node : nodeList) {
|
||||
for (LodQuadTreeNode node : nodeList) {
|
||||
lodDim.addNode(node);
|
||||
|
||||
}
|
||||
} catch (IllegalArgumentException | NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
@@ -130,37 +131,36 @@ public class LodNodeBuilder {
|
||||
* @throws IllegalArgumentException thrown if either the chunk or world is null.
|
||||
*/
|
||||
public List<LodQuadTreeNode> generateLodNodeFromChunk(IChunk chunk, LodBuilderConfig config) throws IllegalArgumentException {
|
||||
LodDetail detail = LodDetail.QUAD;
|
||||
LodDetail detail = LodDetail.HALF;
|
||||
List<LodQuadTreeNode> lodNodeList = new ArrayList<>();
|
||||
if (chunk == null)
|
||||
throw new IllegalArgumentException("generateLodFromChunk given a null chunk");
|
||||
for (int x = 0; x < detail.dataPointLengthCount; x++) {
|
||||
for (int z = 0; z < detail.dataPointLengthCount; z++) {
|
||||
int startX = detail.startX[x];
|
||||
int startZ = detail.startZ[z];
|
||||
int endX = detail.endX[x];
|
||||
int endZ = detail.endZ[z];
|
||||
for (int i = 0; i < detail.dataPointLengthCount*detail.dataPointLengthCount; i++) {
|
||||
int startX = detail.startX[i];
|
||||
int startZ = detail.startZ[i];
|
||||
int endX = detail.endX[i];
|
||||
int endZ = detail.endZ[i];
|
||||
|
||||
// TODO startX/Z and endX/Z are relative coordinates
|
||||
// getMin/Max appear to return world block coordinates
|
||||
// TODO startX/Z and endX/Z are relative coordinates
|
||||
// getMin/Max appear to return world block coordinates
|
||||
|
||||
Color color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ);
|
||||
Color color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ);
|
||||
|
||||
short height;
|
||||
short depth;
|
||||
short height;
|
||||
short depth;
|
||||
|
||||
if (!config.useHeightmap) {
|
||||
height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
} else {
|
||||
height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodChunk.DEFAULT_HEIGHTMAP), startX, startZ, endX, endZ);
|
||||
depth = 0;
|
||||
}
|
||||
lodNodeList.add(new LodQuadTreeNode((byte) detail.detailLevel,
|
||||
LodUtil.convertLevelPos(chunk.getPos().getMinBlockX() + startX,0,detail.detailLevel),
|
||||
LodUtil.convertLevelPos(chunk.getPos().getMinBlockZ() + startZ,0,detail.detailLevel) ,
|
||||
new LodDataPoint(height, depth, color), DistanceGenerationMode.SERVER));
|
||||
if (!config.useHeightmap) {
|
||||
height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
|
||||
} else {
|
||||
height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodChunk.DEFAULT_HEIGHTMAP), startX, startZ, endX, endZ);
|
||||
depth = 0;
|
||||
}
|
||||
lodNodeList.add(new LodQuadTreeNode((byte) detail.detailLevel,
|
||||
LodUtil.convertLevelPos(chunk.getPos().getMinBlockX() + startX, 0, detail.detailLevel),
|
||||
LodUtil.convertLevelPos(chunk.getPos().getMinBlockZ() + startZ, 0, detail.detailLevel),
|
||||
new LodDataPoint(height, depth, color), DistanceGenerationMode.SERVER));
|
||||
|
||||
}
|
||||
|
||||
return lodNodeList;
|
||||
|
||||
@@ -18,11 +18,14 @@
|
||||
package com.seibel.lod.builders.lodNodeTemplates;
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LodQuadTree;
|
||||
import com.seibel.lod.objects.LodQuadTreeDimension;
|
||||
import com.seibel.lod.objects.LodQuadTreeNode;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
|
||||
@@ -48,20 +51,45 @@ public class CubicLodNodeTemplate extends AbstractLodNodeTemplate
|
||||
AxisAlignedBB bbox;
|
||||
|
||||
// Add this LOD to the BufferBuilder
|
||||
int halfWidth = lod.width / 2;
|
||||
|
||||
// returns null if the lod is empty at the given location
|
||||
bbox = generateBoundingBox(
|
||||
lod.getLodDataPoint().height,
|
||||
lod.getLodDataPoint().depth,
|
||||
lod.width,
|
||||
xOffset - halfWidth,
|
||||
yOffset,
|
||||
zOffset - halfWidth);
|
||||
int halfWidth = LodQuadTreeNode.CHUNK_WIDTH / 2;
|
||||
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
|
||||
/*
|
||||
bbox = generateBoundingBox(
|
||||
lod.getLodDataPoint().height,
|
||||
lod.getLodDataPoint().depth,
|
||||
lod.width,
|
||||
xOffset - halfWidth,
|
||||
yOffset,
|
||||
zOffset - halfWidth);
|
||||
|
||||
if (bbox != null) {
|
||||
addBoundingBoxToBuffer(buffer, bbox, lod.getLodDataPoint().color);
|
||||
}
|
||||
|
||||
*/
|
||||
LodQuadTree chunkTree = lodDim.getLevelFromPos(lod.posX, lod.posZ, lod.detailLevel);
|
||||
for(int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++) {
|
||||
int startX = detail.startX[i];
|
||||
int startZ = detail.startZ[i];
|
||||
int posX = LodUtil.convertLevelPos((int) xOffset+startX,0, detail.detailLevel);
|
||||
int posZ = LodUtil.convertLevelPos((int) zOffset+startZ,0, detail.detailLevel);;
|
||||
//LodQuadTreeNode newLod = chunkTree.getNodeAtPos(posX ,posZ ,detail.detailLevel);
|
||||
LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX ,posZ ,detail.detailLevel);
|
||||
if(newLod != null) {
|
||||
bbox = generateBoundingBox(
|
||||
newLod.getLodDataPoint().height,
|
||||
newLod.getLodDataPoint().depth,
|
||||
newLod.width,
|
||||
xOffset + startX,
|
||||
yOffset,
|
||||
zOffset + startZ);
|
||||
|
||||
if (bbox != null) {
|
||||
addBoundingBoxToBuffer(buffer, bbox, newLod.getLodDataPoint().color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bbox != null) {
|
||||
addBoundingBoxToBuffer(buffer, bbox, lod.getLodDataPoint().color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -263,6 +263,42 @@ public class LodQuadTree
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LodQuadTree at the given generic pos and detailLevel.
|
||||
* Returns null if no such LodQuadTreeNode exists.
|
||||
*/
|
||||
public LodQuadTree getLevelAtPos(int posX, int posZ, int detailLevel)
|
||||
{
|
||||
if (detailLevel > LodQuadTreeNode.REGION_LEVEL)
|
||||
throw new IllegalArgumentException("getNodeAtChunkPos given a level of \"" + detailLevel + "\" when \"" + LodQuadTreeNode.REGION_LEVEL + "\" is the max.");
|
||||
|
||||
|
||||
byte currentDetailLevel = lodNode.detailLevel;
|
||||
if (detailLevel == currentDetailLevel)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else if (detailLevel < currentDetailLevel)
|
||||
{
|
||||
// the detail level we need is lower, go down a layer
|
||||
short widthRatio = (short) (lodNode.width / (2 * Math.pow(2, detailLevel)));
|
||||
int WE = Math.abs(Math.floorDiv(posX , widthRatio) % 2);
|
||||
int NS = Math.abs(Math.floorDiv(posZ , widthRatio) % 2);
|
||||
if (getChild(NS, WE) == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
LodQuadTree child = getChild(NS, WE);
|
||||
return child.getLevelAtPos(posX, posZ, detailLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the detail level was higher than this region's
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a child with the given data into the given position.
|
||||
*
|
||||
|
||||
@@ -393,7 +393,51 @@ public class LodQuadTreeDimension
|
||||
|
||||
return region.getNodeAtChunkPos(chunkPos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 LodQuadTreeNode getLodFromCoordinates(int posX, int posZ, int detailLevel)
|
||||
{
|
||||
if (detailLevel > LodQuadTreeNode.REGION_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodQuadTreeNode.REGION_LEVEL + "\" is the max.");
|
||||
|
||||
LodQuadTree region = getRegion(LodUtil.convertGenericPosToRegionPos(posX, posZ, detailLevel));
|
||||
|
||||
if(region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return region.getNodeAtPos(posX, posZ, detailLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 LodQuadTree getLevelFromPos(int posX, int posZ, int detailLevel)
|
||||
{
|
||||
if (detailLevel > LodQuadTreeNode.REGION_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodQuadTreeNode.REGION_LEVEL + "\" is the max.");
|
||||
|
||||
LodQuadTree region = getRegion(LodUtil.convertGenericPosToRegionPos(posX, posZ, detailLevel));
|
||||
|
||||
if(region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return region.getLevelAtPos(posX, posZ, detailLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if and only if the node at that position exist
|
||||
*/
|
||||
|
||||
@@ -313,9 +313,9 @@ public class LodQuadTreeNode
|
||||
{
|
||||
// TODO would it be better to use the average height/depth?
|
||||
// get the lowest height from the all the given LodQuadTreeNodes
|
||||
short height = (short) dataList.stream().mapToInt(x -> (int) x.getLodDataPoint().height).min().getAsInt();
|
||||
short height = (short) dataList.stream().mapToInt(x -> (int) x.getLodDataPoint().height).max().getAsInt();
|
||||
// get the highest depth
|
||||
short depth = (short) dataList.stream().mapToInt(x -> (int) x.getLodDataPoint().depth).max().getAsInt();
|
||||
short depth = (short) dataList.stream().mapToInt(x -> (int) x.getLodDataPoint().depth).min().getAsInt();
|
||||
|
||||
// get the average color
|
||||
int red = dataList.stream().mapToInt(x -> x.getLodDataPoint().color.getRed()).sum() / dataList.size();
|
||||
|
||||
@@ -168,7 +168,7 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.brightnessMultiplier.set(1.0);
|
||||
// LodConfig.CLIENT.saturationMultiplier.set(1.0);
|
||||
|
||||
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
|
||||
LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
// LOGGER.info(lodBufferBuilder.numberOfChunksWaitingToGenerate.get());
|
||||
|
||||
Reference in New Issue
Block a user