added a borderChunk finder function

This commit is contained in:
Leonardo
2021-09-30 01:38:39 +02:00
parent 555e5a78b5
commit 37db05d18f
3 changed files with 279 additions and 228 deletions
@@ -295,10 +295,12 @@ public class LodBufferBuilder
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.x;
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.z;
boolean isItBorderPos = LodUtil.isBorderChunk(vanillaRenderedChunks,chunkXdist + gameChunkRenderDistance + 1,chunkZdist + gameChunkRenderDistance + 1);
if (gameChunkRenderDistance >= Math.abs(chunkXdist)
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& !isItBorderPos)
{
continue;
}
@@ -316,7 +318,8 @@ public class LodBufferBuilder
&& posToRender.contains(detailLevel, xAdj, zAdj)
&& (gameChunkRenderDistance < Math.abs(chunkXdist)
|| gameChunkRenderDistance < Math.abs(chunkZdist)
|| !vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]))
|| !(vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& !LodUtil.isBorderChunk(vanillaRenderedChunks,chunkXdist + gameChunkRenderDistance + 1,chunkZdist + gameChunkRenderDistance + 1))))
{
if (!adjData.containsKey(direction) || adjData.get(direction) == null)
adjData.put(direction, new long[maxVerticalData]);
@@ -442,7 +445,7 @@ public class LodBufferBuilder
drawableVbos[x][z] = new VertexBuffer[1];
} else
{
numberOfBuffers = (int) Math.ceil(memoryRequired / BUFFER_MAX_CAPACITY)+1;
numberOfBuffers = (int) Math.ceil(memoryRequired / BUFFER_MAX_CAPACITY) + 1;
System.out.println(numberOfBuffers);
memoryRequired = BUFFER_MAX_CAPACITY;
bufferSize[x][z] = numberOfBuffers;
@@ -19,6 +19,8 @@ package com.seibel.lod.render;
import java.util.HashSet;
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
import net.minecraft.util.Direction;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL15C;
@@ -58,6 +60,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import org.lwjgl.system.CallbackI;
/**
@@ -74,7 +77,7 @@ public class LodRenderer
* it should be something different than what is used by Minecraft
*/
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
/**
* If true the LODs colors will be replaced with
* a checkerboard, this can be used for debugging.
@@ -97,15 +100,16 @@ public class LodRenderer
*/
private VertexBuffer[][][] vbos;
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
private ChunkPos vbosCenter = new ChunkPos(0,0);
private ChunkPos vbosCenter = new ChunkPos(0, 0);
/**
* This is used to determine if the LODs should be regenerated
*/
private int[] previousPos = new int[]{0,0,0};
private int[] previousPos = new int[]{0, 0, 0};
public NativeImage lightMap = null;
// these variables are used to determine if the buffers should be rebuilt
private long prevDayTime = 0;
private double prevBrightness = 0;
@@ -148,9 +152,9 @@ public class LodRenderer
* Besides drawing the LODs this method also starts
* the async process of generating the Buffers that hold those LODs.
*
* @param lodDim The dimension to draw, if null doesn't replace the current dimension.
* @param lodDim The dimension to draw, if null doesn't replace the current dimension.
* @param mcMatrixStack This matrix stack should come straight from MC's renderChunkLayer (or future equivalent) method
* @param partialTicks how far into the current tick this method was called.
* @param partialTicks how far into the current tick this method was called.
*/
public void drawLODs(LodDimension lodDim, MatrixStack mcMatrixStack, float partialTicks, IProfiler newProfiler)
{
@@ -168,8 +172,8 @@ public class LodRenderer
profiler = newProfiler;
profiler.push("LOD setup");
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
// starting here...
determineIfLodsShouldRegenerate(lodDim);
@@ -197,12 +201,11 @@ public class LodRenderer
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
// ...ending here
if (lodBufferBuilder.newBuffersAvaliable())
{
swapBuffers();
}
//===========================//
@@ -210,7 +213,7 @@ public class LodRenderer
//===========================//
// set the required open GL settings
if (LodConfig.CLIENT.debugging.debugMode.get() == DebugMode.SHOW_DETAIL_WIREFRAME)
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
else
@@ -233,7 +236,7 @@ public class LodRenderer
// OpenGl outputs their matricies in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Matrix4f modelViewMatrix = offsetTheModelViewMatrix(mcMatrixStack, partialTicks);
// required for setupFog and setupProjectionMatrix
@@ -256,16 +259,16 @@ public class LodRenderer
//===========//
// rendering //
//===========//
profiler.popPush("LOD draw");
if (vbos != null)
{
ActiveRenderInfo renderInfo = mc.getGameRenderer().getMainCamera();
Vector3d cameraDir = new Vector3d(renderInfo.getLookVector());
boolean cullingDisabled = LodConfig.CLIENT.graphics.disableDirectionalCulling.get();
// used to determine what type of fog to render
int halfWidth = vbos.length / 2;
int quarterWidth = vbos.length / 4;
@@ -283,7 +286,7 @@ public class LodRenderer
setupFog(fogSettings.far.distance, fogSettings.far.quality);
for(int i = 0; i < lodBufferBuilder.bufferSize[x][z]; i++)
for (int i = 0; i < lodBufferBuilder.bufferSize[x][z]; i++)
{
sendLodsToGpuAndDraw(vbos[x][z][i], modelViewMatrix);
}
@@ -291,7 +294,7 @@ public class LodRenderer
}
}
}
//=========//
// cleanup //
@@ -314,11 +317,11 @@ public class LodRenderer
// reset the projection matrix so anything drawn after
// the LODs will use the correct projection matrix
gameRender.resetProjectionMatrix(mcProjectionMatrix);
// clear the depth buffer so anything drawn is drawn
// over the LODs
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
// end of internal LOD profiling
profiler.pop();
@@ -332,13 +335,13 @@ public class LodRenderer
{
if (vbo == null)
return;
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
// 0L is the starting pointer
LOD_VERTEX_FORMAT.setupBufferState(0L);
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
LOD_VERTEX_FORMAT.clearBufferState();
}
@@ -369,8 +372,7 @@ public class LodRenderer
{
// fancy fog (fragment distance based fog)
glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
}
else
} else
{
// fast fog (frustum distance based fog)
glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV;
@@ -388,16 +390,16 @@ public class LodRenderer
if (fogQuality == FogQuality.FANCY)
{
// for more realistic fog when using FAR
if(LodConfig.CLIENT.graphics.fogDistance.get() == FogDistance.NEAR_AND_FAR)
if (LodConfig.CLIENT.graphics.fogDistance.get() == FogDistance.NEAR_AND_FAR)
{
RenderSystem.fogStart(farPlaneBlockDistance * 0.9f);
RenderSystem.fogEnd(farPlaneBlockDistance * 1.0f);
}else{
} else
{
RenderSystem.fogStart(farPlaneBlockDistance * 0.1f);
RenderSystem.fogEnd(farPlaneBlockDistance * 1.0f);
}
}
else if (fogQuality == FogQuality.FAST)
} else if (fogQuality == FogQuality.FAST)
{
// for the far fog of the normal chunks
// to start right where the LODs' end use:
@@ -405,15 +407,13 @@ public class LodRenderer
RenderSystem.fogStart(farPlaneBlockDistance * 1.5f);
RenderSystem.fogEnd(farPlaneBlockDistance * 2.0f);
}
}
else if (fogDistance == FogDistance.NEAR)
} else if (fogDistance == FogDistance.NEAR)
{
if (fogQuality == FogQuality.FANCY)
{
RenderSystem.fogEnd(mc.getRenderDistance() * 16 * 1.41f);
RenderSystem.fogStart(mc.getRenderDistance() * 16 * 1.6f);
}
else if (fogQuality == FogQuality.FAST)
} else if (fogQuality == FogQuality.FAST)
{
RenderSystem.fogEnd(mc.getRenderDistance() * 16 * 1.0f);
RenderSystem.fogStart(mc.getRenderDistance() * 16 * 1.5f);
@@ -461,12 +461,12 @@ public class LodRenderer
{
// duplicate the last matrix
mcMatrixStack.pushPose();
// get all relevant camera info
ActiveRenderInfo renderInfo = mc.getGameRenderer().getMainCamera();
Vector3d projectedView = renderInfo.getPosition();
// 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)
@@ -475,73 +475,75 @@ public class LodRenderer
double xDiff = eyePos.x - bufferPos.getX();
double zDiff = eyePos.z - bufferPos.getZ();
mcMatrixStack.translate(-xDiff, -projectedView.y, -zDiff);
// get the modified model view matrix
Matrix4f lodModelViewMatrix = mcMatrixStack.last().pose();
Matrix4f lodModelViewMatrix = mcMatrixStack.last().pose();
// remove the lod ModelViewMatrix
mcMatrixStack.popPose();
return lodModelViewMatrix;
}
/** James added this to test if Vivecraft is not using
* the MC FOV setting or if the problem is deeper */
/**
* James added this to test if Vivecraft is not using
* the MC FOV setting or if the problem is deeper
*/
public enum FovTest
{
LOD_USE_FOV(true, false),
MC_USE_FOV(false, true),
NEITHER(false, false),
BOTH(true, true);
boolean lodProjUseFov;
boolean defaultMcProjUseFov;
private FovTest(boolean newLodProjUseFov, boolean newDefaultMcProjUseFov)
{
lodProjUseFov = newLodProjUseFov;
defaultMcProjUseFov = newDefaultMcProjUseFov;
}
}
/**
* create a new projection matrix and send it over to the GPU
*
*
* @param currentProjectionMatrix this is Minecraft's current projection matrix
* @param partialTicks how many ticks into the frame we are
* @param partialTicks how many ticks into the frame we are
*/
private void setupProjectionMatrix(Matrix4f currentProjectionMatrix, float partialTicks)
{
// create the new projection matrix
Matrix4f lodPoj =
Matrix4f.perspective(
getFov(partialTicks, LodConfig.CLIENT.graphics.useFovSetting.get().lodProjUseFov),
(float) this.mc.getWindow().getScreenWidth() / (float) this.mc.getWindow().getScreenHeight(),
mc.getRenderDistance()/2,
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2 / 4);
Matrix4f.perspective(
getFov(partialTicks, LodConfig.CLIENT.graphics.useFovSetting.get().lodProjUseFov),
(float) this.mc.getWindow().getScreenWidth() / (float) this.mc.getWindow().getScreenHeight(),
mc.getRenderDistance() / 2,
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2 / 4);
// get Minecraft's un-edited projection matrix
// (this is before it is zoomed, distorted, etc.)
Matrix4f defaultMcProj = mc.getGameRenderer().getProjectionMatrix(mc.getGameRenderer().getMainCamera(), partialTicks, LodConfig.CLIENT.graphics.useFovSetting.get().defaultMcProjUseFov);
// true here means use "use fov setting" (probably)
// this logic strips away the defaultMcProj matrix so we
// can get the distortionMatrix, which represents all
// transformations, zooming, distortions, etc. done
// to Minecraft's Projection matrix
Matrix4f defaultMcProjInv = defaultMcProj.copy();
defaultMcProjInv.invert();
Matrix4f distortionMatrix = defaultMcProjInv.copy();
distortionMatrix.multiply(currentProjectionMatrix);
// edit the lod projection to match Minecraft's
// (so the LODs line up with the real world)
lodPoj.multiply(distortionMatrix);
// send the projection over to the GPU
gameRender.resetProjectionMatrix(lodPoj);
}
@@ -616,7 +618,7 @@ public class LodRenderer
/**
* Replace the current Vertex Buffers with the newly
* created buffers from the lodBufferBuilder. <br><br>
*
* <p>
* For some reason this has to be called after the frame has been rendered,
* otherwise visual stuttering/rubber banding may happen. I'm not sure why...
*/
@@ -758,27 +760,27 @@ public class LodRenderer
*/
private void determineIfLodsShouldRegenerate(LodDimension lodDim)
{
short chunkRenderDistance = (short) mc.getRenderDistance();
int vanillaRenderedChunksWidth = chunkRenderDistance*2+2;
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
int vanillaRenderedChunksWidth = chunkRenderDistance * 2 + 2;
//=============//
// full regens //
//=============//
// check if the view distance changed
if (ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.graphics.lodChunkRenderDistance.get()
|| mc.getRenderDistance() != prevRenderDistance
|| chunkRenderDistance != prevRenderDistance
|| prevFogDistance != LodConfig.CLIENT.graphics.fogDistance.get())
{
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
DetailDistanceUtil.updateSettings();
fullRegen = true;
previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk);
prevFogDistance = LodConfig.CLIENT.graphics.fogDistance.get();
prevRenderDistance = mc.getRenderDistance();
prevRenderDistance = chunkRenderDistance;
}
// did the user change the debug setting?
@@ -791,7 +793,7 @@ public class LodRenderer
long newTime = System.currentTimeMillis();
if(LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.FANCY)
if (LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.FANCY)
{
// check if the player has moved
if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get())
@@ -800,6 +802,7 @@ public class LodRenderer
|| mc.getPlayer().xChunk != LevelPosUtil.getPosX(previousPos)
|| mc.getPlayer().zChunk != LevelPosUtil.getPosZ(previousPos))
{
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
fullRegen = true;
previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk);
}
@@ -808,7 +811,6 @@ public class LodRenderer
}
//================//
// partial regens //
//================//
@@ -848,8 +850,6 @@ public class LodRenderer
}
//==============//
// LOD skipping //
//==============//
@@ -862,11 +862,11 @@ public class LodRenderer
{
xIndex = (pos.x - mc.getPlayer().xChunk) + (chunkRenderDistance + 1);
zIndex = (pos.z - mc.getPlayer().zChunk) + (chunkRenderDistance + 1);
// sometimes we are given chunks that are outside the render distance,
// This prevents index out of bounds exceptions
if (xIndex >= 0 && zIndex >= 0
&& xIndex < vanillaRenderedChunks.length
&& xIndex < vanillaRenderedChunks.length
&& zIndex < vanillaRenderedChunks.length)
{
if (!vanillaRenderedChunks[xIndex][zIndex])
@@ -877,8 +877,8 @@ public class LodRenderer
}
}
}
// if the player is high enough, draw all LODs
if(chunkPosToSkip.isEmpty() && mc.getPlayer().position().y > 256)
{
+195 -147
View File
@@ -21,6 +21,7 @@ import java.awt.Color;
import java.io.File;
import java.util.HashSet;
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.RegionPos;
@@ -30,6 +31,7 @@ import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.DimensionType;
@@ -42,26 +44,32 @@ import net.minecraft.world.server.ServerWorld;
/**
* This class holds methods and constants that may be used in multiple places.
*
*
* @author James Seibel
* @version 9-7-2021
*/
public class LodUtil
{
private static MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
/** alpha used when drawing chunks in debug mode */
/**
* alpha used when drawing chunks in debug mode
*/
public static final int DEBUG_ALPHA = 255; // 0 - 255
public static final Color COLOR_DEBUG_BLACK = new Color(0, 0, 0, DEBUG_ALPHA);
public static final Color COLOR_DEBUG_WHITE = new Color(255, 255, 255, DEBUG_ALPHA);
public static final Color COLOR_INVISIBLE = new Color(0,0,0,0);
/** a gray-purple color */
public static final Color COLOR_INVISIBLE = new Color(0, 0, 0, 0);
/**
* a gray-purple color
*/
public static final int MYCELIUM_COLOR_INT = LodUtil.colorToInt(Color.decode("#6E6166"));
/** TODO, add a better way to override material colors
/**
* TODO, add a better way to override material colors
* and/or add a method to generate colors based on texture
* issue #64 */
* issue #64
*/
public static final int STONE_COLOR_INT = LodUtil.colorToInt(new Color(150, 150, 150));
public static final int NETHERRACK_COLOR_INT = LodUtil.colorToInt(new Color(95, 38, 38));
public static final int WARPED_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(34, 94, 85));
@@ -71,14 +79,20 @@ public class LodUtil
* In order of nearest to farthest: <br>
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black
*/
public static final Color DEBUG_DETAIL_LEVEL_COLORS[] = new Color[] { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE, Color.MAGENTA, Color.WHITE, Color.GRAY, Color.BLACK };
/** 512 blocks wide */
public static final Color DEBUG_DETAIL_LEVEL_COLORS[] = new Color[]{Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE, Color.MAGENTA, Color.WHITE, Color.GRAY, Color.BLACK};
/**
* 512 blocks wide
*/
public static final byte REGION_DETAIL_LEVEL = 9;
/** 16 blocks wide */
/**
* 16 blocks wide
*/
public static final byte CHUNK_DETAIL_LEVEL = 4;
/** 1 block wide */
/**
* 1 block wide
*/
public static final byte BLOCK_DETAIL_LEVEL = 0;
@@ -86,28 +100,40 @@ public class LodUtil
public static final short MAX_VERTICAL_DATA = 4;
/** measured in Blocks <br>
* detail level 9 */
/**
* measured in Blocks <br>
* detail level 9
*/
public static final short REGION_WIDTH = 512;
/** measured in Blocks <br>
* detail level 4 */
/**
* measured in Blocks <br>
* detail level 4
*/
public static final short CHUNK_WIDTH = 16;
/** measured in Blocks <br>
* detail level 0 */
/**
* measured in Blocks <br>
* detail level 0
*/
public static final short BLOCK_WIDTH = 1;
/** number of chunks wide */
/**
* number of chunks wide
*/
public static final int REGION_WIDTH_IN_CHUNKS = 32;
/** If we ever need to use a heightmap for any reason, use this one. */
/**
* If we ever need to use a heightmap for any reason, use this one.
*/
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
/** This regex finds any characters that are invalid for use in a windows
* (and by extension mac and linux) file path */
/**
* This regex finds any characters that are invalid for use in a windows
* (and by extension mac and linux) file path
*/
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\\\/:*?\\\"<>|]";
/**
* 64 MB by default is the maximum amount of memory that
* can be directly allocated. <br><br>
@@ -120,33 +146,29 @@ public class LodUtil
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
*/
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
/**
* Gets the first valid ServerWorld.
*
*
* @return null if there are no ServerWorlds
*/
public static ServerWorld getFirstValidServerWorld()
{
if (mc.hasSingleplayerServer())
return null;
Iterable<ServerWorld> worlds = mc.getSingleplayerServer().getAllLevels();
for (ServerWorld world : worlds)
return world;
return null;
}
/**
* Gets the ServerWorld for the relevant dimension.
*
*
* @return null if there is no ServerWorld for the given dimension
*/
public static ServerWorld getServerWorldFromDimension(DimensionType dimension)
@@ -154,42 +176,43 @@ public class LodUtil
IntegratedServer server = mc.getSingleplayerServer();
if (server == null)
return null;
Iterable<ServerWorld> worlds = server.getAllLevels();
ServerWorld returnWorld = null;
for (ServerWorld world : worlds)
{
if(world.dimensionType() == dimension)
if (world.dimensionType() == dimension)
{
returnWorld = world;
break;
}
}
return returnWorld;
}
/**
* Convert a 2D absolute position into a quad tree relative position.
* Convert a 2D absolute position into a quad tree relative position.
*/
public static RegionPos convertGenericPosToRegionPos(int x, int z, int detailLevel)
{
int relativePosX = Math.floorDiv(x, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel));
int relativePosZ = Math.floorDiv(z, (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel));
return new RegionPos(relativePosX, relativePosZ);
}
/**
* Convert a 2D absolute position into a quad tree relative position.
*/
public static int convertLevelPos(int pos, int currectDetailLevel, int targetDetailLevel)
{
int newPos = Math.floorDiv(pos, (int) Math.pow(2, targetDetailLevel - currectDetailLevel));
return newPos;
}
/**
* Return whether the given chunk
* has any data in it.
@@ -197,20 +220,19 @@ public class LodUtil
public static boolean chunkHasBlockData(IChunk chunk)
{
ChunkSection[] blockStorage = chunk.getSections();
for(ChunkSection section : blockStorage)
for (ChunkSection section : blockStorage)
{
if(section != null && !section.isEmpty())
if (section != null && !section.isEmpty())
{
return true;
}
}
return false;
}
/**
* If on single player this will return the name of the user's
* world, if in multiplayer it will return the server name, IP,
@@ -218,28 +240,26 @@ public class LodUtil
*/
public static String getWorldID(IWorld world)
{
if(mc.hasSingleplayerServer())
if (mc.hasSingleplayerServer())
{
// chop off the dimension ID as it is not needed/wanted
String dimId = getDimensionIDFromWorld(world);
// get the world name
int saveIndex = dimId.indexOf("saves") + 1 + "saves".length();
int slashIndex = dimId.indexOf(File.separatorChar, saveIndex);
dimId = dimId.substring(saveIndex, slashIndex);
return dimId;
}
else
} else
{
return getServerId();
}
}
/**
* If on single player this will return the name of the user's
* world and the dimensional save folder, if in multiplayer
* world and the dimensional save folder, if in multiplayer
* it will return the server name, ip, game version, and dimension.<br>
* <br>
* This can be used to determine where to save files for a given
@@ -247,58 +267,57 @@ public class LodUtil
*/
public static String getDimensionIDFromWorld(IWorld world)
{
if(mc.hasSingleplayerServer())
if (mc.hasSingleplayerServer())
{
// this will return the world save location
// and the dimension folder
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(world.dimensionType());
if(serverWorld == null)
if (serverWorld == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerWorld for the dimension " + world.dimensionType().effectsLocation().getPath());
ServerChunkProvider provider = serverWorld.getChunkSource();
if(provider == null)
if (provider == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerChunkProvider for the dimension " + world.dimensionType().effectsLocation().getPath());
return provider.dataStorage.dataFolder.toString();
}
else
} else
{
return getServerId() + File.separatorChar + "dim_" + world.dimensionType().effectsLocation().getPath() + File.separatorChar;
}
}
/**
* returns the server name, IP and game version.
*/
public static String getServerId()
{
ServerData server = mc.getCurrentServer();
String serverName = server.name.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverIp = server.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverMcVersion = server.version.getString().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverId = serverName + ", IP " + serverIp + ", GameVersion " + serverMcVersion;
return serverId;
String serverId = serverName + ", IP " + serverIp + ", GameVersion " + serverMcVersion;
return serverId;
}
/**
* Convert a BlockColors int into a Color object.
*/
public static Color intToColor(int num)
{
int filter = 0b11111111;
int red = (num >> 16 ) & filter;
int green = (num >> 8 ) & filter;
int red = (num >> 16) & filter;
int green = (num >> 8) & filter;
int blue = num & filter;
return new Color(red, green, blue);
}
/**
* Convert a Color into a BlockColors object.
*/
@@ -306,8 +325,8 @@ public class LodUtil
{
return color.getRGB();
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
@@ -316,7 +335,7 @@ public class LodUtil
{
return Math.min(max, Math.max(value, min));
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
@@ -325,7 +344,7 @@ public class LodUtil
{
return Math.min(max, Math.max(value, min));
}
/**
* Clamps the given value between the min and max values.
* May behave strangely if min > max.
@@ -337,8 +356,9 @@ public class LodUtil
/**
* This methods return the number of lods that are going to be rendered in a region in the worst case
*
* @param regionPosX x region position to check
* @param regionPosZ z region position to check
* @param regionPosZ z region position to check
* @return number of lods in the region
*/
public static long regionRenderingMemoryUse(int regionPosX, int regionPosZ, LodTemplate template)
@@ -354,8 +374,8 @@ public class LodUtil
| |
X - X - X
*/
int circleCenterX = 256 + 256*xRegionSign;
int circleCenterZ = 256 + 256*zRegionSign;
int circleCenterX = 256 + 256 * xRegionSign;
int circleCenterZ = 256 + 256 * zRegionSign;
int innerRadius;
@@ -366,7 +386,7 @@ public class LodUtil
int maxDistance;
long memoryUse = 0;
int number = 0;
for(byte detailLevel = BLOCK_DETAIL_LEVEL; detailLevel <= REGION_DETAIL_LEVEL; detailLevel++)
for (byte detailLevel = BLOCK_DETAIL_LEVEL; detailLevel <= REGION_DETAIL_LEVEL; detailLevel++)
{
//We find now the inner and outer detail of this area
innerRadius = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel);
@@ -400,59 +420,59 @@ public class LodUtil
}
return memoryUse;
}
/**
* Get a HashSet of all ChunkPos within the normal render distance
* that should not be rendered.
*/
public static HashSet<ChunkPos> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPos playerPos)
{
int chunkRenderDist = mc.getRenderDistance();
ChunkPos centerChunk = new ChunkPos(playerPos);
// skip chunks that are already going to be rendered by Minecraft
HashSet<ChunkPos> posToSkip = getRenderedChunks();
// go through each chunk within the normal view distance
for (int x = centerChunk.x - chunkRenderDist; x < centerChunk.x + chunkRenderDist; x++)
{
for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++)
{
if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z))
continue;
long data = lodDim.getSingleData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
short lodAverageHeight = DataPointUtil.getHeight(data);
if (playerPos.getY() <= lodAverageHeight)
{
// don't draw Lod's that are taller than the player
// to prevent LODs being drawn on top of the player
posToSkip.add(new ChunkPos(x, z));
}
}
}
return posToSkip;
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
* Get a HashSet of all ChunkPos within the normal render distance
* that should not be rendered.
*/
public static HashSet<ChunkPos> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPos playerPos)
{
int chunkRenderDist = mc.getRenderDistance();
ChunkPos centerChunk = new ChunkPos(playerPos);
// skip chunks that are already going to be rendered by Minecraft
HashSet<ChunkPos> posToSkip = getRenderedChunks();
// go through each chunk within the normal view distance
for (int x = centerChunk.x - chunkRenderDist; x < centerChunk.x + chunkRenderDist; x++)
{
for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++)
{
if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z))
continue;
long data = lodDim.getSingleData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
short lodAverageHeight = DataPointUtil.getHeight(data);
if (playerPos.getY() <= lodAverageHeight)
{
// don't draw Lod's that are taller than the player
// to prevent LODs being drawn on top of the player
posToSkip.add(new ChunkPos(x, z));
}
}
}
return posToSkip;
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
public static HashSet<ChunkPos> getRenderedChunks()
{
HashSet<ChunkPos> loadedPos = new HashSet<>();
// Wow those are some long names!
// go through every RenderInfo to get the compiled chunks
WorldRenderer renderer = mc.getLevelRenderer();
for (WorldRenderer.LocalRenderInformationContainer worldrenderer$localrenderinformationcontainer : renderer.renderChunks)
@@ -462,14 +482,42 @@ public class LodUtil
{
// add the ChunkPos for every rendered chunk
BlockPos bpos = worldrenderer$localrenderinformationcontainer.chunk.getOrigin();
loadedPos.add(new ChunkPos(bpos));
}
}
return loadedPos;
}
/**
*
*/
public static boolean isBorderChunk(boolean[][] vanillaRenderedChunks, int x, int z)
{
if (x < 0 || z < 0 || x >= vanillaRenderedChunks.length || z >= vanillaRenderedChunks[0].length)
return false;
int tempX;
int tempZ;
for (Direction direction : Box.ADJ_DIRECTIONS)
{
tempX = x + direction.getNormal().getX();
tempZ = z + direction.getNormal().getZ();
if (!(tempX < 0 || tempZ < 0 || tempX >= vanillaRenderedChunks.length || tempZ >= vanillaRenderedChunks[0].length))
{
if (!vanillaRenderedChunks[tempX][tempZ])
{
return true;
}
}else
{
if (vanillaRenderedChunks[x][z])
{
return true;
}
}
}
return false;
}
}