Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2834a73551 | |||
| 5a7af89f5c | |||
| eff491127b | |||
| 61502c32a6 | |||
| b7911ec4c8 | |||
| 1115c5f6c5 | |||
| 5d001bf7ea | |||
| 4e732f7916 | |||
| 30d392f861 | |||
| f8910b0c3b |
@@ -184,14 +184,16 @@ public class EventApi
|
||||
{
|
||||
if (CONFIG.client().advanced().debugging().getDebugKeybindingsEnabled())
|
||||
{
|
||||
if (key == GLFW.GLFW_KEY_F4 && keyAction == GLFW.GLFW_PRESS)
|
||||
if (key == GLFW.GLFW_KEY_F8 && keyAction == GLFW.GLFW_PRESS)
|
||||
{
|
||||
CONFIG.client().advanced().debugging().setDebugMode(CONFIG.client().advanced().debugging().getDebugMode().getNext());
|
||||
MC.sendChatMessage("F8: Set debug mode " + CONFIG.client().advanced().debugging().getDebugMode());
|
||||
}
|
||||
|
||||
if (key == GLFW.GLFW_KEY_F6 && keyAction == GLFW.GLFW_PRESS)
|
||||
{
|
||||
CONFIG.client().advanced().debugging().setDrawLods(!CONFIG.client().advanced().debugging().getDrawLods());
|
||||
MC.sendChatMessage("F6: Set rendering " + CONFIG.client().advanced().debugging().getDrawLods());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,7 +224,7 @@ public class EventApi
|
||||
|
||||
int newWidth = (int) Math.ceil(chunksWide / (float) LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
// make sure we have an odd number of regions
|
||||
newWidth += (newWidth & 1) == 0 ? 1 : 2;
|
||||
newWidth += (newWidth & 1) == 0 ? 1 : 0;
|
||||
|
||||
// do the dimensions need to change in size?
|
||||
if (ApiShared.lodBuilder.defaultDimensionWidthInRegions != newWidth || recalculateWidths)
|
||||
|
||||
+39
-33
@@ -30,6 +30,8 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
@@ -144,14 +146,17 @@ public class LodBufferBuilderFactory
|
||||
|
||||
private volatile VertexOptimizer[][] vertexOptimizerCache;
|
||||
private volatile PosToRenderContainer[][] setsToRender;
|
||||
private volatile RegionPos center;
|
||||
private volatile int centerRegionX = 0;
|
||||
private volatile int centerRegionZ = 0;
|
||||
|
||||
/**
|
||||
* This is the ChunkPosWrapper the player was at the last time the buffers were built.
|
||||
* IE the center of the buffers last time they were built
|
||||
*/
|
||||
private volatile AbstractChunkPosWrapper drawableCenterChunkPos = WRAPPER_FACTORY.createChunkPos();
|
||||
private volatile AbstractChunkPosWrapper buildableCenterChunkPos = WRAPPER_FACTORY.createChunkPos();
|
||||
private volatile int drawableCenterChunkPosX = 0;
|
||||
private volatile int drawableCenterChunkPosZ = 0;
|
||||
private volatile int buildableCenterChunkPosX = 0;
|
||||
private volatile int buildableCenterChunkPosZ = 0;
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +178,7 @@ public class LodBufferBuilderFactory
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
*/
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
AbstractBlockPosWrapper playerBlockPos, boolean fullRegen)
|
||||
int playerX, int playerY, int playerZ, boolean fullRegen)
|
||||
{
|
||||
|
||||
// only allow one generation process to happen at a time
|
||||
@@ -191,7 +196,7 @@ public class LodBufferBuilderFactory
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
Thread thread = new Thread(() -> generateLodBuffersThread(renderer, lodDim, playerBlockPos, fullRegen));
|
||||
Thread thread = new Thread(() -> generateLodBuffersThread(renderer, lodDim, playerX, playerY, playerZ, fullRegen));
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
}
|
||||
@@ -200,15 +205,17 @@ public class LodBufferBuilderFactory
|
||||
// more easily edited by hot swapping. Because, As far as James is aware
|
||||
// you can't hot swap lambda expressions.
|
||||
private void generateLodBuffersThread(LodRenderer renderer, LodDimension lodDim,
|
||||
AbstractBlockPosWrapper playerBlockPos, boolean fullRegen)
|
||||
int playerX, int playerY, int playerZ, boolean fullRegen)
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
AbstractChunkPosWrapper playerChunkPos = WRAPPER_FACTORY.createChunkPos(playerBlockPos);
|
||||
AbstractBlockPosWrapper playerBlockPosRounded = playerChunkPos.getWorldPosition();
|
||||
int playerChunkX = LevelPosUtil.convert(LodUtil.BLOCK_DETAIL_LEVEL,playerX,LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
int playerChunkZ = LevelPosUtil.convert(LodUtil.BLOCK_DETAIL_LEVEL,playerZ,LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
int playerRegionX = LevelPosUtil.convert(LodUtil.BLOCK_DETAIL_LEVEL,playerX,LodUtil.REGION_DETAIL_LEVEL);
|
||||
int playerRegionZ = LevelPosUtil.convert(LodUtil.BLOCK_DETAIL_LEVEL,playerZ,LodUtil.REGION_DETAIL_LEVEL);
|
||||
|
||||
|
||||
//long startTime = System.currentTimeMillis();
|
||||
@@ -217,11 +224,6 @@ public class LodBufferBuilderFactory
|
||||
|
||||
startBuffers(fullRegen, lodDim);
|
||||
|
||||
|
||||
RegionPos playerRegionPos = new RegionPos(playerChunkPos);
|
||||
if (center == null)
|
||||
center = playerRegionPos;
|
||||
|
||||
if (setsToRender == null)
|
||||
setsToRender = new PosToRenderContainer[lodDim.getWidth()][lodDim.getWidth()];
|
||||
|
||||
@@ -235,14 +237,15 @@ public class LodBufferBuilderFactory
|
||||
vertexOptimizerCache = new VertexOptimizer[lodDim.getWidth()][lodDim.getWidth()];
|
||||
|
||||
// this will be the center of the VBOs once they have been built
|
||||
buildableCenterChunkPos = playerChunkPos;
|
||||
buildableCenterChunkPosX = playerChunkX;
|
||||
buildableCenterChunkPosZ = playerChunkZ;
|
||||
|
||||
|
||||
//================================//
|
||||
// create the nodeToRenderThreads //
|
||||
//================================//
|
||||
|
||||
skyLightPlayer = MC.getWrappedClientWorld().getSkyLight(playerBlockPos);
|
||||
skyLightPlayer = MC.getWrappedClientWorld().getSkyLight(playerX, playerY, playerZ);
|
||||
|
||||
for (int xRegion = 0; xRegion < lodDim.getWidth(); xRegion++)
|
||||
{
|
||||
@@ -308,8 +311,8 @@ public class LodBufferBuilderFactory
|
||||
lodDim.getPosToRender(
|
||||
posToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
playerX,
|
||||
playerZ);
|
||||
|
||||
|
||||
|
||||
@@ -327,14 +330,14 @@ public class LodBufferBuilderFactory
|
||||
posX = posToRender.getNthPosX(index);
|
||||
posZ = posToRender.getNthPosZ(index);
|
||||
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.getX();
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.getZ();
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkX;
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkZ;
|
||||
|
||||
//We don't want to render this fake block if
|
||||
//The block is inside the render distance with, is not bigger than a chunk and is positioned in a chunk set as vanilla rendered
|
||||
//
|
||||
//The block is in the player chunk or in a chunk adjacent to the player
|
||||
if(isThisPositionGoingToBeRendered(detailLevel, posX, posZ, playerChunkPos, vanillaRenderedChunks, gameChunkRenderDistance))
|
||||
if(isThisPositionGoingToBeRendered(detailLevel, posX, posZ, playerChunkX, playerChunkZ, vanillaRenderedChunks, gameChunkRenderDistance))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -355,8 +358,8 @@ public class LodBufferBuilderFactory
|
||||
xAdj = posX + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
zAdj = posZ + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
long data;
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.getX();
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.getZ();
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkX;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkZ;
|
||||
adjPosInPlayerChunk = (chunkXdist == 0 && chunkZdist == 0);
|
||||
|
||||
//If the adj block is rendered in the same region and with same detail
|
||||
@@ -365,7 +368,7 @@ public class LodBufferBuilderFactory
|
||||
// We avoid cases where the adjPosition is in player chunk while the position is not
|
||||
// to always have a wall underwater
|
||||
if(posToRender.contains(detailLevel, xAdj, zAdj)
|
||||
&& !isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkPos, vanillaRenderedChunks, gameChunkRenderDistance)
|
||||
&& !isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkX, playerChunkZ, vanillaRenderedChunks, gameChunkRenderDistance)
|
||||
&& !(posNotInPlayerChunk && adjPosInPlayerChunk))
|
||||
{
|
||||
for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++)
|
||||
@@ -382,7 +385,7 @@ public class LodBufferBuilderFactory
|
||||
|
||||
adjData.get(lodDirection)[0] = DataPointUtil.EMPTY_DATA;
|
||||
|
||||
if ((isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkPos, vanillaRenderedChunks, gameChunkRenderDistance) || (posNotInPlayerChunk && adjPosInPlayerChunk))
|
||||
if ((isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkX, playerChunkZ, vanillaRenderedChunks, gameChunkRenderDistance) || (posNotInPlayerChunk && adjPosInPlayerChunk))
|
||||
&& !DataPointUtil.isVoid(data))
|
||||
{
|
||||
adjShadeDisabled[VertexOptimizer.DIRECTION_INDEX.get(lodDirection)] = DataPointUtil.getAlpha(data) < 255;
|
||||
@@ -418,7 +421,7 @@ public class LodBufferBuilderFactory
|
||||
break;
|
||||
|
||||
//We send the call to create the vertices
|
||||
CONFIG.client().graphics().advancedGraphics().getLodTemplate().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, data, adjData,
|
||||
LodTemplate.CUBIC.template.addLodToBuffer(currentBuffers[bufferIndex], playerX, playerY, playerZ, data, adjData,
|
||||
detailLevel, posX, posZ, vertexOptimizer, renderer.previousDebugMode, adjShadeDisabled);
|
||||
}
|
||||
|
||||
@@ -488,12 +491,12 @@ public class LodBufferBuilderFactory
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isThisPositionGoingToBeRendered(byte detailLevel, int posX, int posZ, AbstractChunkPosWrapper playerChunkPos, boolean[][] vanillaRenderedChunks, int gameChunkRenderDistance){
|
||||
private boolean isThisPositionGoingToBeRendered(byte detailLevel, int posX, int posZ, int chunkPosX, int chunkPosZ, boolean[][] vanillaRenderedChunks, int gameChunkRenderDistance){
|
||||
|
||||
|
||||
// skip any chunks that Minecraft is going to render
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.getX();
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.getZ();
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - chunkPosX;
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - chunkPosZ;
|
||||
|
||||
// check if the chunk is on the border
|
||||
boolean isItBorderPos;
|
||||
@@ -1016,7 +1019,8 @@ public class LodBufferBuilderFactory
|
||||
drawableStorageBufferIds = buildableStorageBufferIds;
|
||||
buildableStorageBufferIds = tmpStorage;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
drawableCenterChunkPosX = buildableCenterChunkPosX;
|
||||
drawableCenterChunkPosZ = buildableCenterChunkPosZ;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
@@ -1032,7 +1036,7 @@ public class LodBufferBuilderFactory
|
||||
}
|
||||
}
|
||||
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableStorageBufferIds, drawableCenterChunkPos);
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableStorageBufferIds, drawableCenterChunkPosX, drawableCenterChunkPosZ);
|
||||
}
|
||||
|
||||
/** A simple container to pass multiple objects back in the getVertexBuffers method. */
|
||||
@@ -1040,13 +1044,15 @@ public class LodBufferBuilderFactory
|
||||
{
|
||||
public final LodVertexBuffer[][][] vbos;
|
||||
public final int[][][] storageBufferIds;
|
||||
public final AbstractChunkPosWrapper drawableCenterChunkPos;
|
||||
public int drawableCenterChunkPosX;
|
||||
public int drawableCenterChunkPosZ;
|
||||
|
||||
public VertexBuffersAndOffset(LodVertexBuffer[][][] newVbos, int[][][] newStorageBufferIds, AbstractChunkPosWrapper newDrawableCenterChunkPos)
|
||||
public VertexBuffersAndOffset(LodVertexBuffer[][][] newVbos, int[][][] newStorageBufferIds, int newDrawableCenterChunkPosX, int newDrawableCenterChunkPosZ)
|
||||
{
|
||||
vbos = newVbos;
|
||||
storageBufferIds = newStorageBufferIds;
|
||||
drawableCenterChunkPos = newDrawableCenterChunkPos;
|
||||
drawableCenterChunkPosX = newDrawableCenterChunkPosX;
|
||||
drawableCenterChunkPosZ = newDrawableCenterChunkPosZ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
/** Uploads the given LOD to the buffer. */
|
||||
public abstract void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
public abstract void addLodToBuffer(LodBufferBuilder buffer, int playerX, int playerY, int playerZ, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled);
|
||||
|
||||
/** add the given position and color to the buffer */
|
||||
|
||||
+7
-10
@@ -27,7 +27,6 @@ import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
/**
|
||||
* Builds LODs as rectangular prisms.
|
||||
@@ -43,7 +42,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, int playerX, int playerY, int playerZ, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
if (vertexOptimizer == null)
|
||||
@@ -65,7 +64,9 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
DataPointUtil.getDepth(data),
|
||||
blockWidth,
|
||||
posX * blockWidth, 0, posZ * blockWidth, // x, y, z offset
|
||||
bufferCenterBlockPos,
|
||||
playerX,
|
||||
playerY,
|
||||
playerZ,
|
||||
adjData,
|
||||
color,
|
||||
DataPointUtil.getLightSkyAlt(data),
|
||||
@@ -78,7 +79,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
private void generateBoundingBox(VertexOptimizer vertexOptimizer,
|
||||
int height, int depth, int width,
|
||||
double xOffset, double yOffset, double zOffset,
|
||||
AbstractBlockPosWrapper bufferCenterBlockPos,
|
||||
int playerX, int playerY, int playerZ,
|
||||
Map<LodDirection, long[]> adjData,
|
||||
int color, byte skyLight, byte blockLight,
|
||||
boolean[] adjShadeDisabled)
|
||||
@@ -95,14 +96,13 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
// offset the AABB by its x/z position in the world since
|
||||
// it uses doubles to specify its location, unlike the model view matrix
|
||||
// which only uses floats
|
||||
double x = -bufferCenterBlockPos.getX();
|
||||
double z = -bufferCenterBlockPos.getZ();
|
||||
double x = -playerX;
|
||||
double z = -playerZ;
|
||||
vertexOptimizer.reset();
|
||||
vertexOptimizer.setColor(color, adjShadeDisabled);
|
||||
vertexOptimizer.setLights(skyLight, blockLight);
|
||||
vertexOptimizer.setWidth(width, height - depth, width);
|
||||
vertexOptimizer.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z));
|
||||
vertexOptimizer.setUpCulling(32, bufferCenterBlockPos);
|
||||
vertexOptimizer.setAdjData(adjData);
|
||||
}
|
||||
|
||||
@@ -113,9 +113,6 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
byte blockLight;
|
||||
for (LodDirection lodDirection : VertexOptimizer.DIRECTIONS)
|
||||
{
|
||||
if(vertexOptimizer.isCulled(lodDirection))
|
||||
continue;
|
||||
|
||||
int verticalFaceIndex = 0;
|
||||
while (vertexOptimizer.shouldRenderFace(lodDirection, verticalFaceIndex))
|
||||
{
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, int playerX, int playerY, int playerZ, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, int playerX, int playerY, int playerZ, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
|
||||
@@ -170,7 +170,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
int startZ;
|
||||
|
||||
|
||||
LodRegion region = lodDim.getRegion(chunk.getPos().getRegionX(), chunk.getPos().getRegionZ());
|
||||
LodRegion region = lodDim.getRegion(chunk.getRegionPosX(), chunk.getRegionPosZ());
|
||||
if (region == null)
|
||||
return;
|
||||
|
||||
@@ -198,18 +198,11 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
|
||||
|
||||
//lodDim.clear(detailLevel, posX, posZ);
|
||||
if (data != null && data.length != 0)
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().getX() * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().getZ() * 16 + startZ, detail.detailLevel);
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, data, false);
|
||||
}
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getChunkPosX() * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getChunkPosZ() * 16 + startZ, detail.detailLevel);
|
||||
lodDim.mergeMultiData(detailLevel, posX, posZ, false, dataToMergeVertical, DataPointUtil.WORLD_HEIGHT / 2 + 1);
|
||||
}
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().getX(), chunk.getPos().getZ());
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getChunkPosX(), chunk.getChunkPosZ());
|
||||
//executeTime = System.currentTimeMillis() - executeTime;
|
||||
//if (executeTime > 0) ClientApi.LOGGER.info("generateLodNodeFromChunk level: " + detailLevel + " time ms: " + executeTime);
|
||||
}
|
||||
@@ -222,8 +215,6 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel);
|
||||
int verticalData = DataPointUtil.WORLD_HEIGHT / 2 + 1;
|
||||
|
||||
AbstractChunkPosWrapper chunkPos = chunk.getPos();
|
||||
int height;
|
||||
int depth;
|
||||
int color;
|
||||
@@ -240,23 +231,22 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
boolean hasCeiling = MC.getWrappedClientWorld().getDimensionType().hasCeiling();
|
||||
boolean hasSkyLight = MC.getWrappedClientWorld().getDimensionType().hasSkyLight();
|
||||
boolean isDefault;
|
||||
AbstractBlockPosWrapper blockPos = FACTORY.createBlockPos();
|
||||
int index;
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
xRel = startX + index % size;
|
||||
zRel = startZ + index / size;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
xAbs = chunk.getMinX() + xRel;
|
||||
zAbs = chunk.getMinZ() + zRel;
|
||||
|
||||
//Calculate the height of the lod
|
||||
yAbs = DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET + 1;
|
||||
yAbs = chunk.getMaxY(xRel, zRel); //DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET + 1;
|
||||
int count = 0;
|
||||
boolean topBlock = true;
|
||||
while (yAbs > 0)
|
||||
{
|
||||
height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
height = determineHeightPointFrom(chunk, config, xAbs, yAbs, zAbs);
|
||||
|
||||
// If the lod is at the default height, it must be void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
@@ -268,21 +258,17 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
depth = determineBottomPointFrom(chunk, config, xAbs, yAbs, zAbs);
|
||||
if (hasCeiling && topBlock)
|
||||
{
|
||||
yAbs = depth;
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, true, hasSkyLight, true);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos);
|
||||
blockPos.set(xAbs, yAbs - 1, zAbs);
|
||||
light = getLightValue(chunk, xAbs,yAbs,zAbs, true, hasSkyLight, true);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock);
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
blockPos.set(xAbs, yAbs + 1, zAbs);
|
||||
light = getLightValue(chunk, xAbs, yAbs, zAbs, hasCeiling, hasSkyLight, topBlock);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs);
|
||||
}
|
||||
lightBlock = light & 0b1111;
|
||||
lightSky = (light >> 4) & 0b1111;
|
||||
@@ -301,14 +287,13 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
* Find the lowest valid point from the bottom.
|
||||
* Used when creating a vertical LOD.
|
||||
*/
|
||||
private short determineBottomPointFrom(IChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs, AbstractBlockPosWrapper blockPos)
|
||||
private short determineBottomPointFrom(IChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs)
|
||||
{
|
||||
short depth = DEFAULT_DEPTH;
|
||||
|
||||
for (int y = yAbs; y >= 0; y--)
|
||||
{
|
||||
blockPos.set(xAbs, y, zAbs);
|
||||
if (!isLayerValidLodPoint(chunk, blockPos))
|
||||
if (!isLayerValidLodPoint(chunk, xAbs, y, zAbs))
|
||||
{
|
||||
depth = (short) (y + 1);
|
||||
break;
|
||||
@@ -318,8 +303,9 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
}
|
||||
|
||||
/** Find the highest valid point from the Top */
|
||||
private short determineHeightPointFrom(IChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs, AbstractBlockPosWrapper blockPos)
|
||||
private short determineHeightPointFrom(IChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs)
|
||||
{
|
||||
|
||||
short height = DEFAULT_HEIGHT;
|
||||
if (config.useHeightmap)
|
||||
height = (short) chunk.getHeightMapValue(xAbs, zAbs);
|
||||
@@ -327,8 +313,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
{
|
||||
for (int y = yAbs; y >= 0; y--)
|
||||
{
|
||||
blockPos.set(xAbs, y, zAbs);
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
if (isLayerValidLodPoint(chunk, xAbs, y, zAbs))
|
||||
{
|
||||
height = (short) (y + 1);
|
||||
break;
|
||||
@@ -348,19 +333,18 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
* Generate the color for the given chunk using biome water color, foliage
|
||||
* color, and grass color.
|
||||
*/
|
||||
private int generateLodColor(IChunkWrapper chunk, LodBuilderConfig builderConfig, int xRel, int yAbs, int zRel, AbstractBlockPosWrapper blockPos)
|
||||
private int generateLodColor(IChunkWrapper chunk, LodBuilderConfig builderConfig, int x, int y, int z)
|
||||
{
|
||||
int colorInt;
|
||||
if (builderConfig.useBiomeColors)
|
||||
{
|
||||
// I have no idea why I need to bit shift to the right, but
|
||||
// if I don't the biomes don't show up correctly.
|
||||
colorInt = chunk.getBiome(xRel, yAbs, zRel).getColorForBiome(xRel, zRel);
|
||||
colorInt = chunk.getBiome(x, y, z).getColorForBiome(x, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, yAbs, chunk.getPos().getMinBlockZ() + zRel);
|
||||
colorInt = getColorForBlock(chunk, blockPos);
|
||||
colorInt = getColorForBlock(chunk, x, y, z);
|
||||
|
||||
// if we are skipping non-full and non-solid blocks that means we ignore
|
||||
// snow, flowers, etc. Get the above block so we can still get the color
|
||||
@@ -368,8 +352,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
int aboveColorInt = 0;
|
||||
if (config.client().worldGenerator().getBlocksToAvoid().nonFull || config.client().worldGenerator().getBlocksToAvoid().noCollision)
|
||||
{
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, yAbs + 1, chunk.getPos().getMinBlockZ() + zRel);
|
||||
aboveColorInt = getColorForBlock(chunk, blockPos);
|
||||
aboveColorInt = getColorForBlock(chunk, x, y, z);
|
||||
}
|
||||
|
||||
//if (colorInt == 0 && yAbs > 0)
|
||||
@@ -386,7 +369,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
}
|
||||
|
||||
/** Gets the light value for the given block position */
|
||||
private int getLightValue(IChunkWrapper chunk, AbstractBlockPosWrapper blockPos, boolean hasCeiling, boolean hasSkyLight, boolean topBlock)
|
||||
private int getLightValue(IChunkWrapper chunk, int x, int y, int z, boolean hasCeiling, boolean hasSkyLight, boolean topBlock)
|
||||
{
|
||||
int skyLight = 0;
|
||||
int blockLight;
|
||||
@@ -395,25 +378,25 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
IWorldWrapper world = MC.getWrappedServerWorld();
|
||||
|
||||
int blockBrightness = chunk.getEmittedBrightness(blockPos);
|
||||
int blockBrightness = chunk.getEmittedBrightness(x, y, z);
|
||||
// get the air block above or below this block
|
||||
if (hasCeiling && topBlock)
|
||||
blockPos.set(blockPos.getX(), blockPos.getY() - 1, blockPos.getZ());
|
||||
y--;
|
||||
else
|
||||
blockPos.set(blockPos.getX(), blockPos.getY() + 1, blockPos.getZ());
|
||||
y++;
|
||||
|
||||
|
||||
|
||||
if (world != null)
|
||||
{
|
||||
// server world sky light (always accurate)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
blockLight = world.getBlockLight(x,y,z);
|
||||
if (topBlock && !hasCeiling && hasSkyLight)
|
||||
skyLight = DEFAULT_MAX_LIGHT;
|
||||
else
|
||||
{
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
skyLight = world.getSkyLight(x,y,z);
|
||||
//else
|
||||
// skyLight = 0;
|
||||
}
|
||||
@@ -421,7 +404,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
{
|
||||
// we are on predicted terrain, and we don't know what the light here is,
|
||||
// lets just take a guess
|
||||
if (blockPos.getY() >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
if (y >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
{
|
||||
skyLight = 12;
|
||||
isDefault = 1;
|
||||
@@ -442,7 +425,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
else
|
||||
{
|
||||
// client world sky light (almost never accurate)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
blockLight = world.getBlockLight(x,y,z);
|
||||
// estimate what the lighting should be
|
||||
if (hasSkyLight || !hasCeiling)
|
||||
{
|
||||
@@ -451,14 +434,14 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
else
|
||||
{
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
skyLight = world.getSkyLight(x,y,z);
|
||||
//else
|
||||
// skyLight = 0;
|
||||
if (!chunk.isLightCorrect() && (skyLight == 0 || skyLight == 15))
|
||||
{
|
||||
// we don't know what the light here is,
|
||||
// lets just take a guess
|
||||
if (blockPos.getY() >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
if (y >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
{
|
||||
skyLight = 12;
|
||||
isDefault = 1;
|
||||
@@ -477,24 +460,19 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
}
|
||||
|
||||
/** Returns a color int for the given block. */
|
||||
private int getColorForBlock(IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
|
||||
private int getColorForBlock(IChunkWrapper chunk, int x, int y, int z)
|
||||
{
|
||||
int colorOfBlock;
|
||||
int colorInt;
|
||||
|
||||
int xRel = blockPos.getX() - chunk.getPos().getMinBlockX();
|
||||
int zRel = blockPos.getZ() - chunk.getPos().getMinBlockZ();
|
||||
//int x = blockPos.getX();
|
||||
int y = blockPos.getY();
|
||||
//int z = blockPos.getZ();
|
||||
|
||||
IBlockColorWrapper blockColorWrapper;
|
||||
IBlockShapeWrapper blockShapeWrapper = chunk.getBlockShapeWrapper(blockPos);
|
||||
IBlockShapeWrapper blockShapeWrapper = chunk.getBlockShapeWrapper(x, y, z);
|
||||
|
||||
if (chunk.isWaterLogged(blockPos))
|
||||
if (chunk.isWaterLogged(x, y, z))
|
||||
blockColorWrapper = BLOCK_COLOR.getWaterColor();
|
||||
else
|
||||
blockColorWrapper = chunk.getBlockColorWrapper(blockPos);
|
||||
blockColorWrapper = chunk.getBlockColorWrapper(x, y, z);
|
||||
|
||||
if (blockShapeWrapper.isToAvoid())
|
||||
return 0;
|
||||
@@ -504,7 +482,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
if (blockColorWrapper.hasTint())
|
||||
{
|
||||
IBiomeWrapper biome = chunk.getBiome(xRel, y, zRel);
|
||||
IBiomeWrapper biome = chunk.getBiome(x, y, z);
|
||||
int tintValue;
|
||||
if (blockColorWrapper.hasGrassTint())
|
||||
// grass and green plants
|
||||
@@ -524,15 +502,15 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
|
||||
/** Is the block at the given blockPos a valid LOD point? */
|
||||
private boolean isLayerValidLodPoint(IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
|
||||
private boolean isLayerValidLodPoint(IChunkWrapper chunk, int x, int y, int z)
|
||||
{
|
||||
if (chunk.isWaterLogged(blockPos))
|
||||
if (chunk.isWaterLogged(x, y, z))
|
||||
return true;
|
||||
|
||||
boolean nonFullAvoidance = config.client().worldGenerator().getBlocksToAvoid().nonFull;
|
||||
boolean noCollisionAvoidance = config.client().worldGenerator().getBlocksToAvoid().noCollision;
|
||||
|
||||
IBlockShapeWrapper block = chunk.getBlockShapeWrapper(blockPos);
|
||||
IBlockShapeWrapper block = chunk.getBlockShapeWrapper(x, y, z);
|
||||
return !block.isToAvoid()
|
||||
&& !(nonFullAvoidance && block.isNonFull())
|
||||
&& !(noCollisionAvoidance && block.hasNoCollision());
|
||||
|
||||
@@ -126,7 +126,7 @@ public class LodGenWorker
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
//try
|
||||
{
|
||||
// only generate LodChunks if they can
|
||||
// be added to the current LodDimension
|
||||
@@ -172,19 +172,19 @@ public class LodGenWorker
|
||||
|
||||
}// if in range
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientApi.LOGGER.error(LodChunkGenThread.class.getSimpleName() + ": ran into an error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
//catch (Exception e)
|
||||
//{
|
||||
// ClientApi.LOGGER.error(LodChunkGenThread.class.getSimpleName() + ": ran into an error: " + e.getMessage());
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
//finally
|
||||
//{
|
||||
// decrement how many threads are running
|
||||
LodWorldGenerator.INSTANCE.numberOfChunksWaitingToGenerate.addAndGet(-1);
|
||||
|
||||
// this position is no longer being generated
|
||||
LodWorldGenerator.INSTANCE.positionsWaitingToBeGenerated.remove(pos);
|
||||
}
|
||||
//}
|
||||
}// run
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class DataMerger
|
||||
{
|
||||
}
|
||||
@@ -40,12 +40,21 @@ public class PositionDataFormat
|
||||
return positionData;
|
||||
}
|
||||
|
||||
public static String toString(short verticalData, short positionData)
|
||||
{
|
||||
return getLodCount(verticalData) + " " +
|
||||
getLightFlag(verticalData) + " " +
|
||||
getGenerationMode(verticalData) + " " +
|
||||
isVoid(verticalData) + " " +
|
||||
doesItExist(verticalData) + " " +'\n';
|
||||
}
|
||||
|
||||
public static byte getLodCount(short dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> LOD_COUNT_SHIFT) & LOD_COUNT_MASK);
|
||||
}
|
||||
|
||||
public static boolean getFlag(short dataPoint)
|
||||
public static boolean getLightFlag(short dataPoint)
|
||||
{
|
||||
return ((dataPoint >>> CORRECT_LIGHT_SHIFT) & CORRECT_LIGHT_MASK) == 1;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ public class VerticalDataFormat
|
||||
{
|
||||
public final static short MIN_WORLD_HEIGHT = -2048;
|
||||
public final static short MAX_WORLD_HEIGHT = 2047;
|
||||
public final static short WORLD_HEIGHT = MAX_WORLD_HEIGHT - MIN_WORLD_HEIGHT;
|
||||
|
||||
public final static byte HEIGHT_SHIFT = 20;
|
||||
public final static byte DEPTH_SHIFT = 8;
|
||||
@@ -25,8 +26,8 @@ public class VerticalDataFormat
|
||||
public static int createVerticalData(int height, int depth, int level, boolean transparent, boolean bottom)
|
||||
{
|
||||
int verticalData = 0;
|
||||
verticalData |= (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
verticalData |= (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
verticalData |= ((height - MIN_WORLD_HEIGHT) & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
verticalData |= ((depth - MIN_WORLD_HEIGHT) & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
verticalData |= (level & LEVEL_MASK) << LEVEL_SHIFT;
|
||||
if (bottom)
|
||||
verticalData |= BOTTOM_TYPE_MASK << BOTTOM_TYPE_SHIFT;
|
||||
@@ -37,14 +38,24 @@ public class VerticalDataFormat
|
||||
return verticalData;
|
||||
}
|
||||
|
||||
public static String toString(int verticalData, short positionData)
|
||||
{
|
||||
return getHeight(verticalData) + " " +
|
||||
getDepth(verticalData) + " " +
|
||||
getLevel(verticalData) + " " +
|
||||
isTransparent(verticalData) + " " +
|
||||
isBottom(verticalData) + " " +
|
||||
doesItExist(verticalData) + " " + '\n';
|
||||
}
|
||||
|
||||
public static short getHeight(int verticalData)
|
||||
{
|
||||
return (short) ((verticalData >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
return (short) (((verticalData >>> HEIGHT_SHIFT) & HEIGHT_MASK) + MIN_WORLD_HEIGHT);
|
||||
}
|
||||
|
||||
public static short getDepth(int verticalData)
|
||||
{
|
||||
return (short) ((verticalData >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
return (short) (((verticalData >>> DEPTH_SHIFT) & DEPTH_MASK) + MIN_WORLD_HEIGHT);
|
||||
}
|
||||
|
||||
public static byte getLevel(int verticalData)
|
||||
|
||||
@@ -200,8 +200,6 @@ public class VertexOptimizer
|
||||
public final Map<LodDirection, byte[]> skyLights;
|
||||
public byte blockLight;
|
||||
|
||||
/** Holds if the given direction should be culled or not */
|
||||
public final boolean[] culling;
|
||||
|
||||
|
||||
/** creates an empty box */
|
||||
@@ -235,8 +233,6 @@ public class VertexOptimizer
|
||||
put(LodDirection.SOUTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.NORTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
}};
|
||||
|
||||
culling = new boolean[6];
|
||||
}
|
||||
|
||||
/** Set the light of the columns */
|
||||
@@ -309,31 +305,6 @@ public class VertexOptimizer
|
||||
}
|
||||
}
|
||||
|
||||
/** determine which faces should be culled */
|
||||
public void setUpCulling(int cullingDistance, AbstractBlockPosWrapper playerPos)
|
||||
{
|
||||
for (LodDirection lodDirection : DIRECTIONS)
|
||||
{
|
||||
if (lodDirection == LodDirection.DOWN || lodDirection == LodDirection.WEST || lodDirection == LodDirection.NORTH)
|
||||
culling[DIRECTION_INDEX.get(lodDirection)] = playerPos.get(lodDirection.getAxis()) > getFacePos(lodDirection) + cullingDistance;
|
||||
|
||||
else if (lodDirection == LodDirection.UP || lodDirection == LodDirection.EAST || lodDirection == LodDirection.SOUTH)
|
||||
culling[DIRECTION_INDEX.get(lodDirection)] = playerPos.get(lodDirection.getAxis()) < getFacePos(lodDirection) - cullingDistance;
|
||||
|
||||
culling[DIRECTION_INDEX.get(lodDirection)] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lodDirection direction that we want to check if it's culled
|
||||
* @return true if and only if the face of the direction is culled
|
||||
*/
|
||||
public boolean isCulled(LodDirection lodDirection)
|
||||
{
|
||||
return culling[DIRECTION_INDEX.get(lodDirection)];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method create all the shared face culling based on the adjacent data
|
||||
* @param adjData data adjacent to the column we are going to render
|
||||
@@ -363,9 +334,6 @@ public class VertexOptimizer
|
||||
//TODO clean some similar cases
|
||||
for (LodDirection lodDirection : ADJ_DIRECTIONS)
|
||||
{
|
||||
if (isCulled(lodDirection))
|
||||
continue;
|
||||
|
||||
long[] dataPoint = adjData.get(lodDirection);
|
||||
if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0]))
|
||||
{
|
||||
@@ -520,17 +488,6 @@ public class VertexOptimizer
|
||||
boxOffset[Z] = zOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method return the position of a face in the axis of the face
|
||||
* This is useful for the face culling
|
||||
* @param lodDirection that we want to check
|
||||
* @return position in the axis of the face
|
||||
*/
|
||||
public int getFacePos(LodDirection lodDirection)
|
||||
{
|
||||
return boxOffset[FACE_DIRECTION.get(lodDirection)[0]] + boxWidth[FACE_DIRECTION.get(lodDirection)[0]] * FACE_DIRECTION.get(lodDirection)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the given direction should be rendered.
|
||||
*/
|
||||
|
||||
@@ -112,4 +112,6 @@ public interface LevelContainer
|
||||
* @return data as a String
|
||||
*/
|
||||
int getMaxNumberOfLods();
|
||||
|
||||
void mergeMultiData(int posX, int posZ, long[] dataToMergeVertical, int inputVerticalData);
|
||||
}
|
||||
|
||||
@@ -909,4 +909,39 @@ public class LodDimension
|
||||
{
|
||||
isRegionDirty[i][j] = val;
|
||||
}
|
||||
|
||||
public void mergeMultiData(byte detailLevel, int posX, int posZ, boolean dontSave, long[] dataToMergeVertical, int inputVerticalData)
|
||||
{
|
||||
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
LodRegion region = getRegion(regionPosX, regionPosZ);
|
||||
if (region == null)
|
||||
return;
|
||||
|
||||
region.mergeMultiData(detailLevel, posX, posZ, dataToMergeVertical, inputVerticalData);
|
||||
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// mark the region as dirty, so it will be saved to disk
|
||||
int xIndex = (regionPosX - center.x) + halfWidth;
|
||||
int zIndex = (regionPosZ - center.z) + halfWidth;
|
||||
|
||||
isRegionDirty[xIndex][zIndex] = true;
|
||||
regenRegionBuffer[xIndex][zIndex] = true;
|
||||
regenDimensionBuffers = true;
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
// If this happens, the method was probably
|
||||
// called when the dimension was changing size.
|
||||
// Hopefully this shouldn't be an issue.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,4 +610,16 @@ public class LodRegion
|
||||
{
|
||||
return getLevel(LodUtil.REGION_DETAIL_LEVEL).toString();
|
||||
}
|
||||
|
||||
public void mergeMultiData(byte detailLevel, int posX, int posZ, long[] dataToMergeVertical, int inputVerticalData)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
// The dataContainer could have null entries if the
|
||||
// detailLevel changes.
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
|
||||
this.dataContainer[detailLevel].mergeMultiData(posX, posZ, dataToMergeVertical, inputVerticalData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.core.objects.lod;
|
||||
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
@@ -35,10 +36,22 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
|
||||
public final byte detailLevel;
|
||||
public final int size;
|
||||
public final int chunkCount = 0;
|
||||
public final int chunkSize = 0;
|
||||
|
||||
public final int maxVerticalData;
|
||||
|
||||
public final long[] dataContainer;
|
||||
|
||||
//length should be chunkCount
|
||||
public final byte[] verticalSize = null;
|
||||
|
||||
//length should be chunkCount
|
||||
public final short[] positionData = null;
|
||||
public final int[][] verticalData = null;
|
||||
public final int[][] colorData = null;
|
||||
public final byte[][] lightData = null;
|
||||
|
||||
public VerticalLevelContainer(byte detailLevel)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
@@ -196,7 +209,6 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
int lowerMaxVertical = dataToMerge.length / 4;
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
long[] data;
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
@@ -207,9 +219,7 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
dataToMerge[(z * 2 + x) * lowerMaxVertical + verticalIndex] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex);
|
||||
}
|
||||
}
|
||||
data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getMaxVerticalData());
|
||||
|
||||
addVerticalData(data, posX, posZ);
|
||||
mergeMultiData(posX, posZ, dataToMerge, lowerMaxVertical);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -244,6 +254,325 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
return tempData;
|
||||
}
|
||||
|
||||
public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
for (int i = 0; i < arraySize - start; i++)
|
||||
{
|
||||
array[start + i] = array[start + length + i];
|
||||
//remove comment to not leave garbage at the end
|
||||
//array[start + packetSize + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void extendArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
for (int i = arraySize - start - 1; i >= 0; i--)
|
||||
{
|
||||
array[start + length + i] = array[start + i];
|
||||
array[start + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param positionDataToMerge
|
||||
* @effect
|
||||
*/
|
||||
public void computePositionData(short[] positionDataToMerge)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param verticalDataToMerge
|
||||
* @param maxVerticalData max vertical size of the merged data
|
||||
* @effect save in
|
||||
*/
|
||||
public void computeHeightAndDepthData(int[] verticalDataToMerge, int maxVerticalData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param colorDataToMerge
|
||||
* @param lightDataToMerge
|
||||
* @effect
|
||||
*/
|
||||
public void computeColorLightVerticalData(int[] colorDataToMerge, byte[] lightDataToMerge, int[] verticalDataToMerge)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method merge column of multiple data together
|
||||
* @param dataToMerge one or more columns of data
|
||||
* @param inputVerticalData vertical size of an input data
|
||||
*/
|
||||
public void mergeMultiData(int posX, int posZ, long[] dataToMerge, int inputVerticalData)
|
||||
{
|
||||
int size = dataToMerge.length / inputVerticalData;
|
||||
final int arrayPos = (posX * this.size + posZ) * maxVerticalData;
|
||||
// We initialize the arrays that are going to be used
|
||||
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((DataPointUtil.WORLD_HEIGHT / 2 + 1) * 2);
|
||||
|
||||
|
||||
int genMode = DistanceGenerationMode.FULL.complexity;
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
boolean allDefault;
|
||||
long singleData;
|
||||
|
||||
|
||||
short depth;
|
||||
short height;
|
||||
int count = 0;
|
||||
int i;
|
||||
int ii;
|
||||
int dataIndex;
|
||||
//We collect the indexes of the data, ordered by the depth
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndex];
|
||||
if (DataPointUtil.doesItExist(singleData))
|
||||
{
|
||||
genMode = Math.min(genMode, DataPointUtil.getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!DataPointUtil.isVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
depth = DataPointUtil.getDepth(singleData);
|
||||
height = DataPointUtil.getHeight(singleData);
|
||||
|
||||
int botPos = -1;
|
||||
int topPos = -1;
|
||||
//values fall in between and possibly require extension of array
|
||||
boolean botExtend = false;
|
||||
boolean topExtend = false;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (depth <= heightAndDepth[i * 2] && depth >= heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
botPos = i;
|
||||
break;
|
||||
}
|
||||
else if (depth < heightAndDepth[i * 2 + 1] && ((i + 1 < count && depth > heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
botPos = i;
|
||||
botExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (height <= heightAndDepth[i * 2] && height >= heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
topPos = i;
|
||||
break;
|
||||
}
|
||||
else if (height < heightAndDepth[i * 2 + 1] && ((i + 1 < count && height > heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
topPos = i;
|
||||
topExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topPos == -1)
|
||||
{
|
||||
if (botPos == -1)
|
||||
{
|
||||
//whole block falls above
|
||||
extendArray(heightAndDepth, 2, 0, 1, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count++;
|
||||
}
|
||||
else if (!botExtend)
|
||||
{
|
||||
//only top falls above extending it there, while bottom is inside existing
|
||||
shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
count -= botPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//top falls between some blocks, extending those as well
|
||||
shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count -= botPos;
|
||||
}
|
||||
}
|
||||
else if (!topExtend)
|
||||
{
|
||||
if (!botExtend)
|
||||
//both top and bottom are within some exiting blocks, possibly merging them
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
else
|
||||
//top falls between some blocks, extending it there
|
||||
heightAndDepth[topPos * 2 + 1] = depth;
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!botExtend)
|
||||
{
|
||||
//only top is within some exiting block, extending it
|
||||
topPos++; //to make it easier
|
||||
heightAndDepth[topPos * 2] = height;
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//both top and bottom are outside existing blocks
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
extendArray(heightAndDepth, 2, topPos + 1, 1, count);
|
||||
count++;
|
||||
heightAndDepth[topPos * 2 + 2] = height;
|
||||
heightAndDepth[topPos * 2 + 3] = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//We check if there is any data that's not empty or void
|
||||
if (allEmpty)
|
||||
return;
|
||||
if (allVoid)
|
||||
{
|
||||
dataContainer[arrayPos] = DataPointUtil.createVoidDataPoint(genMode);
|
||||
return;
|
||||
}
|
||||
|
||||
//we limit the vertical portion to maxVerticalData
|
||||
int j = 0;
|
||||
while (count > maxVerticalData)
|
||||
{
|
||||
ii = DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET;
|
||||
for (i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii)
|
||||
{
|
||||
ii = heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2];
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1];
|
||||
for (i = j + 1; i < count - 1; i++)
|
||||
{
|
||||
heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2];
|
||||
heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1];
|
||||
}
|
||||
//System.arraycopy(heightAndDepth, j + 1, heightAndDepth, j, count - j - 1);
|
||||
count--;
|
||||
}
|
||||
//As standard the vertical lods are ordered from top to bottom
|
||||
for (j = count - 1; j >= 0; j--)
|
||||
{
|
||||
if (j >= heightAndDepth.length / 2)
|
||||
break;
|
||||
|
||||
height = heightAndDepth[j * 2];
|
||||
depth = heightAndDepth[j * 2 + 1];
|
||||
|
||||
if ((depth == 0 && height == 0))
|
||||
break;
|
||||
|
||||
int numberOfChildren = 0;
|
||||
int tempAlpha = 0;
|
||||
int tempRed = 0;
|
||||
int tempGreen = 0;
|
||||
int tempBlue = 0;
|
||||
int tempLightBlock = 0;
|
||||
int tempLightSky = 0;
|
||||
byte tempGenMode = DistanceGenerationMode.FULL.complexity;
|
||||
allEmpty = true;
|
||||
allVoid = true;
|
||||
allDefault = true;
|
||||
long data = 0;
|
||||
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndex];
|
||||
if (DataPointUtil.doesItExist(singleData) && !DataPointUtil.isVoid(singleData))
|
||||
{
|
||||
|
||||
if ((depth <= DataPointUtil.getDepth(singleData) && DataPointUtil.getDepth(singleData) <= height)
|
||||
|| (depth <= DataPointUtil.getHeight(singleData) && DataPointUtil.getHeight(singleData) <= height))
|
||||
{
|
||||
if (DataPointUtil.getHeight(singleData) > DataPointUtil.getHeight(data))
|
||||
data = singleData;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!DataPointUtil.doesItExist(data))
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData];
|
||||
data = DataPointUtil.createVoidDataPoint(DataPointUtil.getGenerationMode(singleData));
|
||||
}
|
||||
|
||||
if (DataPointUtil.doesItExist(data))
|
||||
{
|
||||
allEmpty = false;
|
||||
if (!DataPointUtil.isVoid(data))
|
||||
{
|
||||
numberOfChildren++;
|
||||
allVoid = false;
|
||||
tempAlpha += DataPointUtil.getAlpha(data);
|
||||
tempRed += DataPointUtil.getRed(data);
|
||||
tempGreen += DataPointUtil.getGreen(data);
|
||||
tempBlue += DataPointUtil.getBlue(data);
|
||||
tempLightBlock += DataPointUtil.getLightBlock(data);
|
||||
tempLightSky += DataPointUtil.getLightSky(data);
|
||||
if (!DataPointUtil.getFlag(data)) allDefault = false;
|
||||
}
|
||||
tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data));
|
||||
}
|
||||
else
|
||||
tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity);
|
||||
}
|
||||
|
||||
if (allEmpty)
|
||||
//no child has been initialized
|
||||
dataContainer[arrayPos + j] = DataPointUtil.EMPTY_DATA;
|
||||
else if (allVoid)
|
||||
//all the children are void
|
||||
dataContainer[arrayPos + j] = DataPointUtil.createVoidDataPoint(tempGenMode);
|
||||
else
|
||||
{
|
||||
//we have at least 1 child
|
||||
tempAlpha = tempAlpha / numberOfChildren;
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
dataContainer[arrayPos + j] = DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
public String toString()
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.seibel.lod.core.render;
|
||||
import java.awt.Color;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
@@ -49,8 +50,6 @@ import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
@@ -94,7 +93,8 @@ public class LodRenderer
|
||||
@SuppressWarnings("unused")
|
||||
private int[][][] storageBufferIds;
|
||||
|
||||
private AbstractChunkPosWrapper vbosCenter = FACTORY.createChunkPos();
|
||||
private int vbosCenterX = 0;
|
||||
private int vbosCenterZ = 0;
|
||||
|
||||
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
@@ -193,7 +193,7 @@ public class LodRenderer
|
||||
if ((partialRegen || fullRegen) && !lodBufferBuilderFactory.generatingBuffers && !lodBufferBuilderFactory.newBuffersAvailable())
|
||||
{
|
||||
// generate the LODs on a separate thread to prevent stuttering or freezing
|
||||
lodBufferBuilderFactory.generateLodBuffersAsync(this, lodDim, MC.getPlayerBlockPos(), true);
|
||||
lodBufferBuilderFactory.generateLodBuffersAsync(this, lodDim, MC.getPlayerBlockPos().getX(), MC.getPlayerBlockPos().getY(), MC.getPlayerBlockPos().getZ(), true);
|
||||
|
||||
// the regen process has been started,
|
||||
// it will be done when lodBufferBuilder.newBuffersAvailable()
|
||||
@@ -376,8 +376,10 @@ public class LodRenderer
|
||||
boolean renderBufferStorage = CONFIG.client().advanced().buffers().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
|
||||
|
||||
// where the center of the buffers is (needed when culling regions)
|
||||
RegionPos vboCenterRegionPos = new RegionPos(vbosCenter);
|
||||
RegionPos vboPos = new RegionPos();
|
||||
int vboCenterRegionPosX = vbosCenterX;
|
||||
int vboCenterRegionPosZ = vbosCenterZ;
|
||||
int vboPosX;
|
||||
int vboPosZ;
|
||||
|
||||
|
||||
// render each of the buffers
|
||||
@@ -385,10 +387,13 @@ public class LodRenderer
|
||||
{
|
||||
for (int z = 0; z < vbos.length; z++)
|
||||
{
|
||||
vboPos.x = x + vboCenterRegionPos.x - (lodDim.getWidth() / 2);
|
||||
vboPos.z = z + vboCenterRegionPos.z - (lodDim.getWidth() / 2);
|
||||
vboPosX = x + vboCenterRegionPosX - (lodDim.getWidth() / 2);
|
||||
vboPosZ = z + vboCenterRegionPosZ - (lodDim.getWidth() / 2);
|
||||
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(), MC_RENDER.getLookAtVector(), vboPos.blockPos()))
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(),
|
||||
MC_RENDER.getLookAtVector(),
|
||||
LodUtil.convertLevelPos(LodUtil.REGION_DETAIL_LEVEL, vboPosX, LodUtil.BLOCK_DETAIL_LEVEL),
|
||||
LodUtil.convertLevelPos(LodUtil.REGION_DETAIL_LEVEL, vboPosZ, LodUtil.BLOCK_DETAIL_LEVEL)))
|
||||
{
|
||||
// fog may be different from region to region
|
||||
applyFog(shaderProgram,
|
||||
@@ -531,12 +536,12 @@ public class LodRenderer
|
||||
// far fog //
|
||||
|
||||
if (CONFIG.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
|
||||
fogConfig.farFogStart = farPlaneBlockDistance * 1.6f * 0.9f;
|
||||
fogConfig.farFogStart = farPlaneBlockDistance * 0.9f;
|
||||
else
|
||||
// for more realistic fog when using FAR
|
||||
fogConfig.farFogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f * 1.6f);
|
||||
fogConfig.farFogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f);
|
||||
|
||||
fogConfig.farFogEnd = farPlaneBlockDistance * 1.6f;
|
||||
fogConfig.farFogEnd = farPlaneBlockDistance;
|
||||
|
||||
|
||||
// near fog //
|
||||
@@ -579,9 +584,10 @@ public class LodRenderer
|
||||
// translate the camera relative to the regions' center
|
||||
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
// accuracy vs the model view matrix, which only uses floats)
|
||||
AbstractBlockPosWrapper bufferPos = vbosCenter.getWorldPosition();
|
||||
double xDiff = projectedView.x - bufferPos.getX();
|
||||
double zDiff = projectedView.z - bufferPos.getZ();
|
||||
int bufferPosX = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, vbosCenterX, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
int bufferPosZ = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, vbosCenterZ, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
double xDiff = projectedView.x - bufferPosX;
|
||||
double zDiff = projectedView.z - bufferPosZ;
|
||||
mcModelViewMatrix.multiplyTranslationMatrix(-xDiff, -projectedView.y, -zDiff);
|
||||
|
||||
return mcModelViewMatrix;
|
||||
@@ -593,9 +599,10 @@ public class LodRenderer
|
||||
*/
|
||||
private Vec3f getTranslatedCameraPos()
|
||||
{
|
||||
AbstractBlockPosWrapper worldCenter = vbosCenter.getWorldPosition();
|
||||
int worldCenterX = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, vbosCenterX, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
int worldCenterZ = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, vbosCenterZ, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
return new Vec3f((float)cameraPos.x - worldCenter.getX(), (float)cameraPos.y, (float)cameraPos.z - worldCenter.getZ());
|
||||
return new Vec3f((float)cameraPos.x - worldCenterX, (float)cameraPos.y, (float)cameraPos.z - worldCenterZ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +678,8 @@ public class LodRenderer
|
||||
VertexBuffersAndOffset result = lodBufferBuilderFactory.getVertexBuffers();
|
||||
vbos = result.vbos;
|
||||
storageBufferIds = result.storageBufferIds;
|
||||
vbosCenter = result.drawableCenterChunkPos;
|
||||
vbosCenterX = result.drawableCenterChunkPosX;
|
||||
vbosCenterZ = result.drawableCenterChunkPosZ;
|
||||
}
|
||||
|
||||
/** Calls the BufferBuilder's destroyBuffers method. */
|
||||
|
||||
@@ -85,11 +85,11 @@ public class RenderUtil
|
||||
* Returns true if one of the region's 4 corners is in front
|
||||
* of the camera.
|
||||
*/
|
||||
public static boolean isRegionInViewFrustum(AbstractBlockPosWrapper playerBlockPos, Vec3f cameraDir, AbstractBlockPosWrapper vboCenterPos)
|
||||
public static boolean isRegionInViewFrustum(AbstractBlockPosWrapper playerBlockPos, Vec3f cameraDir, int vboCenterPosX, int vboCenterPosZ)
|
||||
{
|
||||
// convert the vbo position into a direction vector
|
||||
// starting from the player's position
|
||||
Vec3f vboVec = new Vec3f(vboCenterPos.getX(), 0, vboCenterPos.getZ());
|
||||
Vec3f vboVec = new Vec3f(vboCenterPosX, 0, vboCenterPosZ);
|
||||
Vec3f playerVec = new Vec3f(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
|
||||
|
||||
vboVec.subtract(playerVec);
|
||||
|
||||
@@ -263,6 +263,7 @@ public class DataPointUtil
|
||||
* @param maxVerticalData max vertical size of the merged data
|
||||
* @return one column of correctly parsed data
|
||||
*/
|
||||
@Deprecated
|
||||
public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData)
|
||||
{
|
||||
int size = dataToMerge.length / inputVerticalData;
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockShapeWrapper;
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
@@ -32,21 +34,27 @@ public interface IChunkWrapper
|
||||
{
|
||||
int getHeight();
|
||||
|
||||
boolean isPositionInWater(AbstractBlockPosWrapper blockPos);
|
||||
boolean isPositionInWater(int x, int y, int z);
|
||||
|
||||
int getHeightMapValue(int xRel, int zRel);
|
||||
|
||||
IBiomeWrapper getBiome(int xRel, int yAbs, int zRel);
|
||||
IBiomeWrapper getBiome(int x, int y, int z);
|
||||
IBlockColorWrapper getBlockColorWrapper(int x, int y, int z);
|
||||
IBlockShapeWrapper getBlockShapeWrapper(int x, int y, int z);
|
||||
|
||||
IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
AbstractChunkPosWrapper getPos();
|
||||
int getChunkPosX();
|
||||
int getChunkPosZ();
|
||||
int getRegionPosX();
|
||||
int getRegionPosZ();
|
||||
int getMaxY(int x, int z);
|
||||
int getMaxX();
|
||||
int getMaxZ();
|
||||
int getMinX();
|
||||
int getMinZ();
|
||||
|
||||
boolean isLightCorrect();
|
||||
|
||||
boolean isWaterLogged(AbstractBlockPosWrapper blockPos);
|
||||
boolean isWaterLogged(int x, int y, int z);
|
||||
|
||||
int getEmittedBrightness(AbstractBlockPosWrapper blockPos);
|
||||
int getEmittedBrightness(int x, int y, int z);
|
||||
}
|
||||
|
||||
+1
-12
@@ -184,17 +184,6 @@ public interface ILodConfigWrapperSingleton
|
||||
{
|
||||
String DESC = "Graphics options that are a bit more technical.";
|
||||
|
||||
LodTemplate LOD_TEMPLATE_DEFAULT = LodTemplate.CUBIC;
|
||||
String LOD_TEMPLATE_DESC = ""
|
||||
+ " How should the LODs be drawn? \n"
|
||||
+ " NOTE: Currently only " + LodTemplate.CUBIC + " is implemented! \n"
|
||||
+ " \n"
|
||||
+ " " + LodTemplate.CUBIC + ": LOD Chunks are drawn as rectangular prisms (boxes). \n"
|
||||
+ " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n"
|
||||
+ " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between each other, \n"
|
||||
+ " " + " unless a neighboring chunk is at a significantly different height. \n";
|
||||
LodTemplate getLodTemplate();
|
||||
void setLodTemplate(LodTemplate newLodTemplate);
|
||||
|
||||
boolean DISABLE_DIRECTIONAL_CULLING_DEFAULT = false;
|
||||
String DISABLE_DIRECTIONAL_CULLING_DESC = ""
|
||||
@@ -451,7 +440,7 @@ public interface ILodConfigWrapperSingleton
|
||||
|
||||
boolean DEBUG_KEYBINDINGS_ENABLED_DEFAULT = true;
|
||||
String DEBUG_KEYBINDINGS_ENABLED_DESC = ""
|
||||
+ " If true the F4 key can be used to cycle through the different debug modes. \n"
|
||||
+ " If true the F8 key can be used to cycle through the different debug modes. \n"
|
||||
+ " and the F6 key can be used to enable and disable LOD rendering.";
|
||||
boolean getDebugKeybindingsEnabled();
|
||||
void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings);
|
||||
|
||||
@@ -36,11 +36,9 @@ public interface IWorldWrapper
|
||||
|
||||
WorldType getWorldType();
|
||||
|
||||
int getBlockLight(AbstractBlockPosWrapper blockPos);
|
||||
int getBlockLight(int x, int y, int z);
|
||||
|
||||
int getSkyLight(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
IBiomeWrapper getBiome(AbstractBlockPosWrapper blockPos);
|
||||
int getSkyLight(int x, int y, int z);
|
||||
|
||||
boolean hasCeiling();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user