delete deprecated classes
This commit is contained in:
parent
329559bfd7
commit
222a3ebe9f
@ -1800,6 +1800,7 @@ Safe executor service creation in non final static contexts
|
||||
Fix reloading client world repeatedly
|
||||
AI manager thread safeing
|
||||
AI manager better error handling
|
||||
Delete deprecated classes
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,706 +0,0 @@
|
||||
package electrosphere.client.terrain.cells;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.client.terrain.cache.ChunkData;
|
||||
import electrosphere.client.terrain.cells.DrawCell.DrawCellFace;
|
||||
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
||||
import electrosphere.collision.PhysicsEntityUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
import electrosphere.renderer.shader.VisualShader;
|
||||
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* Manages the graphical entities for the terrain chunks
|
||||
*
|
||||
*
|
||||
*
|
||||
Notes for integrating with transvoxel algo:
|
||||
Different problems to tackle
|
||||
|
||||
For all chunks within minimum radius, check if they can be updated and update accordingly <--- we do this currently
|
||||
|
||||
|
||||
For all chunks between minimum radius and first LOD radius, check if we can make a LOD chunk
|
||||
If we can, make a lod chunk or see if it can be updated
|
||||
This check will be:
|
||||
For every position, check if all four positions required for LOD chunk are within lod radius
|
||||
if yes, make lod chunk
|
||||
|
||||
If we cannot, create a fullres chunk
|
||||
This check will be:
|
||||
For every position, check if all four positions required for LOD chunk are within lod radius
|
||||
if yes, make lod chunk
|
||||
if they are outside the far bound, create lod chunk
|
||||
if they are within the near bound, create a fullres chunk
|
||||
|
||||
|
||||
|
||||
*/
|
||||
public class DrawCellManager {
|
||||
|
||||
|
||||
//the center of this cell manager's array in cell space
|
||||
int cellX;
|
||||
int cellY;
|
||||
int cellZ;
|
||||
|
||||
//all currently displaying mini cells
|
||||
Set<DrawCell> cells = new HashSet<DrawCell>();
|
||||
Map<String,DrawCell> keyCellMap = new HashMap<String,DrawCell>();
|
||||
|
||||
//status of all position keys
|
||||
Set<String> hasNotRequested = new HashSet<String>();
|
||||
Set<String> requested = new HashSet<String>();
|
||||
Set<String> drawable = new HashSet<String>();
|
||||
Set<String> undrawable = new HashSet<String>();
|
||||
Set<String> updateable = new HashSet<String>();
|
||||
|
||||
//LOD level of all position keys
|
||||
Map<String,Integer> positionLODLevel = new HashMap<String,Integer>();
|
||||
|
||||
//voxel atlas
|
||||
VoxelTextureAtlas atlas;
|
||||
|
||||
//shader program for drawable cells
|
||||
VisualShader program;
|
||||
|
||||
|
||||
|
||||
//the real-space radius for which we will construct draw cells inside of
|
||||
//ie, we check if the draw cell's entity would be inside this radius. If it would, create the draw cell, otherwise don't
|
||||
double drawFullModelRadius = 70;
|
||||
|
||||
//the radius we'll draw LODed chunks for
|
||||
double drawLODRadius = drawFullModelRadius + ServerTerrainChunk.CHUNK_DIMENSION * (2*2 + 4*4 + 8*8 + 16*16);
|
||||
|
||||
|
||||
//the number of possible LOD levels
|
||||
//1,2,4,8,16
|
||||
static final int NUMBER_OF_LOD_LEVELS = 5;
|
||||
|
||||
//the table of lod leve -> radius at which we will look for chunks within this log
|
||||
double[] lodLevelRadiusTable = new double[5];
|
||||
|
||||
//the radius for which physics meshes are created when draw cells are created
|
||||
int physicsRadius = 3;
|
||||
|
||||
//ready to start updating?
|
||||
boolean update = false;
|
||||
|
||||
//controls whether we try to generate the drawable entities
|
||||
//we want this to be false when in server-only mode
|
||||
boolean generateDrawables = false;
|
||||
|
||||
|
||||
/**
|
||||
* DrawCellManager constructor
|
||||
* @param commonWorldData The common world data
|
||||
* @param clientTerrainManager The client terrain manager
|
||||
* @param discreteX The initial discrete position X coordinate
|
||||
* @param discreteY The initial discrete position Y coordinate
|
||||
*/
|
||||
public DrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){
|
||||
cellX = discreteX;
|
||||
cellY = discreteY;
|
||||
cellZ = discreteZ;
|
||||
|
||||
program = Globals.terrainShaderProgram;
|
||||
|
||||
//the first lod level is set by user
|
||||
lodLevelRadiusTable[0] = drawFullModelRadius;
|
||||
//generate LOD radius table
|
||||
for(int i = 1; i < NUMBER_OF_LOD_LEVELS; i++){
|
||||
double sizeOfSingleModel = Math.pow(2,i) * ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
//size of the radius for this lod level should be three times the size of a model + the previous radius
|
||||
//this guarantees we get at least one adapter chunk, one proper chunk, and also that the radius accounts for the previous lod level chunks
|
||||
lodLevelRadiusTable[i] = lodLevelRadiusTable[i-1] + sizeOfSingleModel * 3;
|
||||
}
|
||||
|
||||
physicsRadius = Globals.userSettings.getGameplayPhysicsCellRadius();
|
||||
|
||||
invalidateAllCells();
|
||||
|
||||
update = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
*/
|
||||
DrawCellManager(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's current position in cell-space
|
||||
* @param cellPos The cell's position
|
||||
*/
|
||||
public void setPlayerCell(Vector3i cellPos){
|
||||
cellX = cellPos.x;
|
||||
cellY = cellPos.y;
|
||||
cellZ = cellPos.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update function that is called if a cell has not been requested
|
||||
*/
|
||||
void updateUnrequestedCell(){
|
||||
if(hasNotRequested.size() > 0){
|
||||
String targetKey = hasNotRequested.iterator().next();
|
||||
hasNotRequested.remove(targetKey);
|
||||
Vector3i worldPos = getVectorFromKey(targetKey);
|
||||
|
||||
//
|
||||
//Because of the way marching cubes works, we need to request the adjacent chunks so we know how to properly blend between one chunk and the next
|
||||
//The following loop-hell does this
|
||||
//
|
||||
for(int i = 0; i < 2; i++){
|
||||
for(int j = 0; j < 2; j++){
|
||||
for(int k = 0; k < 2; k++){
|
||||
Vector3i posToCheck = new Vector3i(worldPos).add(i,j,k);
|
||||
String requestKey = getCellKey(posToCheck.x,posToCheck.y,posToCheck.z);
|
||||
if(
|
||||
posToCheck.x >= 0 &&
|
||||
posToCheck.x < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
posToCheck.y >= 0 &&
|
||||
posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
posToCheck.z >= 0 &&
|
||||
posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
!Globals.clientTerrainManager.containsChunkDataAtWorldPoint(posToCheck.x, posToCheck.y, posToCheck.z, ChunkData.NO_STRIDE)
|
||||
){
|
||||
if(!requested.contains(requestKey)){
|
||||
//client should request chunk data from server for each chunk necessary to create the model
|
||||
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestChunkDataMessage(
|
||||
posToCheck.x,
|
||||
posToCheck.y,
|
||||
posToCheck.z
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
undrawable.add(targetKey);
|
||||
requested.add(targetKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes one of the undrawable cells drawable
|
||||
*/
|
||||
void makeCellDrawable(){
|
||||
if(undrawable.size() > 0){
|
||||
String targetKey = undrawable.iterator().next();
|
||||
Vector3i worldPos = getVectorFromKey(targetKey);
|
||||
|
||||
//
|
||||
//Checks if all chunk data necessary to generate a mesh is present
|
||||
boolean containsNecessaryChunks = true;
|
||||
for(int i = 0; i < 2; i++){
|
||||
for(int j = 0; j < 2; j++){
|
||||
for(int k = 0; k < 2; k++){
|
||||
Vector3i posToCheck = new Vector3i(worldPos).add(i,j,k);
|
||||
if(worldPos.x >= 0 &&
|
||||
posToCheck.x < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
posToCheck.y >= 0 &&
|
||||
posToCheck.y < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
posToCheck.z >= 0 &&
|
||||
posToCheck.z < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
!containsChunkDataAtWorldPoint(posToCheck.x,posToCheck.y,posToCheck.z)
|
||||
){
|
||||
containsNecessaryChunks = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//if contains data for all chunks necessary to generate visuals
|
||||
if(containsNecessaryChunks){
|
||||
|
||||
//update the status of the terrain key
|
||||
undrawable.remove(targetKey);
|
||||
drawable.add(targetKey);
|
||||
|
||||
//build the cell
|
||||
DrawCell cell = DrawCell.generateTerrainCell(
|
||||
worldPos,
|
||||
0
|
||||
);
|
||||
cells.add(cell);
|
||||
keyCellMap.put(targetKey,cell);
|
||||
List<DrawCellFace> higherLODFace = null;
|
||||
keyCellMap.get(targetKey).generateDrawableEntity(atlas,0,higherLODFace);
|
||||
|
||||
// //evaluate for foliage
|
||||
// Globals.clientFoliageManager.evaluateChunk(worldPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a cell that can be updated
|
||||
*/
|
||||
void updateCellModel(){
|
||||
if(updateable.size() > 0){
|
||||
String targetKey = updateable.iterator().next();
|
||||
updateable.remove(targetKey);
|
||||
Vector3i worldPos = getVectorFromKey(targetKey);
|
||||
if(
|
||||
worldPos.x >= 0 &&
|
||||
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
worldPos.y >= 0 &&
|
||||
worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
worldPos.z >= 0 &&
|
||||
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
|
||||
){
|
||||
keyCellMap.get(targetKey).destroy();
|
||||
List<DrawCellFace> higherLODFace = null;
|
||||
keyCellMap.get(targetKey).generateDrawableEntity(atlas,0,higherLODFace);
|
||||
}
|
||||
drawable.add(targetKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the manager contains a cell position that hasn't had its chunk data requested from the server yet
|
||||
* @return true if there is an unrequested cell, false otherwise
|
||||
*/
|
||||
public boolean containsUnrequestedCell(){
|
||||
return hasNotRequested.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the manager contains a cell who hasn't been made drawable yet
|
||||
* @return true if there is an undrawable cell, false otherwise
|
||||
*/
|
||||
public boolean containsUndrawableCell(){
|
||||
return undrawable.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the manager contains a cell who needs to be updated
|
||||
* @return true if there is an updateable cell, false otherwise
|
||||
*/
|
||||
public boolean containsUpdateableCell(){
|
||||
return updateable.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Transforms a real coordinate into a cell-space coordinate
|
||||
* @param input the real coordinate
|
||||
* @return the cell coordinate
|
||||
*/
|
||||
public int transformRealSpaceToCellSpace(double input){
|
||||
return (int)(input / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the valid set and adds all keys to invalid set
|
||||
*/
|
||||
public void invalidateAllCells(){
|
||||
drawable.clear();
|
||||
hasNotRequested.clear();
|
||||
clearOutOfBoundsCells();
|
||||
queueNewCells();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates whether the position of the player has changed and if so, invalidates and cleans up cells accordingly
|
||||
*/
|
||||
private void calculateDeltas(){
|
||||
//check if any not requested cells no longer need to be requested
|
||||
clearOutOfBoundsCells();
|
||||
//check if any cells should be added
|
||||
queueNewCells();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all cells outside of draw radius
|
||||
*/
|
||||
private void clearOutOfBoundsCells(){
|
||||
Set<DrawCell> cellsToRemove = new HashSet<DrawCell>();
|
||||
for(DrawCell cell : cells){
|
||||
Vector3d realPos = cell.getRealPos();
|
||||
if(Globals.playerEntity != null && EntityUtils.getPosition(Globals.playerEntity).distance(realPos) > drawFullModelRadius){
|
||||
cellsToRemove.add(cell);
|
||||
}
|
||||
}
|
||||
for(DrawCell cell : cellsToRemove){
|
||||
cells.remove(cell);
|
||||
String key = getCellKey(cell.worldPos.x, cell.worldPos.y, cell.worldPos.z);
|
||||
hasNotRequested.remove(key);
|
||||
drawable.remove(key);
|
||||
undrawable.remove(key);
|
||||
updateable.remove(key);
|
||||
keyCellMap.remove(key);
|
||||
requested.remove(key);
|
||||
cell.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues new cells that are in bounds but not currently accounted for
|
||||
*/
|
||||
private void queueNewCells(){
|
||||
if(Globals.playerEntity != null && Globals.clientWorldData != null){
|
||||
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
|
||||
for(int x = -(int)drawFullModelRadius; x < drawFullModelRadius; x = x + ChunkData.CHUNK_DATA_SIZE){
|
||||
for(int y = -(int)drawFullModelRadius; y < drawFullModelRadius; y = y + ChunkData.CHUNK_DATA_SIZE){
|
||||
for(int z = -(int)drawFullModelRadius; z < drawFullModelRadius; z = z + ChunkData.CHUNK_DATA_SIZE){
|
||||
Vector3d newPos = new Vector3d(playerPos.x + x, playerPos.y + y, playerPos.z + z);
|
||||
Vector3i worldPos = new Vector3i(
|
||||
Globals.clientWorldData.convertRealToChunkSpace(newPos.x),
|
||||
Globals.clientWorldData.convertRealToChunkSpace(newPos.y),
|
||||
Globals.clientWorldData.convertRealToChunkSpace(newPos.z)
|
||||
);
|
||||
Vector3d chunkRealSpace = new Vector3d(
|
||||
Globals.clientWorldData.convertChunkToRealSpace(worldPos.x),
|
||||
Globals.clientWorldData.convertChunkToRealSpace(worldPos.y),
|
||||
Globals.clientWorldData.convertChunkToRealSpace(worldPos.z)
|
||||
);
|
||||
if(
|
||||
playerPos.distance(chunkRealSpace) < drawFullModelRadius &&
|
||||
worldPos.x >= 0 &&
|
||||
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
worldPos.y >= 0 &&
|
||||
worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||
worldPos.z >= 0 &&
|
||||
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
|
||||
){
|
||||
String key = getCellKey(
|
||||
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.x),
|
||||
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.y),
|
||||
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.z)
|
||||
);
|
||||
if(!keyCellMap.containsKey(key) && !hasNotRequested.contains(key) && !undrawable.contains(key) && !drawable.contains(key) &&
|
||||
!requested.contains(key)){
|
||||
hasNotRequested.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates cells that need updating in this manager
|
||||
*/
|
||||
public void update(){
|
||||
calculateDeltas();
|
||||
if(containsUnrequestedCell() && !containsUndrawableCell()){
|
||||
updateUnrequestedCell();
|
||||
} else if(containsUndrawableCell()){
|
||||
makeCellDrawable();
|
||||
} else if(containsUpdateableCell()){
|
||||
updateCellModel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the client generates drawable chunks or just physics chunks (ie if running a headless client)
|
||||
* @param generate true to generate graphics, false otherwise
|
||||
*/
|
||||
public void setGenerateDrawables(boolean generate){
|
||||
this.generateDrawables = generate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the terrain cache has a chunk at a given world point
|
||||
* @param worldX the x coordinate
|
||||
* @param worldY the y coordinate
|
||||
* @param worldZ the z coordinate
|
||||
* @return true if the chunk data exists, false otherwise
|
||||
*/
|
||||
boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
|
||||
if(Globals.clientTerrainManager != null){
|
||||
return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk data at a given point
|
||||
* @param worldX The world position x component of the cell
|
||||
* @param worldY The world position y component of the cell
|
||||
* @param worldZ The world position z component of the cell
|
||||
* @return The chunk data at the specified points
|
||||
*/
|
||||
ChunkData getChunkDataAtPoint(int worldX, int worldY, int worldZ){
|
||||
return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ,ChunkData.NO_STRIDE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a unique key for the cell
|
||||
* @param worldX The world position x component of the cell
|
||||
* @param worldY The world position y component of the cell
|
||||
* @param worldZ The world position z component of the cell
|
||||
* @return The key
|
||||
*/
|
||||
private String getCellKey(int worldX, int worldY, int worldZ){
|
||||
return worldX + "_" + worldY + "_" + worldZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a vector3i from the cell key
|
||||
* @param key The cell key
|
||||
* @return The vector3i containing the components of the cell key
|
||||
*/
|
||||
private Vector3i getVectorFromKey(String key){
|
||||
String[] keyComponents = key.split("_");
|
||||
return new Vector3i(Integer.parseInt(keyComponents[0]),Integer.parseInt(keyComponents[1]),Integer.parseInt(keyComponents[2]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a data cell as updateable (can be regenerated with a new model because the underlying data has changed)
|
||||
* @param chunkX The chunk x coordinate
|
||||
* @param chunkY The chunk y coordinate
|
||||
* @param chunkZ The chunk z coordinate
|
||||
*/
|
||||
public void markUpdateable(int chunkX, int chunkY, int chunkZ){
|
||||
updateable.add(getCellKey(chunkX, chunkY, chunkZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all chunks
|
||||
*/
|
||||
public void evictAll(){
|
||||
//destroy models
|
||||
for(String key : drawable){
|
||||
keyCellMap.get(key).destroy();
|
||||
}
|
||||
keyCellMap.clear();
|
||||
hasNotRequested.clear();
|
||||
requested.clear();
|
||||
drawable.clear();
|
||||
undrawable.clear();
|
||||
updateable.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the radius within which full-detail models are drawn
|
||||
* @return the radius
|
||||
*/
|
||||
public double getDrawFullModelRadius(){
|
||||
return drawFullModelRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the voxel texture atlas
|
||||
*/
|
||||
public void attachTextureAtlas(VoxelTextureAtlas voxelTextureAtlas){
|
||||
atlas = voxelTextureAtlas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the draw cell at the given world position has generated physics
|
||||
* @param worldPos The world position
|
||||
* @return true if has generated physics, false otherwise
|
||||
*/
|
||||
public boolean generatedPhysics(Vector3i worldPos){
|
||||
String key = this.getCellKey(worldPos.x, worldPos.y, worldPos.z);
|
||||
if(!keyCellMap.containsKey(key)){
|
||||
return false;
|
||||
}
|
||||
DrawCell cell = this.keyCellMap.get(key);
|
||||
return cell.modelEntity != null && PhysicsEntityUtils.getDBody(cell.modelEntity) != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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.convertRealToWorldSpace(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,245 +0,0 @@
|
||||
package electrosphere.renderer.meshgen;
|
||||
|
||||
/**
|
||||
* Utilities for generating and managing skyboxes
|
||||
*/
|
||||
public class SkyboxMeshgen {
|
||||
|
||||
|
||||
// public static Model createSkyboxModel(Material optionalMaterial){
|
||||
// Model skyboxModel = new Model();
|
||||
// skyboxModel.meshes = new ArrayList<Mesh>();
|
||||
|
||||
// skyboxModel.modelMatrix = new Matrix4d();
|
||||
|
||||
|
||||
|
||||
// // boolean apply_lighting = false;
|
||||
// // boolean has_bones = false;
|
||||
|
||||
// Mesh skyboxmesh = new Mesh("skybox"){
|
||||
// @Override
|
||||
// public void complexDraw(RenderPipelineState renderPipelineState){
|
||||
// if(renderPipelineState.getUseMeshShader()){
|
||||
// GL11.glDepthFunc(GL_LEQUAL);
|
||||
// glUseProgram(shader.getShaderId());
|
||||
// }
|
||||
|
||||
// if(renderPipelineState.getUseMaterial()){
|
||||
// if(this.getMaterial() == null){
|
||||
// Globals.materialDefault.apply_material(0,1);
|
||||
// Iterator<Vector3f> colorIterator = Globals.skyboxColors.iterator();
|
||||
// int counter = 0;
|
||||
// float[] temp = new float[3];
|
||||
// while(colorIterator.hasNext()){
|
||||
// Vector3f colorCurrent = colorIterator.next();
|
||||
// temp[0] = colorCurrent.x / 255.0f;
|
||||
// temp[1] = colorCurrent.y / 255.0f;
|
||||
// temp[2] = colorCurrent.z / 255.0f;
|
||||
// // System.out.println("colors[" + counter + "] " + temp[0] + " " + temp[1] + " " + temp[2]);
|
||||
// glUniform3fv(glGetUniformLocation(shader.getShaderId(), "colors[" + counter + "]"), temp);
|
||||
// counter++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// glBindVertexArray(vertexArrayObject);
|
||||
|
||||
|
||||
|
||||
// if(renderPipelineState.getBufferStandardUniforms()){
|
||||
// //buffer model/view/proj matrices
|
||||
// glUniformMatrix4fv(shader.shaderVertexModelLoc, false, parent.modelMatrix.get(new float[16]));
|
||||
// glUniformMatrix4fv(shader.shaderVertexViewLoc, false, new Matrix4f(Globals.viewMatrix).scale(100).get(new float[16]));
|
||||
// glUniformMatrix4fv(shader.shaderVertexProjectionLoc, false, Globals.projectionMatrix.get(new float[16]));
|
||||
// glUniform3fv(shader.shaderVertexViewPosLoc, CameraEntityUtils.getCameraEye(Globals.playerCamera).get(BufferUtils.createFloatBuffer(3)));
|
||||
// }
|
||||
|
||||
// GL11.glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_INT, 0);
|
||||
// glBindVertexArray(0);
|
||||
|
||||
// if(renderPipelineState.getUseMeshShader()){
|
||||
// GL11.glDepthFunc(GL_LESS);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// //
|
||||
// // VAO
|
||||
// //
|
||||
// skyboxmesh.generateVAO();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// float[] vertexcoords = {
|
||||
// 100.0f, 100.0f, 100.0f,
|
||||
// 100.0f, 100.0f,-100.0f,
|
||||
// 100.0f,-100.0f, 100.0f,
|
||||
// 100.0f,-100.0f,-100.0f,
|
||||
// -100.0f, 100.0f, 100.0f,
|
||||
// -100.0f, 100.0f,-100.0f,
|
||||
// -100.0f,-100.0f, 100.0f,
|
||||
// -100.0f,-100.0f,-100.0f,
|
||||
|
||||
// };
|
||||
|
||||
// //
|
||||
// //Buffer data to GPU
|
||||
// //
|
||||
|
||||
// try {
|
||||
// skyboxmesh.vertexCount = vertexcoords.length / 3;
|
||||
// FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount * 3);
|
||||
// float[] temp = new float[3];
|
||||
// for (int i = 0; i < skyboxmesh.vertexCount; i++) {
|
||||
// temp[0] = vertexcoords[i * 3 + 0];
|
||||
// temp[1] = vertexcoords[i * 3 + 1];
|
||||
// temp[2] = vertexcoords[i * 3 + 2];
|
||||
// VertexArrayBufferData.put(temp);
|
||||
// }
|
||||
// VertexArrayBufferData.flip();
|
||||
// skyboxmesh.buffer_vertices(VertexArrayBufferData, 3);
|
||||
// } catch (NullPointerException ex){
|
||||
// ex.printStackTrace();
|
||||
// }
|
||||
|
||||
// int[] facedata = {
|
||||
// 0,1,4,
|
||||
// 1,4,5,
|
||||
// 1,3,5,
|
||||
// 3,5,7,
|
||||
// 4,5,7,
|
||||
// 4,6,7,
|
||||
|
||||
// 0,2,4,
|
||||
// 2,4,6,
|
||||
// 0,1,2,
|
||||
// 1,2,3,
|
||||
|
||||
// 2,3,6,
|
||||
// 3,6,7,
|
||||
|
||||
// };
|
||||
|
||||
// //
|
||||
// // FACES
|
||||
// //
|
||||
// skyboxmesh.faceCount = facedata.length / 3;
|
||||
// skyboxmesh.elementCount = facedata.length;
|
||||
// IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(skyboxmesh.elementCount);
|
||||
// for(int i = 0; i < skyboxmesh.faceCount; i++){
|
||||
// int[] temp = new int[3];
|
||||
// temp[0] = facedata[i * 3 + 0];
|
||||
// temp[1] = facedata[i * 3 + 1];
|
||||
// temp[2] = facedata[i * 3 + 2];
|
||||
// elementArrayBufferData.put(temp);
|
||||
// }
|
||||
// elementArrayBufferData.flip();
|
||||
// skyboxmesh.buffer_faces(elementArrayBufferData);
|
||||
|
||||
|
||||
|
||||
|
||||
// if(optionalMaterial != null){
|
||||
// //
|
||||
// // NORMALS
|
||||
// //
|
||||
// try {
|
||||
// skyboxmesh.normalCount = vertexcoords.length / 3;
|
||||
// FloatBuffer NormalArrayBufferData;
|
||||
// if(skyboxmesh.normalCount > 0){
|
||||
// NormalArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.normalCount * 3);
|
||||
// float[] temp = new float[3];
|
||||
// for (int i = 0; i < skyboxmesh.normalCount; i++) {
|
||||
// temp[0] = vertexcoords[i * 3 + 0];
|
||||
// temp[1] = vertexcoords[i * 3 + 1];
|
||||
// temp[2] = vertexcoords[i * 3 + 2];
|
||||
// NormalArrayBufferData.put(temp);
|
||||
// }
|
||||
// NormalArrayBufferData.flip();
|
||||
// skyboxmesh.buffer_normals(NormalArrayBufferData, 3);
|
||||
// }
|
||||
// } catch (NullPointerException ex){
|
||||
// ex.printStackTrace();
|
||||
// }
|
||||
// //
|
||||
// // TEXTURE COORDINATES
|
||||
// //
|
||||
// /*try {
|
||||
// skyboxmesh.textureCoordCount = mesh.mTextureCoords(0).capacity();
|
||||
// FloatBuffer TextureArrayBufferData;
|
||||
// if(skyboxmesh.textureCoordCount > 0){
|
||||
// TextureArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.textureCoordCount * 2);
|
||||
// float[] temp = new float[2];
|
||||
// for (int i = 0; i < skyboxmesh.textureCoordCount; i++) {
|
||||
// AIVector3D normal = texturecoords.get(i);
|
||||
// temp[0] = normal.x();
|
||||
// temp[1] = normal.y();
|
||||
// // temp[2] = normal.z();
|
||||
// TextureArrayBufferData.put(temp);
|
||||
// }
|
||||
// TextureArrayBufferData.flip();
|
||||
// skyboxmesh.buffer_texture_coords(TextureArrayBufferData);
|
||||
// }
|
||||
// } catch (NullPointerException ex){
|
||||
// ex.printStackTrace();
|
||||
// }
|
||||
|
||||
// skyboxmesh.shader = ShaderProgram.smart_assemble_shader(has_bones, apply_lighting);
|
||||
|
||||
// skybox_model.materials.add(optionalMaterial);
|
||||
// */
|
||||
// } else {
|
||||
// skyboxmesh.shader = ShaderProgram.loadSpecificShader("/Shaders/skybox/VertexShaderNoTexture.vs", "/Shaders/skybox/FragmentShaderNoTexture.fs");
|
||||
// try {
|
||||
// FloatBuffer ColorArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount);
|
||||
// for (int i = 0; i < skyboxmesh.vertexCount; i++) {
|
||||
// ColorArrayBufferData.put(i);
|
||||
// }
|
||||
// ColorArrayBufferData.flip();
|
||||
// int idBuffer = glGenBuffers();
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, idBuffer);
|
||||
// GL15.glBufferData(GL_ARRAY_BUFFER, ColorArrayBufferData, GL_STATIC_DRAW);
|
||||
// glVertexAttribPointer(1, 1, GL11.GL_FLOAT, false, 0, 0);
|
||||
// glEnableVertexAttribArray(1);
|
||||
// } catch (NullPointerException ex){
|
||||
// ex.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// skyboxmesh.setHasBones(false);
|
||||
|
||||
|
||||
|
||||
|
||||
// glBindVertexArray(0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// skyboxmesh.setParent(skyboxModel);
|
||||
|
||||
|
||||
// skyboxModel.meshes.add(skyboxmesh);
|
||||
|
||||
|
||||
// return skyboxModel;
|
||||
// }
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user