Re-add biome blending
This commit is contained in:
@@ -347,19 +347,17 @@ public class Config
|
||||
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
|
||||
.build();
|
||||
|
||||
// TODO fixme
|
||||
//public static ConfigEntry<Integer> lodBiomeBlending = new ConfigEntry.Builder<Integer>()
|
||||
// .setMinDefaultMax(0,1,7)
|
||||
// .comment(""
|
||||
// + "This is the same as vanilla Biome Blending settings for Lod area. \n"
|
||||
// + " Note that anything other than '0' will greatly effect Lod building time \n"
|
||||
// + " and increase triangle count. The cost on chunk generation speed is also \n"
|
||||
// + " quite large if set too high.\n"
|
||||
// + "\n"
|
||||
// + " '0' equals to Vanilla Biome Blending of '1x1' or 'OFF', \n"
|
||||
// + " '1' equals to Vanilla Biome Blending of '3x3', \n"
|
||||
// + " '2' equals to Vanilla Biome Blending of '5x5'...")
|
||||
// .build();
|
||||
public static ConfigEntry<Integer> lodBiomeBlending = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(0,3,3) // going higher than 3 causes banding issues for blending across LOD borders and an exponential increase in load times
|
||||
.comment(""
|
||||
+ "This is the same as vanilla Biome Blending settings for Lod area. \n"
|
||||
+ " Note that anything other than '0' will greatly effect Lod building time. \n"
|
||||
+ "\n"
|
||||
+ " '0' equals to Vanilla Biome Blending of '1x1' or 'OFF', \n"
|
||||
+ " '1' equals to Vanilla Biome Blending of '3x3', \n"
|
||||
+ " '2' equals to Vanilla Biome Blending of '5x5'...")
|
||||
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class Ssao
|
||||
|
||||
+10
@@ -114,6 +114,15 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
|
||||
this.put(EDhApiQualityPreset.HIGH, false);
|
||||
this.put(EDhApiQualityPreset.EXTREME, false);
|
||||
}});
|
||||
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, Integer> biomeBlending = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.lodBiomeBlending,
|
||||
new HashMap<EDhApiQualityPreset, Integer>()
|
||||
{{
|
||||
this.put(EDhApiQualityPreset.MINIMUM, 0);
|
||||
this.put(EDhApiQualityPreset.LOW, 1);
|
||||
this.put(EDhApiQualityPreset.MEDIUM, 3);
|
||||
this.put(EDhApiQualityPreset.HIGH, 3);
|
||||
this.put(EDhApiQualityPreset.EXTREME, 3);
|
||||
}});
|
||||
|
||||
|
||||
|
||||
@@ -133,6 +142,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
|
||||
this.configList.add(this.vanillaFade);
|
||||
this.configList.add(this.dhDither);
|
||||
this.configList.add(this.caveCulling);
|
||||
this.configList.add(this.biomeBlending);
|
||||
|
||||
|
||||
for (ConfigEntryWithPresetOptions<EDhApiQualityPreset, ?> config : this.configList)
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
|
||||
public String getKeyDisplayString() { return DhSectionPos.toString(this.pos); }
|
||||
|
||||
@Override
|
||||
public Long getPos() { return this.pos; }
|
||||
public long getPos() { return this.pos; }
|
||||
|
||||
public void resizeDataStructuresForRepopulation(long pos)
|
||||
{
|
||||
|
||||
+79
-3
@@ -32,7 +32,9 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pooling.AbstractPhantomArrayList;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListCheckout;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListPool;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.util.*;
|
||||
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
@@ -281,10 +283,83 @@ public class FullDataSourceV2
|
||||
|
||||
|
||||
//======//
|
||||
// data //
|
||||
// getters //
|
||||
//======//
|
||||
|
||||
public LongArrayList get(int relX, int relZ) throws IndexOutOfBoundsException { return this.dataPoints[relativePosToIndex(relX, relZ)]; }
|
||||
public LongArrayList get(int relX, int relZ) throws IndexOutOfBoundsException
|
||||
{ return this.dataPoints[relativePosToIndex(relX, relZ)]; }
|
||||
|
||||
/**
|
||||
* returns {@link FullDataPointUtil#EMPTY_DATA_POINT} if the given {@link DhBlockPos}
|
||||
* is outside this data source's boundaries.
|
||||
*/
|
||||
public long getAtBlockPos(DhBlockPos blockPos)
|
||||
{
|
||||
DhLodPos requestedPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.getX(), blockPos.getZ());
|
||||
|
||||
// stop if the requested blockPos is outside this datasource
|
||||
{
|
||||
// get the detail levels for this request
|
||||
byte requestedDetailLevel = requestedPos.detailLevel;
|
||||
byte requestedSectionDetailLevel = (byte) (requestedDetailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
|
||||
// get the positions for this request
|
||||
long sectionPos = requestedPos.getSectionPosWithSectionDetailLevel(requestedSectionDetailLevel);
|
||||
if (!DhSectionPos.contains(this.pos, sectionPos))
|
||||
{
|
||||
return FullDataPointUtil.EMPTY_DATA_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get the relative data source position
|
||||
byte requestDetailLevel = (byte) (DhSectionPos.getDetailLevel(this.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
DhLodPos relativePos = requestedPos.getDhSectionRelativePositionForDetailLevel(requestDetailLevel);
|
||||
|
||||
// get the data column
|
||||
LongArrayList dataColumn = this.get(relativePos.x, relativePos.z);
|
||||
if (dataColumn == null)
|
||||
{
|
||||
return FullDataPointUtil.EMPTY_DATA_POINT;
|
||||
}
|
||||
|
||||
|
||||
// search for a datapoint that contains the given block y position
|
||||
long dataPoint;
|
||||
for (int i = 0; i < dataColumn.size(); i++)
|
||||
{
|
||||
dataPoint = dataColumn.getLong(i);
|
||||
|
||||
// we are looking for a specific datapoint,
|
||||
// don't look at null ones
|
||||
if (dataPoint == FullDataPointUtil.EMPTY_DATA_POINT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int requestedY = blockPos.getY();
|
||||
int bottomY = FullDataPointUtil.getBottomY(dataPoint) + this.levelMinY;
|
||||
int height = FullDataPointUtil.getHeight(dataPoint);
|
||||
int topY = bottomY + height;
|
||||
|
||||
// does this datapoint contain the requested Y position?
|
||||
if (bottomY <= requestedY
|
||||
&& requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY
|
||||
{
|
||||
return dataPoint;
|
||||
}
|
||||
}
|
||||
|
||||
return FullDataPointUtil.EMPTY_DATA_POINT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// updating //
|
||||
//==========//
|
||||
|
||||
@Override
|
||||
public boolean update(@NotNull FullDataSourceV2 inputDataSource, @Nullable IDhLevel level) { return this.update(inputDataSource); }
|
||||
@@ -991,6 +1066,7 @@ public class FullDataSourceV2
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
@@ -1075,7 +1151,7 @@ public class FullDataSourceV2
|
||||
//=====================//
|
||||
|
||||
@Override
|
||||
public Long getPos() { return this.pos; }
|
||||
public long getPos() { return this.pos; }
|
||||
|
||||
@Override
|
||||
public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); }
|
||||
|
||||
+15
-10
@@ -131,7 +131,7 @@ public class FullDataToRenderDataTransformer
|
||||
LongArrayList dataColumn = fullDataSource.get(x, z);
|
||||
|
||||
updateOrReplaceRenderDataViewColumnWithFullDataColumn(
|
||||
levelWrapper, fullDataSource.mapping,
|
||||
levelWrapper, fullDataSource,
|
||||
// bitshift is to account for LODs with a detail level greater than 0 so the block pos is correct
|
||||
baseX + BitShiftUtil.pow(x,dataDetail), baseZ + BitShiftUtil.pow(z,dataDetail),
|
||||
columnArrayView, dataColumn);
|
||||
@@ -145,13 +145,14 @@ public class FullDataToRenderDataTransformer
|
||||
|
||||
/** Updates the given {@link ColumnArrayView} to match the incoming Full data {@link LongArrayList} */
|
||||
public static void updateOrReplaceRenderDataViewColumnWithFullDataColumn(
|
||||
IClientLevelWrapper levelWrapper,
|
||||
FullDataPointIdMap fullDataMapping, int blockX, int blockZ,
|
||||
IClientLevelWrapper levelWrapper,
|
||||
FullDataSourceV2 fullDataSource, int blockX, int blockZ,
|
||||
ColumnArrayView columnArrayView,
|
||||
LongArrayList fullDataColumn)
|
||||
{
|
||||
// we can't do anything if the full data is missing or empty
|
||||
if (fullDataColumn == null || fullDataColumn.size() == 0)
|
||||
if (fullDataColumn == null
|
||||
|| fullDataColumn.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -160,7 +161,7 @@ public class FullDataToRenderDataTransformer
|
||||
if (fullDataLength <= columnArrayView.verticalSize())
|
||||
{
|
||||
// Directly use the arrayView since it fits.
|
||||
setRenderColumnView(levelWrapper, fullDataMapping, blockX, blockZ, columnArrayView, fullDataColumn);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, columnArrayView, fullDataColumn);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -171,7 +172,7 @@ public class FullDataToRenderDataTransformer
|
||||
{
|
||||
// expand the ColumnArrayView to fit the new larger max vertical size
|
||||
ColumnArrayView newColumnArrayView = new ColumnArrayView(dataArrayList, fullDataLength, 0, fullDataLength);
|
||||
setRenderColumnView(levelWrapper, fullDataMapping, blockX, blockZ, newColumnArrayView, fullDataColumn);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, newColumnArrayView, fullDataColumn);
|
||||
columnArrayView.changeVerticalSizeFrom(newColumnArrayView);
|
||||
}
|
||||
finally
|
||||
@@ -181,7 +182,7 @@ public class FullDataToRenderDataTransformer
|
||||
}
|
||||
}
|
||||
private static void setRenderColumnView(
|
||||
IClientLevelWrapper levelWrapper, FullDataPointIdMap fullDataMapping,
|
||||
IClientLevelWrapper levelWrapper, FullDataSourceV2 fullDataSource,
|
||||
int blockX, int blockZ,
|
||||
ColumnArrayView renderColumnData, LongArrayList fullColumnData)
|
||||
{
|
||||
@@ -222,6 +223,8 @@ public class FullDataToRenderDataTransformer
|
||||
// convert full data to render data //
|
||||
//==================================//
|
||||
|
||||
FullDataPointIdMap fullDataMapping = fullDataSource.mapping;
|
||||
|
||||
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable(blockX, 0, blockZ);
|
||||
|
||||
// goes from the top down
|
||||
@@ -320,11 +323,13 @@ public class FullDataToRenderDataTransformer
|
||||
//=======================//
|
||||
|
||||
if (ignoreNonCollidingBlocks
|
||||
&& !block.isSolid() && !block.isLiquid() && block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE)
|
||||
&& !block.isSolid()
|
||||
&& !block.isLiquid()
|
||||
&& block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE)
|
||||
{
|
||||
if (colorBelowWithAvoidedBlocks)
|
||||
{
|
||||
int tempColor = levelWrapper.getBlockColor(mutableBlockPos, biome, block);
|
||||
int tempColor = levelWrapper.getBlockColor(mutableBlockPos, biome, fullDataSource, block);
|
||||
|
||||
// don't transfer the color when alpha is 0
|
||||
// this prevents issues if grass is transparent
|
||||
@@ -345,7 +350,7 @@ public class FullDataToRenderDataTransformer
|
||||
if (colorToApplyToNextBlock == -1)
|
||||
{
|
||||
// use this block's color
|
||||
color = levelWrapper.getBlockColor(mutableBlockPos, biome, block);
|
||||
color = levelWrapper.getBlockColor(mutableBlockPos, biome, fullDataSource, block);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.seibel.distanthorizons.core.sql.dto.IBaseDTO;
|
||||
*/
|
||||
public interface IDataSource<TDhLevel extends IDhLevel> extends IBaseDTO<Long>, AutoCloseable
|
||||
{
|
||||
Long getPos();
|
||||
long getPos();
|
||||
|
||||
/** @return true if the data was changed */
|
||||
boolean update(FullDataSourceV2 chunkData, TDhLevel level);
|
||||
|
||||
@@ -221,11 +221,27 @@ public class DhSectionPos
|
||||
byte offset = (byte) (detailLevel - returnDetailLevel);
|
||||
return BitShiftUtil.powerOfTwo(offset);
|
||||
}
|
||||
|
||||
/** @return how wide this section is in blocks */
|
||||
public static int getBlockWidth(long pos) { return BitShiftUtil.powerOfTwo(getDetailLevel(pos)); }
|
||||
|
||||
|
||||
/** @return how wide this section is in chunks */
|
||||
public static int getChunkWidth(long pos) { return DhSectionPos.getBlockWidth(pos) / LodUtil.CHUNK_WIDTH; }
|
||||
/** @see DhSectionPos#getDetailLevelWidthInBlocks(byte) */
|
||||
public static int getBlockWidth(long pos) { return getDetailLevelWidthInBlocks(getDetailLevel(pos)); }
|
||||
/**
|
||||
* Returns how many blocks wide a single LOD at the given detail level would be in blocks. <br>
|
||||
* IE: <br>
|
||||
* <code>
|
||||
* 0 => 1 <br>
|
||||
* 1 => 2 <br>
|
||||
* 2 => 4 <br>
|
||||
* 3 => 8 <br>
|
||||
* 4 => 16 <br>
|
||||
* 5 => 32 <br>
|
||||
* 6 => 64 <br>
|
||||
* etc. <br>
|
||||
* </code>
|
||||
*/
|
||||
public static int getDetailLevelWidthInBlocks(byte detailLevel) { return BitShiftUtil.powerOfTwo(detailLevel); }
|
||||
|
||||
|
||||
public static DhBlockPos2D getCenterBlockPos(long pos) { return new DhBlockPos2D(getCenterBlockPosX(pos), getCenterBlockPosZ(pos)); }
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -34,7 +35,7 @@ public interface IClientLevelWrapper extends ILevelWrapper
|
||||
@Nullable
|
||||
IServerLevelWrapper tryGetServerSideWrapper();
|
||||
|
||||
int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState);
|
||||
int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockState);
|
||||
/** @return -1 if there was a problem getting the color */
|
||||
int getDirtBlockColor();
|
||||
/** @return -1 if there was a problem getting the color */
|
||||
|
||||
Reference in New Issue
Block a user