transvoxel position checking work

This commit is contained in:
austin 2024-06-30 13:38:41 -04:00
parent bc66523cde
commit df4fe45dd5

View File

@ -491,6 +491,182 @@ public class DrawCellManager {
}
/**
transvoxel algorithm spacing management
want to specify a radius and have it be a circle so we're not wasting resolution on far off corners
To benefit from the LOD, should have a series of for loops
First loop iterates over (-largest radius) -> (largest radius) at an interval of the width of the lowest level of detail chunk
We check all 8 corners of the chunk to see if they all fall within the largest lod concentric circle
There are a few cases to consider
- All fall outside the largest LOD radius (ignore)
- All but one fall outside thel argest LOD radius (ignore)
- All fall within the largest LOD circle (make LOD chunk)
- One is within the next LOD radius, others are within the current LOD radius (ignore for this pass)
- All are within a lower LOD radius (ignore)
Once we're done with the largest LOD radius, we go to a higher resolution radius and iterate for smaller bounds
In a middle LOD level, if all corners are outside, but the lower resolution didn't
already pick it up, still need to generate a chunk at the current resolution
Detection of this case is tricky
We could snap the currently considered position to the nearest low-resolution chunk and then bounds check that low resolution chunk for every
higher resolution position we're considering
This is probably a bad idea
We could recurse every time a chunk doesn't work for the current level of detail, then evaluate it for a higher level of detail at this closer value
*/
//the number of corners to consider for a valid chunk
static final int NUM_CORNERS_TO_CONSIDER = 8;
//offsets to get from current position to the actual corner to consider
int[] cornerOffsetsX = new int[]{0,1,0,1,0,1,0,1,};
int[] cornerOffsetsY = new int[]{0,0,0,0,1,1,1,1,};
int[] cornerOffsetsZ = new int[]{0,0,1,1,0,0,1,1,};
/**
* Recursive function that does chunk validity checking
* @param playerChunkPos
* @param minPoint
* @param maxPoint
* @param currentLOD
*/
public void assesChunkPositionsAtLOD(
Vector3i playerChunkPos,
Vector3i minPoint,
Vector3i maxPoint,
int currentLOD
){
Vector3i currentChunkPositionConsidered = new Vector3i(playerChunkPos); // The chunk position we're currently considering
double currentRadius = lodLevelRadiusTable[currentLOD];
double nextRadius = 0;
int increment = 1;
if(currentLOD > 0){
//only works when the LOD is greater than 0. When it's 0, there is no lower bound on chunk positions to generate
nextRadius = lodLevelRadiusTable[currentLOD-1];
increment = (int)Math.pow(2,currentLOD);
}
//iterate
for(int x = minPoint.x; x < maxPoint.x; x = x + increment){
for(int y = minPoint.y; y < maxPoint.x; y = y + increment){
for(int z = minPoint.z; z < maxPoint.x; z = z + increment){
//we have 8 corners to consider
//need to identify which case the current position is
int positionCase = 0;
for(int j = 0; j < NUM_CORNERS_TO_CONSIDER; j++){
currentChunkPositionConsidered.set(
x + cornerOffsetsX[j] * increment,
y + cornerOffsetsY[j] * increment,
z + cornerOffsetsZ[j] * increment
);
//figure out the case of this corner
double distance = currentChunkPositionConsidered.distance(playerChunkPos);
if(distance > currentRadius){
positionCase = 1;
break;
} else if(distance <= nextRadius){
positionCase = 2;
break;
}
}
switch(positionCase){
case 0: {
//fully within current band, generate chunk
} break;
case 1: {
//partially outside bound, ignore
} break;
case 2: {
//partially inside higher resolution bound, recurse
assesChunkPositionsAtLOD(
playerChunkPos,
new Vector3i(x,y,z),
new Vector3i(x+increment,y+increment,z+increment),
currentLOD
);
} break;
}
}
}
}
}
/**
* Assess all LOD chunk levels
*/
public void assesLODChunks(){
//pre-existing values
Vector3d playerPosition = EntityUtils.getPosition(Globals.playerEntity);
Vector3i playerChunkPosition = Globals.clientWorldData.convertRealToChunkSpace(playerPosition);
//variables used while iterating across chunk positions
double currentRadius = 0; //the current radius is in units of chunks, even though it's a double (it's discrete, not real)
double nextRadius = 0; //the next radius is in units of chunks, even though it's a double (it's discrete, not real)
int increment = 1; //the increment is in units of chunks, not real
//the offsets from the player's position to
//the nearest possible spot we could place a chunk of the current LOD at (in units of chunks)
Vector3i lowerOffsets = new Vector3i(0,0,0);
Vector3i currentChunkPositionConsidered = new Vector3i(playerChunkPosition); // The chunk position we're currently considering
//actual logic to search for valid chunks
for(int i = NUMBER_OF_LOD_LEVELS - 1; i >= 0; i--){
currentRadius = lodLevelRadiusTable[i];
nextRadius = 0;
increment = 1;
if(i > 0){
//only works when the LOD is greater than 0. When it's 0, there is no lower bound on chunk positions to generate
nextRadius = lodLevelRadiusTable[i-1];
increment = (int)Math.pow(2,i);
}
//calculate offsets to get from player's current chunk position to the lower resolution grid for the current LOD
lowerOffsets.x = playerChunkPosition.x % ((int)increment);
lowerOffsets.y = playerChunkPosition.y % ((int)increment);
lowerOffsets.z = playerChunkPosition.z % ((int)increment);
//iterate
for(int x = -(int)currentRadius - lowerOffsets.x; x < currentRadius; x = x + increment){
for(int y = -(int)currentRadius - lowerOffsets.y; y < currentRadius; y = y + increment){
for(int z = -(int)currentRadius - lowerOffsets.z; z < currentRadius; z = z + increment){
//we have 8 corners to consider
//need to identify which case the current position is
int positionCase = 0;
for(int j = 0; j < NUM_CORNERS_TO_CONSIDER; j++){
currentChunkPositionConsidered.set(
x + cornerOffsetsX[j] * increment,
y + cornerOffsetsY[j] * increment,
z + cornerOffsetsZ[j] * increment
);
//figure out the case of this corner
double distance = currentChunkPositionConsidered.distance(playerChunkPosition);
if(distance > currentRadius){
positionCase = 1;
break;
} else if(distance <= nextRadius){
positionCase = 2;
break;
}
}
switch(positionCase){
case 0: {
//fully within current band, generate chunk
} break;
case 1: {
//partially outside bound, ignore
} break;
case 2: {
//partially inside higher resolution bound, recurse
} break;
}
}
}
}
}
}
}