CutExpend: Fixed Cut bugs and some general fix to LodFileHandler stuff.

This commit is contained in:
tom lee
2022-01-04 16:39:00 +08:00
parent 44bcc5ae01
commit 054988851d
4 changed files with 126 additions and 110 deletions
@@ -849,7 +849,7 @@ public class LodBufferBuilderFactory
drawableVbos = buildableVbos;
buildableVbos = tmpVbo;
ClientApi.LOGGER.info("Lod Swapped Buffers: "+drawableVbos.toDetailString());
//ClientApi.LOGGER.info("Lod Swapped Buffers: "+drawableVbos.toDetailString());
int tempX = drawableCenterBlockX;
int tempY = drawableCenterBlockY;
@@ -105,19 +105,35 @@ public class LodDimensionFileHandler
//================//
// read from file //
//================//
/**
* Returns the LodRegion at the given coordinates.
* Returns a new LodRegion at the given coordinates.
* Returns an empty region if the file doesn't exist.
*/
public LodRegion loadRegionFromFile(byte detailLevel, RegionPos regionPos, DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
{
int regionX = regionPos.x;
int regionZ = regionPos.z;
LodRegion region = new LodRegion(LodUtil.REGION_DETAIL_LEVEL, regionPos, generationMode, verticalQuality);
LodRegion region = new LodRegion((byte) (LodUtil.REGION_DETAIL_LEVEL+1), regionPos, generationMode, verticalQuality);
return loadRegionFromFile(detailLevel, region, generationMode, verticalQuality);
}
/**
* Returns the LodRegion that is filled at the given coordinates.
* Returns an empty region if the file doesn't exist.
*/
public LodRegion loadRegionFromFile(byte detailLevel, LodRegion region, DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
{
if (region.getGenerationMode().compareTo(generationMode)<0 || region.getVerticalQuality().compareTo(verticalQuality)<0) {
//TODO: add flush and save region for old one
region = new LodRegion((byte) (LodUtil.REGION_DETAIL_LEVEL+1), region.getRegionPos(), generationMode, verticalQuality);
}
int regionX = region.regionPosX;
int regionZ = region.regionPosZ;
for (byte tempDetailLevel = LodUtil.REGION_DETAIL_LEVEL; tempDetailLevel >= detailLevel; tempDetailLevel--)
for (byte tempDetailLevel = (byte) (region.getMinDetailLevel()-1); tempDetailLevel >= detailLevel; tempDetailLevel--)
{
File file = getBestMatchingRegionFile(tempDetailLevel, regionX, regionZ, generationMode, verticalQuality);
if (file == null) {
region.addLevelContainer(new VerticalLevelContainer(tempDetailLevel));
@@ -366,14 +382,14 @@ public class LodDimensionFileHandler
// Return null if no file found
private File getBestMatchingRegionFile(byte detailLevel, int regionX, int regionZ, DistanceGenerationMode targetGenMode, VerticalQuality targetVertQuality) {
DistanceGenerationMode genMode = targetGenMode;
DistanceGenerationMode genMode = DistanceGenerationMode.FULL;
// Search from least GenMode to max GenMode, than least vertQuality to max vertQuality
do {
File file = getRegionFile(regionX, regionZ, genMode, detailLevel, targetVertQuality);
if (file.exists()) return file; // Found target file.
targetGenMode = DistanceGenerationMode.next(targetGenMode);
if (targetGenMode == null) { // Failed to find any files for this vertQuality. Try next one up.
targetGenMode = genMode;
genMode = DistanceGenerationMode.previous(genMode);
if (genMode==null || genMode==DistanceGenerationMode.previous(targetGenMode)) { // Failed to find any files for this vertQuality. Try next one up.
genMode = DistanceGenerationMode.FULL;
targetVertQuality = VerticalQuality.next(targetVertQuality);
}
} while (targetVertQuality != null);
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.util.concurrent.ExecutorService;
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.GenerationPriority;
import com.seibel.lod.core.enums.config.VerticalQuality;
@@ -92,10 +93,9 @@ public class LodDimension
private final RegionPos center;
/** prevents the cutAndExpandThread from expanding at the same location multiple times */
private volatile AbstractChunkPosWrapper lastExpandedChunk;
/** prevents the cutAndExpandThread from cutting at the same location multiple times */
private volatile AbstractChunkPosWrapper lastCutChunk;
private boolean isCutting = false;
private boolean isExpanding = false;
private final ExecutorService cutAndExpandThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - Cut and Expand"));
/**
@@ -104,8 +104,6 @@ public class LodDimension
*/
public LodDimension(IDimensionTypeWrapper newDimension, LodWorld lodWorld, int newWidth)
{
lastCutChunk = null;
lastExpandedChunk = null;
dimension = newDimension;
width = newWidth;
halfWidth = width / 2;
@@ -159,6 +157,7 @@ public class LodDimension
*/
public synchronized void move(RegionPos regionOffset)
{
ClientApi.LOGGER.info("LodDim MOVE. Offset: "+regionOffset);
int xOffset = regionOffset.x;
int zOffset = regionOffset.z;
@@ -261,6 +260,7 @@ public class LodDimension
// update the new center
center.x += xOffset;
center.z += zOffset;
ClientApi.LOGGER.info("LodDim MOVE complete. Offset: "+regionOffset);
}
@@ -362,109 +362,98 @@ public class LodDimension
*/
public void cutRegionNodesAsync(int playerPosX, int playerPosZ)
{
AbstractChunkPosWrapper newPlayerChunk = FACTORY.createChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
if (lastCutChunk == null)
lastCutChunk = FACTORY.createChunkPos(newPlayerChunk.getX() + 1, newPlayerChunk.getZ() - 1);
if (isCutting) return;
isCutting = true;
// don't run the tree cutter multiple times
// for the same location
if (newPlayerChunk.getX() != lastCutChunk.getX() || newPlayerChunk.getZ() != lastCutChunk.getZ()) {
lastCutChunk = newPlayerChunk;
Runnable thread = () -> {
//ClientApi.LOGGER.info("LodDim cut Region: " + playerPosX + "," + playerPosZ);
Runnable thread = () -> {
// go over every region in the dimension
iterateWithSpiral((int x, int z) -> {
int regionX;
int regionZ;
int minDistance;
byte detail;
byte minAllowedDetailLevel;
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
// go over every region in the dimension
iterateWithSpiral((int x, int z) -> {
int regionX;
int regionZ;
int minDistance;
byte detail;
byte minAllowedDetailLevel;
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
if (regions[x][z] != null) {
// check what detail level this region should be
// and cut it if it is higher then that
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ,
playerPosX, playerPosZ);
detail = DetailDistanceUtil.getTreeCutDetailFromDistance(minDistance);
minAllowedDetailLevel = DetailDistanceUtil.getCutLodDetail(detail);
if (regions[x][z] != null) {
// check what detail level this region should be
// and cut it if it is higher then that
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ,
playerPosX, playerPosZ);
detail = DetailDistanceUtil.getTreeCutDetailFromDistance(minDistance);
minAllowedDetailLevel = DetailDistanceUtil.getCutLodDetail(detail);
if (regions[x][z].getMinDetailLevel() > minAllowedDetailLevel) {
regions[x][z].cutTree(minAllowedDetailLevel);
regenRegionBuffer[x][z] = 2;
regenDimensionBuffers = true;
}
if (regions[x][z].getMinDetailLevel() < minAllowedDetailLevel) {
regions[x][z].cutTree(minAllowedDetailLevel);
regenRegionBuffer[x][z] = 2;
regenDimensionBuffers = true;
}
});
};
cutAndExpandThread.execute(thread);
}
}
});
//ClientApi.LOGGER.info("LodDim cut Region complete: " + playerPosX + "," + playerPosZ);
isCutting = false;
};
cutAndExpandThread.execute(thread);
}
/** Either expands or loads all regions in the rendered LOD area */
public void expandOrLoadRegionsAsync(int playerPosX, int playerPosZ) {
DistanceGenerationMode generationMode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
AbstractChunkPosWrapper newPlayerChunk = FACTORY.createChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX),
LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
VerticalQuality verticalQuality = CONFIG.client().graphics().quality().getVerticalQuality();
if (lastExpandedChunk == null)
lastExpandedChunk = FACTORY.createChunkPos(newPlayerChunk.getX() + 1, newPlayerChunk.getZ() - 1);
if (isExpanding) return;
isExpanding = true;
DistanceGenerationMode generationMode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
VerticalQuality verticalQuality = CONFIG.client().graphics().quality().getVerticalQuality();
// don't run the expander multiple times
// for the same location
if (newPlayerChunk.getX() != lastExpandedChunk.getX() || newPlayerChunk.getZ() != lastExpandedChunk.getZ()) {
lastExpandedChunk = newPlayerChunk;
Runnable thread = () -> {
//ClientApi.LOGGER.info("LodDim expend Region: " + playerPosX + "," + playerPosZ);
Runnable thread = () -> {
iterateWithSpiral((int x, int z) -> {
int regionX;
int regionZ;
LodRegion region;
int minDistance;
int maxDistance;
byte minDetail;
byte maxDetail;
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
final RegionPos regionPos = new RegionPos(regionX, regionZ);
region = regions[x][z];
iterateWithSpiral((int x, int z) -> {
int regionX;
int regionZ;
LodRegion region;
int minDistance;
byte detail;
byte levelToGen;
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
final RegionPos regionPos = new RegionPos(regionX, regionZ);
region = regions[x][z];
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX,
playerPosZ);
maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX,
playerPosZ);
minDetail = DetailDistanceUtil.getTreeGenDetailFromDistance(minDistance);
maxDetail = DetailDistanceUtil.getTreeGenDetailFromDistance(maxDistance);
boolean updated = false;
if (region == null) {
regions[x][z] = getRegionFromFile(regionPos, minDetail, generationMode, verticalQuality);
updated = true;
} else if (region.getGenerationMode().compareTo(generationMode) < 0 ||
region.getVerticalQuality() != verticalQuality ||
region.getMinDetailLevel() > minDetail) {
regions[x][z] = getRegionFromFile(regions[x][z], minDetail, generationMode, verticalQuality);
updated = true;
}
if (updated) {
regenRegionBuffer[x][z] = 2;
regenDimensionBuffers = true;
}
});
//ClientApi.LOGGER.info("LodDim expend Region complete: " + playerPosX + "," + playerPosZ);
isExpanding = false;
};
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX,
playerPosZ);
detail = DetailDistanceUtil.getTreeGenDetailFromDistance(minDistance);
levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel;
// check that the region isn't null and at least this detail level
if (region == null || region.getGenerationMode() != generationMode) {
// First case, region has to be created
// try to get the region from file
regions[x][z] = getRegionFromFile(regionPos, levelToGen, generationMode, verticalQuality);
// if there is no region file create an empty region
if (regions[x][z] == null)
regions[x][z] = new LodRegion(levelToGen, regionPos, generationMode, verticalQuality);
regenRegionBuffer[x][z] = 2;
regenDimensionBuffers = true;
} else if (region.getMinDetailLevel() > levelToGen) {
// Second case, the region exists at a higher detail level.
// Expand the region by introducing the missing layer
region.growTree(levelToGen);
regions[x][z] = getRegionFromFile(regionPos, levelToGen, generationMode, verticalQuality);
regenRegionBuffer[x][z] = 2;
regenDimensionBuffers = true;
}
});
};
cutAndExpandThread.execute(thread);
}
cutAndExpandThread.execute(thread);
}
/**
@@ -846,7 +835,18 @@ public class LodDimension
public LodRegion getRegionFromFile(RegionPos regionPos, byte detailLevel,
DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
{
return fileHandler != null ? fileHandler.loadRegionFromFile(detailLevel, regionPos, generationMode, verticalQuality) : null;
return fileHandler != null ? fileHandler.loadRegionFromFile(detailLevel, regionPos, generationMode, verticalQuality) :
new LodRegion(detailLevel, regionPos, generationMode, verticalQuality);
}
/**
* Loads the region at the given region from file,
* if a file exists for that region.
*/
public LodRegion getRegionFromFile(LodRegion existingRegion, byte detailLevel,
DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
{
return fileHandler != null ? fileHandler.loadRegionFromFile(detailLevel, existingRegion, generationMode, verticalQuality) :
new LodRegion(detailLevel, existingRegion.getRegionPos(), generationMode, verticalQuality);
}
/** Save all dirty regions in this LodDimension to file. */
@@ -425,20 +425,20 @@ public class LodRegion
int startX;
int startZ;
// TODO what are each of these loops updating?
for (byte down = (byte) (minDetailLevel + 1); down <= detailLevel; down++)
// Update the level lower or equal to the detail level
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 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 the level higher than the detail level
for (byte up = (byte)(Math.max(detailLevel, minDetailLevel)+1); up <= LodUtil.REGION_DETAIL_LEVEL; up++)
{
update(up,
LevelPosUtil.convert(detailLevel, posX, up),