Merge remote-tracking branch 'origin/main'

This commit is contained in:
TomTheFurry
2023-06-12 13:25:47 +08:00
29 changed files with 827 additions and 284 deletions
@@ -21,12 +21,7 @@ package com.seibel.lod.api.enums.config;
/**
* NONE, <br>
* NON_FULL, <br>
* NO_COLLISION, <br>
* BOTH, <br>
*
* @author Leonardo Amato
* @version 2022-7-1
* NON_COLLIDING, <br>
*/
public enum EBlocksToAvoid
{
@@ -34,20 +29,11 @@ public enum EBlocksToAvoid
// when adding items up the API minor version
// when removing items up the API major version
NONE(false, false),
NONE(false),
NON_COLLIDING(true);
NON_FULL(true, false),
NO_COLLISION(false, true),
BOTH(true, true);
public final boolean nonFull;
public final boolean noCollision;
EBlocksToAvoid(boolean nonFull, boolean noCollision)
{
this.nonFull = nonFull;
this.noCollision = noCollision;
}
EBlocksToAvoid(boolean noCollision) { this.noCollision = noCollision; }
}
@@ -23,12 +23,7 @@ package com.seibel.lod.api.enums.config;
* LOWEST <br>
* LOW <br>
* MEDIUM <br>
* HIGH <br> <br>
*
* this indicates the base of the quadratic function we use for the quality drop-off
*
* @author Leonardo Amato
* @version 9-29-2021
* HIGH <br>
*/
public enum EHorizontalQuality
{
@@ -37,22 +32,27 @@ public enum EHorizontalQuality
// when removing items up the API major version
/** 1.0 AKA Linear */
LOWEST(1.0f),
// FIXME any quadraticBase less than 2.0f has issues with DetailDistanceUtil, and will always return the lowest detail level.
// So for now we are limiting the lowest value to 2.0
// LOWEST was originally 1.0f and LOW was 1.5f
/** exponent 1.5 */
LOW(1.5f),
LOWEST(2.0f, 4),
LOW(2.0f, 8),
MEDIUM(2.0f, 12),
HIGH(2.2f, 24),
EXTREME(2.4f, 64),
UNLIMITED(-1, -1);
/** exponent 2.0 */
MEDIUM(2.0f),
/** exponent 2.2 */
HIGH(2.2f);
public final double quadraticBase;
public final int distanceUnitInBlocks;
EHorizontalQuality(double distanceUnit)
EHorizontalQuality(double quadraticBase, int distanceUnitInBlocks)
{
this.quadraticBase = distanceUnit;
this.quadraticBase = quadraticBase;
this.distanceUnitInBlocks = distanceUnitInBlocks;
}
}
@@ -54,8 +54,6 @@ public enum EHorizontalResolution
/**
* How many DataPoints should
* be drawn per side, per LodChunk
@@ -92,15 +90,15 @@ public enum EHorizontalResolution
EHorizontalResolution(int newLengthCount, int newDetailLevel)
{
detailLevel = (byte) newDetailLevel;
dataPointLengthCount = newLengthCount;
dataPointWidth = 16 / dataPointLengthCount;
this.detailLevel = (byte) newDetailLevel;
this.dataPointLengthCount = newLengthCount;
this.dataPointWidth = 16 / this.dataPointLengthCount;
startX = new int[dataPointLengthCount * dataPointLengthCount];
endX = new int[dataPointLengthCount * dataPointLengthCount];
this.startX = new int[this.dataPointLengthCount * this.dataPointLengthCount];
this.endX = new int[this.dataPointLengthCount * this.dataPointLengthCount];
startZ = new int[dataPointLengthCount * dataPointLengthCount];
endZ = new int[dataPointLengthCount * dataPointLengthCount];
this.startZ = new int[this.dataPointLengthCount * this.dataPointLengthCount];
this.endZ = new int[this.dataPointLengthCount * this.dataPointLengthCount];
int index = 0;
@@ -108,11 +106,11 @@ public enum EHorizontalResolution
{
for (int z = 0; z < newLengthCount; z++)
{
startX[index] = x * dataPointWidth;
startZ[index] = z * dataPointWidth;
this.startX[index] = x * this.dataPointWidth;
this.startZ[index] = z * this.dataPointWidth;
endX[index] = (x * dataPointWidth) + dataPointWidth;
endZ[index] = (z * dataPointWidth) + dataPointWidth;
this.endX[index] = (x * this.dataPointWidth) + this.dataPointWidth;
this.endZ[index] = (z * this.dataPointWidth) + this.dataPointWidth;
index++;
}
@@ -122,8 +120,9 @@ public enum EHorizontalResolution
//================//
// static methods //
//================//
/**
* Returns an array of all LodDetails that have a detail level
@@ -169,7 +168,6 @@ public enum EHorizontalResolution
int index = MathUtil.clamp(0, distance / distanceBetweenDetails, lowerDetails.length - 1);
return lowerDetails[index];
}
}
@@ -20,30 +20,20 @@
package com.seibel.lod.api.enums.config;
/**
* Low <br>
* Medium <br>
* High <br>
* <br>
* this is a quality scale for the detail drop-off
*
* @author Leonardo Amato
* @version 9-25-2021
* NONE <br>
* LIGHT <br>
* MEDIUM <br>
* HEAVY <br> <br>
*/
public enum EHorizontalScale
public enum EOverdrawPrevention
{
/** Lods are 2D with heightMap */
LOW(64),
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** Lods expand in three dimension */
MEDIUM(128),
NONE,
LIGHT,
MEDIUM,
HEAVY;
/** Lods expand in three dimension */
HIGH(256);
public final int distanceUnit;
EHorizontalScale(int distanceUnit)
{
this.distanceUnit = distanceUnit;
}
}
}
@@ -37,7 +37,7 @@ public enum EVerticalQuality
LOW(new int[] { 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }),
MEDIUM(new int[] { 6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1 }),
HIGH(new int[] { 8, 6, 4, 2, 2, 2, 2, 1, 1, 1, 1 }),
ULTRA(new int[] { 16, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1 });
EXTREME(new int[] { 16, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1 });
/** represents how many LODs can be rendered in a single vertical slice */
public final int[] maxVerticalData;
@@ -28,7 +28,7 @@ package com.seibel.lod.api.enums.config.quickOptions;
* HIGH, <br>
* EXTREME, <br>
*/
public enum EQuickQuality
public enum EQualityPreset
{
// Reminder:
// when adding items up the API minor version
@@ -25,10 +25,10 @@ package com.seibel.lod.api.enums.config.quickOptions;
* MINIMAL_IMPACT, <br>
* LOW_IMPACT, <br>
* BALANCED, <br>
* AGGRESSIVE_LOADING, <br>
* AGGRESSIVE, <br>
* I_PAID_FOR_THE_WHOLE_CPU, <br>
*/
public enum EQuickThread
public enum EThreadPreset
{
// Reminder:
// when adding items up the API minor version
@@ -39,7 +39,7 @@ public enum EQuickThread
MINIMAL_IMPACT,
LOW_IMPACT,
BALANCED,
AGGRESSIVE_LOADING,
AGGRESSIVE,
I_PAID_FOR_THE_WHOLE_CPU;
}
@@ -20,18 +20,9 @@
package com.seibel.lod.api.enums.rendering;
/**
* OFF, <br>
* SHOW_WIREFRAME, <br>
* SHOW_DETAIL, <br>
* SHOW_DETAIL_WIREFRAME, <br>
* SHOW_GENMODE, <br>
* SHOW_GENMODE_WIREFRAME, <br>
* SHOW_OVERLAPPING_QUADS, <br>
* SHOW_OVERLAPPING_QUADS_WIREFRAME, <br>
*
* @author Leetom
* @author James Seibel
* @version 2022-7-2
* DISABLED, <br>
* FAKE, <br>
* COMPLETE, <br>
*/
public enum ETransparency
{
@@ -44,12 +35,13 @@ public enum ETransparency
FAKE(true, true),
COMPLETE(true, false);
public final boolean tranparencyEnabled;
public final boolean transparencyEnabled;
public final boolean fakeTransparencyEnabled;
ETransparency(boolean tranparencyEnabled, boolean fakeTransparencyEnabled)
ETransparency(boolean transparencyEnabled, boolean fakeTransparencyEnabled)
{
this.tranparencyEnabled = tranparencyEnabled;
this.transparencyEnabled = transparencyEnabled;
this.fakeTransparencyEnabled = fakeTransparencyEnabled;
}
}
@@ -6,10 +6,16 @@ import com.seibel.lod.api.interfaces.IDhApiUnsafeWrapper;
* A Minecraft version independent way of handling Blocks.
*
* @author James Seibel
* @version 2022-11-12
* @version 2023-6-11
*/
public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper
{
boolean isAir();
boolean isSolid();
boolean isLiquid();
// TODO:
// boolean hasNoCollision();
// boolean noFaceIsFullFace();
}
@@ -39,4 +39,26 @@ public class StringUtil
pos = str.indexOf(substr, pos + 1);
return pos;
}
/** Combines each item in the given list together separated by the given delimiter. */
public static <T> String join(String delimiter, Iterable<T> list)
{
StringBuilder stringBuilder = new StringBuilder();
boolean firstItem = true;
for (T item : list)
{
if (!firstItem)
{
stringBuilder.append(delimiter);
}
stringBuilder.append(item);
firstItem = false;
}
return stringBuilder.toString();
}
}
@@ -22,11 +22,10 @@ package com.seibel.lod.core.api.external.methods.config.both;
import com.seibel.lod.api.interfaces.config.IDhApiConfigValue;
import com.seibel.lod.api.interfaces.config.both.IDhApiWorldGenerationConfig;
import com.seibel.lod.api.objects.config.DhApiConfigValue;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.Config.Client.Advanced.WorldGenerator;
import com.seibel.lod.api.enums.config.EBlocksToAvoid;
import com.seibel.lod.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.lod.api.enums.config.EGenerationPriority;
import com.seibel.lod.api.enums.config.ELightGenerationMode;
/**
* Distant Horizons' world generation configuration. <br><br>
@@ -55,12 +54,12 @@ public class DhApiWorldGenerationConfig implements IDhApiWorldGenerationConfig
@Deprecated
@Override
public IDhApiConfigValue<EBlocksToAvoid> getBlocksToAvoid()
{ return new DhApiConfigValue<>(WorldGenerator.blocksToAvoid); }
{ return new DhApiConfigValue<>(Config.Client.Advanced.Graphics.Quality.blocksToIgnore); }
@Deprecated
@Override
public IDhApiConfigValue<Boolean> getTintWithAvoidedBlocks()
{ return new DhApiConfigValue<>(WorldGenerator.tintWithAvoidedBlocks); }
{ return new DhApiConfigValue<>(Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks); }
}
@@ -24,7 +24,6 @@ import com.seibel.lod.api.interfaces.config.IDhApiConfigValue;
import com.seibel.lod.api.interfaces.config.client.IDhApiGraphicsConfig;
import com.seibel.lod.api.objects.config.DhApiConfigValue;
import com.seibel.lod.coreapi.util.converters.RenderModeEnabledConverter;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.api.enums.rendering.ERendererMode;
import com.seibel.lod.core.config.Config.Client.Advanced.Graphics.Quality;
import com.seibel.lod.core.config.Config.Client.Advanced.Debugging;
@@ -94,7 +93,7 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig
@Override
public IDhApiConfigValue<Boolean> getUseExtendedNearClipPlane()
{ return new DhApiConfigValue<>(AdvancedGraphics.useExtendedNearClipPlane); }
{ return new DhApiConfigValue<>(AdvancedGraphics.overdrawPrevention); }
@Override
public IDhApiConfigValue<Double> getBrightnessMultiplier()
@@ -21,11 +21,13 @@ package com.seibel.lod.core.config;
import com.seibel.lod.api.enums.config.*;
import com.seibel.lod.api.enums.config.quickOptions.EQuickQuality;
import com.seibel.lod.api.enums.config.quickOptions.EQuickThread;
import com.seibel.lod.api.enums.config.quickOptions.EQualityPreset;
import com.seibel.lod.api.enums.config.quickOptions.EThreadPreset;
import com.seibel.lod.api.enums.rendering.*;
import com.seibel.lod.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.lod.core.config.eventHandlers.presets.RenderQualityPresetConfigEventHandler;
import com.seibel.lod.core.config.eventHandlers.RenderCacheConfigEventHandler;
import com.seibel.lod.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
import com.seibel.lod.core.config.types.*;
import com.seibel.lod.core.config.types.enums.*;
import com.seibel.lod.coreapi.ModInfo;
@@ -78,29 +80,32 @@ public class Config
public static ConfigLinkedEntry quickLodChunkRenderDistance = new ConfigLinkedEntry(Advanced.Graphics.Quality.lodChunkRenderDistance);
public static ConfigEntry<EQuickQuality> quickQualitySetting = new ConfigEntry.Builder<EQuickQuality>()
.set(EQuickQuality.MEDIUM)
public static ConfigEntry<EQualityPreset> qualityPresetSetting = new ConfigEntry.Builder<EQualityPreset>()
.set(EQualityPreset.MEDIUM) // the default value is set via the listener when accessed
.comment(""
+ "Changing this setting will modify a number of different settings that will change the \n"
+ "visual fidelity of the rendered LODs.\n"
+ "\n"
+ "Higher settings will improve the graphical quality while increasing GPU and memory use.\n"
+ "")
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) // TODO set when the game boots
//.addListener(null) // TODO add listener
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(RenderQualityPresetConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<EQuickThread> quickThreadSetting = new ConfigEntry.Builder<EQuickThread>()
.set(EQuickThread.BALANCED)
public static ConfigEntry<EThreadPreset> threadPresetSetting = new ConfigEntry.Builder<EThreadPreset>()
.set(EThreadPreset.LOW_IMPACT) // the default value is set via the listener when accessed
.comment(""
+ "Changing this setting will modify a number of different settings that will change \n"
+ "the load that Distant Horizons is allowed to put on your CPU. \n"
+ "\n"
+ "Higher options will improve LOD generation and loading speed, \n"
+ "but will increase CPU load and may introduce stuttering.\n"
+ "\n"
+ "Note: on CPUs with 4 cores or less these settings will be less effective \n"
+ " and some settings will give similar results. \n"
+ "")
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) // TODO set when the game boots
//.addListener(null) // TODO add listener
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(ThreadPresetConfigEventHandler.INSTANCE)
.build();
public static ConfigLinkedEntry quickEnableWorldGenerator = new ConfigLinkedEntry(Advanced.WorldGenerator.enableDistantGeneration);
@@ -114,14 +119,14 @@ public class Config
public static ConfigCategory advanced = new ConfigCategory.Builder().set(Advanced.class).build();
public static ConfigCategory resetSettingsConfirmation = new ConfigCategory.Builder().set(ResetConfirmation.class).build();
// public static ConfigCategory resetSettingsConfirmation = new ConfigCategory.Builder().set(ResetConfirmation.class).build();
public static class Advanced
{
public static ConfigCategory graphics = new ConfigCategory.Builder().set(Graphics.class).build();
public static ConfigCategory worldGenerator = new ConfigCategory.Builder().set(WorldGenerator.class).build();
public static ConfigCategory multiplayer = new ConfigCategory.Builder().set(Multiplayer.class).build();
public static ConfigCategory threading = new ConfigCategory.Builder().set(MultiThreading.class).build();
public static ConfigCategory multiThreading = new ConfigCategory.Builder().set(MultiThreading.class).build();
public static ConfigCategory buffers = new ConfigCategory.Builder().set(GpuBuffers.class).build();
public static ConfigCategory autoUpdater = new ConfigCategory.Builder().set(AutoUpdater.class).build();
@@ -172,20 +177,11 @@ public class Config
+ "will increase memory and GPU usage. \n"
+ "\n"
+ "Lowest Quality: " + EVerticalQuality.HEIGHT_MAP + "\n"
+ "Highest Quality: " + EVerticalQuality.ULTRA)
+ "Highest Quality: " + EVerticalQuality.EXTREME)
.setPerformance(EConfigEntryPerformance.VERY_HIGH)
.addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
// TODO merge with horizontal quality
public static ConfigEntry<Integer> horizontalScale = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(2, 12, 64)
.comment(""
+ "This indicates how quickly fake chunks decrease in quality the further away they are. \n"
+ "Higher settings will render higher quality fake chunks farther away, \n"
+ " but will increase memory and GPU usage.")
.build();
public static ConfigEntry<EHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EHorizontalQuality>()
.set(EHorizontalQuality.MEDIUM)
.comment(""
@@ -207,6 +203,30 @@ public class Config
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build();
public static ConfigEntry<EBlocksToAvoid> blocksToIgnore = new ConfigEntry.Builder<EBlocksToAvoid>()
.set(EBlocksToAvoid.NON_COLLIDING)
.comment(""
+ "What blocks shouldn't be rendered as LODs? \n"
+ "\n"
+ EBlocksToAvoid.NONE + ": Represent all blocks in the LODs \n"
+ EBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n"
+ "")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Boolean> tintWithAvoidedBlocks = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "Should the blocks underneath avoided blocks gain the color of the avoided block? \n"
+ "\n"
+ "True: a red flower will tint the grass below it red. \n"
+ "False: skipped blocks will not change color of surface below them. "
+"")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
// TODO fixme
// public static ConfigEntry<Integer> lodBiomeBlending = new ConfigEntry.Builder<Integer>()
// .setMinDefaultMax(0,1,7)
@@ -224,12 +244,6 @@ public class Config
public static class Fog
{
public static ConfigEntry<EFogDistance> fogDistance = new ConfigEntry.Builder<EFogDistance>()
.set(EFogDistance.FAR)
.comment("At what distance should Fog be drawn on the LODs?")
.setPerformance(EConfigEntryPerformance.NONE)
.build();
public static ConfigEntry<EFogDrawMode> fogDrawMode = new ConfigEntry.Builder<EFogDrawMode>()
.set(EFogDrawMode.FOG_ENABLED)
.comment(""
@@ -244,6 +258,12 @@ public class Config
.setPerformance(EConfigEntryPerformance.VERY_LOW)
.build();
public static ConfigEntry<EFogDistance> fogDistance = new ConfigEntry.Builder<EFogDistance>()
.set(EFogDistance.FAR)
.comment("At what distance should Fog be drawn on the LODs?")
.setPerformance(EConfigEntryPerformance.NONE)
.build();
public static ConfigEntry<EFogColorMode> fogColorMode = new ConfigEntry.Builder<EFogColorMode>()
.set(EFogColorMode.USE_WORLD_FOG_COLOR)
.comment(""
@@ -477,12 +497,18 @@ public class Config
// + "Disable this if you see LODs disappearing at the corners of your vision.")
// .build();
// TODO replace with better options
public static ConfigEntry<Boolean> useExtendedNearClipPlane = new ConfigEntry.Builder<Boolean>()
.set(true)
public static ConfigEntry<EOverdrawPrevention> overdrawPrevention = new ConfigEntry.Builder<EOverdrawPrevention>()
.set(EOverdrawPrevention.MEDIUM)
.comment(""
+ "Will prevent some overdraw issues, but may cause nearby fake chunks to render incorrectly \n"
+ " especially when in/near an ocean.")
+ "Determines how far Distant Horizon's near clip plane will render. \n"
+ "\n"
+ "Higher values will prevent LODs from rendering behind vanilla blocks at a higher distance,\n"
+ "but may cause holes to appear in the LODs. \n"
+ "Holes are most likely at the left and right edges of the screen \n"
+ "when flying through unloaded terrain. \n"
+ "\n"
+ "Increasing the vanilla render distance increases the effectiveness of these options."
+ "")
.setPerformance(EConfigEntryPerformance.NONE)
.build();
@@ -506,7 +532,6 @@ public class Config
+ "2 = very saturated")
.build();
// TODO replace with better options
public static ConfigEntry<Boolean> enableCaveCulling = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
@@ -651,30 +676,6 @@ public class Config
.setPerformance(EConfigEntryPerformance.NONE)
.build();
// TODO fixme
public static ConfigEntry<EBlocksToAvoid> blocksToAvoid = new ConfigEntry.Builder<EBlocksToAvoid>()
.set(EBlocksToAvoid.BOTH)
.comment(""
+ "When generating fake chunks, what blocks should be ignored? \n"
+ "Ignored blocks don't affect the height of the fake chunk, but might affect the color. \n"
+ "So using " + EBlocksToAvoid.BOTH + " will prevent snow covered blocks from appearing one block too tall, \n"
+ " but will still show the snow's color.\n"
+ "\n"
+ EBlocksToAvoid.NONE + ": Use all blocks when generating fake chunks \n"
+ EBlocksToAvoid.NON_FULL + ": Only use full blocks when generating fake chunks (ignores slabs, lanterns, torches, tall grass, etc.) \n"
+ EBlocksToAvoid.NO_COLLISION + ": Only use solid blocks when generating fake chunks (ignores tall grass, torches, etc.) \n"
+ EBlocksToAvoid.BOTH + ": Only use full solid blocks when generating fake chunks")
.setPerformance(EConfigEntryPerformance.NONE)
.build();
// TODO fixme
public static ConfigEntry<Boolean> tintWithAvoidedBlocks = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "Should the blocks underneath avoided blocks gain the color of the avoided block? \n"
+ " True: a red flower on grass will tint the grass below it red"
+ " False: skipped blocks will not change color of surface below them")
.build();
}
public static class Multiplayer
@@ -0,0 +1,47 @@
package com.seibel.lod.core.config;
import com.seibel.lod.core.config.types.ConfigEntry;
import java.util.HashMap;
import java.util.HashSet;
public class ConfigEntryWithPresetOptions<TQuickEnum, TConfig>
{
public final ConfigEntry<TConfig> configEntry;
private final HashMap<TQuickEnum, TConfig> configOptionByQualityOption;
public ConfigEntryWithPresetOptions(ConfigEntry<TConfig> configEntry, HashMap<TQuickEnum, TConfig> configOptionByQualityOption)
{
this.configEntry = configEntry;
this.configOptionByQualityOption = configOptionByQualityOption;
}
public void updateConfigEntry(TQuickEnum quickQuality)
{
TConfig newValue = this.configOptionByQualityOption.get(quickQuality);
this.configEntry.set(newValue);
}
public HashSet<TQuickEnum> getPossibleQualitiesFromCurrentOptionValue()
{
TConfig inputOptionValue = this.configEntry.get();
HashSet<TQuickEnum> possibleQualities = new HashSet<>();
for (TQuickEnum key : this.configOptionByQualityOption.keySet())
{
TConfig optionValue = this.configOptionByQualityOption.get(key);
if (optionValue.equals(inputOptionValue))
{
possibleQualities.add(key);
}
}
return possibleQualities;
}
}
@@ -4,9 +4,7 @@ import com.seibel.lod.api.DhApiMain;
import com.seibel.lod.api.enums.config.EHorizontalResolution;
import com.seibel.lod.api.enums.config.EVerticalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.core.config.listeners.IConfigListener;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.util.DetailDistanceUtil;
/**
@@ -59,7 +57,7 @@ public class RenderCacheConfigEventHandler implements IConfigListener
if (refreshRenderData)
{
// TODO add a timeout to prevent rapidly changing settings causing the render data thrashing.
DetailDistanceUtil.minDetail = newHorizontalResolution.detailLevel;
DetailDistanceUtil.updateSettings();
DhApiMain.Delayed.renderProxy.clearRenderDataCache();
}
@@ -0,0 +1,36 @@
package com.seibel.lod.core.config.eventHandlers;
import com.seibel.lod.api.DhApiMain;
import com.seibel.lod.api.enums.config.EHorizontalResolution;
import com.seibel.lod.api.enums.config.EVerticalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.core.config.listeners.IConfigListener;
import com.seibel.lod.core.util.DetailDistanceUtil;
public class ResetConfigEventHandler
{
public static ResetConfigEventHandler INSTANCE = new ResetConfigEventHandler();
public final ConfigChangeListener<Boolean> configChangeListener;
/** private since we only ever need one handler at a time */
private ResetConfigEventHandler()
{
this.configChangeListener = new ConfigChangeListener<>(Config.Client.ResetConfirmation.resetAllSettings, (resetSettings) -> { doStuff(resetSettings); });
}
private void doStuff(boolean resetSettings)
{
if (!resetSettings)
{
return;
}
Config.Client.ResetConfirmation.resetAllSettings.set(false);
}
}
@@ -0,0 +1,136 @@
package com.seibel.lod.core.config.eventHandlers.presets;
import com.seibel.lod.core.config.ConfigEntryWithPresetOptions;
import com.seibel.lod.core.config.listeners.IConfigListener;
import com.seibel.lod.coreapi.interfaces.config.IConfigEntry;
import com.seibel.lod.coreapi.util.StringUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;
public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<?>> implements IConfigListener
{
private static final Logger LOGGER = LogManager.getLogger();
protected final ArrayList<ConfigEntryWithPresetOptions<TPresetEnum, ?>> configList = new ArrayList<>();
protected boolean changingPreset = false;
//===========//
// listeners //
//===========//
@Override
public void onConfigValueSet()
{
TPresetEnum qualityPreset = this.getPresetConfigEntry().get();
if (qualityPreset == null)
{
// the value will be null when the config menu is first opened,
// set the value to what it should be.
TPresetEnum currentQualitySetting = this.getCurrentQualityPreset();
this.getPresetConfigEntry().set(currentQualitySetting);
return;
}
// if the quick value is custom, nothing needs to be changed
if (qualityPreset == this.getCustomPresetEnum())
{
return;
}
LOGGER.debug("changing preset to: " + qualityPreset);
this.changingPreset = true;
for (ConfigEntryWithPresetOptions<TPresetEnum, ?> configEntry : this.configList)
{
configEntry.updateConfigEntry(qualityPreset);
}
this.changingPreset = false;
LOGGER.debug("preset active: "+qualityPreset);
}
@Override
public void onUiModify() { /* do nothing, we only care about modified config values */ }
/**
* listen for changed graphics settings and set the
* quick quality to "custom" if anything was changed
*/
public void onConfigValueChanged()
{
if (this.changingPreset)
{
// if a preset is currently being applied, ignore all changes
return;
}
TPresetEnum newPreset = this.getCurrentQualityPreset();
TPresetEnum currentPreset = this.getPresetConfigEntry().get();
if (newPreset != currentPreset)
{
this.getPresetConfigEntry().set(this.getCustomPresetEnum());
}
}
//================//
// helper methods //
//================//
/** @return what {@link TPresetEnum} is currently viable based on the {@link AbstractPresetConfigEventHandler#configList}. */
public TPresetEnum getCurrentQualityPreset()
{
// get all quick options
HashSet<TPresetEnum> possiblePresetSet = new HashSet<>(this.getPresetEnumList());
// remove any quick options that aren't possible with the currently selected options
for (ConfigEntryWithPresetOptions<TPresetEnum, ?> configEntry : this.configList)
{
HashSet<TPresetEnum> optionPresetSet = configEntry.getPossibleQualitiesFromCurrentOptionValue();
possiblePresetSet.retainAll(optionPresetSet);
}
ArrayList<TPresetEnum> possiblePrestList = new ArrayList<>(possiblePresetSet);
if (possiblePrestList.size() > 1)
{
// we shouldn't have multiple options, but just in case
LOGGER.warn("Multiple potential preset options ["+StringUtil.join(", ", possiblePrestList)+"], defaulting to the first one.");
}
if (possiblePrestList.size() == 0)
{
// if no options are valid, return "CUSTOM"
possiblePrestList.add(this.getCustomPresetEnum());
}
return possiblePrestList.get(0);
}
//==================//
// abstract methods //
//==================//
protected abstract IConfigEntry<TPresetEnum> getPresetConfigEntry();
protected abstract List<TPresetEnum> getPresetEnumList();
protected abstract TPresetEnum getCustomPresetEnum();
}
@@ -0,0 +1,98 @@
package com.seibel.lod.core.config.eventHandlers.presets;
import com.seibel.lod.api.enums.config.EHorizontalQuality;
import com.seibel.lod.api.enums.config.EHorizontalResolution;
import com.seibel.lod.api.enums.config.EVerticalQuality;
import com.seibel.lod.api.enums.config.quickOptions.EQualityPreset;
import com.seibel.lod.api.enums.rendering.ETransparency;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.ConfigEntryWithPresetOptions;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.coreapi.interfaces.config.IConfigEntry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;
public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigEventHandler<EQualityPreset>
{
public static final RenderQualityPresetConfigEventHandler INSTANCE = new RenderQualityPresetConfigEventHandler();
private static final Logger LOGGER = LogManager.getLogger();
private final ConfigEntryWithPresetOptions<EQualityPreset, EHorizontalResolution> drawResolution = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.drawResolution,
new HashMap<EQualityPreset, EHorizontalResolution>()
{{
this.put(EQualityPreset.MINIMUM, EHorizontalResolution.TWO_BLOCKS);
this.put(EQualityPreset.LOW, EHorizontalResolution.BLOCK);
this.put(EQualityPreset.MEDIUM, EHorizontalResolution.BLOCK);
this.put(EQualityPreset.HIGH, EHorizontalResolution.BLOCK);
this.put(EQualityPreset.EXTREME, EHorizontalResolution.BLOCK);
}});
private final ConfigEntryWithPresetOptions<EQualityPreset, EVerticalQuality> verticalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.verticalQuality,
new HashMap<EQualityPreset, EVerticalQuality>()
{{
this.put(EQualityPreset.MINIMUM, EVerticalQuality.HEIGHT_MAP);
this.put(EQualityPreset.LOW, EVerticalQuality.LOW);
this.put(EQualityPreset.MEDIUM, EVerticalQuality.MEDIUM);
this.put(EQualityPreset.HIGH, EVerticalQuality.HIGH);
this.put(EQualityPreset.EXTREME, EVerticalQuality.EXTREME);
}});
private final ConfigEntryWithPresetOptions<EQualityPreset, EHorizontalQuality> horizontalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality,
new HashMap<EQualityPreset, EHorizontalQuality>()
{{
this.put(EQualityPreset.MINIMUM, EHorizontalQuality.LOWEST);
this.put(EQualityPreset.LOW, EHorizontalQuality.LOW);
this.put(EQualityPreset.MEDIUM, EHorizontalQuality.MEDIUM);
this.put(EQualityPreset.HIGH, EHorizontalQuality.HIGH);
this.put(EQualityPreset.EXTREME, EHorizontalQuality.EXTREME);
}});
private final ConfigEntryWithPresetOptions<EQualityPreset, ETransparency> transparency = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency,
new HashMap<EQualityPreset, ETransparency>()
{{
this.put(EQualityPreset.MINIMUM, ETransparency.DISABLED);
this.put(EQualityPreset.LOW, ETransparency.FAKE);
this.put(EQualityPreset.MEDIUM, ETransparency.COMPLETE);
this.put(EQualityPreset.HIGH, ETransparency.COMPLETE);
this.put(EQualityPreset.EXTREME, ETransparency.COMPLETE);
}});
//==============//
// constructors //
//==============//
/** private since we only ever need one handler at a time */
private RenderQualityPresetConfigEventHandler()
{
// add each config used by this preset
this.configList.add(this.drawResolution);
this.configList.add(this.verticalQuality);
this.configList.add(this.horizontalQuality);
this.configList.add(this.transparency);
for (ConfigEntryWithPresetOptions<EQualityPreset, ?> config : this.configList)
{
// ignore try-using, the listener should only ever be added once and should never be removed
new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); });
}
}
//==============//
// enum getters //
//==============//
@Override
protected IConfigEntry<EQualityPreset> getPresetConfigEntry() { return Config.Client.qualityPresetSetting; }
@Override
protected List<EQualityPreset> getPresetEnumList() { return Arrays.asList(EQualityPreset.values()); }
@Override
protected EQualityPreset getCustomPresetEnum() { return EQualityPreset.CUSTOM; }
}
@@ -0,0 +1,127 @@
package com.seibel.lod.core.config.eventHandlers.presets;
import com.seibel.lod.api.enums.config.quickOptions.EThreadPreset;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.ConfigEntryWithPresetOptions;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.coreapi.interfaces.config.IConfigEntry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHandler<EThreadPreset>
{
public static final ThreadPresetConfigEventHandler INSTANCE = new ThreadPresetConfigEventHandler();
private static final Logger LOGGER = LogManager.getLogger();
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> worldGen = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads,
new HashMap<EThreadPreset, Integer>()
{{
this.put(EThreadPreset.MINIMAL_IMPACT, 1);
this.put(EThreadPreset.LOW_IMPACT, getThreadCountByPercent(0.1));
this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4));
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
}});
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> bufferBuilders = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfBufferBuilderThreads,
new HashMap<EThreadPreset, Integer>()
{{
this.put(EThreadPreset.MINIMAL_IMPACT, 1);
this.put(EThreadPreset.LOW_IMPACT, getThreadCountByPercent(0.1));
this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4));
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
}});
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> fileHandlers = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads,
new HashMap<EThreadPreset, Integer>()
{{
this.put(EThreadPreset.MINIMAL_IMPACT, 1);
this.put(EThreadPreset.LOW_IMPACT, getThreadCountByPercent(0.1));
this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2));
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
}});
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> dataConverters = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfDataConverterThreads,
new HashMap<EThreadPreset, Integer>()
{{
this.put(EThreadPreset.MINIMAL_IMPACT, 1);
this.put(EThreadPreset.LOW_IMPACT, getThreadCountByPercent(0.1));
this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2));
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
}});
//==============//
// constructors //
//==============//
/** private since we only ever need one handler at a time */
private ThreadPresetConfigEventHandler()
{
// add each config used by this preset
this.configList.add(this.worldGen);
this.configList.add(this.bufferBuilders);
this.configList.add(this.fileHandlers);
this.configList.add(this.dataConverters);
for (ConfigEntryWithPresetOptions<EThreadPreset, ?> config : this.configList)
{
// ignore try-using, the listener should only ever be added once and should never be removed
new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); });
}
}
//================//
// helper methods //
//================//
/**
* Pre-computed values for your convenience: <br>
* Format: percent: 4coreCpu-8coreCpu-16coreCpu <br><br>
* <code>
* 0.1: 1-1-2 <br>
* 0.2: 1-2-4 <br>
* 0.4: 2-4-7 <br>
* 0.6: 3-5-10 <br>
* 0.8: 4-7-13 <br>
* 1.0: 4-8-16 <br>
* </code>
*/
private static int getThreadCountByPercent(double percent) throws IllegalArgumentException
{
if (percent <= 0 || percent > 1)
{
throw new IllegalArgumentException("percent must be greater than 0 and less than or equal to 1.");
}
// this is logical processor count, not physical CPU cores
int totalProcessorCount = Runtime.getRuntime().availableProcessors();
int coreCount = (int) Math.ceil(totalProcessorCount * percent);
return Math.max(1, coreCount);
}
//==============//
// enum getters //
//==============//
@Override
protected IConfigEntry<EThreadPreset> getPresetConfigEntry() { return Config.Client.threadPresetSetting; }
@Override
protected List<EThreadPreset> getPresetEnumList() { return Arrays.asList(EThreadPreset.values()); }
@Override
protected EThreadPreset getCustomPresetEnum() { return EThreadPreset.CUSTOM; }
}
@@ -5,7 +5,10 @@ public interface IConfigListener
/** Called whenever the value is set (including in core DH code) */
void onConfigValueSet();
/** Called whenever the value is changed through the UI (only when the done button is pressed) */
void onUiModify(); // TODO
/**
* TODO not implemented
* Called whenever the value is changed through the UI (only when the done button is pressed)
*/
void onUiModify();
}
@@ -65,7 +65,7 @@ public class ColumnRenderBufferBuilder
{
try
{
boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().tranparencyEnabled;
boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled;
EVENT_LOGGER.trace("RenderRegion start QuadBuild @ "+renderSource.sectionPos);
boolean enableSkyLightCulling = Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get();
@@ -1,5 +1,6 @@
package com.seibel.lod.core.dataObjects.transformers;
import com.seibel.lod.api.enums.config.EBlocksToAvoid;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleColumnFullDataAccessor;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
@@ -235,9 +236,16 @@ public class FullDataToRenderDataTransformer
private static void iterateAndConvert(IDhClientLevel level, int blockX, int blockZ, int genMode, ColumnArrayView column, SingleColumnFullDataAccessor data)
{
FullDataPointIdMap mapping = data.getMapping();
boolean avoidSolidBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EBlocksToAvoid.NON_COLLIDING);
boolean colorBelowWithAvoidedBlocks = Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks.get();
FullDataPointIdMap fullDataMapping = data.getMapping();
boolean isVoid = true;
int offset = 0;
int colorToApplyToNextBlock = -1;
int columnOffset = 0;
// goes from the top down
for (int i = 0; i < data.getSingleLength(); i++)
{
long fullData = data.getSingle(i);
@@ -245,20 +253,50 @@ public class FullDataToRenderDataTransformer
int blockHeight = FullDataPointUtil.getHeight(fullData);
int id = FullDataPointUtil.getId(fullData);
int light = FullDataPointUtil.getLight(fullData);
IBiomeWrapper biome = mapping.getBiomeWrapper(id);
IBlockStateWrapper block = mapping.getBlockStateWrapper(id);
IBiomeWrapper biome = fullDataMapping.getBiomeWrapper(id);
IBlockStateWrapper block = fullDataMapping.getBlockStateWrapper(id);
if (block.equals(AIR))
{
// we don't render air
continue;
}
// solid block check
if (avoidSolidBlocks && !block.isSolid() && !block.isLiquid())
{
if (colorBelowWithAvoidedBlocks)
{
colorToApplyToNextBlock = level.computeBaseColor(new DhBlockPos(blockX, bottomY + level.getMinY(), blockZ), biome, block);
}
// don't add this block
continue;
}
int color;
if (colorToApplyToNextBlock == -1)
{
// use this block's color
color = level.computeBaseColor(new DhBlockPos(blockX, bottomY + level.getMinY(), blockZ), biome, block);
}
else
{
// use the previous block's color
color = colorToApplyToNextBlock;
colorToApplyToNextBlock = -1;
}
// add the block
isVoid = false;
int color = level.computeBaseColor(new DhBlockPos(blockX, bottomY + level.getMinY(), blockZ), biome, block);
long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, light, genMode);
column.set(offset, columnData);
offset++;
column.set(columnOffset, columnData);
columnOffset++;
}
if (isVoid)
{
column.set(0, RenderDataPointUtil.createVoidDataPoint((byte) genMode));
@@ -84,6 +84,8 @@ public abstract class AbstractDhClientLevel implements IDhClientLevel
return false;
}
// TODO this should probably be handled via a config change listener
// recreate the RenderState if the render distance changes
if (clientRenderState.quadtree.blockRenderDistance != Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH)
{
if (!this.ClientRenderStateRef.compareAndSet(clientRenderState, null))
@@ -1,5 +1,8 @@
package com.seibel.lod.core.render;
import com.seibel.lod.api.enums.config.EHorizontalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.listeners.ConfigChangeListener;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.pos.DhBlockPos2D;
@@ -7,12 +10,10 @@ import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.file.renderfile.ILodRenderSourceProvider;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
import com.seibel.lod.core.util.objects.quadTree.QuadTree;
import org.apache.logging.log4j.Logger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -38,6 +39,8 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
private final IDhClientLevel level; //FIXME: Proper hierarchy to remove this reference!
private final ConfigChangeListener<EHorizontalQuality> horizontalScaleChangeListener;
@@ -53,6 +56,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
this.renderSourceProvider = provider;
this.blockRenderDistance = viewDistanceInBlocks;
this.horizontalScaleChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality, (newHorizontalScale) -> this.onHorizontalQualityChange());
}
@@ -352,6 +356,32 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
//==================//
// config listeners //
//==================//
private void onHorizontalQualityChange()
{
// TODO this Util should probably be somewhere else or handled differently, but it works for now
// Updating this util is necessary whenever the horizontal quality is changed, since it handles the detail drop-off
DetailDistanceUtil.updateSettings();
// flush the current render data to make sure the new settings are used
Iterator<QuadNode<LodRenderSection>> nodeIterator = this.nodeIterator();
while (nodeIterator.hasNext())
{
QuadNode<LodRenderSection> quadNode = nodeIterator.next();
if (quadNode.value != null)
{
quadNode.value.disposeRenderData();
quadNode.value = null;
}
}
}
//==============//
// base methods //
//==============//
@@ -374,6 +404,8 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
{
LOGGER.info("Shutting down "+ LodQuadTree.class.getSimpleName()+"...");
this.horizontalScaleChangeListener.close();
Iterator<QuadNode<LodRenderSection>> nodeIterator = this.nodeIterator();
while (nodeIterator.hasNext())
{
@@ -20,7 +20,6 @@
package com.seibel.lod.core.render.renderer;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.api.enums.rendering.EDebugMode;
import com.seibel.lod.api.enums.rendering.EFogColorMode;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
@@ -185,7 +184,7 @@ public class LodRenderer
transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().tranparencyEnabled;
transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled;
fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled;
GL32.glDisable(GL32.GL_BLEND); // We render opaque first, then transparent
@@ -19,8 +19,8 @@
package com.seibel.lod.core.util;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.api.enums.config.EHorizontalQuality;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.coreapi.util.MathUtil;
/**
@@ -31,67 +31,67 @@ import com.seibel.lod.coreapi.util.MathUtil;
@Deprecated
public class DetailDistanceUtil
{
public static byte minDetail = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
/** smallest numerical detail level */
private static byte maxDetailLevel = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
private static final byte maxDetail = Byte.MAX_VALUE;
/** largest numerical detail level */
private static final byte minDetailLevel = Byte.MAX_VALUE;
private static final double minDistance = 0;
private static double distanceUnit = 16 * Config.Client.Advanced.Graphics.Quality.horizontalScale.get();
private static double maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * 16 * 2;
// TODO merge with updateSettings() below
private static double distanceUnit = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().distanceUnitInBlocks * LodUtil.CHUNK_WIDTH;
private static double maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2;
private static double logBase = Math.log(Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase);
public static void updateSettings()
{
distanceUnit = 16 * Config.Client.Advanced.Graphics.Quality.horizontalScale.get();
minDetail = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * 16 * 8;
maxDetailLevel = Config.Client.Advanced.Graphics.Quality.drawResolution.get().detailLevel;
distanceUnit = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().distanceUnitInBlocks * LodUtil.CHUNK_WIDTH;
maxDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2;
logBase = Math.log(Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase);
}
public static double baseDistanceFunction(int detail)
{
if (detail <= minDetail)
return minDistance;
if (detail >= maxDetail)
return maxDistance;
detail-=minDetail;
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.LOWEST)
return ((double)detail * distanceUnit);
else
if (detail <= maxDetailLevel)
{
double base = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase;
return Math.pow(base, detail) * distanceUnit;
return minDistance;
}
else if (detail >= minDetailLevel)
{
return maxDistance;
}
double base = Config.Client.Advanced.Graphics.Quality.horizontalQuality.get().quadraticBase;
return Math.pow(base, detail) * distanceUnit;
}
public static double getDrawDistanceFromDetail(int detail)
{
return baseDistanceFunction(detail);
}
public static double getDrawDistanceFromDetail(int detail) { return baseDistanceFunction(detail); }
public static byte baseInverseFunction(double distance)
{
double maxDetailDistance = getDrawDistanceFromDetail(maxDetail-1);
if (distance > maxDetailDistance) {
//ApiShared.LOGGER.info("DEBUG: Scale as max: {}", distance);
return maxDetail-1;
// special case, never drop the quality
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.UNLIMITED)
{
return maxDetailLevel;
}
int detail;
if (Config.Client.Advanced.Graphics.Quality.horizontalQuality.get() == EHorizontalQuality.LOWEST)
detail = (int) (distance/distanceUnit);
else
detail = (int) (Math.log(distance/distanceUnit) / logBase);
double maxDetailDistance = getDrawDistanceFromDetail(minDetailLevel -1);
if (distance > maxDetailDistance)
{
return minDetailLevel - 1;
}
return (byte) MathUtil.clamp(minDetail, detail+minDetail, maxDetail - 1);
int detailLevel = (int) (Math.log(distance / distanceUnit) / logBase);
return (byte) MathUtil.clamp(maxDetailLevel, detailLevel, minDetailLevel - 1);
}
public static byte getDetailLevelFromDistance(double distance)
{
return baseInverseFunction(distance);
}
public static byte getDetailLevelFromDistance(double distance) { return baseInverseFunction(distance); }
}
@@ -19,6 +19,7 @@
package com.seibel.lod.core.util;
import com.seibel.lod.api.enums.config.EOverdrawPrevention;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.world.IDhClientWorld;
import com.seibel.lod.core.api.internal.SharedApi;
@@ -176,20 +177,48 @@ public class RenderUtil
public static float getNearClipPlaneDistanceInBlocks(float partialTicks)
{
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
int chunkRenderDistance = MC_RENDER.getRenderDistance();
if (chunkRenderDistance % 2 == 0)
{
chunkRenderDistance += 1;
}
int vanillaBlockRenderedDistance = chunkRenderDistance * LodUtil.CHUNK_WIDTH;
vanillaBlockRenderedDistance *= 2;
float nearClipPlane;
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
{
nearClipPlane = 0.1f;
}
else if (Config.Client.Advanced.Graphics.AdvancedGraphics.useExtendedNearClipPlane.get())
else
{
nearClipPlane = Math.min(vanillaBlockRenderedDistance - LodUtil.CHUNK_WIDTH, (float) 8 * LodUtil.CHUNK_WIDTH); // allow a max near clip plane of 8 chunks
}
else
{
nearClipPlane = 16f;
// TODO make this option dependent on player speed.
// if the player is flying quickly, lower the near clip plane to account for slow chunk loading.
// If the player is moving quickly they are less likely to notice overdraw.
EOverdrawPrevention clipPlaneDistance = Config.Client.Advanced.Graphics.AdvancedGraphics.overdrawPrevention.get();
switch (clipPlaneDistance)
{
default: // shouldn't be necessary, just here to make the compiler happy
case NONE:
nearClipPlane = 0.1f;
break;
case LIGHT:
nearClipPlane = vanillaBlockRenderedDistance * 0.25f;
break;
case MEDIUM:
nearClipPlane = vanillaBlockRenderedDistance * 0.4f;
break;
case HEAVY:
// recommend render distance ot 6 or higher, otherwise holes may appear
nearClipPlane = vanillaBlockRenderedDistance * 0.6f;
break;
}
}
// modify the based on the player's FOV
@@ -12,8 +12,4 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper
{
String serialize();
// TODO:
// boolean hasFaceCullingFor(ELodDirection dir);
// boolean hasNoCollision();
// boolean noFaceIsFullFace();
}
@@ -54,14 +54,14 @@
"lod.config.client.quickEnableRendering.@tooltip":
"Determines if Distant Horizons Renders LODs.",
"lod.config.client.quickQualitySetting":
"Overall Quality",
"lod.config.client.quickQualitySetting.@tooltip":
"Will modify a number of settings to quickly change Distant Horizons' rendering quality.",
"lod.config.client.quickThreadSetting":
"lod.config.client.qualityPresetSetting":
"Quality Preset",
"lod.config.client.qualityPresetSetting.@tooltip":
"Modifies a number of graphical settings to quickly change Distant Horizons' rendering quality. \n\nLower this setting if your GPU is at max usage or you are having framerate issues.",
"lod.config.client.threadPresetSetting":
"CPU Load",
"lod.config.client.quickThreadSetting.@tooltip":
"Will modify a number of settings to quickly change how many CPU resources Distant Horizons' is allowed to use. \n\nIncreasing this setting will improve Distant Generator speed and LOD loading speed, \nbut will also increase CPU/memory usage and may introduce stuttering.",
"lod.config.client.threadPresetSetting.@tooltip":
"Modifies how many threads Distant Horizons' will use. \n\nIncreasing this setting will improve the Distant Generator speed and LOD loading speed, \nbut will also increase CPU/memory usage and may introduce stuttering. \n\nNote: on CPUs with 4 cores or less these settings will be less effective \nand some settings will give similar results.",
"lod.config.client.optionsButton":
"Show The Options Button",
@@ -90,16 +90,20 @@
"Vertical Quality",
"lod.config.client.advanced.graphics.quality.verticalQuality.@tooltip":
"How well LODs represent overhangs, caves, cliffsides, etc.\n\nHigher options will increase memory and GPU usage.",
"lod.config.client.advanced.graphics.quality.horizontalScale":
"Horizontal Scale",
"lod.config.client.advanced.graphics.quality.horizontalScale.@tooltip":
"How quickly LODs drop off in quality.\n\nLarger numbers will improve how distant terrain looks\nbut will increase memory and GPU usage.",
"lod.config.client.advanced.graphics.quality.horizontalQuality":
"Horizontal Quality",
"lod.config.client.advanced.graphics.quality.horizontalQuality.@tooltip":
"How far apart drops in quality are.\n\nHigher settings will increase the distance between drops\nbut will increase memory and GPU usage.",
"lod.config.client.advanced.graphics.quality.transparency":
"Transparency",
"lod.config.client.advanced.graphics.quality.blocksToIgnore":
"Blocks To Ignore",
"lod.config.client.advanced.graphics.quality.blocksToIgnore.@tooltip":
"Defines the types of blocks to ignore when generating LODs.",
"lod.config.client.advanced.graphics.quality.tintWithAvoidedBlocks":
"Tint With Avoided Blocks",
"lod.config.client.advanced.graphics.quality.tintWithAvoidedBlocks.@tooltip":
"§4Note: makes snow, carpet, and trapdoors look really bad§r\nShould the blocks underneath avoided blocks gain the color of the avoided block?\n§6True:§r a red flower on grass will tint the grass below it red\n§6False:§r skipped blocks will not change color of surface below them",
"lod.config.client.advanced.graphics.quality.lodBiomeBlending":
"Biome Blending",
"lod.config.client.advanced.graphics.quality.lodBiomeBlending.@tooltip":
@@ -107,16 +111,16 @@
"lod.config.client.advanced.graphics.fog":
"Fog Options",
"lod.config.client.advanced.graphics.fog.fogDistance":
"Fog Distance",
"lod.config.client.advanced.graphics.fog.fogDistance.@tooltip":
"The distance(s) Fog will be rendered on the LODs.",
"Fog",
"lod.config.client.advanced.graphics.fog.fogDrawMode":
"Fog Draw Mode",
"lod.config.client.advanced.graphics.fog.fogDrawMode.@tooltip":
"When fog will be rendered on the LODs.",
"lod.config.client.advanced.graphics.fog.fogDistance":
"Fog Distance",
"lod.config.client.advanced.graphics.fog.fogDistance.@tooltip":
"The distance(s) Fog will be rendered on the LODs.",
"lod.config.client.advanced.graphics.fog.fogColorMode":
"Fog Color Mode",
"lod.config.client.advanced.graphics.fog.fogColorMode.@tooltip":
@@ -221,9 +225,9 @@
"lod.config.client.advanced.graphics.advancedGraphics":
"Advanced Graphics Options",
"lod.config.client.advanced.graphics.advancedGraphics.useExtendedNearClipPlane":
"Use extended near clip plane",
"lod.config.client.advanced.graphics.advancedGraphics.useExtendedNearClipPlane.@tooltip":
"lod.config.client.advanced.graphics.advancedGraphics.overdrawPrevention":
"Overdraw Prevention",
"lod.config.client.advanced.graphics.advancedGraphics.overdrawPrevention.@tooltip":
"Enabling this will prevent some overdraw issues,\nbut may cause nearby LODs to render incorrectly, especially when near fancy leaves or non-full blocks.\nLess noticeable with a longer vanilla render distance.",
"lod.config.client.advanced.graphics.advancedGraphics.brightnessMultiplier":
"Brightness Multiplier",
@@ -270,14 +274,6 @@
"Generation Priority",
"lod.config.client.advanced.worldGenerator.generationPriority.@tooltip":
"The priority for chunks being generated around the player.",
"lod.config.client.advanced.worldGenerator.blocksToAvoid":
"Blocks To Avoid",
"lod.config.client.advanced.worldGenerator.blocksToAvoid.@tooltip":
"Defines the types of blocks to ignore when generating LODs.",
"lod.config.client.advanced.worldGenerator.tintWithAvoidedBlocks":
"Tint With Avoided Blocks",
"lod.config.client.advanced.worldGenerator.tintWithAvoidedBlocks.@tooltip":
"§4Note: makes snow, carpet, and trapdoors look really bad§r\nShould the blocks underneath avoided blocks gain the color of the avoided block?\n§6True:§r a red flower on grass will tint the grass below it red\n§6False:§r skipped blocks will not change color of surface below them",
"lod.config.client.advanced.multiplayer":
@@ -294,24 +290,24 @@
"lod.config.client.advanced.threading":
"lod.config.client.advanced.multiThreading":
"Threading",
"lod.config.client.advanced.threading.numberOfWorldGenerationThreads":
"lod.config.client.advanced.multiThreading.numberOfWorldGenerationThreads":
"NO. of world generation threads",
"lod.config.client.advanced.threading.numberOfWorldGenerationThreads.@tooltip":
"lod.config.client.advanced.multiThreading.numberOfWorldGenerationThreads.@tooltip":
"How many threads should be used when generating LODs \n outside the normal render distance? \n\nIf it this is less than 1, it will be treated as a percentage \nof time a single thread can run before going idle. \n\nIf you experience stuttering when generating distant LODs, \ndecrease this number. If you want to increase LOD \ngeneration speed, increase this number. \n\nThis and the number of buffer builder threads are independent, \nif they add up to more threads than your CPU has cores \nthat is ok.",
"lod.config.client.advanced.threading.numberOfBufferBuilderThreads":
"lod.config.client.advanced.multiThreading.numberOfBufferBuilderThreads":
"NO. of buffer builder threads",
"lod.config.client.advanced.threading.numberOfBufferBuilderThreads.@tooltip":
"lod.config.client.advanced.multiThreading.numberOfBufferBuilderThreads.@tooltip":
"The number of threads used when building geometry data.\nCan only be between 1 and your CPU's processor count.",
"lod.config.client.advanced.threading.numberOfFileHandlerThreads":
"lod.config.client.advanced.multiThreading.numberOfFileHandlerThreads":
"NO. of file handler threads",
"lod.config.client.advanced.threading.numberOfFileHandlerThreads.@tooltip":
"lod.config.client.advanced.multiThreading.numberOfFileHandlerThreads.@tooltip":
"The number of threads used when building vertex buffers\n(The things sent to your GPU to draw the LODs).\nCan only be between 1 and your CPU's processor count.",
"lod.config.client.advanced.threading.numberOfDataConverterThreads":
"lod.config.client.advanced.multiThreading.numberOfDataConverterThreads":
"NO. of data converter threads",
"lod.config.client.advanced.threading.numberOfDataConverterThreads.@tooltip":
"lod.config.client.advanced.multiThreading.numberOfDataConverterThreads.@tooltip":
"The number of threads used when converting ID data to render-able data.\n(This generally happens when generating new terrain or changing graphics settings).\nCan only be between 1 and your CPU's processor count.",
@@ -337,7 +333,11 @@
"Only Render LODs",
"lod.config.client.advanced.debugging.lodOnlyMode.@tooltip":
"If enabled this will disable (most) vanilla Minecraft rendering. \n\nNOTE: Do not report any issues when this mode is on! \nThis setting is only for fun and debugging. \nMod compatibility is not guaranteed.",
"lod.config.client.advanced.debugging.debugWireframeRendering":
"Enable Debug Wireframe Rendering",
"lod.config.client.advanced.debugging.debugWireframeRendering.@tooltip":
"If enabled, various wireframes for debugging internal functions will be drawn.",
"lod.config.client.advanced.buffers":
"Buffers",
"lod.config.client.advanced.buffers.gpuUploadMethod":
@@ -431,30 +431,30 @@
"lod.config.enum.EQuickQuality.CUSTOM":
"lod.config.enum.EQualityPreset.CUSTOM":
"Custom",
"lod.config.enum.EQuickQuality.MINIMUM":
"lod.config.enum.EQualityPreset.MINIMUM":
"Minimum",
"lod.config.enum.EQuickQuality.LOW":
"lod.config.enum.EQualityPreset.LOW":
"Low",
"lod.config.enum.EQuickQuality.MEDIUM":
"lod.config.enum.EQualityPreset.MEDIUM":
"Medium",
"lod.config.enum.EQuickQuality.HIGH":
"lod.config.enum.EQualityPreset.HIGH":
"High",
"lod.config.enum.EQuickQuality.EXTREME":
"lod.config.enum.EQualityPreset.EXTREME":
"Extreme",
"lod.config.enum.EQuickThread.CUSTOM":
"lod.config.enum.EThreadPreset.CUSTOM":
"Custom",
"lod.config.enum.EQuickThread.MINIMAL_IMPACT":
"lod.config.enum.EThreadPreset.MINIMAL_IMPACT":
"Minimal Impact",
"lod.config.enum.EQuickThread.LOW_IMPACT":
"lod.config.enum.EThreadPreset.LOW_IMPACT":
"Low Impact",
"lod.config.enum.EQuickThread.BALANCED":
"lod.config.enum.EThreadPreset.BALANCED":
"Balanced",
"lod.config.enum.EQuickThread.AGGRESSIVE_LOADING":
"Aggressive Loading",
"lod.config.enum.EQuickThread.I_PAID_FOR_THE_WHOLE_CPU":
"lod.config.enum.EThreadPreset.AGGRESSIVE":
"Aggressive",
"lod.config.enum.EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU":
"I Paid For The Whole CPU",
"lod.config.enum.EHorizontalResolution.BLOCK":
@@ -476,8 +476,8 @@
"Medium",
"lod.config.enum.EVerticalQuality.HIGH":
"High",
"lod.config.enum.EVerticalQuality.ULTRA":
"Ultra",
"lod.config.enum.EVerticalQuality.EXTREME":
"Extreme",
"lod.config.enum.EHorizontalQuality.LOWEST":
"Lowest",
"lod.config.enum.EHorizontalQuality.LOW":
@@ -486,6 +486,10 @@
"Medium",
"lod.config.enum.EHorizontalQuality.HIGH":
"High",
"lod.config.enum.EHorizontalQuality.EXTREME":
"Extreme",
"lod.config.enum.EHorizontalQuality.UNLIMITED":
"Unlimited",
"lod.config.enum.ETransparency.DISABLED":
"Disabled",
@@ -591,12 +595,17 @@
"lod.config.enum.EBlocksToAvoid.NONE":
"None",
"lod.config.enum.EBlocksToAvoid.NON_FULL":
"Non full",
"lod.config.enum.EBlocksToAvoid.NO_COLLISION":
"No collision",
"lod.config.enum.EBlocksToAvoid.BOTH":
"Both",
"lod.config.enum.EBlocksToAvoid.NON_COLLIDING":
"Non-Colliding",
"lod.config.enum.EOverdrawPrevention.NONE":
"None",
"lod.config.enum.EOverdrawPrevention.LIGHT":
"Light",
"lod.config.enum.EOverdrawPrevention.MEDIUM":
"Medium",
"lod.config.enum.EOverdrawPrevention.HEAVY":
"Heavy",
"lod.config.enum.EServerFolderNameMode.NAME_ONLY":
"Name Only",