Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ad081e0c6 | |||
| 936a3a7ece | |||
| 98f36936d0 | |||
| f6f012c42c | |||
| a3e6c09268 | |||
| 10cb46c9f9 | |||
| 95aa9cb9ab | |||
| 638a0ddae1 | |||
| d321833335 | |||
| b8cba0dc4c | |||
| bd8ccb4a05 | |||
| 895895da04 | |||
| 09d5df2856 | |||
| 668f225528 | |||
| 1cd71a6b50 | |||
| f041f79ae3 | |||
| ef3ac96b2c | |||
| 59f527e6de | |||
| 16a082b17f | |||
| a24d28b0e2 | |||
| 910f11f688 | |||
| e00de99e31 | |||
| f80af39e0e | |||
| 5bba3cb3eb | |||
| d4261d4ccf | |||
| 8b854e3abd | |||
| 4064155567 | |||
| 6243201f2d |
Binary file not shown.
@@ -181,8 +181,7 @@ public class LodBufferBuilder
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
generateLodBuffersThread(renderer, lodDim, playerBlockPos, fullRegen));
|
||||
Thread thread = new Thread(() -> generateLodBuffersThread(renderer, lodDim, playerBlockPos, fullRegen));
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
}
|
||||
@@ -243,8 +242,8 @@ public class LodBufferBuilder
|
||||
if (lodDim.doesRegionNeedBufferRegen(xRegion, zRegion) || fullRegen)
|
||||
{
|
||||
RegionPos regionPos = new RegionPos(
|
||||
xRegion + lodDim.getCenterRegionPosX() - Math.floorDiv(lodDim.getWidth(), 2),
|
||||
zRegion + lodDim.getCenterRegionPosZ() - Math.floorDiv(lodDim.getWidth(), 2));
|
||||
xRegion + lodDim.getCenterRegionPosX() - lodDim.getWidth() / 2,
|
||||
zRegion + lodDim.getCenterRegionPosZ() - lodDim.getWidth() / 2);
|
||||
|
||||
// local position in the vbo and bufferBuilder arrays
|
||||
BufferBuilder[] currentBuffers = buildableBuffers[xRegion][zRegion];
|
||||
@@ -311,7 +310,7 @@ public class LodBufferBuilder
|
||||
|
||||
for (int index = 0; index < posToRender.getNumberOfPos(); index++)
|
||||
{
|
||||
bufferIndex = Math.floorMod(index, currentBuffers.length);
|
||||
bufferIndex = index % currentBuffers.length;
|
||||
detailLevel = posToRender.getNthDetailLevel(index);
|
||||
posX = posToRender.getNthPosX(index);
|
||||
posZ = posToRender.getNthPosZ(index);
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.seibel.lod.enums.VerticalQuality;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
@@ -61,6 +62,7 @@ import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.data.BlockModelProvider;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
@@ -98,7 +100,6 @@ public class LodBuilder
|
||||
public static final ConcurrentMap<Block, Integer> colorMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Integer> tintColor = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Boolean> toTint = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, VoxelShape> shapeMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ConcurrentMap<Block, Boolean> notFullBlock = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Boolean> smallBlock = new ConcurrentHashMap<>();
|
||||
@@ -216,13 +217,12 @@ public class LodBuilder
|
||||
return;
|
||||
|
||||
// determine how many LODs to generate horizontally
|
||||
HorizontalResolution detail;
|
||||
byte minDetailLevel = region.getMinDetailLevel();
|
||||
detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel);
|
||||
HorizontalResolution detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel);
|
||||
|
||||
|
||||
// determine how many LODs to generate vertically
|
||||
VerticalQuality verticalQuality = LodConfig.CLIENT.graphics.qualityOption.verticalQuality.get();
|
||||
//VerticalQuality verticalQuality = LodConfig.CLIENT.graphics.qualityOption.verticalQuality.get();
|
||||
byte detailLevel = detail.detailLevel;
|
||||
|
||||
|
||||
@@ -236,18 +236,18 @@ public class LodBuilder
|
||||
endX = detail.endX[i];
|
||||
endZ = detail.endZ[i];
|
||||
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
|
||||
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
|
||||
|
||||
//lodDim.clear(detailLevel, posX, posZ);
|
||||
if (data != null && data.length != 0)
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, data,false);
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, data, false);
|
||||
}
|
||||
}
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
}
|
||||
@@ -260,7 +260,7 @@ public class LodBuilder
|
||||
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel);
|
||||
|
||||
int verticalData = DataPointUtil.worldHeight;
|
||||
int verticalData = DataPointUtil.worldHeight / 2 + 1;
|
||||
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
int height;
|
||||
@@ -284,8 +284,8 @@ public class LodBuilder
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
xRel = Math.floorMod(index, size) + startX;
|
||||
zRel = Math.floorDiv(index, size) + startZ;
|
||||
xRel = startX + index % size;
|
||||
zRel = startZ + index / size;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
|
||||
@@ -551,8 +551,6 @@ public class LodBuilder
|
||||
if (colorMap.containsKey(block) && toTint.containsKey(block))
|
||||
return colorMap.get(block);
|
||||
|
||||
|
||||
|
||||
World world = mc.getClientWorld();
|
||||
TextureAtlasSprite texture;
|
||||
List<BakedQuad> quads = null;
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.seibel.lod.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.ChunkLoader;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
@@ -191,8 +190,9 @@ public class LodGenWorker implements IWorker
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
/*
|
||||
IChunk loadedChunk = null;
|
||||
if (LodConfig.CLIENT.advancedModOptions.debugging.usePregen.get() && lodDim.isChunkPreGenerated(pos.x, pos.z))
|
||||
if (lodDim.isChunkPreGenerated(pos.x, pos.z) && LodConfig.CLIENT.worldGenerator.useExperimentalPreGenLoading.get())
|
||||
{
|
||||
// generate a Lod like normal
|
||||
loadedChunk = ChunkLoader.getChunkFromFile(pos);
|
||||
@@ -227,7 +227,7 @@ public class LodGenWorker implements IWorker
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{*/
|
||||
switch (generationMode)
|
||||
{
|
||||
case NONE:
|
||||
@@ -251,7 +251,7 @@ public class LodGenWorker implements IWorker
|
||||
generateWithServer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
//lodRenderer.regenerateLODsNextFrame();
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ public class LodWorldGenerator
|
||||
// an easy way to do so.
|
||||
|
||||
// add the near positions
|
||||
if (nearIndex < posToGenerate.getNumberOfNearPos() && posToGenerate.getNthDetail(nearIndex, true) != 0)
|
||||
if (posToGenerate.getNthDetail(nearIndex, true) != 0 && nearIndex < posToGenerate.getNumberOfNearPos())
|
||||
{
|
||||
detailLevel = (byte) (posToGenerate.getNthDetail(nearIndex, true) - 1);
|
||||
posX = posToGenerate.getNthPosX(nearIndex, true);
|
||||
@@ -160,7 +160,7 @@ public class LodWorldGenerator
|
||||
|
||||
|
||||
// add the far positions
|
||||
if (farIndex < posToGenerate.getNumberOfFarPos() && posToGenerate.getNthDetail(farIndex, false) != 0)
|
||||
if (posToGenerate.getNthDetail(farIndex, false) != 0 && farIndex < posToGenerate.getNumberOfFarPos())
|
||||
{
|
||||
detailLevel = (byte) (posToGenerate.getNthDetail(farIndex, false) - 1);
|
||||
posX = posToGenerate.getNthPosX(farIndex, false);
|
||||
|
||||
@@ -51,8 +51,9 @@ import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
/**
|
||||
* This handles any configuration the user has access to.
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 10-23-2021
|
||||
* @version 10-25-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class LodConfig
|
||||
@@ -188,6 +189,8 @@ public class LodConfig
|
||||
|
||||
public final ForgeConfigSpec.EnumValue<FogDrawOverride> fogDrawOverride;
|
||||
|
||||
public final ForgeConfigSpec.BooleanValue disableVanillaFog;
|
||||
|
||||
FogQualityOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
|
||||
@@ -198,7 +201,7 @@ public class LodConfig
|
||||
+ " At what distance should Fog be drawn on the fake chunks? \n"
|
||||
+ " If the fog cuts off abruptly or you are using Optifine's \"fast\" fog option \n"
|
||||
+ " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n")
|
||||
.defineEnum("Fog Distance", FogDistance.NEAR_AND_FAR);
|
||||
.defineEnum("Fog Distance", FogDistance.FAR);
|
||||
|
||||
fogDrawOverride = builder
|
||||
.comment("\n\n"
|
||||
@@ -208,6 +211,16 @@ public class LodConfig
|
||||
+ " " + FogDrawOverride.FAST + ": Always draw fast fog on the LODs \n"
|
||||
+ " " + FogDrawOverride.FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n")
|
||||
.defineEnum("Fog Draw Override", FogDrawOverride.FANCY);
|
||||
|
||||
disableVanillaFog = builder
|
||||
.comment("\n\n"
|
||||
+ " If true disable vanilla Minecraft's fog. \n\n"
|
||||
+ ""
|
||||
+ " Unlike Optifine or Sodium's fog disabling option this won't change \n"
|
||||
+ " performance (we don't actually disable the fog, we just tell it to render a infinite distance away). \n"
|
||||
+ " May or may not play nice with other mods edit fog. \n")
|
||||
.define("Disable Vanilla Fog", true);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
@@ -225,6 +238,8 @@ public class LodConfig
|
||||
|
||||
public final ForgeConfigSpec.EnumValue<GpuUploadMethod> gpuUploadMethod;
|
||||
|
||||
public final ForgeConfigSpec.BooleanValue useExtendedNearClipPlane;
|
||||
|
||||
AdvancedGraphicsOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
|
||||
@@ -269,12 +284,12 @@ public class LodConfig
|
||||
+ " How often should LODs be drawn on top of regular chunks? \n"
|
||||
+ " HALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves. \n\n"
|
||||
+ " " + VanillaOverdraw.NEVER + ": LODs won't render on top of vanilla chunks. \n"
|
||||
+ " " + VanillaOverdraw.BORDER + ": LODs will render only on the border of vanilla chunks preventing only some holes in the world. \n"
|
||||
+ " " + VanillaOverdraw.DYNAMIC + ": LODs will render on top of distant vanilla chunks to hide delayed loading. \n"
|
||||
+ " " + " More effective on higher render distances. \n"
|
||||
+ " " + " For vanilla render distances less than or equal to " + LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW + " \n"
|
||||
+ " " + " " + VanillaOverdraw.NEVER + " or " + VanillaOverdraw.ALWAYS + " may be used depending on the dimension. \n"
|
||||
+ " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n"
|
||||
+ " " + VanillaOverdraw.BORDER + ": LODs will render only on the border of vanilla chunks preventing only some holes in the world. \n")
|
||||
+ " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n")
|
||||
.defineEnum("Vanilla Overdraw", VanillaOverdraw.DYNAMIC);
|
||||
|
||||
gpuUploadMethod = builder
|
||||
@@ -286,6 +301,14 @@ public class LodConfig
|
||||
+ " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly better than " + GpuUploadMethod.SUB_DATA + " if using a integrated GPU. \n")
|
||||
.defineEnum("GPU Upload Method", GpuUploadMethod.BUFFER_STORAGE);
|
||||
|
||||
// This is a temporary fix (like vanilla overdraw)
|
||||
// hopefully we can remove both once we get individual chunk rendering figured out
|
||||
useExtendedNearClipPlane = builder
|
||||
.comment("\n\n"
|
||||
+ " Will prevent some overdraw issues, but may cause nearby fake chunks to render incorrectly \n"
|
||||
+ " especially when in/near an ocean. \n")
|
||||
.define("Use Extended Near Clip Plane", false);
|
||||
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
@@ -480,24 +503,18 @@ public class LodConfig
|
||||
{
|
||||
public final ForgeConfigSpec.BooleanValue drawLods;
|
||||
public final ForgeConfigSpec.EnumValue<DebugMode> debugMode;
|
||||
public final ForgeConfigSpec.BooleanValue usePregen;
|
||||
public final ForgeConfigSpec.BooleanValue enableDebugKeybindings;
|
||||
|
||||
Debugging(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment("These settings can be used to look for bugs, or see how certain aspects of the mod work.").push(this.getClass().getSimpleName());
|
||||
|
||||
usePregen = builder
|
||||
.comment("\n\n"
|
||||
+ " if true the game will use pregen when possible \n")
|
||||
.define("Use Pregen", false);
|
||||
|
||||
drawLods = builder
|
||||
.comment("\n\n"
|
||||
+ " If true, the mod is enabled and fake chunks will be drawn. \n"
|
||||
+ " If false, the mod will still generate fake chunks, \n"
|
||||
+ " but they won't be rendered. \n")
|
||||
.define("Disable Drawing", true);
|
||||
.define("Enable Rendering", true);
|
||||
|
||||
debugMode = builder
|
||||
.comment("\n\n"
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.GenerationPriority;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
@@ -438,6 +437,7 @@ public class LodDimension
|
||||
}
|
||||
|
||||
/**
|
||||
* Use addVerticalData when possible.
|
||||
* Add the given LOD to this dimension at the coordinate
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinate it will be overwritten.
|
||||
@@ -603,9 +603,6 @@ public class LodDimension
|
||||
//if(lodRegion.isChunkPreGenerated(xChunkToCheck,zChunkToCheck))
|
||||
// complexity = DistanceGenerationMode.SERVER.complexity;
|
||||
//else
|
||||
if(LodConfig.CLIENT.advancedModOptions.debugging.usePregen.get() && isChunkPreGenerated(xChunkToCheck, zChunkToCheck))
|
||||
complexity = DistanceGenerationMode.SERVER.complexity;
|
||||
else
|
||||
complexity = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get().complexity;
|
||||
|
||||
|
||||
@@ -821,15 +818,15 @@ public class LodDimension
|
||||
/**
|
||||
* Return true if the chunk has been pregenerated in game
|
||||
*/
|
||||
public boolean isChunkPreGenerated(int xChunkPos, int zChunkPos)
|
||||
{
|
||||
|
||||
LodRegion region = getRegion(LodUtil.CHUNK_DETAIL_LEVEL, xChunkPos, zChunkPos);
|
||||
if (region == null)
|
||||
return false;
|
||||
|
||||
return region.isChunkPreGenerated(xChunkPos, zChunkPos);
|
||||
}
|
||||
//public boolean isChunkPreGenerated(int xChunkPos, int zChunkPos)
|
||||
//{
|
||||
//
|
||||
// LodRegion region = getRegion(LodUtil.CHUNK_DETAIL_LEVEL, xChunkPos, zChunkPos);
|
||||
// if (region == null)
|
||||
// return false;
|
||||
//
|
||||
// return region.isChunkPreGenerated(xChunkPos, zChunkPos);
|
||||
//}
|
||||
|
||||
/**
|
||||
* Returns whether the region at the given RegionPos
|
||||
@@ -870,7 +867,7 @@ public class LodDimension
|
||||
public void setRegionWidth(int newWidth)
|
||||
{
|
||||
width = newWidth;
|
||||
halfWidth = Math.floorDiv(width, 2);
|
||||
halfWidth = width/ 2;
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
@@ -25,13 +25,6 @@ import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.storage.RegionFile;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LevelContainers acting as a quad tree
|
||||
@@ -65,7 +58,7 @@ public class LodRegion
|
||||
/**
|
||||
* This chunk Pos has been generated
|
||||
*/
|
||||
private final boolean[] preGeneratedChunkPos;
|
||||
//private final boolean[] preGeneratedChunkPos;
|
||||
|
||||
/**
|
||||
* the generation mode for this region
|
||||
@@ -103,9 +96,9 @@ public class LodRegion
|
||||
|
||||
boolean fileFound = false;
|
||||
|
||||
|
||||
/*
|
||||
preGeneratedChunkPos = new boolean[32 * 32];
|
||||
if (MinecraftWrapper.INSTANCE.hasSinglePlayerServer())
|
||||
if (MinecraftWrapper.INSTANCE.hasSinglePlayerServer() && LodConfig.CLIENT.worldGenerator.useExperimentalPreGenLoading.get())
|
||||
{
|
||||
File regionFileDirHead;
|
||||
File regionFileDirParent;
|
||||
@@ -115,7 +108,7 @@ public class LodRegion
|
||||
|
||||
// provider needs a separate variable to prevent
|
||||
// the compiler from complaining
|
||||
//StringBuilder string = new StringBuilder();
|
||||
StringBuilder string = new StringBuilder();
|
||||
try
|
||||
{
|
||||
ServerChunkProvider provider = serverWorld.getChunkSource();
|
||||
@@ -126,7 +119,7 @@ public class LodRegion
|
||||
{
|
||||
regionFileDirParent = regionFileDirHead.getParentFile();
|
||||
//string.append(regionFileDirParent.toString());
|
||||
//string.append(regionFileDirHead);
|
||||
string.append(regionFileDirHead);
|
||||
RegionFile regionFile = new RegionFile(regionFileDirHead, regionFileDirParent, true);
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
@@ -136,7 +129,7 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
|
||||
/*string.append("region " + regionPosX + " " + regionPosZ + "\n");
|
||||
string.append("region " + regionPosX + " " + regionPosZ + "\n");
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
for (int z = 0; z < 32; z++)
|
||||
@@ -144,8 +137,8 @@ public class LodRegion
|
||||
//regionFile.doesChunkExist()
|
||||
string.append(preGeneratedChunkPos[x * 32 + z] + "\t");
|
||||
}
|
||||
//string.append("\n");
|
||||
}*/
|
||||
string.append("\n");
|
||||
}
|
||||
regionFile.close();
|
||||
}
|
||||
}
|
||||
@@ -153,8 +146,8 @@ public class LodRegion
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println(string);
|
||||
}
|
||||
System.out.println(string);
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -162,12 +155,12 @@ public class LodRegion
|
||||
/**
|
||||
* Return true if the chunk has been pregenerated in game
|
||||
*/
|
||||
public boolean isChunkPreGenerated(int xChunkPos, int zChunkPos)
|
||||
{
|
||||
xChunkPos = LevelPosUtil.getRegionModule(LodUtil.CHUNK_DETAIL_LEVEL, xChunkPos);
|
||||
zChunkPos = LevelPosUtil.getRegionModule(LodUtil.CHUNK_DETAIL_LEVEL, zChunkPos);
|
||||
return preGeneratedChunkPos[xChunkPos * 32 + zChunkPos];
|
||||
}
|
||||
//public boolean isChunkPreGenerated(int xChunkPos, int zChunkPos)
|
||||
//{
|
||||
// xChunkPos = LevelPosUtil.getRegionModule(LodUtil.CHUNK_DETAIL_LEVEL, xChunkPos);
|
||||
// zChunkPos = LevelPosUtil.getRegionModule(LodUtil.CHUNK_DETAIL_LEVEL, zChunkPos);
|
||||
// return preGeneratedChunkPos[xChunkPos * 32 + zChunkPos];
|
||||
//}
|
||||
|
||||
/**
|
||||
* Inserts the data point into the region.
|
||||
|
||||
@@ -36,7 +36,7 @@ public class NearFarFogSettings
|
||||
|
||||
/**
|
||||
* If true that means Minecraft is
|
||||
* rendering fog alongside us
|
||||
* rendering fog
|
||||
*/
|
||||
public boolean vanillaIsRenderingFog = true;
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
@Override
|
||||
public void clear(int posX, int posZ)
|
||||
{
|
||||
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++)
|
||||
@@ -68,7 +67,6 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
@Override
|
||||
public boolean addData(long data, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = data;
|
||||
@@ -78,7 +76,6 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
@Override
|
||||
public boolean addVerticalData(long[] data, int posX, int posZ)
|
||||
{
|
||||
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++)
|
||||
@@ -134,7 +131,7 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
index++;
|
||||
maxVerticalData = inputData[index];
|
||||
index++;
|
||||
size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int x = size * size * maxVerticalData;
|
||||
this.dataContainer = new long[x];
|
||||
for (int i = 0; i < x; i++)
|
||||
@@ -177,13 +174,7 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
}
|
||||
data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getMaxVerticalData());
|
||||
|
||||
for (int verticalIndex = 0; (verticalIndex < data.length) && (verticalIndex < maxVerticalData); verticalIndex++)
|
||||
{
|
||||
addData(data[verticalIndex],
|
||||
posX,
|
||||
posZ,
|
||||
verticalIndex);
|
||||
}
|
||||
addVerticalData(data, posX, posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,7 +208,7 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
{
|
||||
/*
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
for (int x = 0; x < size; x++)
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
package com.seibel.lod.proxy;
|
||||
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.util.text.TextComponent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -175,9 +173,11 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.worldGenerator.lodQualityMode.set(VerticalQuality.VOXEL);
|
||||
|
||||
// LodConfig.CLIENT.graphics.fogQualityOption.fogDistance.set(FogDistance.FAR);
|
||||
// LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
// LodConfig.CLIENT.graphics.fogQualityOption.fogDrawOverride.set(FogDrawOverride.FANCY);
|
||||
// LodConfig.CLIENT.graphics.fogQualityOption.disableVanillaFog.set(true);
|
||||
// LodConfig.CLIENT.graphics.shadingMode.set(ShadingMode.DARKEN_SIDES);
|
||||
// LodConfig.CLIENT.graphics.vanillaOverdraw.set(VanillaOverdraw.HALF);
|
||||
|
||||
// LodConfig.CLIENT.graphics.advancedGraphicsOption.vanillaOverdraw.set(VanillaOverdraw.DYNAMIC);
|
||||
|
||||
// LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.set(GpuUploadMethod.BUFFER_STORAGE);
|
||||
|
||||
@@ -301,17 +301,6 @@ public class ClientProxy
|
||||
{
|
||||
LodConfig.CLIENT.advancedModOptions.debugging.drawLods.set(!LodConfig.CLIENT.advancedModOptions.debugging.drawLods.get());
|
||||
}
|
||||
|
||||
if (LodConfig.CLIENT.advancedModOptions.debugging.enableDebugKeybindings.get()
|
||||
&& event.getKey() == GLFW.GLFW_KEY_F7 && event.getAction() == GLFW.GLFW_PRESS)
|
||||
{
|
||||
LodConfig.CLIENT.advancedModOptions.debugging.usePregen.set(!LodConfig.CLIENT.advancedModOptions.debugging.usePregen.get());
|
||||
ClientPlayerEntity player = MinecraftWrapper.INSTANCE.getPlayer();
|
||||
if(LodConfig.CLIENT.advancedModOptions.debugging.usePregen.get())
|
||||
player.sendMessage(new StringTextComponent("pregen activated."),player.getUUID());
|
||||
else
|
||||
player.sendMessage(new StringTextComponent("pregen de-activated."),player.getUUID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.seibel.lod.render;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL15C;
|
||||
import org.lwjgl.opengl.NVFogDistance;
|
||||
@@ -49,10 +48,10 @@ import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -65,7 +64,7 @@ import net.minecraft.util.math.vector.Vector3d;
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-23-2021
|
||||
* @version 10-25-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
@@ -73,7 +72,7 @@ public class LodRenderer
|
||||
* this is the light used when rendering the LODs,
|
||||
* it should be something different from what is used by Minecraft
|
||||
*/
|
||||
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
|
||||
private static final int LOD_GL_LIGHT_NUMBER = GL15.GL_LIGHT2;
|
||||
|
||||
/**
|
||||
* If true the LODs colors will be replaced with
|
||||
@@ -106,6 +105,7 @@ public class LodRenderer
|
||||
private int[] previousPos = new int[] { 0, 0, 0 };
|
||||
|
||||
public NativeImage lightMap = null;
|
||||
public NativeImage lastLightMap = null;
|
||||
|
||||
// these variables are used to determine if the buffers should be rebuilt
|
||||
private float prevSkyBrightness = 0;
|
||||
@@ -132,6 +132,7 @@ public class LodRenderer
|
||||
*/
|
||||
public boolean[][] vanillaRenderedChunks;
|
||||
public boolean vanillaRenderedChunksChanged;
|
||||
public boolean vanillaRenderedChunksEmptySkip = false;
|
||||
public int vanillaBlockRenderedDistance;
|
||||
|
||||
|
||||
@@ -161,6 +162,10 @@ public class LodRenderer
|
||||
@SuppressWarnings("deprecation")
|
||||
public void drawLODs(LodDimension lodDim, MatrixStack mcMatrixStack, float partialTicks, IProfiler newProfiler)
|
||||
{
|
||||
//=================================//
|
||||
// determine if LODs should render //
|
||||
//=================================//
|
||||
|
||||
if (lodDim == null)
|
||||
{
|
||||
// if there aren't any loaded LodChunks
|
||||
@@ -168,6 +173,17 @@ public class LodRenderer
|
||||
return;
|
||||
}
|
||||
|
||||
if (mc.getPlayer().getActiveEffectsMap().get(Effects.BLINDNESS) != null)
|
||||
{
|
||||
// if the player is blind don't render LODs,
|
||||
// and don't change minecraft's fog
|
||||
// which blindness relies on.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// initial setup //
|
||||
@@ -218,27 +234,27 @@ public class LodRenderer
|
||||
// set the required open GL settings
|
||||
|
||||
if (LodConfig.CLIENT.advancedModOptions.debugging.debugMode.get() == DebugMode.SHOW_DETAIL_WIREFRAME)
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_LINE);
|
||||
else
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_FILL);
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
GL15.glDisable(GL15.GL_TEXTURE_2D);
|
||||
GL15.glEnable(GL15.GL_CULL_FACE);
|
||||
GL15.glEnable(GL15.GL_COLOR_MATERIAL);
|
||||
GL15.glEnable(GL15.GL_DEPTH_TEST);
|
||||
|
||||
// enable transparent rendering
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL15.glBlendFunc(GL15.GL_SRC_ALPHA, GL15.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL15.glEnable(GL15.GL_BLEND);
|
||||
|
||||
// disable the lights Minecraft uses
|
||||
GL11.glDisable(GL11.GL_LIGHT0);
|
||||
GL11.glDisable(GL11.GL_LIGHT1);
|
||||
GL15.glDisable(GL15.GL_LIGHT0);
|
||||
GL15.glDisable(GL15.GL_LIGHT1);
|
||||
|
||||
// get the default projection matrix, so we can
|
||||
// reset it after drawing the LODs
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
Matrix4f mcProjectionMatrix = new Matrix4f(mcProjMatrixRaw);
|
||||
// OpenGl outputs their matrices in col,row form instead of row,col
|
||||
// (or maybe vice versa I have no idea :P)
|
||||
@@ -252,7 +268,8 @@ public class LodRenderer
|
||||
else
|
||||
farPlaneBlockDistance = LodConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
setupProjectionMatrix(mcProjectionMatrix, partialTicks);
|
||||
setupProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, partialTicks);
|
||||
|
||||
// commented out until we can add shaders to handle lighting
|
||||
//setupLighting(lodDim, partialTicks);
|
||||
|
||||
@@ -260,11 +277,10 @@ public class LodRenderer
|
||||
|
||||
// determine the current fog settings, so they can be
|
||||
// reset after drawing the LODs
|
||||
float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START);
|
||||
float defaultFogEndDist = GL11.glGetFloat(GL11.GL_FOG_END);
|
||||
int defaultFogMode = GL11.glGetInteger(GL11.GL_FOG_MODE);
|
||||
int defaultFogDistance = GL11.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV);
|
||||
|
||||
float defaultFogStartDist = GL15.glGetFloat(GL15.GL_FOG_START);
|
||||
float defaultFogEndDist = GL15.glGetFloat(GL15.GL_FOG_END);
|
||||
int defaultFogMode = GL15.glGetInteger(GL15.GL_FOG_MODE);
|
||||
int defaultFogDistance = GlProxy.getInstance().fancyFogAvailable ? GL15.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV) : -1;
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
@@ -323,13 +339,13 @@ public class LodRenderer
|
||||
|
||||
profiler.popPush("LOD cleanup");
|
||||
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_FILL);
|
||||
GL15.glEnable(GL15.GL_TEXTURE_2D);
|
||||
GL15.glDisable(LOD_GL_LIGHT_NUMBER);
|
||||
GL15.glDisable(GL15.GL_BLEND);
|
||||
// re-enable the lights Minecraft uses
|
||||
GL11.glEnable(GL11.GL_LIGHT0);
|
||||
GL11.glEnable(GL11.GL_LIGHT1);
|
||||
GL15.glEnable(GL15.GL_LIGHT0);
|
||||
GL15.glEnable(GL15.GL_LIGHT1);
|
||||
RenderSystem.disableLighting();
|
||||
|
||||
// reset the fog settings so the normal chunks
|
||||
@@ -342,7 +358,7 @@ public class LodRenderer
|
||||
|
||||
// clear the depth buffer so anything drawn is drawn
|
||||
// over the LODs
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GL15.glClear(GL15.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
@@ -360,7 +376,7 @@ public class LodRenderer
|
||||
// 0L is the starting pointer
|
||||
LodUtil.LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
vbo.draw(modelViewMatrix, GL15.GL_QUADS);
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
LodUtil.LOD_VERTEX_FORMAT.clearBufferState();
|
||||
@@ -377,7 +393,7 @@ public class LodRenderer
|
||||
// 0L is the starting pointer
|
||||
LodUtil.LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
vbo.draw(modelViewMatrix, GL15.GL_QUADS);
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
LodUtil.LOD_VERTEX_FORMAT.clearBufferState();
|
||||
@@ -395,8 +411,7 @@ public class LodRenderer
|
||||
{
|
||||
if (fogQuality == FogQuality.OFF)
|
||||
{
|
||||
FogRenderer.setupNoFog();
|
||||
RenderSystem.disableFog();
|
||||
GL15.glDisable(GL15.GL_FOG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,15 +474,18 @@ public class LodRenderer
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnable(GL11.GL_FOG);
|
||||
GL15.glEnable(GL15.GL_FOG);
|
||||
RenderSystem.enableFog();
|
||||
RenderSystem.setupNvFogDistance();
|
||||
RenderSystem.fogMode(GlStateManager.FogMode.LINEAR);
|
||||
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, glFogDistanceMode);
|
||||
|
||||
if (GlProxy.getInstance().fancyFogAvailable)
|
||||
GL15.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, glFogDistanceMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert any changes that were made to the fog.
|
||||
/**
|
||||
* Revert any changes that were made to the fog
|
||||
* and sets up the fog for Minecraft.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void cleanupFog(NearFarFogSettings fogSettings,
|
||||
@@ -477,15 +495,27 @@ public class LodRenderer
|
||||
RenderSystem.fogStart(defaultFogStartDist);
|
||||
RenderSystem.fogEnd(defaultFogEndDist);
|
||||
RenderSystem.fogMode(defaultFogMode);
|
||||
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, defaultFogDistance);
|
||||
|
||||
// disable fog if Minecraft wasn't rendering fog,
|
||||
// but we were
|
||||
if (!fogSettings.vanillaIsRenderingFog &&
|
||||
(fogSettings.near.quality != FogQuality.OFF ||
|
||||
fogSettings.far.quality != FogQuality.OFF))
|
||||
// this setting is only valid if the GPU supports fancy fog
|
||||
if (GlProxy.getInstance().fancyFogAvailable)
|
||||
GL15.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, defaultFogDistance);
|
||||
|
||||
// disable fog if Minecraft wasn't rendering fog
|
||||
// or we want it disabled
|
||||
if (!fogSettings.vanillaIsRenderingFog
|
||||
|| LodConfig.CLIENT.graphics.fogQualityOption.disableVanillaFog.get())
|
||||
{
|
||||
GL11.glDisable(GL11.GL_FOG);
|
||||
// Make fog render a infinite distance away.
|
||||
// This doesn't technically disable Minecraft's fog
|
||||
// so performance will probably be the same regardless, unlike
|
||||
// Optifine's no fog setting.
|
||||
|
||||
// we can't disable minecraft's fog outright because by default
|
||||
// minecraft will re-enable the fog after our code
|
||||
|
||||
RenderSystem.fogStart(0.0F);
|
||||
RenderSystem.fogEnd(Float.MAX_VALUE);
|
||||
RenderSystem.fogDensity(0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,12 +541,12 @@ public class LodRenderer
|
||||
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
// accuracy vs the model view matrix, which only uses floats)
|
||||
BlockPos bufferPos = vbosCenter.getWorldPosition();
|
||||
Vector3d eyePos = mc.getPlayer().getEyePosition(partialTicks);
|
||||
double xDiff = eyePos.x - bufferPos.getX();
|
||||
double zDiff = eyePos.z - bufferPos.getZ();
|
||||
double xDiff = projectedView.x - bufferPos.getX();
|
||||
double zDiff = projectedView.z - bufferPos.getZ();
|
||||
mcMatrixStack.translate(-xDiff, -projectedView.y, -zDiff);
|
||||
|
||||
|
||||
|
||||
// get the modified model view matrix
|
||||
Matrix4f lodModelViewMatrix = mcMatrixStack.last().pose();
|
||||
// remove the lod ModelViewMatrix
|
||||
@@ -524,44 +554,21 @@ public class LodRenderer
|
||||
|
||||
return lodModelViewMatrix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
final boolean lodProjUseFov;
|
||||
final boolean defaultMcProjUseFov;
|
||||
|
||||
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 vanillaBlockRenderedDistance Minecraft's vanilla far plane distance
|
||||
* @param partialTicks how many ticks into the frame we are
|
||||
*/
|
||||
private void setupProjectionMatrix(Matrix4f currentProjectionMatrix, float partialTicks)
|
||||
private void setupProjectionMatrix(Matrix4f currentProjectionMatrix, float vanillaBlockRenderedDistance, float partialTicks)
|
||||
{
|
||||
//Minimum radious of view in 2 render distance
|
||||
int minDistance = 1;
|
||||
// create the new projection matrix
|
||||
Matrix4f lodPoj =
|
||||
Matrix4f.perspective(
|
||||
getFov(partialTicks, true),
|
||||
(float) this.mc.getWindow().getScreenWidth() / (float) this.mc.getWindow().getScreenHeight(),
|
||||
minDistance,
|
||||
LodConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.get() ? vanillaBlockRenderedDistance / 5 : 1,
|
||||
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2);
|
||||
|
||||
// get Minecraft's un-edited projection matrix
|
||||
@@ -625,8 +632,8 @@ public class LodRenderer
|
||||
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(16);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
GL11.glLightfv(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
|
||||
GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
|
||||
GL15.glLightfv(LOD_GL_LIGHT_NUMBER, GL15.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
|
||||
GL15.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
|
||||
|
||||
RenderSystem.enableLighting();
|
||||
}*/
|
||||
@@ -669,9 +676,7 @@ public class LodRenderer
|
||||
vbosCenter = result.drawableCenterChunkPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the BufferBuilder's destroyBuffers method.
|
||||
*/
|
||||
/** Calls the BufferBuilder's destroyBuffers method. */
|
||||
public void destroyBuffers()
|
||||
{
|
||||
lodBufferBuilder.destroyBuffers();
|
||||
@@ -684,9 +689,7 @@ public class LodRenderer
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return what fog settings should be used when rendering.
|
||||
*/
|
||||
/** Return what fog settings should be used when rendering. */
|
||||
private NearFarFogSettings determineFogSettings()
|
||||
{
|
||||
NearFarFogSettings fogSettings = new NearFarFogSettings();
|
||||
@@ -871,6 +874,11 @@ public class LodRenderer
|
||||
prevSkyBrightness = skyBrightness;
|
||||
}
|
||||
|
||||
/*if (lightMap != lastLightMap)
|
||||
{
|
||||
fullRegen = true;
|
||||
lastLightMap = lightMap;
|
||||
}*/
|
||||
|
||||
//================//
|
||||
// partial regens //
|
||||
@@ -884,7 +892,6 @@ public class LodRenderer
|
||||
{
|
||||
partialRegen = true;
|
||||
vanillaRenderedChunksChanged = false;
|
||||
|
||||
}
|
||||
prevVanillaChunkTime = newTime;
|
||||
}
|
||||
@@ -913,6 +920,8 @@ public class LodRenderer
|
||||
int zIndex;
|
||||
for (ChunkPos pos : chunkPosToSkip)
|
||||
{
|
||||
vanillaRenderedChunksEmptySkip = false;
|
||||
|
||||
xIndex = (pos.x - mc.getPlayer().xChunk) + (chunkRenderDistance + 1);
|
||||
zIndex = (pos.z - mc.getPlayer().zChunk) + (chunkRenderDistance + 1);
|
||||
|
||||
@@ -933,10 +942,11 @@ public class LodRenderer
|
||||
|
||||
|
||||
// if the player is high enough, draw all LODs
|
||||
if (chunkPosToSkip.isEmpty() && mc.getPlayer().position().y > 256)
|
||||
if (chunkPosToSkip.isEmpty() && mc.getPlayer().position().y > 256 && !vanillaRenderedChunksEmptySkip)
|
||||
{
|
||||
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
|
||||
vanillaRenderedChunksChanged = true;
|
||||
vanillaRenderedChunksEmptySkip = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ public class DataPointUtil
|
||||
int size = dataToMerge.length / inputVerticalData;
|
||||
|
||||
// We initialize the arrays that are going to be used
|
||||
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((worldHeight + 1) * 2);
|
||||
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((worldHeight / 2 + 1) * 2);
|
||||
long[] dataPoint = ThreadMapUtil.getVerticalDataArray(DetailDistanceUtil.getMaxVerticalData(0));
|
||||
|
||||
|
||||
|
||||
@@ -97,12 +97,13 @@ public class DetailDistanceUtil
|
||||
return (byte) minDetail;
|
||||
int distanceUnit = LodConfig.CLIENT.graphics.qualityOption.horizontalScale.get().distanceUnit;
|
||||
if (LodConfig.CLIENT.graphics.qualityOption.horizontalQuality.get() == HorizontalQuality.LOWEST)
|
||||
detail = (byte) Math.floorDiv(distance, distanceUnit);
|
||||
detail = (byte) distance / distanceUnit;
|
||||
else
|
||||
{
|
||||
double base = LodConfig.CLIENT.graphics.qualityOption.horizontalQuality.get().quadraticBase;
|
||||
double logBase = Math.log(base);
|
||||
detail = (byte) (Math.log(Math.floorDiv(distance, distanceUnit)) / logBase);
|
||||
//noinspection IntegerDivisionInFloatingPointContext
|
||||
detail = (byte) (Math.log(distance / distanceUnit) / logBase);
|
||||
}
|
||||
return (byte) LodUtil.clamp(minDetail, detail, maxDetail - 1);
|
||||
}
|
||||
@@ -119,14 +120,11 @@ public class DetailDistanceUtil
|
||||
|
||||
public static byte getTreeCutDetailFromDistance(int distance)
|
||||
{
|
||||
|
||||
return baseInverseFunction((int) (distance * treeCutMultiplier), minGenDetail, true);
|
||||
}
|
||||
|
||||
|
||||
public static byte getTreeGenDetailFromDistance(int distance)
|
||||
{
|
||||
|
||||
return baseInverseFunction((int) (distance * treeGenMultiplier), minGenDetail, true);
|
||||
}
|
||||
|
||||
@@ -156,30 +154,20 @@ public class DetailDistanceUtil
|
||||
public static HorizontalResolution getLodGenDetail(int detail)
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
{
|
||||
return lodGenDetails[minGenDetail];
|
||||
}
|
||||
else
|
||||
{
|
||||
return lodGenDetails[detail];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static byte getCutLodDetail(int detail)
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
{
|
||||
return lodGenDetails[minGenDetail].detailLevel;
|
||||
}
|
||||
else if (detail == maxDetail)
|
||||
{
|
||||
return LodUtil.REGION_DETAIL_LEVEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lodGenDetails[detail].detailLevel;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getMaxVerticalData(int detail)
|
||||
|
||||
@@ -149,6 +149,10 @@ public class LevelPosUtil
|
||||
return convert(detailLevel, pos, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
public static int myPow2(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
public static int maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ)
|
||||
{
|
||||
@@ -156,13 +160,15 @@ public class LevelPosUtil
|
||||
|
||||
int startPosX = posX * width;
|
||||
int startPosZ = posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
int endPosX = myPow2(playerPosX - startPosX - width);
|
||||
int endPosZ = myPow2(playerPosZ - startPosZ - width);
|
||||
startPosX = myPow2(playerPosX - startPosX);
|
||||
startPosZ = myPow2(playerPosZ - startPosZ);
|
||||
|
||||
int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
int maxDistance = (int) Math.sqrt(startPosX + startPosZ);
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(startPosX + endPosZ));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(endPosX + startPosZ));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(endPosX + endPosZ));
|
||||
|
||||
return maxDistance;
|
||||
}
|
||||
@@ -205,10 +211,15 @@ public class LevelPosUtil
|
||||
}
|
||||
else
|
||||
{
|
||||
int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
startPosX = myPow2(playerPosX - startPosX);
|
||||
startPosZ = myPow2(playerPosZ - startPosZ);
|
||||
endPosX = myPow2(playerPosX - endPosX);
|
||||
endPosZ = myPow2(playerPosZ - endPosZ);
|
||||
|
||||
int minDistance = (int) Math.sqrt(startPosX + startPosZ);
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(startPosX + endPosZ));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(endPosX + startPosZ));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(endPosX + endPosZ));
|
||||
return minDistance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,8 +201,8 @@ public class LodUtil
|
||||
/** 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));
|
||||
int relativePosX = Math.floorDiv(x, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
int relativePosZ = Math.floorDiv(z, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
|
||||
return new RegionPos(relativePosX, relativePosZ);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ public class LodUtil
|
||||
/** Convert a 2D absolute position into a quad tree relative position. */
|
||||
public static int convertLevelPos(int pos, int currentDetailLevel, int targetDetailLevel)
|
||||
{
|
||||
return Math.floorDiv(pos, (int) Math.pow(2, targetDetailLevel - currentDetailLevel));
|
||||
return pos / (1 << (targetDetailLevel - currentDetailLevel));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,9 +224,7 @@ public class LodUtil
|
||||
for (ChunkSection section : blockStorage)
|
||||
{
|
||||
if (section != null && !section.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -492,20 +490,9 @@ public class LodUtil
|
||||
{
|
||||
tempX = x + Box.DIRECTION_NORMAL_MAP.get(direction).getX();
|
||||
tempZ = z + Box.DIRECTION_NORMAL_MAP.get(direction).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;
|
||||
}
|
||||
}
|
||||
if (vanillaRenderedChunks[x][z] || (!(tempX < 0 || tempZ < 0 || tempX >= vanillaRenderedChunks.length || tempZ >= vanillaRenderedChunks[0].length)
|
||||
&& !vanillaRenderedChunks[tempX][tempZ]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public class ThreadMapUtil
|
||||
int size = 1;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
array[i] = new long[size * size * DataPointUtil.worldHeight + 1];
|
||||
array[i] = new long[size * size * DataPointUtil.worldHeight / 2 + 1];
|
||||
size = size << 1;
|
||||
}
|
||||
threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.seibel.lod.wrappers.Block;
|
||||
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
//This class wraps the minecraft BlockPos.Mutable (and BlockPos) class
|
||||
public class BlockPosWrapper
|
||||
{
|
||||
private BlockPos.Mutable blockPos;
|
||||
|
||||
|
||||
public BlockPosWrapper()
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable();
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z)
|
||||
{
|
||||
blockPos.set(x, y, z);
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return blockPos.getX();
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return blockPos.getY();
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return blockPos.getZ();
|
||||
}
|
||||
|
||||
public BlockPos.Mutable getBlockPos()
|
||||
{
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
return blockPos.equals(o);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(blockPos);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
package com.seibel.lod.wrappers.Block;
|
||||
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
//This class wraps the minecraft Block class
|
||||
public class BlockWrapper
|
||||
{
|
||||
//set of block which require tint
|
||||
public static final ConcurrentMap<Block, BlockWrapper> blockWrapperMap = new ConcurrentHashMap<>();
|
||||
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
public static Random random = new Random(0);
|
||||
|
||||
|
||||
private Block block;
|
||||
private boolean nonFull;
|
||||
private boolean noCollision;
|
||||
private int color;
|
||||
private boolean isColored;
|
||||
private boolean toTint;
|
||||
private boolean leavesTint;
|
||||
private boolean grassTint;
|
||||
private boolean waterTint;
|
||||
|
||||
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockWrapper(Block block)
|
||||
{
|
||||
this.nonFull = true;
|
||||
this.noCollision = true;
|
||||
this.color = 0;
|
||||
this.isColored = true;
|
||||
this.toTint = false;
|
||||
this.block = block;
|
||||
setupColorAndTint();
|
||||
setupShapes();
|
||||
}
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block Block object to wrap
|
||||
*/
|
||||
static public BlockWrapper getBlockWrapper(Block block)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if(blockWrapperMap.containsKey(block) && blockWrapperMap.get(block) != null)
|
||||
return blockWrapperMap.get(block);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockWrapper blockWrapper = new BlockWrapper(block);
|
||||
blockWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the color of the given block from its texture
|
||||
* and store it for later use.
|
||||
*/
|
||||
private void setupColorAndTint()
|
||||
{
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
TextureAtlasSprite texture;
|
||||
List<BakedQuad> quads = null;
|
||||
|
||||
boolean isTinted = false;
|
||||
int listSize = 0;
|
||||
|
||||
// first step is to check if this block has a tinted face
|
||||
for (Direction direction : Direction.values())
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(block.defaultBlockState(), direction, random, dataMap);
|
||||
listSize = Math.max(listSize, quads.size());
|
||||
for (BakedQuad bakedQuad : quads)
|
||||
{
|
||||
isTinted |= bakedQuad.isTinted();
|
||||
}
|
||||
}
|
||||
|
||||
//if it contains a tinted face then we store this block in the toTint set
|
||||
if(isTinted)
|
||||
this.toTint = true;
|
||||
|
||||
//now we get the first non empty face
|
||||
for (Direction direction : Direction.values())
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(block.defaultBlockState(), direction, random, dataMap);
|
||||
if (!quads.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
//the quads list is not empty we extract the first one
|
||||
if (!quads.isEmpty())
|
||||
texture = quads.get(0).getSprite();
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int alpha = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int numberOfGreyPixel = 0;
|
||||
int tempColor;
|
||||
int colorMultiplier;
|
||||
|
||||
// generate the block's color
|
||||
for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getHeight(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getWidth(); v++)
|
||||
{
|
||||
if (texture.isTransparent(frameIndex, u, v))
|
||||
continue;
|
||||
|
||||
tempColor = texture.getPixelRGBA(frameIndex, u, v);
|
||||
|
||||
// determine if this pixel is gray
|
||||
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
boolean isGray = colorMax < colorMin;
|
||||
if (isGray)
|
||||
numberOfGreyPixel++;
|
||||
|
||||
|
||||
// for flowers, weight their non-green color higher
|
||||
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
|
||||
colorMultiplier = 5;
|
||||
else
|
||||
colorMultiplier = 1;
|
||||
|
||||
|
||||
// add to the running averages
|
||||
count += colorMultiplier;
|
||||
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
|
||||
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
|
||||
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
|
||||
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = 0;
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
alpha /= count;
|
||||
red /= count;
|
||||
green /= count;
|
||||
blue /= count;
|
||||
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
// determine if this block should use the biome color tint
|
||||
if ((grassInstance() || leavesInstance() || waterIstance()) && (float) numberOfGreyPixel / count > 0.75f)
|
||||
this.toTint = true;
|
||||
|
||||
// we check which kind of tint we need to apply
|
||||
if (grassInstance() && this.toTint)
|
||||
this.grassTint = true;
|
||||
|
||||
if (leavesInstance() && this.toTint)
|
||||
this.leavesTint = true;
|
||||
|
||||
if (waterIstance() && this.toTint)
|
||||
this.waterTint = true;
|
||||
|
||||
color = tempColor;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's grass color */
|
||||
private boolean grassInstance()
|
||||
{
|
||||
return block instanceof GrassBlock
|
||||
|| block instanceof BushBlock
|
||||
|| block instanceof IGrowable
|
||||
|| block instanceof AbstractPlantBlock
|
||||
|| block instanceof AbstractTopPlantBlock
|
||||
|| block instanceof TallGrassBlock;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean leavesInstance()
|
||||
{
|
||||
return block instanceof LeavesBlock
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.SUGAR_CANE;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean waterIstance()
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
private void setupShapes(){
|
||||
|
||||
}
|
||||
|
||||
//--------------//
|
||||
//Colors getters//
|
||||
//--------------//
|
||||
|
||||
public boolean hasColor()
|
||||
{
|
||||
return isColored;
|
||||
}
|
||||
|
||||
public int getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------//
|
||||
//Tint getters//
|
||||
//------------//
|
||||
|
||||
|
||||
public boolean hasTint()
|
||||
{
|
||||
return toTint;
|
||||
}
|
||||
|
||||
public boolean hasGrassTint()
|
||||
{
|
||||
return grassTint;
|
||||
}
|
||||
|
||||
public boolean hasLeavesTint()
|
||||
{
|
||||
return leavesTint;
|
||||
}
|
||||
|
||||
public boolean hasWaterTint()
|
||||
{
|
||||
return waterTint;
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockWrapper))
|
||||
return false;
|
||||
BlockWrapper that = (BlockWrapper) o;
|
||||
return Objects.equals(block, that.block);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(block);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.seibel.lod.wrappers.Chunk;
|
||||
|
||||
|
||||
//This class will contain all methods usefull to generate the fake ChunkWrapper
|
||||
public class ChunkGenerator
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.seibel.lod.wrappers.Chunk;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
//This class wraps the minecraft ChunkPos class
|
||||
public class ChunkPosWrapper
|
||||
{
|
||||
private ChunkPos chunkPos;
|
||||
|
||||
public ChunkPosWrapper(ChunkPos chunkPos)
|
||||
{
|
||||
this.chunkPos = chunkPos;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return chunkPos.x;
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return chunkPos.z;
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
return chunkPos.equals(o);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(chunkPos);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.seibel.lod.wrappers.Chunk;
|
||||
|
||||
import com.seibel.lod.wrappers.Block.BlockWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
|
||||
public class ChunkWrapper
|
||||
{
|
||||
|
||||
private IChunk chunk;
|
||||
private ChunkPosWrapper chunkPos;
|
||||
|
||||
public ChunkWrapper(IChunk chunk)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
|
||||
}
|
||||
|
||||
public BlockWrapper getBlock(BlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockWrapper.getBlockWrapper(chunk.getBlockState(blockPos.getBlockPos()).getBlock());
|
||||
}
|
||||
|
||||
public ChunkPosWrapper getChunkPos(){
|
||||
return chunkPos;
|
||||
}
|
||||
public int getEmittedBrightness(BlockPosWrapper blockPos)
|
||||
{
|
||||
return chunk.getLightEmission(blockPos.getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.seibel.lod.wrappers;
|
||||
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
|
||||
|
||||
public class LigthMapWrapper
|
||||
{
|
||||
static NativeImage lightMap = null;
|
||||
|
||||
public static void setLightMap(NativeImage lightMap)
|
||||
{
|
||||
lightMap = null;
|
||||
}
|
||||
|
||||
public static int getLightValue(int skyLight, int blockLight)
|
||||
{
|
||||
return lightMap.getPixelRGBA(skyLight, blockLight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.wrappers.Vertex;
|
||||
|
||||
public class BufferBuilderWrapper
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.wrappers.Vertex;
|
||||
|
||||
public class VertexBufferWrapper
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockWrapper;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
//This class wraps the minecraft BlockPos.Mutable (and BlockPos) class
|
||||
public class BiomeWrapper
|
||||
{
|
||||
|
||||
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
private Biome biome;
|
||||
|
||||
public BiomeWrapper(Biome biome)
|
||||
{
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
static public BiomeWrapper getBiomeWrapper(Biome biome)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(biomeWrapperMap.containsKey(biome) && biomeWrapperMap.get(biome) != null)
|
||||
return biomeWrapperMap.get(biome);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BiomeWrapper biomeWrapper = new BiomeWrapper(biome);
|
||||
biomeWrapperMap.put(biome, biomeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return biomeWrapper;
|
||||
}
|
||||
|
||||
|
||||
/** Returns a color int for the given biome. */
|
||||
public int getColorForBiome(int x, int z)
|
||||
{
|
||||
int colorInt;
|
||||
int color;
|
||||
int tint;
|
||||
|
||||
switch (biome.getBiomeCategory())
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.NETHERRACK).getColor();
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.END_STONE).getColor();
|
||||
break;
|
||||
|
||||
case BEACH:
|
||||
case DESERT:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.SAND).getColor();
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.STONE).getColor();
|
||||
break;
|
||||
|
||||
case MUSHROOM:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.MYCELIUM).getColor();
|
||||
break;
|
||||
|
||||
case ICY:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.SNOW).getColor();
|
||||
break;
|
||||
|
||||
case MESA:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.RED_SAND).getColor();
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
colorInt = biome.getWaterColor();
|
||||
break;
|
||||
|
||||
case SWAMP:
|
||||
case FOREST:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.OAK_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
case TAIGA:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.SPRUCE_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
case JUNGLE:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.JUNGLE_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
default:
|
||||
case NONE:
|
||||
case PLAINS:
|
||||
case SAVANNA:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.GRASS_BLOCK).getColor();
|
||||
tint = biome.getGrassColor(x,z);
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BiomeWrapper))
|
||||
return false;
|
||||
BiomeWrapper that = (BiomeWrapper) o;
|
||||
return Objects.equals(biome, that.biome);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(biome);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class DimensionTypeWrapper
|
||||
{
|
||||
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
|
||||
private DimensionType dimensionType;
|
||||
|
||||
public DimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
this.dimensionType = dimensionType;
|
||||
}
|
||||
|
||||
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
|
||||
return dimensionTypeWrapperMap.get(dimensionType);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
||||
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return dimensionTypeWrapper;
|
||||
}
|
||||
|
||||
public static void clearMap()
|
||||
{
|
||||
dimensionTypeWrapperMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import net.minecraft.world.IWorld;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class WorldWrapper
|
||||
{
|
||||
private static final ConcurrentMap<IWorld, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
|
||||
private IWorld world;
|
||||
|
||||
public WorldWrapper(IWorld world)
|
||||
{
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public WorldWrapper getWorldWrapper(IWorld world)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
|
||||
return worldWrapperMap.get(world);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
WorldWrapper worldWrapper = new WorldWrapper(world);
|
||||
worldWrapperMap.put(world, worldWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return worldWrapper;
|
||||
}
|
||||
|
||||
public static void clearMap()
|
||||
{
|
||||
worldWrapperMap.clear();
|
||||
}
|
||||
|
||||
public DimensionTypeWrapper getDimensionType()
|
||||
{
|
||||
return DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
|
||||
}
|
||||
|
||||
public int getBlockLight(BlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().skyEngine.getLightValue(blockPos.getBlockPos());
|
||||
}
|
||||
|
||||
public int getSkyLight(BlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().blockEngine.getLightValue(blockPos.getBlockPos());
|
||||
}
|
||||
|
||||
public BiomeWrapper getBiome(BlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(world.getBiome(blockPos.getBlockPos()));
|
||||
}
|
||||
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return world.dimensionType().hasCeiling();
|
||||
}
|
||||
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return world.dimensionType().hasSkyLight();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user