Changed various names, changed the memory calculator
This commit is contained in:
@@ -4,6 +4,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.builders.lodTemplates.Box;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.HorizontalQuality;
|
||||
import com.seibel.lod.enums.HorizontalScale;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
@@ -12,44 +15,29 @@ public class Main
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
/*
|
||||
try
|
||||
for(byte detail = 0; detail < 13; detail++)
|
||||
{
|
||||
@SuppressWarnings("serial")
|
||||
Map<Direction, long[]> adjData = new HashMap<Direction, long[]>()
|
||||
{{
|
||||
put(Direction.EAST, new long[]{DataPointUtil.createDataPoint(60, 30, 0, 0, 0, 0), DataPointUtil.createDataPoint(25, 10, 0, 0, 0, 0)});
|
||||
put(Direction.WEST, new long[]{DataPointUtil.createDataPoint(60, 10, 0, 0, 0, 0)});
|
||||
put(Direction.NORTH, new long[]{DataPointUtil.createDataPoint(40, 20, 0, 0, 0, 0)});
|
||||
put(Direction.SOUTH, new long[]{DataPointUtil.createDataPoint(40, 20, 0, 0, 0, 0)});
|
||||
}};
|
||||
|
||||
Box box = new Box();
|
||||
int height = 60;
|
||||
int depth = 20;
|
||||
|
||||
box.set(10, height - depth, 10);
|
||||
box.move(0, depth, 0);
|
||||
box.setAdjData(adjData);
|
||||
|
||||
for(Direction direction : Box.DIRECTIONS)
|
||||
byte minGenDetail = 0;
|
||||
byte maxDetail = 10;
|
||||
int distance;
|
||||
if (detail <= minGenDetail)
|
||||
distance = 0;
|
||||
else if (detail >= maxDetail)
|
||||
distance = 10000;
|
||||
else
|
||||
{
|
||||
int adjIndex = 0;
|
||||
while (box.shouldContinue(direction, adjIndex))
|
||||
int distanceUnit = HorizontalScale.LOW.distanceUnit;
|
||||
switch (HorizontalQuality.HIGH)
|
||||
{
|
||||
System.out.println(direction.toString());
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
System.out.println(box.getX(direction, i) + " " + box.getY(direction, i, adjIndex) + " " + box.getZ(direction, i));
|
||||
}
|
||||
adjIndex++;
|
||||
case LINEAR:
|
||||
;
|
||||
distance = (detail * distanceUnit);
|
||||
default:
|
||||
double base = HorizontalQuality.HIGH.quadraticBase;
|
||||
distance = (int) (Math.pow(base, detail) * distanceUnit);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println(distance);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,23 +20,13 @@ package com.seibel.lod.config;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import com.seibel.lod.enums.*;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||
import com.seibel.lod.ModInfo;
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.enums.DetailDropOff;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.DistanceQualityDropOff;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.GenerationPriority;
|
||||
import com.seibel.lod.enums.HorizontalQuality;
|
||||
import com.seibel.lod.enums.HorizontalResolution;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -90,8 +80,7 @@ public class LodConfig
|
||||
public ForgeConfigSpec.EnumValue<HorizontalResolution> drawResolution;
|
||||
|
||||
// public ForgeConfigSpec.EnumValue<ShadingMode> shadingMode;
|
||||
|
||||
public ForgeConfigSpec.EnumValue<HorizontalQuality> horizontalQuality;
|
||||
|
||||
|
||||
public ForgeConfigSpec.EnumValue<DetailDropOff> detailDropOff;
|
||||
|
||||
@@ -143,10 +132,9 @@ public class LodConfig
|
||||
detailDropOff = builder
|
||||
.comment("\n\n"
|
||||
+ " How smooth should the detail transition for LODs be? \n"
|
||||
+ DetailDropOff.BY_CHUNK + ": quality is determined per-chunk (best quality option, may cause stuttering when moving)\n"
|
||||
+ DetailDropOff.BY_REGION_FANCY + ": quality is determined per-region (quality option)\n"
|
||||
+ DetailDropOff.BY_REGION_FAST + ": quality is determined per-region (performance option)\n")
|
||||
.defineEnum("detailDropOff", DetailDropOff.BY_CHUNK);
|
||||
+ DetailDropOff.FANCY + ": quality is determined per-block (best quality option, may cause stuttering when moving)\n"
|
||||
+ DetailDropOff.FAST + ": quality is determined per-region (performance option)\n")
|
||||
.defineEnum("detailDropOff", DetailDropOff.FANCY);
|
||||
|
||||
drawResolution = builder
|
||||
.comment("\n\n"
|
||||
@@ -157,14 +145,7 @@ public class LodConfig
|
||||
+ " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n")
|
||||
.defineEnum("Draw resolution", HorizontalResolution.BLOCK);
|
||||
|
||||
horizontalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ " This indicates how quickly LODs drop off in quality. \n"
|
||||
+ " " + HorizontalQuality.LOW + ": quality drops every 4 chunks. \n"
|
||||
+ " " + HorizontalQuality.MEDIUM + ": quality drops every 8 chunks. \n"
|
||||
+ " " + HorizontalQuality.HIGH + ": quality drops every 16 chunks. \n")
|
||||
.defineEnum("lodDrawQuality", HorizontalQuality.MEDIUM);
|
||||
|
||||
|
||||
lodChunkRenderDistance = builder
|
||||
.comment("\n\n"
|
||||
@@ -217,7 +198,8 @@ public class LodConfig
|
||||
public ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
|
||||
public ForgeConfigSpec.EnumValue<GenerationPriority> generationPriority;
|
||||
public ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
|
||||
public ForgeConfigSpec.EnumValue<DistanceQualityDropOff> lodDistanceCalculatorType;
|
||||
public ForgeConfigSpec.EnumValue<HorizontalScale> horizontalScale;
|
||||
public ForgeConfigSpec.EnumValue<HorizontalQuality> horizontalQuality;
|
||||
|
||||
WorldGenerator(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
@@ -240,19 +222,23 @@ public class LodConfig
|
||||
+ " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n")
|
||||
.defineEnum("Generation Resolution", HorizontalResolution.BLOCK);
|
||||
|
||||
lodDistanceCalculatorType = builder
|
||||
.comment("\n\n"
|
||||
+ " " + DistanceQualityDropOff.LINEAR + " \n"
|
||||
+ " with LINEAR calculator the quality of block decrease \n"
|
||||
+ " linearly to the distance of the player \n"
|
||||
|
||||
+ "\n"
|
||||
+ " " + DistanceQualityDropOff.QUADRATIC + " \n"
|
||||
+ " with QUADRATIC calculator the quality of block decrease \n"
|
||||
+ " quadratically to the distance of the player \n")
|
||||
.defineEnum("lodDistanceComputation", DistanceQualityDropOff.LINEAR);
|
||||
|
||||
|
||||
horizontalScale = builder
|
||||
.comment("\n\n"
|
||||
+ " This indicates how quickly LODs drop off in quality. \n"
|
||||
+ " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit/16 + " chunks. \n"
|
||||
+ " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit/16 + " chunks. \n"
|
||||
+ " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit/16 + " chunks. \n")
|
||||
.defineEnum("horizontal scale", HorizontalScale.MEDIUM);
|
||||
|
||||
horizontalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ " This indicates the exponential base of the quadratic drop-off \n"
|
||||
+ " " + HorizontalQuality.LINEAR + ": base " + HorizontalQuality.LINEAR.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n")
|
||||
.defineEnum("horizontal quality", HorizontalQuality.MEDIUM);
|
||||
generationPriority = builder
|
||||
.comment("\n\n"
|
||||
+ " " + GenerationPriority.FAR_FIRST + " \n"
|
||||
|
||||
@@ -28,11 +28,8 @@ package com.seibel.lod.enums;
|
||||
public enum DetailDropOff
|
||||
{
|
||||
/** quality is determined per-region, using the lowest quality that would be used in BY_CHUNK */
|
||||
BY_REGION_FAST,
|
||||
|
||||
/** quality is determined per-region, using the highest quality that would be used in BY_CHUNK */
|
||||
BY_REGION_FANCY,
|
||||
|
||||
/** quality is determined per-chunk (best quality option, may cause stuttering when moving) */
|
||||
BY_CHUNK,
|
||||
FAST,
|
||||
|
||||
/** quality is determined per-block (best quality option, may cause stuttering when moving) */
|
||||
FANCY,
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 8-22-2021
|
||||
*/
|
||||
public enum DistanceQualityDropOff
|
||||
{
|
||||
/** detail drops off linearly to the distance */
|
||||
LINEAR,
|
||||
|
||||
/** detail drops off quadratically to the distance */
|
||||
QUADRATIC,
|
||||
}
|
||||
@@ -22,26 +22,29 @@ package com.seibel.lod.enums;
|
||||
* Medium <br>
|
||||
* High <br>
|
||||
* <br>
|
||||
* TODO what will the represent when it is hooked up?
|
||||
* this indicate the base of the quadratic function we use for the quality drop off
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-25-2021
|
||||
* @version 9-29-2021
|
||||
*/
|
||||
public enum HorizontalQuality
|
||||
{
|
||||
/** Lods are 2D with heightMap */
|
||||
LOW(64),
|
||||
|
||||
LINEAR(1.0f),
|
||||
|
||||
/** Lods are 2D with heightMap */
|
||||
LOW(1.5f),
|
||||
|
||||
/** Lods expand in three dimension */
|
||||
MEDIUM(128),
|
||||
|
||||
MEDIUM(2f),
|
||||
|
||||
/** Lods expand in three dimension */
|
||||
HIGH(256);
|
||||
|
||||
public int distanceUnit;
|
||||
|
||||
HorizontalQuality(int distanceUnit)
|
||||
HIGH(Math.E);
|
||||
|
||||
public double quadraticBase;
|
||||
|
||||
HorizontalQuality(double distanceUnit)
|
||||
{
|
||||
this.distanceUnit = distanceUnit;
|
||||
this.quadraticBase = distanceUnit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
/**
|
||||
* Low <br>
|
||||
* Medium <br>
|
||||
* High <br>
|
||||
* <br>
|
||||
* this is a quality scale for the detail drop-off
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-25-2021
|
||||
*/
|
||||
public enum HorizontalScale
|
||||
{
|
||||
/** Lods are 2D with heightMap */
|
||||
LOW(64),
|
||||
|
||||
/** Lods expand in three dimension */
|
||||
MEDIUM(128),
|
||||
|
||||
/** Lods expand in three dimension */
|
||||
HIGH(256);
|
||||
|
||||
public int distanceUnit;
|
||||
|
||||
HorizontalScale(int distanceUnit)
|
||||
{
|
||||
this.distanceUnit = distanceUnit;
|
||||
}
|
||||
}
|
||||
@@ -884,17 +884,26 @@ public class LodDimension
|
||||
break;
|
||||
case BY_REGION_FAST:
|
||||
}*/
|
||||
|
||||
/*return regions[x][z].getMinMemoryNeeded(template);*/
|
||||
|
||||
/*TODO add memory use calculated with the following cases
|
||||
switch (LodConfig.CLIENT.graphics.detailDropOff.get())
|
||||
{
|
||||
default:
|
||||
case BY_BLOCK:
|
||||
break;
|
||||
case BY_REGION_FANCY:
|
||||
break;
|
||||
case BY_REGION_FAST:
|
||||
}*/
|
||||
int minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, x, z, halfWidth, halfWidth);
|
||||
int detail = DetailDistanceUtil.getTreeCutDetailFromDistance(minDistance);
|
||||
int levelToGen = DetailDistanceUtil.getLodDrawDetail(detail);
|
||||
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelToGen);
|
||||
int maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detail);
|
||||
|
||||
int numberOfLods = size * size * maxVerticalData;
|
||||
int memoryUse = numberOfLods * template.getBufferMemoryForSingleLod(maxVerticalData);
|
||||
|
||||
int memoryUse = LodUtil.regionRenderingMemoryUse(x,z,template);
|
||||
System.out.println(detail + " " + memoryUse + " " + template.getBufferMemoryForSingleLod(maxVerticalData));
|
||||
return memoryUse;
|
||||
//return memoryUse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,42 +13,53 @@ import com.seibel.lod.util.LodUtil;
|
||||
/**
|
||||
* This object holds all loaded LevelContainers
|
||||
* for a given region. <Br><Br>
|
||||
*
|
||||
*
|
||||
* <strong>Coordinate Standard: </strong><br>
|
||||
* Coordinate called posX or posZ are relative LevelPos coordinates <br>
|
||||
* unless stated otherwise. <br>
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-27-2021
|
||||
*/
|
||||
public class LodRegion
|
||||
{
|
||||
/** TODO what does this represent, and should it be defined here? */
|
||||
/**
|
||||
* TODO what does this represent, and should it be defined here?
|
||||
*/
|
||||
private static final byte POSSIBLE_LOD = 10;
|
||||
|
||||
|
||||
/** Holds the lowest (least detailed) detail level in this region
|
||||
* TODO is that correct? */
|
||||
|
||||
|
||||
/**
|
||||
* Holds the lowest (least detailed) detail level in this region
|
||||
* TODO is that correct?
|
||||
*/
|
||||
private byte minDetailLevel;
|
||||
|
||||
/** This holds all data for this region */
|
||||
|
||||
/**
|
||||
* This holds all data for this region
|
||||
*/
|
||||
private LevelContainer[] dataContainer;
|
||||
|
||||
/** the generation mode for this region
|
||||
* TODO will this ever change through a region's life? */
|
||||
|
||||
/**
|
||||
* the generation mode for this region
|
||||
* TODO will this ever change through a region's life?
|
||||
*/
|
||||
private DistanceGenerationMode generationMode;
|
||||
/** the vertical quality of this region */
|
||||
/**
|
||||
* the vertical quality of this region
|
||||
*/
|
||||
private VerticalQuality verticalQuality;
|
||||
|
||||
/** this region's x RegionPos */
|
||||
|
||||
/**
|
||||
* this region's x RegionPos
|
||||
*/
|
||||
public final int regionPosX;
|
||||
/** this region's z RegionPos */
|
||||
/**
|
||||
* this region's z RegionPos
|
||||
*/
|
||||
public final int regionPosZ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public LodRegion(RegionPos regionPos)
|
||||
{
|
||||
this.minDetailLevel = LodUtil.REGION_DETAIL_LEVEL;
|
||||
@@ -56,7 +67,7 @@ public class LodRegion
|
||||
this.regionPosZ = regionPos.z;
|
||||
dataContainer = new LevelContainer[POSSIBLE_LOD];
|
||||
}
|
||||
|
||||
|
||||
public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
|
||||
{
|
||||
this.minDetailLevel = minDetailLevel;
|
||||
@@ -65,37 +76,37 @@ public class LodRegion
|
||||
this.verticalQuality = verticalQuality;
|
||||
this.generationMode = generationMode;
|
||||
dataContainer = new LevelContainer[POSSIBLE_LOD];
|
||||
|
||||
|
||||
|
||||
|
||||
// Initialize all the different matrices
|
||||
for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++)
|
||||
{
|
||||
switch (verticalQuality)
|
||||
{
|
||||
default:
|
||||
case HEIGHTMAP:
|
||||
dataContainer[lod] = new SingleLevelContainer(lod);
|
||||
break;
|
||||
case VOXEL:
|
||||
dataContainer[lod] = new VerticalLevelContainer(lod);
|
||||
break;
|
||||
default:
|
||||
case HEIGHTMAP:
|
||||
dataContainer[lod] = new SingleLevelContainer(lod);
|
||||
break;
|
||||
case VOXEL:
|
||||
dataContainer[lod] = new VerticalLevelContainer(lod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inserts the data point into the region.
|
||||
*
|
||||
* TODO this will always return true unless it has
|
||||
* <p>
|
||||
* TODO this will always return true unless it has
|
||||
*
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
|
||||
// The dataContainer could have null entries if the
|
||||
// detailLevel changes.
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
@@ -105,97 +116,97 @@ public class LodRegion
|
||||
else
|
||||
this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
}
|
||||
|
||||
|
||||
this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level,
|
||||
* 0 if the data doesn't exist.
|
||||
* 0 if the data doesn't exist.
|
||||
*/
|
||||
public long getData(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[detailLevel].getData(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level,
|
||||
* 0 if the data doesn't exist.
|
||||
* 0 if the data doesn't exist.
|
||||
*/
|
||||
public long getSingleData(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
return dataContainer[detailLevel].getSingleData(posX, posZ);
|
||||
}
|
||||
|
||||
/** Clears the datapoint at the given relative position */
|
||||
|
||||
/**
|
||||
* Clears the datapoint at the given relative position
|
||||
*/
|
||||
public void clear(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
dataContainer[detailLevel].clear(posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will fill the posToGenerate array with all levelPos that
|
||||
* This method will fill the posToGenerate array with all levelPos that
|
||||
* are render-able.
|
||||
*
|
||||
* <p>
|
||||
* TODO why don't we return the posToGenerate, it would make this easier to understand
|
||||
*/
|
||||
public void getDataToGenerate(PosToGenerateContainer posToGenerate,
|
||||
int playerBlockPosX, int playerBlockPosZ)
|
||||
public void getDataToGenerate(PosToGenerateContainer posToGenerate,
|
||||
int playerBlockPosX, int playerBlockPosZ)
|
||||
{
|
||||
getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerBlockPosX, playerBlockPosZ);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A recursive method that fills the posToGenerate array with all levelPos that
|
||||
* A recursive method that fills the posToGenerate array with all levelPos that
|
||||
* need to be generated.
|
||||
*
|
||||
* <p>
|
||||
* TODO why don't we return the posToGenerate, it would make this easier to understand
|
||||
*/
|
||||
private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel,
|
||||
int childOffsetPosX, int childOffsetPosZ, int playerPosX, int playerPosZ)
|
||||
private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel,
|
||||
int childOffsetPosX, int childOffsetPosZ, int playerPosX, int playerPosZ)
|
||||
{
|
||||
// equivalent to 2^(...)
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
|
||||
// calculate what LevelPos are in range to generate
|
||||
int maxDistance = LevelPosUtil.maxDistance(detailLevel, childOffsetPosX, childOffsetPosZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
|
||||
|
||||
// determine this child's levelPos
|
||||
byte childDetailLevel = (byte) (detailLevel - 1);
|
||||
int childPosX = childOffsetPosX * 2;
|
||||
int childPosZ = childOffsetPosZ * 2;
|
||||
|
||||
|
||||
int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel);
|
||||
|
||||
|
||||
byte targetDetailLevel = DetailDistanceUtil.getLodGenDetail(DetailDistanceUtil.getGenerationDetailFromDistance(maxDistance)).detailLevel;
|
||||
if (targetDetailLevel > detailLevel)
|
||||
{
|
||||
// we have gone beyond the target Detail level
|
||||
// we can stop generating
|
||||
return;
|
||||
}
|
||||
else if (targetDetailLevel == detailLevel)
|
||||
} else if (targetDetailLevel == detailLevel)
|
||||
{
|
||||
if (!doesDataExist(detailLevel, childOffsetPosX, childOffsetPosZ))
|
||||
posToGenerate.addPosToGenerate(detailLevel, childOffsetPosX + regionPosX * size, childOffsetPosZ + regionPosZ * size);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
// we want at max one request per chunk (since the world generator creates chunks).
|
||||
// So for lod smaller than a chunk, only recurse down
|
||||
// the top right child
|
||||
|
||||
|
||||
if (detailLevel > LodUtil.CHUNK_DETAIL_LEVEL)
|
||||
{
|
||||
int ungeneratedChildren = 0;
|
||||
|
||||
|
||||
// make sure all children are generated to this detailLevel
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
@@ -208,19 +219,18 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// only if all the children are correctly generated
|
||||
// should we go deeper
|
||||
if (ungeneratedChildren == 0)
|
||||
for (int x = 0; x <= 1; x++)
|
||||
for (int z = 0; z <= 1; z++)
|
||||
getDataToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
// The detail Level is smaller than a chunk.
|
||||
// Only recurse down the top right child.
|
||||
|
||||
|
||||
if (DetailDistanceUtil.getLodGenDetail(childDetailLevel).detailLevel <= (childDetailLevel))
|
||||
{
|
||||
if (!doesDataExist(childDetailLevel, childPosX, childPosZ))
|
||||
@@ -231,102 +241,89 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method will fill the posToRender array with all levelPos that
|
||||
* This method will fill the posToRender array with all levelPos that
|
||||
* are render-able.
|
||||
*
|
||||
* <p>
|
||||
* TODO why don't we return the posToRender, it would make this easier to understand
|
||||
*/
|
||||
public void getDataToRender(PosToRenderContainer posToRender,
|
||||
int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel)
|
||||
public void getDataToRender(PosToRenderContainer posToRender,
|
||||
int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel)
|
||||
{
|
||||
getDataToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, requireCorrectDetailLevel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will fill the posToRender array with all levelPos that
|
||||
* This method will fill the posToRender array with all levelPos that
|
||||
* are render-able.
|
||||
*
|
||||
* <p>
|
||||
* TODO why don't we return the posToRender, it would make this easier to understand
|
||||
* TODO this needs some more comments, James was only able to figure out part of it
|
||||
*/
|
||||
private void getDataToRender(PosToRenderContainer posToRender,
|
||||
byte detailLevel, int posX, int posZ,
|
||||
int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel)
|
||||
private void getDataToRender(PosToRenderContainer posToRender,
|
||||
byte detailLevel, int posX, int posZ,
|
||||
int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel)
|
||||
{
|
||||
// equivalent to 2^(...)
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
|
||||
byte desiredLevel;
|
||||
int maxDistance;
|
||||
boolean stopNow = false;
|
||||
int minDistance;
|
||||
int childLevel;
|
||||
|
||||
|
||||
|
||||
|
||||
// calculate the LevelPos that are in range
|
||||
switch (LodConfig.CLIENT.graphics.detailDropOff.get())
|
||||
{
|
||||
default:
|
||||
case BY_CHUNK:
|
||||
maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance));
|
||||
minDistance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
childLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(minDistance));
|
||||
stopNow = detailLevel == childLevel - 1;
|
||||
break;
|
||||
|
||||
case BY_REGION_FANCY:
|
||||
desiredLevel = minDetailLevel;
|
||||
break;
|
||||
|
||||
case BY_REGION_FAST:
|
||||
int playerRegionX = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX);
|
||||
int playerRegionZ = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ);
|
||||
if (playerRegionX == regionPosX && playerRegionZ == regionPosZ)
|
||||
{
|
||||
|
||||
case FAST:
|
||||
int playerRegionX = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX);
|
||||
int playerRegionZ = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ);
|
||||
if (playerRegionX == regionPosX && playerRegionZ == regionPosZ)
|
||||
{
|
||||
maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance));
|
||||
minDistance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
childLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(minDistance));
|
||||
stopNow = detailLevel == childLevel - 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case FANCY:
|
||||
maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance));
|
||||
minDistance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
childLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(minDistance));
|
||||
stopNow = detailLevel == childLevel - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerRegionX * 512 + 256, playerRegionZ * 512 + 256);
|
||||
desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance));
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (stopNow)
|
||||
{
|
||||
posToRender.addPosToRender(detailLevel,
|
||||
posX + regionPosX * size,
|
||||
posZ + regionPosZ * size);
|
||||
}
|
||||
else if (desiredLevel > detailLevel)
|
||||
} else if (desiredLevel > detailLevel)
|
||||
{
|
||||
// we have gone beyond the target Detail level
|
||||
// we can stop generating
|
||||
return;
|
||||
}
|
||||
else if (desiredLevel == detailLevel)
|
||||
} else if (desiredLevel == detailLevel)
|
||||
{
|
||||
posToRender.addPosToRender(detailLevel,
|
||||
posX + regionPosX * size,
|
||||
posZ + regionPosZ * size);
|
||||
}
|
||||
else //case where (detailLevel > desiredLevel)
|
||||
} 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++)
|
||||
@@ -340,8 +337,8 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (!requireCorrectDetailLevel)
|
||||
{
|
||||
// If all the four children exist go deeper
|
||||
@@ -350,8 +347,7 @@ public class LodRegion
|
||||
for (int x = 0; x <= 1; x++)
|
||||
for (int z = 0; z <= 1; z++)
|
||||
getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
posToRender.addPosToRender(detailLevel,
|
||||
posX + regionPosX * size,
|
||||
@@ -360,11 +356,11 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates all children.
|
||||
*
|
||||
* <p>
|
||||
* TODO could this be renamed mergeArea?
|
||||
*/
|
||||
public void updateArea(byte detailLevel, int posX, int posZ)
|
||||
@@ -372,20 +368,20 @@ public class LodRegion
|
||||
int width;
|
||||
int startX;
|
||||
int startZ;
|
||||
|
||||
|
||||
// TODO what are each of these loops updating?
|
||||
for (byte down = (byte) (minDetailLevel + 1); down <= detailLevel; down++)
|
||||
{
|
||||
startX = LevelPosUtil.convert(detailLevel, posX, down);
|
||||
startZ = LevelPosUtil.convert(detailLevel, posZ, down);
|
||||
width = 1 << (detailLevel - down);
|
||||
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int z = 0; z < width; z++)
|
||||
update(down, startX + x, startZ + z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for (byte up = (byte) (detailLevel + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++)
|
||||
{
|
||||
update(up,
|
||||
@@ -393,18 +389,18 @@ public class LodRegion
|
||||
LevelPosUtil.convert(detailLevel, posZ, up));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the child at the given relative Pos
|
||||
*
|
||||
* <p>
|
||||
* TODO could this be renamed mergeChildData?
|
||||
*/
|
||||
private void update(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
dataContainer[detailLevel].updateData(dataContainer[detailLevel - 1], posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns if data exists at the given relative Pos.
|
||||
*/
|
||||
@@ -412,16 +408,16 @@ public class LodRegion
|
||||
{
|
||||
if (detailLevel < minDetailLevel)
|
||||
return false;
|
||||
|
||||
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
|
||||
if (dataContainer == null || dataContainer[detailLevel] == null)
|
||||
return false;
|
||||
|
||||
|
||||
return dataContainer[detailLevel].doesItExist(posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the generation mode for the data point at the given relative pos.
|
||||
*/
|
||||
@@ -434,34 +430,36 @@ public class LodRegion
|
||||
else
|
||||
return DistanceGenerationMode.NONE.complexity;
|
||||
}
|
||||
|
||||
/** Returns the lowest detail level in this region
|
||||
* TODO is that right? */
|
||||
|
||||
/**
|
||||
* Returns the lowest detail level in this region
|
||||
* TODO is that right?
|
||||
*/
|
||||
public byte getMinDetailLevel()
|
||||
{
|
||||
return minDetailLevel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the LevelContainer for the detailLevel
|
||||
*
|
||||
*
|
||||
* @throws IllegalArgumentException if the detailLevel is less than minDetailLevel
|
||||
*/
|
||||
public LevelContainer getLevel(byte detailLevel)
|
||||
{
|
||||
if (detailLevel < minDetailLevel)
|
||||
throw new IllegalArgumentException("getLevel asked for a detail level that does not exist: minimum: [" + minDetailLevel + "] level requested: [" + detailLevel + "]");
|
||||
|
||||
|
||||
return dataContainer[detailLevel];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the levelContainer to this Region, updating the minDetailLevel
|
||||
* if necessary.
|
||||
*
|
||||
*
|
||||
* @throws IllegalArgumentException if the LevelContainer's detailLevel
|
||||
* is 2 or more detail levels lower than the
|
||||
* minDetailLevel of this region.
|
||||
* is 2 or more detail levels lower than the
|
||||
* minDetailLevel of this region.
|
||||
*/
|
||||
public void addLevelContainer(LevelContainer levelContainer)
|
||||
{
|
||||
@@ -473,17 +471,17 @@ public class LodRegion
|
||||
+ "only allows adding LevelContainers with a "
|
||||
+ "detail level of [" + (minDetailLevel - 1) + "]");
|
||||
}
|
||||
|
||||
if (levelContainer.getDetailLevel() == minDetailLevel - 1)
|
||||
|
||||
if (levelContainer.getDetailLevel() == minDetailLevel - 1)
|
||||
minDetailLevel = levelContainer.getDetailLevel();
|
||||
|
||||
|
||||
dataContainer[levelContainer.getDetailLevel()] = levelContainer;
|
||||
}
|
||||
|
||||
|
||||
// TODO James thinks cutTree and growTree (which he renamed to match cutTree)
|
||||
// should have more descriptive names, to make sure the "Tree" portion isn't
|
||||
// confused with Minecraft trees (the plant).
|
||||
|
||||
|
||||
/**
|
||||
* Removes any dataContainers that are higher than
|
||||
* the given detailLevel
|
||||
@@ -494,11 +492,11 @@ public class LodRegion
|
||||
{
|
||||
for (byte detailLevelIndex = 0; detailLevelIndex < detailLevel; detailLevelIndex++)
|
||||
dataContainer[detailLevelIndex] = null;
|
||||
|
||||
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make this region more detailed to the detailLevel given.
|
||||
* TODO is that correct?
|
||||
@@ -511,20 +509,24 @@ public class LodRegion
|
||||
{
|
||||
if (dataContainer[detailLevelIndex + 1] == null)
|
||||
dataContainer[detailLevelIndex + 1] = new SingleLevelContainer((byte) (detailLevelIndex + 1));
|
||||
|
||||
|
||||
dataContainer[detailLevelIndex] = dataContainer[detailLevelIndex + 1].expand();
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/** return RegionPos of this lod region */
|
||||
|
||||
/**
|
||||
* return RegionPos of this lod region
|
||||
*/
|
||||
public RegionPos getRegionPos()
|
||||
{
|
||||
return new RegionPos(regionPosX, regionPosZ);
|
||||
}
|
||||
|
||||
/** Returns the minimum memory needed in bytes */
|
||||
|
||||
/**
|
||||
* Returns the minimum memory needed in bytes
|
||||
*/
|
||||
public int getMinMemoryNeeded(LodTemplate template)
|
||||
{
|
||||
int memory = 0;
|
||||
@@ -535,33 +537,35 @@ public class LodRegion
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
/** Returns how many LODs are in this region */
|
||||
|
||||
/**
|
||||
* Returns how many LODs are in this region
|
||||
*/
|
||||
public int getNumberOfLods()
|
||||
{
|
||||
int count = 0;
|
||||
for (LevelContainer container : dataContainer)
|
||||
count += container.getMaxNumberOfLods();
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public VerticalQuality getVerticalQuality()
|
||||
{
|
||||
return verticalQuality;
|
||||
}
|
||||
|
||||
|
||||
public DistanceGenerationMode getGenerationMode()
|
||||
{
|
||||
return generationMode;
|
||||
}
|
||||
|
||||
|
||||
public int getMaxVerticalData(byte detailLevel)
|
||||
{
|
||||
return dataContainer[detailLevel].getMaxVerticalData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
||||
@@ -782,7 +782,7 @@ public class LodRenderer
|
||||
|
||||
long newTime = System.currentTimeMillis();
|
||||
|
||||
if(LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.BY_CHUNK)
|
||||
if(LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.FANCY)
|
||||
{
|
||||
// check if the player has moved
|
||||
if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get())
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.seibel.lod.util;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.HorizontalResolution;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
|
||||
public class DetailDistanceUtil
|
||||
{
|
||||
@@ -14,8 +15,6 @@ public class DetailDistanceUtil
|
||||
private static int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1;
|
||||
private static int minDistance = 0;
|
||||
private static int maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 2;
|
||||
private static int base = 2;
|
||||
private static double logBase = Math.log(2);
|
||||
|
||||
private static int[] maxVerticalData = {
|
||||
4,
|
||||
@@ -49,46 +48,50 @@ public class DetailDistanceUtil
|
||||
public static void updateSettings(){
|
||||
minGenDetail = LodConfig.CLIENT.worldGenerator.generationResolution.get().detailLevel;
|
||||
minDrawDetail = Math.max(LodConfig.CLIENT.graphics.drawResolution.get().detailLevel,LodConfig.CLIENT.worldGenerator.generationResolution.get().detailLevel);
|
||||
maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 2;
|
||||
maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 8;
|
||||
}
|
||||
|
||||
public static int baseDistanceFunction(int detail)
|
||||
{
|
||||
int distanceUnit = LodConfig.CLIENT.graphics.horizontalQuality.get().distanceUnit;
|
||||
if (detail <= minGenDetail)
|
||||
return minDistance;
|
||||
if (detail == maxDetail)
|
||||
if (detail >= maxDetail)
|
||||
return maxDistance;
|
||||
if (detail == maxDetail + 1)
|
||||
return maxDistance;
|
||||
switch (LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.get())
|
||||
{
|
||||
|
||||
int distanceUnit = LodConfig.CLIENT.worldGenerator.horizontalScale.get().distanceUnit;
|
||||
switch (LodConfig.CLIENT.worldGenerator.horizontalQuality.get()){
|
||||
|
||||
case LINEAR:;
|
||||
return (detail * distanceUnit);
|
||||
default:
|
||||
case QUADRATIC:
|
||||
double base = LodConfig.CLIENT.worldGenerator.horizontalQuality.get().quadraticBase;
|
||||
return (int) (Math.pow(base, detail) * distanceUnit);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getDrawDistanceFromDetail(int detail)
|
||||
{
|
||||
return baseDistanceFunction(detail);
|
||||
}
|
||||
|
||||
public static byte baseInverseFunction(int distance, int minDetail)
|
||||
{
|
||||
int distanceUnit = LodConfig.CLIENT.graphics.horizontalQuality.get().distanceUnit;
|
||||
byte detail = 0;
|
||||
|
||||
int detail = 0;
|
||||
if (distance == 0)
|
||||
detail = (byte) minDetail;
|
||||
if (distance > maxDistance)
|
||||
detail = (byte) (maxDetail-1);
|
||||
switch (LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.get())
|
||||
{
|
||||
return (byte) minDetail;
|
||||
int distanceUnit = LodConfig.CLIENT.worldGenerator.horizontalScale.get().distanceUnit;
|
||||
switch (LodConfig.CLIENT.worldGenerator.horizontalQuality.get()){
|
||||
case LINEAR:
|
||||
detail = (byte) Math.floorDiv(distance, distanceUnit);
|
||||
break;
|
||||
case QUADRATIC:
|
||||
default:
|
||||
double base = LodConfig.CLIENT.worldGenerator.horizontalQuality.get().quadraticBase;
|
||||
double logBase = Math.log(base);
|
||||
detail = (byte) (Math.log(Math.floorDiv(distance, distanceUnit))/logBase);
|
||||
break;
|
||||
}
|
||||
return (byte) Math.min(detail, LodUtil.REGION_DETAIL_LEVEL);
|
||||
return (byte) LodUtil.clamp(minDetail, detail, maxDetail-1);
|
||||
}
|
||||
|
||||
public static byte getDrawDetailFromDistance(int distance)
|
||||
@@ -162,6 +165,8 @@ public class DetailDistanceUtil
|
||||
|
||||
public static int getMaxVerticalData(int detail)
|
||||
{
|
||||
if(LodConfig.CLIENT.worldGenerator.lodQualityMode.get() == VerticalQuality.HEIGHTMAP)
|
||||
return 1;
|
||||
return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.seibel.lod.util;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
|
||||
public class LevelPosUtil
|
||||
{
|
||||
public static int[] convert(int[] levelPos, byte newDetailLevel)
|
||||
@@ -143,19 +145,10 @@ public class LevelPosUtil
|
||||
|
||||
public static int maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ, int xRegion, int zRegion)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = xRegion * 512 + posX * width;
|
||||
int startPosZ = zRegion * 512 + posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
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)));
|
||||
|
||||
return maxDistance;
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int newPosX = xRegion * width + posX;
|
||||
int newPosZ = zRegion * width + posZ;
|
||||
return maxDistance(detailLevel, newPosX, newPosZ, playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,38 +190,10 @@ public class LevelPosUtil
|
||||
|
||||
public static int minDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ, int xRegion, int zRegion)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = xRegion * 512 + posX * width;
|
||||
int startPosZ = zRegion * 512 + posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX;
|
||||
boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ;
|
||||
if (inXArea && inZArea)
|
||||
{
|
||||
return 0;
|
||||
} else if (inXArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosZ - startPosZ),
|
||||
Math.abs(playerPosZ - endPosZ)
|
||||
);
|
||||
} else if (inZArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosX - startPosX),
|
||||
Math.abs(playerPosX - endPosX)
|
||||
);
|
||||
} 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)));
|
||||
return minDistance;
|
||||
}
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int newPosX = xRegion * width + posX;
|
||||
int newPosZ = zRegion * width + posZ;
|
||||
return minDistance(detailLevel, newPosX, newPosZ, playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
public static int compareDistance(int firstDistance, int secondDistance)
|
||||
|
||||
@@ -21,7 +21,10 @@ import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
@@ -318,7 +321,73 @@ public class LodUtil
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This methods return the number of lods that are going to be rendered in a region in the worst case
|
||||
* @param regionPosX x region position to check
|
||||
* @param regionPosZ z region position to check
|
||||
* @return number of lods in the region
|
||||
*/
|
||||
public static int regionRenderingMemoryUse(int regionPosX, int regionPosZ, LodTemplate template)
|
||||
{
|
||||
int xRegionSign = (int) Math.signum(regionPosX);
|
||||
int zRegionSign = (int) Math.signum(regionPosZ);
|
||||
|
||||
//we first find the center of the circle which is one of the following X position in the center region
|
||||
/*
|
||||
X - X - X
|
||||
| |
|
||||
X X X
|
||||
| |
|
||||
X - X - X
|
||||
*/
|
||||
int circleCenterX = 256 + 256*xRegionSign;
|
||||
int circleCenterZ = 256 + 256*zRegionSign;
|
||||
|
||||
|
||||
int innerRadius;
|
||||
int outerRadius;
|
||||
int size;
|
||||
int count;
|
||||
int minDistance;
|
||||
int maxDistance;
|
||||
int memoryUse = 0;
|
||||
int number = 0;
|
||||
for(byte detailLevel = BLOCK_DETAIL_LEVEL; detailLevel <= REGION_DETAIL_LEVEL; detailLevel++)
|
||||
{
|
||||
//We find now the inner and outer detail of this area
|
||||
innerRadius = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel);
|
||||
outerRadius = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel + 1);
|
||||
|
||||
//we skip if the region does not intersect the two circles.
|
||||
minDistance = LevelPosUtil.minDistance(REGION_DETAIL_LEVEL, regionPosX, regionPosZ, circleCenterX, circleCenterZ);
|
||||
maxDistance = LevelPosUtil.maxDistance(REGION_DETAIL_LEVEL, regionPosX, regionPosZ, circleCenterX, circleCenterZ);
|
||||
if (innerRadius > maxDistance || minDistance > outerRadius)
|
||||
continue;
|
||||
|
||||
//we proceed to count all the position in the region that fall between these two circle
|
||||
size = 1 << (REGION_DETAIL_LEVEL - detailLevel);
|
||||
count = 0;
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
minDistance = LevelPosUtil.minDistance(detailLevel, x, z, circleCenterX, circleCenterZ, regionPosX, regionPosZ);
|
||||
if (innerRadius < minDistance && minDistance < outerRadius)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
//we multiply the data with the max vertical data of this detail level
|
||||
int maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
|
||||
number += count;
|
||||
count *= maxVerticalData;
|
||||
memoryUse += template.getBufferMemoryForSingleLod(maxVerticalData) * count;
|
||||
}
|
||||
System.out.println(number);
|
||||
return memoryUse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user