Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| afe4e111c3 | |||
| 3675c5da46 | |||
| a4cc39dbac | |||
| e3787079b7 | |||
| b2f98e2d92 | |||
| e1edd01069 | |||
| eb3455452b | |||
| 34baf923b2 | |||
| 499308870d | |||
| f852a79a0e | |||
| fa98454151 | |||
| 286fc91db6 | |||
| 99209f920d | |||
| 19fd1aff98 | |||
| 9ebc5aeb32 | |||
| 7c890a4627 | |||
| ccc661225e | |||
| d7b13a2e0b | |||
| c53ce15f7d | |||
| 35ac6fc756 | |||
| 6bcf58959b | |||
| 5051508e42 | |||
| 196e02e61a | |||
| 814ac5df84 | |||
| 55f9d142e6 | |||
| 58607ab1fc | |||
| 433ab4f92f | |||
| 8840973a1e |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 93 KiB |
File diff suppressed because one or more lines are too long
+1
-1
@@ -18,7 +18,7 @@ apply plugin: 'org.spongepowered.mixin'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
version = 'a1.3'
|
||||
version = 'a1.3.2'
|
||||
group = 'com.backsun.lod'
|
||||
archivesBaseName = 'lod_1.16.5'
|
||||
|
||||
|
||||
@@ -17,15 +17,11 @@
|
||||
*/
|
||||
package com.seibel.lod;
|
||||
|
||||
import org.lwjgl.opengl.GL;
|
||||
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.DeferredWorkQueue;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
@@ -55,22 +51,6 @@ public class LodMain
|
||||
private void init(final FMLCommonSetupEvent event)
|
||||
{
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, LodConfig.clientSpec);
|
||||
|
||||
|
||||
Thread setFancyFog = new Thread(() ->
|
||||
{
|
||||
LodRenderer.fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
if (!LodRenderer.fancyFogAvailable)
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
|
||||
}
|
||||
});
|
||||
|
||||
// This will be run on the main thread when it is able.
|
||||
// If it wasn't run on the main thread GL.getCapabilities()
|
||||
// would fail.
|
||||
DeferredWorkQueue.runLater(setFancyFog);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,5 +28,5 @@ public final class ModInfo
|
||||
public static final String MODID = "lod";
|
||||
public static final String MODNAME = "Level of Detail";
|
||||
public static final String MODAPI = "LodAPI";
|
||||
public static final String VERSION = "a1.3";
|
||||
public static final String VERSION = "a1.3.2";
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.seibel.lod.builders.worldGeneration.LodChunkGenWorker;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
@@ -34,8 +35,6 @@ import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.biome.BiomeContainer;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.WorldWorkerManager;
|
||||
|
||||
@@ -43,7 +42,7 @@ import net.minecraftforge.common.WorldWorkerManager;
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 06-19-2021
|
||||
* @version 07-25-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
@@ -90,15 +89,11 @@ public class LodBufferBuilder
|
||||
}
|
||||
|
||||
|
||||
private BiomeContainer biomeContainer = null;
|
||||
private LodDimension previousDimension = null;
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread to asynchronously generate LOD buffers
|
||||
* centered around the given camera X and Z.
|
||||
* <br>
|
||||
* This method will write to the drawableNearBuffers and drawableFarBuffers.
|
||||
* This method will write to the drawable near and far buffers.
|
||||
* <br>
|
||||
* After the buildable buffers have been generated they must be
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
@@ -113,12 +108,6 @@ public class LodBufferBuilder
|
||||
if (buildableNearBuffer == null || buildableFarBuffer == null)
|
||||
throw new IllegalStateException("generateLodBuffersAsync was called before the buildableNearBuffer and buildableFarBuffer were created.");
|
||||
|
||||
if (previousDimension != lodDim)
|
||||
{
|
||||
biomeContainer = LodUtil.getServerWorldFromDimension(lodDim.dimension).getChunk(0, 0, ChunkStatus.EMPTY).getBiomes();
|
||||
previousDimension = lodDim;
|
||||
}
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
@@ -168,12 +157,14 @@ public class LodBufferBuilder
|
||||
continue;
|
||||
}
|
||||
|
||||
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
|
||||
|
||||
// set where this square will be drawn in the world
|
||||
double xOffset = (LodChunk.WIDTH * i) + // offset by the number of LOD blocks
|
||||
startX; // offset so the center LOD block is centered underneath the player
|
||||
startX + // offset so the center LOD block is centered underneath the player
|
||||
detail.offset; // truncation(?) correction
|
||||
double yOffset = 0;
|
||||
double zOffset = (LodChunk.WIDTH * j) + startZ;
|
||||
double zOffset = (LodChunk.WIDTH * j) + startZ + detail.offset;
|
||||
|
||||
LodChunk lod = lodDim.getLodFromCoordinates(chunkX, chunkZ);
|
||||
|
||||
@@ -209,8 +200,9 @@ public class LodBufferBuilder
|
||||
// issue #40
|
||||
// TODO optimize this code,
|
||||
// using the purely optimized code above we can achieve close to
|
||||
// 100% CPU utilization, this code generally achieves 40 - 50 %
|
||||
// I'm sure there is a better data structure for this.
|
||||
// 100% CPU utilization, this code generally achieves 40 - 50%
|
||||
// after a certain point; and I'm sure there is a better data
|
||||
// structure for this.
|
||||
if (newDistance < minChunkDist)
|
||||
{
|
||||
// this chunk is closer, clear any previous
|
||||
@@ -269,11 +261,12 @@ public class LodBufferBuilder
|
||||
chunkGenIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// don't render this null chunk
|
||||
} // lod null and can generate more chunks
|
||||
|
||||
// don't render this null/empty chunk
|
||||
continue;
|
||||
}
|
||||
|
||||
} // lod null or empty
|
||||
|
||||
|
||||
BufferBuilder currentBuffer = null;
|
||||
@@ -290,6 +283,7 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
|
||||
// issue #19
|
||||
// TODO add a way for a server side mod to generate chunks requested here
|
||||
if(mc.hasSingleplayerServer())
|
||||
{
|
||||
@@ -315,7 +309,7 @@ public class LodBufferBuilder
|
||||
|
||||
numberOfChunksWaitingToGenerate.addAndGet(1);
|
||||
|
||||
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld, biomeContainer);
|
||||
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld);
|
||||
WorldWorkerManager.addWorker(genWorker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ import net.minecraft.block.AbstractPlantBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.BushBlock;
|
||||
import net.minecraft.block.FlowingFluidBlock;
|
||||
import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
@@ -50,7 +50,7 @@ import net.minecraft.world.gen.Heightmap;
|
||||
* (specifically: Lod World, Dimension, Region, and Chunk objects)
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 6-27-2021
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodChunkBuilder
|
||||
{
|
||||
@@ -64,6 +64,13 @@ public class LodChunkBuilder
|
||||
public static final int CHUNK_SECTION_HEIGHT = LodChunk.WIDTH;
|
||||
|
||||
|
||||
|
||||
// reminder now how to access biome info
|
||||
// String name = biome.getRegistryName().getPath();
|
||||
// String deepColdName = Biomes.DEEP_COLD_OCEAN.location().getPath();
|
||||
// Biome deepCold = WorldGenRegistries.BIOME.get(Biomes.DEEP_COLD_OCEAN);
|
||||
|
||||
|
||||
|
||||
public LodChunkBuilder()
|
||||
{
|
||||
@@ -289,7 +296,7 @@ public class LodChunkBuilder
|
||||
// enough blocks in this
|
||||
// layer to count as an
|
||||
// LOD point
|
||||
return (short) (y + (section * CHUNK_SECTION_HEIGHT));
|
||||
return (short) (y + 1 + (section * CHUNK_SECTION_HEIGHT));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,7 +341,7 @@ public class LodChunkBuilder
|
||||
* If true use biome foliage, water, and grass colors, <br>
|
||||
* otherwise only use the block's material color
|
||||
*/
|
||||
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
|
||||
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
|
||||
{
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
@@ -374,7 +381,8 @@ public class LodChunkBuilder
|
||||
|
||||
if (config.useBiomeColors)
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
|
||||
// the bit shift is equivalent to dividing by 4
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2, z >> 2);
|
||||
|
||||
if (biome.getBiomeCategory() == Biome.Category.OCEAN ||
|
||||
biome.getBiomeCategory() == Biome.Category.RIVER)
|
||||
@@ -414,7 +422,9 @@ public class LodChunkBuilder
|
||||
}
|
||||
else
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
|
||||
// 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.
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2, z >> 2);
|
||||
colorInt = getColorForBlock(x,z, blockState, biome);
|
||||
}
|
||||
|
||||
@@ -434,7 +444,6 @@ public class LodChunkBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,12 +466,17 @@ public class LodChunkBuilder
|
||||
{
|
||||
int colorInt = 0;
|
||||
|
||||
// block special cases
|
||||
if (blockState == Blocks.AIR.defaultBlockState())
|
||||
{
|
||||
colorInt = biome.getGrassColor(x, z);
|
||||
}
|
||||
else if (blockState == Blocks.MYCELIUM.defaultBlockState())
|
||||
{
|
||||
colorInt = MaterialColor.COLOR_LIGHT_GRAY.col;
|
||||
}
|
||||
|
||||
|
||||
// plant life
|
||||
else if (blockState.getBlock() instanceof LeavesBlock)
|
||||
{
|
||||
Color leafColor = LodUtil.intToColor(biome.getFoliageColor()).darker();
|
||||
@@ -473,12 +487,18 @@ public class LodChunkBuilder
|
||||
blockState.getBlock() instanceof BushBlock ||
|
||||
blockState.getBlock() instanceof IGrowable)
|
||||
{
|
||||
colorInt = biome.getGrassColor(x, z);
|
||||
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
|
||||
tmp = tmp.darker();
|
||||
colorInt = LodUtil.colorToInt(tmp);
|
||||
}
|
||||
else if (blockState.getBlock() instanceof FlowingFluidBlock)
|
||||
|
||||
// water
|
||||
else if (blockState.getBlock() == Blocks.WATER)
|
||||
{
|
||||
colorInt = biome.getWaterColor();
|
||||
}
|
||||
|
||||
// everything else
|
||||
else
|
||||
{
|
||||
colorInt = blockState.materialColor.col;
|
||||
|
||||
@@ -19,11 +19,12 @@ package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.ColorDirection;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
@@ -32,7 +33,7 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||
* Builds LODs as rectangular prisms.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 06-16-2021
|
||||
* @version 07-25-2021
|
||||
*/
|
||||
public class CubicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -104,77 +105,82 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color c)
|
||||
{
|
||||
Color topColor = c;
|
||||
Color northSouthColor = c;
|
||||
Color eastWestColor = c;
|
||||
Color bottomColor = c;
|
||||
|
||||
// darken the bottom and side colors if requested
|
||||
if (LodConfig.CLIENT.shadingMode.get() == ShadingMode.DARKEN_SIDES)
|
||||
{
|
||||
// the side colors are different because
|
||||
// when using fast lighting in Minecraft the north/south
|
||||
// and east/west sides are different in a similar way
|
||||
int northSouthDarkenAmount = 25;
|
||||
int eastWestDarkenAmount = 50;
|
||||
int bottomDarkenAmount = 75;
|
||||
|
||||
northSouthColor = new Color(Math.max(0, c.getRed() - northSouthDarkenAmount), Math.max(0, c.getGreen() - northSouthDarkenAmount), Math.max(0, c.getBlue() - northSouthDarkenAmount), c.getAlpha());
|
||||
eastWestColor = new Color(Math.max(0, c.getRed() - eastWestDarkenAmount), Math.max(0, c.getGreen() - eastWestDarkenAmount), Math.max(0, c.getBlue() - eastWestDarkenAmount), c.getAlpha());
|
||||
bottomColor = new Color(Math.max(0, c.getRed() - bottomDarkenAmount), Math.max(0, c.getGreen() - bottomDarkenAmount), Math.max(0, c.getBlue() - bottomDarkenAmount), c.getAlpha());
|
||||
}
|
||||
|
||||
|
||||
// apply the user specified saturation and brightness
|
||||
float saturationMultiplier = LodConfig.CLIENT.saturationMultiplier.get().floatValue();
|
||||
float brightnessMultiplier = LodConfig.CLIENT.brightnessMultiplier.get().floatValue();
|
||||
|
||||
topColor = applySaturationAndBrightnessMultipliers(topColor, saturationMultiplier, brightnessMultiplier);
|
||||
northSouthColor = applySaturationAndBrightnessMultipliers(northSouthColor, saturationMultiplier, brightnessMultiplier);
|
||||
bottomColor = applySaturationAndBrightnessMultipliers(bottomColor, saturationMultiplier, brightnessMultiplier);
|
||||
|
||||
|
||||
|
||||
// top (facing up)
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, topColor.getRed(), topColor.getGreen(), topColor.getBlue(), topColor.getAlpha());
|
||||
// bottom (facing down)
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), bottomColor.getAlpha());
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
// north (facing +Z)
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, northSouthColor.getRed(), northSouthColor.getGreen(), northSouthColor.getBlue(), northSouthColor.getAlpha());
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
// east (facing +X)
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, eastWestColor.getRed(), eastWestColor.getGreen(), eastWestColor.getBlue(), eastWestColor.getAlpha());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color[] c)
|
||||
/**
|
||||
* Edit the given color as a HSV (Hue Saturation Value) color.
|
||||
*/
|
||||
private Color applySaturationAndBrightnessMultipliers(Color color, float saturationMultiplier, float brightnessMultiplier)
|
||||
{
|
||||
// top (facing up)
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
|
||||
// bottom (facing down)
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
|
||||
// north (facing +Z)
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
|
||||
// east (facing +X)
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
float[] hsv = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
|
||||
return Color.getHSBColor(
|
||||
hsv[0], // hue
|
||||
LodUtil.clamp(0.0f, hsv[1] * saturationMultiplier, 1.0f),
|
||||
LodUtil.clamp(0.0f, hsv[2] * brightnessMultiplier, 1.0f));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ import net.minecraft.util.WeightedList.Entry;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.palette.UpgradeData;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeContainer;
|
||||
import net.minecraft.world.chunk.ChunkPrimer;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
@@ -70,11 +69,11 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
|
||||
* This is used to generate a LodChunk at a given ChunkPos.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-5-2021
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodChunkGenWorker implements IWorker
|
||||
{
|
||||
public static final ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
|
||||
public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
|
||||
|
||||
private boolean threadStarted = false;
|
||||
private LodChunkGenThread thread;
|
||||
@@ -88,12 +87,29 @@ public class LodChunkGenWorker implements IWorker
|
||||
|
||||
public LodChunkGenWorker(ChunkPos newPos, LodRenderer newLodRenderer,
|
||||
LodChunkBuilder newLodBuilder, LodBufferBuilder newLodBufferBuilder,
|
||||
LodDimension newLodDimension, ServerWorld newServerWorld,
|
||||
BiomeContainer newBiomeContainer)
|
||||
LodDimension newLodDimension, ServerWorld newServerWorld)
|
||||
{
|
||||
// just a few sanity checks
|
||||
if (newPos == null)
|
||||
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ChunkPos");
|
||||
|
||||
if (newLodRenderer == null)
|
||||
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null LodRenderer");
|
||||
|
||||
if (newLodBuilder == null)
|
||||
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodChunkBuilder");
|
||||
|
||||
if (newLodBufferBuilder == null)
|
||||
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodBufferBuilder");
|
||||
|
||||
if (newLodDimension == null)
|
||||
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodDimension");
|
||||
|
||||
if (newServerWorld == null)
|
||||
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ServerWorld");
|
||||
|
||||
throw new IllegalArgumentException("LodChunkGenThread requires a non-null ServerWorld");
|
||||
|
||||
|
||||
|
||||
thread = new LodChunkGenThread(newPos, newLodRenderer,
|
||||
newLodBuilder, newLodBufferBuilder,
|
||||
newLodDimension, newServerWorld);
|
||||
@@ -124,6 +140,7 @@ public class LodChunkGenWorker implements IWorker
|
||||
|
||||
// useful for debugging
|
||||
// ClientProxy.LOGGER.info(thread.lodDim.getNumberOfLods());
|
||||
// ClientProxy.LOGGER.info(genThreads.toString());
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -144,7 +161,7 @@ public class LodChunkGenWorker implements IWorker
|
||||
public final LodDimension lodDim;
|
||||
public final LodChunkBuilder lodChunkBuilder;
|
||||
public final LodRenderer lodRenderer;
|
||||
private LodBufferBuilder lodBufferBuilder;
|
||||
private final LodBufferBuilder lodBufferBuilder;
|
||||
|
||||
private ChunkPos pos;
|
||||
|
||||
@@ -246,7 +263,7 @@ public class LodChunkGenWorker implements IWorker
|
||||
|
||||
// these heights are of course aren't super accurate,
|
||||
// they are just to simulate height data where there isn't any
|
||||
switch(chunk.getBiomes().getNoiseBiome(x, seaLevel, z).getBiomeCategory())
|
||||
switch(chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
|
||||
{
|
||||
case NETHER:
|
||||
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
|
||||
@@ -383,7 +400,7 @@ public class LodChunkGenWorker implements IWorker
|
||||
{
|
||||
for (int z = 0; z < LodChunk.WIDTH; z++)
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x, serverWorld.getSeaLevel(), z);
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
|
||||
|
||||
// Issue #35
|
||||
// For some reason Jungle biomes cause incredible lag
|
||||
@@ -573,6 +590,28 @@ public class LodChunkGenWorker implements IWorker
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stops the current genThreads if they are running
|
||||
* and then recreates the Executer service. <br><br>
|
||||
*
|
||||
* This is done to clear any outstanding tasks
|
||||
* that may exist after the player leaves their current world.
|
||||
* If this isn't done unfinished tasks may be left in the queue
|
||||
* preventing new LodChunks form being generated.
|
||||
*/
|
||||
public static void restartExecuterService()
|
||||
{
|
||||
if (genThreads != null && !genThreads.isShutdown())
|
||||
{
|
||||
genThreads.shutdownNow();
|
||||
}
|
||||
genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* performance/generation tests related to
|
||||
* serverWorld.getChunk(x, z, ChunkStatus. *** )
|
||||
|
||||
@@ -67,7 +67,7 @@ import net.minecraft.world.storage.IWorldInfo;
|
||||
* to multithread generation.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-4-2021
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodServerWorld implements ISeedReader {
|
||||
|
||||
@@ -101,7 +101,7 @@ public class LodServerWorld implements ISeedReader {
|
||||
@Override
|
||||
public Biome getBiome(BlockPos pos)
|
||||
{
|
||||
return chunk.getBiomes().getNoiseBiome(pos.getX(), pos.getY(), pos.getZ());
|
||||
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,6 +160,17 @@ public class LodServerWorld implements ISeedReader {
|
||||
return new WorldLightManager(null, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return serverWorld.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicRegistries registryAccess()
|
||||
{
|
||||
return serverWorld.registryAccess();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -190,10 +201,6 @@ public class LodServerWorld implements ISeedReader {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
@Override
|
||||
public DynamicRegistries registryAccess() {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
@Override
|
||||
public BiomeManager getBiomeManager() {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
@@ -221,11 +228,6 @@ public class LodServerWorld implements ISeedReader {
|
||||
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft) {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,31 +17,30 @@
|
||||
*/
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDataPoint;
|
||||
|
||||
/**
|
||||
* single, double, quad, half, full
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 06-13-2021
|
||||
* @version 07-26-2021
|
||||
*/
|
||||
public enum LodDetail
|
||||
{
|
||||
/** render 1 LOD for each chunk */
|
||||
SINGLE(1),
|
||||
SINGLE(1, 4),
|
||||
|
||||
/** render 4 LODs for each chunk */
|
||||
DOUBLE(2),
|
||||
DOUBLE(2, 2),
|
||||
|
||||
/** render 16 LODs for each chunk */
|
||||
QUAD(4),
|
||||
QUAD(4, 1),
|
||||
|
||||
/** render 64 LODs for each chunk */
|
||||
HALF(8),
|
||||
HALF(8, 0),
|
||||
|
||||
/** render 256 LODs for each chunk */
|
||||
FULL(16);
|
||||
FULL(16, 0);
|
||||
|
||||
|
||||
/** How many DataPoints should
|
||||
@@ -62,19 +61,19 @@ public enum LodDetail
|
||||
* when creating a LodChunk with this detail level */
|
||||
public final int lodChunkStringDelimiterCount;
|
||||
|
||||
/** in LodBufferBuilder some detail options don't render
|
||||
* in the correct spot, this number fixes that.
|
||||
* TODO find out why this is needed and see if it
|
||||
* needed / could be removed */
|
||||
public final int offset;
|
||||
|
||||
|
||||
|
||||
private LodDetail(int newLengthCount)
|
||||
private LodDetail(int newLengthCount, int newOffset)
|
||||
{
|
||||
dataPointLengthCount = newLengthCount;
|
||||
dataPointWidth = 16 / dataPointLengthCount;
|
||||
|
||||
if(newLengthCount == LodChunk.WIDTH)
|
||||
{
|
||||
// this is to prevent overflow
|
||||
newLengthCount = LodChunk.WIDTH - 1;
|
||||
}
|
||||
offset = newOffset;
|
||||
|
||||
startX = new int[dataPointLengthCount * dataPointLengthCount];
|
||||
endX = new int[dataPointLengthCount * dataPointLengthCount];
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
/**
|
||||
* NONE, DARKEN_SIDES
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-25-2020
|
||||
*/
|
||||
public enum ShadingMode
|
||||
{
|
||||
/** LODs will have the same lighting on every side.
|
||||
Fastest, but can make large similarly colored areas hard to differentiate */
|
||||
NONE,
|
||||
|
||||
/** LODs will have darker sides and bottoms to simulate top down lighting.
|
||||
Fastest */
|
||||
DARKEN_SIDES;
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -40,7 +41,7 @@ import net.minecraftforge.fml.config.ModConfig;
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-5-2021
|
||||
* @version 7-25-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class LodConfig
|
||||
@@ -65,10 +66,15 @@ public class LodConfig
|
||||
|
||||
public ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
|
||||
|
||||
public ForgeConfigSpec.EnumValue<ShadingMode> shadingMode;
|
||||
|
||||
/** this is multiplied by the default view distance
|
||||
* to determine how far out to generate/render LODs */
|
||||
public ForgeConfigSpec.IntValue lodChunkRadiusMultiplier;
|
||||
|
||||
public ForgeConfigSpec.DoubleValue brightnessMultiplier;
|
||||
|
||||
public ForgeConfigSpec.DoubleValue saturationMultiplier;
|
||||
|
||||
|
||||
Client(ForgeConfigSpec.Builder builder)
|
||||
@@ -177,11 +183,11 @@ public class LodConfig
|
||||
+ " This will also show player made structures if you \n"
|
||||
+ " are adding the mod to a pre-existing world. \n"
|
||||
+ " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n")
|
||||
.defineEnum("distanceBiomeOnlyGeneration", DistanceGenerationMode.SURFACE);
|
||||
.defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE);
|
||||
|
||||
allowUnstableFeatureGeneration = builder
|
||||
.comment("\n\n"
|
||||
+ " When using the " + DistanceGenerationMode.FEATURES.toString() + "generation mode \n"
|
||||
+ " When using the " + DistanceGenerationMode.FEATURES.toString() + " generation mode \n"
|
||||
+ " some features may not be thread safe, which could \n"
|
||||
+ " cause instability and crashes. \n"
|
||||
+ " By default (false) those features are skipped, \n"
|
||||
@@ -210,6 +216,36 @@ public class LodConfig
|
||||
)
|
||||
.defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
shadingMode = builder
|
||||
.comment("\n\n"
|
||||
+ " What kind of shading should LODs have? \n"
|
||||
+ " " + ShadingMode.NONE.toString() + " \n"
|
||||
+ " " + "LODs will have the same lighting on every side. \n"
|
||||
+ " " + "Can make large similarly colored areas hard to differentiate. \n"
|
||||
+ " " + "Fastest"
|
||||
+ "/n"
|
||||
+ " " + ShadingMode.DARKEN_SIDES.toString() + " \n"
|
||||
+ " " + "LODs will have darker sides and bottoms to simulate top down lighting."
|
||||
+ " " + "Fastest /n")
|
||||
.defineEnum("lightingMode", ShadingMode.DARKEN_SIDES);
|
||||
|
||||
|
||||
|
||||
brightnessMultiplier = builder
|
||||
.comment("\n\n"
|
||||
+ " Change how bright LOD colors are. \n"
|
||||
+ " 0 = black \n"
|
||||
+ " 1 = normal color value \n"
|
||||
+ " 2 = washed out colors \n")
|
||||
.defineInRange("brightnessMultiplier", 1.0, 0, 2);
|
||||
|
||||
saturationMultiplier = builder
|
||||
.comment("\n\n"
|
||||
+ " Change how saturated LOD colors are. \n"
|
||||
+ " 0 = black and white \n"
|
||||
+ " 1 = normal saturation \n"
|
||||
+ " 2 = very saturated \n")
|
||||
.defineInRange("saturationMultiplier", 1.0, 0, 2);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ public class LodDimension
|
||||
public volatile LodRegion regions[][];
|
||||
public volatile boolean isRegionDirty[][];
|
||||
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
private volatile int centerX;
|
||||
private volatile int centerZ;
|
||||
|
||||
private LodDimensionFileHandler fileHandler;
|
||||
|
||||
@@ -108,7 +108,7 @@ public class LodDimension
|
||||
* Move the center of this LodDimension and move all owned
|
||||
* regions over by the given x and z offset.
|
||||
*/
|
||||
public void move(int xOffset, int zOffset)
|
||||
public synchronized void move(int xOffset, int zOffset)
|
||||
{
|
||||
// if the x or z offset is equal to or greater than
|
||||
// the total size, just delete the current data
|
||||
@@ -236,7 +236,7 @@ public class LodDimension
|
||||
* Overwrite the LodRegion at the location of newRegion with newRegion.
|
||||
* @throws ArrayIndexOutOfBoundsException if newRegion is outside what can be stored in this LodDimension.
|
||||
*/
|
||||
public void setRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
|
||||
public void addOrOverwriteRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
int xIndex = (newRegion.x - centerX) + halfWidth;
|
||||
int zIndex = (centerZ - newRegion.z) + halfWidth;
|
||||
@@ -273,13 +273,13 @@ public class LodDimension
|
||||
{
|
||||
// if no region exists, create it
|
||||
region = new LodRegion(pos.x, pos.z);
|
||||
setRegion(region);
|
||||
addOrOverwriteRegion(region);
|
||||
}
|
||||
|
||||
region.addLod(lod);
|
||||
|
||||
// don't save empty place holders to disk
|
||||
if (!lod.isPlaceholder() && fileHandler != null)
|
||||
// only save valid LODs to disk
|
||||
if (!(lod.isPlaceholder() || lod.dontSave) && fileHandler != null)
|
||||
{
|
||||
// mark the region as dirty so it will be saved to disk
|
||||
int xIndex = (pos.x - centerX) + halfWidth;
|
||||
@@ -388,13 +388,22 @@ public class LodDimension
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
if (regions != null)
|
||||
{
|
||||
// we want to get the length directly from the
|
||||
// source to make sure it is in sync with region
|
||||
// and isRegionDirty
|
||||
return regions.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return width;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRegionWidth(int newWidth)
|
||||
{
|
||||
width = newWidth;
|
||||
halfWidth = (int)Math.floor(width / 2);
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
/**
|
||||
* A LodRegion is the a 32x32
|
||||
* A LodRegion is a 32x32
|
||||
* 2D array of LodChunk objects.
|
||||
* Each LodRegion corresponds to
|
||||
* one file in the file system.
|
||||
|
||||
@@ -22,6 +22,9 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.seibel.lod.builders.LodBufferBuilder;
|
||||
import com.seibel.lod.builders.LodChunkBuilder;
|
||||
import com.seibel.lod.builders.worldGeneration.LodChunkGenWorker;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.handlers.LodConfig;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
@@ -42,7 +45,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
* and is the starting point for most of this program.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 06-27-2021
|
||||
* @version 7-9-2021
|
||||
*/
|
||||
public class ClientProxy
|
||||
{
|
||||
@@ -111,21 +114,27 @@ public class ClientProxy
|
||||
|
||||
|
||||
// for testing
|
||||
// LodConfig.CLIENT.drawLODs.set(true);
|
||||
// LodConfig.CLIENT.debugMode.set(false);
|
||||
|
||||
// LodConfig.CLIENT.lodDetail.set(LodDetail.DOUBLE);
|
||||
LodConfig.CLIENT.lodDetail.set(LodDetail.QUAD);
|
||||
// LodConfig.CLIENT.lodChunkRadiusMultiplier.set(12);
|
||||
// LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
|
||||
// LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
// LodConfig.CLIENT.shadingMode.set(ShadingMode.DARKEN_SIDES);
|
||||
// LodConfig.CLIENT.brightnessMultiplier.set(1.0);
|
||||
// LodConfig.CLIENT.saturationMultiplier.set(1.0);
|
||||
|
||||
// LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
|
||||
LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
|
||||
// LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
// LOGGER.info(lodBufferBuilder.numberOfChunksWaitingToGenerate.get());
|
||||
|
||||
|
||||
// Note to self:
|
||||
// if "unspecified" shows up in the pie chart, it is
|
||||
// possibly because the amount of time between sections
|
||||
// is too small for the profile to measure
|
||||
// is too small for the profiler to measure
|
||||
IProfiler profiler = mc.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("LOD");
|
||||
@@ -167,6 +176,10 @@ public class ClientProxy
|
||||
|
||||
if(mc.getConnection().getLevel() == null)
|
||||
{
|
||||
// if this isn't done unfinished tasks may be left in the queue
|
||||
// preventing new LodChunks form being generated
|
||||
LodChunkGenWorker.restartExecuterService();
|
||||
|
||||
lodBufferBuilder.numberOfChunksWaitingToGenerate.set(0);
|
||||
// the player has disconnected from a server
|
||||
lodWorld.deselectWorld();
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.NVFogDistance;
|
||||
|
||||
@@ -87,7 +88,7 @@ public class LodRenderer
|
||||
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
|
||||
|
||||
/** Does this computer's GPU support fancy fog? */
|
||||
public static boolean fancyFogAvailable = false;
|
||||
private static Boolean fancyFogAvailable = null;
|
||||
|
||||
|
||||
|
||||
@@ -153,6 +154,7 @@ public class LodRenderer
|
||||
* @param newDimension The dimension to draw, if null doesn't replace the current dimension.
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void drawLODs(LodDimension lodDim, float partialTicks, IProfiler newProfiler)
|
||||
{
|
||||
if (lodDim == null)
|
||||
@@ -174,6 +176,20 @@ public class LodRenderer
|
||||
profiler = newProfiler;
|
||||
profiler.push("LOD setup");
|
||||
|
||||
|
||||
// only check the GPU capability's once
|
||||
if (fancyFogAvailable == null)
|
||||
{
|
||||
// see if this GPU can run fancy fog
|
||||
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
if (!LodRenderer.fancyFogAvailable)
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ClientPlayerEntity player = mc.player;
|
||||
|
||||
// should LODs be regenerated?
|
||||
@@ -405,7 +421,7 @@ public class LodRenderer
|
||||
|
||||
|
||||
// determine the fog distance mode to use
|
||||
int glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
|
||||
int glFogDistanceMode;
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
// fancy fog (fragment distance based fog)
|
||||
@@ -467,6 +483,7 @@ public class LodRenderer
|
||||
/**
|
||||
* Revert any changes that were made to the fog.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void cleanupFog(NearFarFogSettings fogSettings,
|
||||
float defaultFogStartDist, float defaultFogEndDist,
|
||||
int defaultFogMode, int defaultFogDistance)
|
||||
@@ -549,15 +566,16 @@ public class LodRenderer
|
||||
matrixStack.mulPose(vector3f.rotationDegrees(f2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this projection matrix allows us to see past the normal
|
||||
// world render distance
|
||||
Matrix4f projectionMatrix =
|
||||
Matrix4f.perspective(
|
||||
getFov(partialTicks, true),
|
||||
(float)this.mc.getWindow().getScreenWidth() / (float)this.mc.getWindow().getScreenHeight(),
|
||||
0.5F,
|
||||
(float)this.mc.getWindow().getScreenWidth() / (float)this.mc.getWindow().getScreenHeight(),
|
||||
// it is possible to see the near clip plane, but
|
||||
// you have to be flying quickly in spectator mode through ungenerated
|
||||
// terrain, so I don't think it is much of an issue.
|
||||
LodConfig.CLIENT.lodChunkRadiusMultiplier.get(),
|
||||
this.farPlaneDistance * LodConfig.CLIENT.lodChunkRadiusMultiplier.get() * 2);
|
||||
|
||||
// add the screen space distortions
|
||||
@@ -570,11 +588,12 @@ public class LodRenderer
|
||||
/**
|
||||
* setup the lighting to be used for the LODs
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setupLighting(LodDimension lodDimension, float partialTicks)
|
||||
{
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.level.getSkyDarken(partialTicks) : 0.2f;
|
||||
float gammaMultiplyer = (float)mc.options.gamma - 0.5f;
|
||||
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.2f);
|
||||
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.3f);
|
||||
|
||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||
|
||||
|
||||
@@ -254,4 +254,32 @@ public class LodUtil
|
||||
{
|
||||
return color.getRGB();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static int clamp(int min, int value, int max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static float clamp(float min, float value, float max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static double clamp(double min, double value, double max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ modId="lod" #mandatory
|
||||
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
#// see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="a1.3" #mandatory
|
||||
version="a1.3.2" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
displayName="Level of Detail" #mandatory
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"modid": "lod",
|
||||
"name": "Level Of Detail",
|
||||
"description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.",
|
||||
"version": "a1.3",
|
||||
"version": "a1.3.2",
|
||||
"mcversion": "1.16.4",
|
||||
"url": "",
|
||||
"updateUrl": "",
|
||||
|
||||
Reference in New Issue
Block a user