Added different LodDetail support

This commit is contained in:
Leonardo
2021-08-10 17:11:36 +02:00
parent 2e32e4d768
commit bb61cdad70
7 changed files with 194 additions and 84 deletions
@@ -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());