From d4123a44ed2976451178e0510d00a1880a7a87ee Mon Sep 17 00:00:00 2001 From: tom lee Date: Fri, 7 Jan 2022 18:58:29 +0800 Subject: [PATCH] Add DropoffQuality --- .../lod/core/enums/config/DropoffQuality.java | 48 ++++++++++++++++ .../lod/core/objects/lod/LodDimension.java | 18 ++++-- .../lod/core/objects/lod/LodRegion.java | 55 +++++++++++++++++-- .../config/ILodConfigWrapperSingleton.java | 16 ++++++ 4 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/seibel/lod/core/enums/config/DropoffQuality.java diff --git a/src/main/java/com/seibel/lod/core/enums/config/DropoffQuality.java b/src/main/java/com/seibel/lod/core/enums/config/DropoffQuality.java new file mode 100644 index 000000000..271c8c68b --- /dev/null +++ b/src/main/java/com/seibel/lod/core/enums/config/DropoffQuality.java @@ -0,0 +1,48 @@ +/* + * This file is part of the Distant Horizon mod (formerly the LOD Mod), + * licensed under the GNU GPL v3 License. + * + * Copyright (C) 2022 Tom Lee (TomTheFurry) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.core.enums.config; + +/** + * AUTO
+ * SMOOTH_DROPOFF
+ * PERFORMANCE_FOCUSED
+ *
+ * Determines how lod level drop off should be done + * + * @author Tom Lee + * @version 7-1-2022 + */ +public enum DropoffQuality { + + /** SMOOTH_DROPOFF when <128 lod view distance, or PERFORMANCE_FOCUSED otherwise */ + AUTO(-1), + + SMOOTH_DROPOFF(10), + + PERFORMANCE_FOCUSED(0); + + public final int fastModeSwitch; + + DropoffQuality(int fastModeSwitch) { + this.fastModeSwitch = fastModeSwitch; + } + + +} diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java index b249e95fe..3b59af3ce 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java @@ -26,6 +26,7 @@ import java.util.concurrent.Executors; import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.enums.config.DistanceGenerationMode; +import com.seibel.lod.core.enums.config.DropoffQuality; import com.seibel.lod.core.enums.config.GenerationPriority; import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.handlers.LodDimensionFileHandler; @@ -385,7 +386,11 @@ public class LodDimension DistanceGenerationMode generationMode = CONFIG.client().worldGenerator().getDistanceGenerationMode(); VerticalQuality verticalQuality = CONFIG.client().graphics().quality().getVerticalQuality(); - + DropoffQuality dropoffQuality = CONFIG.client().graphics().quality().getDropoffQuality(); + if (dropoffQuality == DropoffQuality.AUTO) + dropoffQuality = CONFIG.client().graphics().quality().getLodChunkRenderDistance() < 128 ? + DropoffQuality.SMOOTH_DROPOFF : DropoffQuality.PERFORMANCE_FOCUSED; + int dropoffSwitch = dropoffQuality.fastModeSwitch; // don't run the expander multiple times // for the same location Runnable thread = () -> { @@ -423,10 +428,10 @@ public class LodDimension region = getRegionFromFile(regions[x][z], minDetail, generationMode, verticalQuality); regions[x][z] = region; updated = true; - } else if (region.lastMaxDetailLevel != maxDetail) { + } else if (minDetail <= dropoffSwitch && region.lastMaxDetailLevel != maxDetail) { region.lastMaxDetailLevel = maxDetail; updated = true; - } else if (region.lastMaxDetailLevel != region.getMinDetailLevel()) { + } else if (minDetail <= dropoffSwitch && region.lastMaxDetailLevel != region.getMinDetailLevel()) { updated = true; } if (updated) { @@ -503,11 +508,16 @@ public class LodDimension GenerationPriority generationPriority = CONFIG.client().worldGenerator().getGenerationPriority(); if (generationPriority == GenerationPriority.AUTO) generationPriority = MC.hasSinglePlayerServer() ? GenerationPriority.FAR_FIRST : GenerationPriority.NEAR_FIRST; + + DropoffQuality dropoffQuality = CONFIG.client().graphics().quality().getDropoffQuality(); + if (dropoffQuality == DropoffQuality.AUTO) + dropoffQuality = CONFIG.client().graphics().quality().getLodChunkRenderDistance() < 128 ? + DropoffQuality.SMOOTH_DROPOFF : DropoffQuality.PERFORMANCE_FOCUSED; boolean requireCorrectDetailLevel = generationPriority == GenerationPriority.NEAR_FIRST; if (region != null) - region.getPosToRender(posToRender, playerPosX, playerPosZ, requireCorrectDetailLevel); + region.getPosToRender(posToRender, playerPosX, playerPosZ, requireCorrectDetailLevel, dropoffQuality); } /** diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java index 936d16d21..b5dc6a9aa 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java @@ -20,6 +20,7 @@ package com.seibel.lod.core.objects.lod; import com.seibel.lod.core.enums.config.DistanceGenerationMode; +import com.seibel.lod.core.enums.config.DropoffQuality; import com.seibel.lod.core.enums.config.GenerationPriority; import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.objects.PosToGenerateContainer; @@ -192,7 +193,6 @@ public class LodRegion { int childPosX = childOffsetPosX * 2; int childPosZ = childOffsetPosZ * 2; - int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel); byte targetDetailLevel = DetailDistanceUtil.getGenerationDetailFromDistance(minDistance); if (targetDetailLevel <= detailLevel) { @@ -233,9 +233,15 @@ public class LodRegion { * understand */ public void getPosToRender(PosToRenderContainer posToRender, int playerPosX, int playerPosZ, - boolean requireCorrectDetailLevel) { - getPosToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, - requireCorrectDetailLevel); + boolean requireCorrectDetailLevel, DropoffQuality dropoffQuality) { + int minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, regionPosX, regionPosZ); + byte targetLevel = DetailDistanceUtil.getDrawDetailFromDistance(minDistance); + if (targetLevel <= dropoffQuality.fastModeSwitch) { + getPosToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, + requireCorrectDetailLevel); + } else { + getPosToRenderFlat(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, targetLevel, requireCorrectDetailLevel); + } } /** @@ -305,6 +311,47 @@ public class LodRegion { } } + /** + * This method will fill the posToRender array with all levelPos that are + * render-able. But the entire region try use the same detail level. + */ + private void getPosToRenderFlat(PosToRenderContainer posToRender, byte detailLevel, int posX, int posZ, byte targetLevel, boolean requireCorrectDetailLevel) { + // equivalent to 2^(...) + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); + + if (detailLevel == targetLevel) { + posToRender.addPosToRender(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); + } else // case where (detailLevel > desiredLevel) + { + int childPosX = posX * 2; + int childPosZ = posZ * 2; + byte childDetailLevel = (byte) (detailLevel - 1); + int childrenCount = 0; + + for (int x = 0; x <= 1; x++) { + for (int z = 0; z <= 1; z++) { + if (doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) { + if (!requireCorrectDetailLevel) + childrenCount++; + else + getPosToRenderFlat(posToRender, childDetailLevel, childPosX + x, childPosZ + z, targetLevel, requireCorrectDetailLevel); + } + } + } + + if (!requireCorrectDetailLevel) { + // If all the four children exist go deeper + if (childrenCount == 4) { + for (int x = 0; x <= 1; x++) + for (int z = 0; z <= 1; z++) + getPosToRenderFlat(posToRender, childDetailLevel, childPosX + x, childPosZ + z, targetLevel, requireCorrectDetailLevel); + } else { + posToRender.addPosToRender(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); + } + } + } + } + /** * Updates all children. *

diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java index 8b2d8092a..00da18d5c 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java @@ -22,6 +22,7 @@ package com.seibel.lod.core.wrapperInterfaces.config; import com.seibel.lod.core.enums.config.BlocksToAvoid; import com.seibel.lod.core.enums.config.BufferRebuildTimes; import com.seibel.lod.core.enums.config.DistanceGenerationMode; +import com.seibel.lod.core.enums.config.DropoffQuality; import com.seibel.lod.core.enums.config.GenerationPriority; import com.seibel.lod.core.enums.config.GpuUploadMethod; import com.seibel.lod.core.enums.config.HorizontalQuality; @@ -140,6 +141,21 @@ public interface ILodConfigWrapperSingleton + " Highest Quality: " + HorizontalQuality.HIGH; HorizontalQuality getHorizontalQuality(); void setHorizontalQuality(HorizontalQuality newHorizontalQuality); + + DropoffQuality DROPOFF_QUALITY_DEFAULT = DropoffQuality.AUTO; + String DROPOFF_QUALITY_DESC = "" + + " This determines how lod level drop off will be done. \n" + + "\n" + + " " + DropoffQuality.SMOOTH_DROPOFF + ": \n" + + " The lod level is calculated for each point, making the drop off a smooth circle. \n" + + " " + DropoffQuality.PERFORMANCE_FOCUSED + ": \n" + + " One detail level for an entire region. Minimize CPU usage and \n" + + " improve terrain refresh delay, especially for high Lod render distance. \n" + + " " + DropoffQuality.AUTO + ": \n" + + " Use "+ DropoffQuality.SMOOTH_DROPOFF + " for less then 128 Lod render distance, \n" + + " or "+ DropoffQuality.PERFORMANCE_FOCUSED +" otherwise. \n"; + DropoffQuality getDropoffQuality(); + void setDropoffQuality(DropoffQuality newDropoffQuality); } interface IFogQuality