pathfinding tiling work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-02 16:46:46 -04:00
parent 18023872b0
commit e489def162
4 changed files with 90 additions and 13 deletions

View File

@ -1649,6 +1649,7 @@ Fix blocks not saving to disk when being ejected from cache
Block chunk memory pooling Block chunk memory pooling
Rename MoveToTree Rename MoveToTree
Major pathfinding work -- breaking MoteToTree Major pathfinding work -- breaking MoteToTree
Pathfinding tiling work

View File

@ -84,7 +84,6 @@ import electrosphere.server.datacell.EntityDataCellMapper;
import electrosphere.server.datacell.RealmManager; import electrosphere.server.datacell.RealmManager;
import electrosphere.server.db.DatabaseController; import electrosphere.server.db.DatabaseController;
import electrosphere.server.entity.poseactor.PoseModel; import electrosphere.server.entity.poseactor.PoseModel;
import electrosphere.server.pathfinding.Pathfinder;
import electrosphere.server.saves.Save; import electrosphere.server.saves.Save;
import electrosphere.server.simulation.MacroSimulation; import electrosphere.server.simulation.MacroSimulation;
import electrosphere.server.simulation.MicroSimulation; import electrosphere.server.simulation.MicroSimulation;
@ -431,9 +430,6 @@ public class Globals {
public static Entity draggedItem = null; public static Entity draggedItem = null;
public static Object dragSourceInventory = null; public static Object dragSourceInventory = null;
//pathfinder
public static Pathfinder pathfinder;
@ -522,9 +518,6 @@ public class Globals {
gameConfigCurrent = gameConfigDefault; gameConfigCurrent = gameConfigDefault;
NetConfig.readNetConfig(); NetConfig.readNetConfig();
//pathfinder
Globals.pathfinder = new Pathfinder();
// //
//Values that depend on the loaded config //Values that depend on the loaded config
Globals.clientSelectedVoxelType = (VoxelType)gameConfigCurrent.getVoxelData().getTypes().toArray()[1]; Globals.clientSelectedVoxelType = (VoxelType)gameConfigCurrent.getVoxelData().getTypes().toArray()[1];

View File

@ -40,6 +40,7 @@ import electrosphere.server.datacell.physics.PhysicsDataCell;
import electrosphere.server.entity.ServerContentManager; import electrosphere.server.entity.ServerContentManager;
import electrosphere.server.entity.serialization.ContentSerialization; import electrosphere.server.entity.serialization.ContentSerialization;
import electrosphere.server.pathfinding.NavMeshConstructor; import electrosphere.server.pathfinding.NavMeshConstructor;
import electrosphere.server.pathfinding.Pathfinder;
import electrosphere.server.physics.block.manager.ServerBlockManager; import electrosphere.server.physics.block.manager.ServerBlockManager;
import electrosphere.server.physics.fluid.manager.ServerFluidChunk; import electrosphere.server.physics.fluid.manager.ServerFluidChunk;
import electrosphere.server.physics.fluid.manager.ServerFluidManager; import electrosphere.server.physics.fluid.manager.ServerFluidManager;
@ -159,6 +160,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
*/ */
Map<Long,Vector3i> physicsQueue = new HashMap<Long,Vector3i>(); Map<Long,Vector3i> physicsQueue = new HashMap<Long,Vector3i>();
/**
* The pathfinder for the manager
*/
Pathfinder pathfinder;
/** /**
* Constructor * Constructor
* @param parent The gridded data cell manager's parent realm * @param parent The gridded data cell manager's parent realm
@ -188,6 +194,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
this.serverContentManager + " " this.serverContentManager + " "
); );
} }
this.pathfinder = new Pathfinder();
} }
/** /**
@ -369,6 +376,15 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
if(pathingMeshData == null){ if(pathingMeshData == null){
throw new Error("Failed to build pathing data from existing vertices!"); throw new Error("Failed to build pathing data from existing vertices!");
} }
pathingMeshData.header.x = worldPos.x;
pathingMeshData.header.y = worldPos.z;
pathingMeshData.header.bmin[0] = worldPos.x;
pathingMeshData.header.bmin[1] = worldPos.y;
pathingMeshData.header.bmin[2] = worldPos.z;
pathingMeshData.header.bmax[0] = worldPos.x + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathingMeshData.header.bmax[1] = worldPos.y + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathingMeshData.header.bmax[2] = worldPos.z + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathfinder.addTile(pathingMeshData);
trackingData.setNavMeshData(pathingMeshData); trackingData.setNavMeshData(pathingMeshData);
} }
@ -754,7 +770,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
Map<Long, PhysicsDataCell> posPhysicsMap, Map<Long, PhysicsDataCell> posPhysicsMap,
Map<Long, ServerDataCell> groundDataCells, Map<Long, ServerDataCell> groundDataCells,
Map<ServerDataCell,GriddedDataCellTrackingData> cellTrackingMap, Map<ServerDataCell,GriddedDataCellTrackingData> cellTrackingMap,
Realm realm Realm realm,
Pathfinder pathfinder
){ ){
//get data to generate with //get data to generate with
Vector3d realPos = new Vector3d( Vector3d realPos = new Vector3d(
@ -811,6 +828,15 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
if(pathingMeshData == null){ if(pathingMeshData == null){
throw new Error("Failed to build pathing data from existing vertices!"); throw new Error("Failed to build pathing data from existing vertices!");
} }
pathingMeshData.header.x = worldPos.x;
pathingMeshData.header.y = worldPos.z;
pathingMeshData.header.bmin[0] = worldPos.x;
pathingMeshData.header.bmin[1] = worldPos.y;
pathingMeshData.header.bmin[2] = worldPos.z;
pathingMeshData.header.bmax[0] = worldPos.x + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathingMeshData.header.bmax[1] = worldPos.y + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathingMeshData.header.bmax[2] = worldPos.z + ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
pathfinder.addTile(pathingMeshData);
trackingData.setNavMeshData(pathingMeshData); trackingData.setNavMeshData(pathingMeshData);
} }
@ -861,7 +887,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
//generates physics for the cell in a dedicated thread then finally registers //generates physics for the cell in a dedicated thread then finally registers
loadedCellsLock.lock(); loadedCellsLock.lock();
PhysicsDataCell cell = posPhysicsMap.get(key); PhysicsDataCell cell = posPhysicsMap.get(key);
GriddedDataCellManager.runPhysicsGenerationThread(localWorldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.cellTrackingMap,this.parent); GriddedDataCellManager.runPhysicsGenerationThread(localWorldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.cellTrackingMap,this.parent,this.pathfinder);
loadedCellsLock.unlock(); loadedCellsLock.unlock();
@ -1123,7 +1149,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
if(trackingMeshData == null){ if(trackingMeshData == null){
throw new Error("Tracking mesh data is null!"); throw new Error("Tracking mesh data is null!");
} }
List<Vector3d> points = Globals.pathfinder.solve(trackingMeshData, start, end); List<Vector3d> points = this.pathfinder.solve(trackingMeshData, start, end);
return points; return points;
} }

View File

@ -1,8 +1,11 @@
package electrosphere.server.pathfinding; package electrosphere.server.pathfinding;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -10,6 +13,7 @@ import org.recast4j.detour.DefaultQueryFilter;
import org.recast4j.detour.FindNearestPolyResult; import org.recast4j.detour.FindNearestPolyResult;
import org.recast4j.detour.MeshData; import org.recast4j.detour.MeshData;
import org.recast4j.detour.NavMesh; import org.recast4j.detour.NavMesh;
import org.recast4j.detour.NavMeshParams;
import org.recast4j.detour.NavMeshQuery; import org.recast4j.detour.NavMeshQuery;
import org.recast4j.detour.QueryFilter; import org.recast4j.detour.QueryFilter;
import org.recast4j.detour.Result; import org.recast4j.detour.Result;
@ -28,6 +32,57 @@ public class Pathfinder {
*/ */
static final int MAX_STRAIGHT_PATH_POINTS = 100; static final int MAX_STRAIGHT_PATH_POINTS = 100;
/**
* The root navmesh
*/
NavMesh navMesh;
/**
* The map of ref -> nav tile
*/
Map<MeshData,Long> meshRefMap = new HashMap<MeshData,Long>();
/**
* The lock for thread safety
*/
ReentrantLock lock = new ReentrantLock();
/**
* Creates the pathfinder
*/
public Pathfinder(){
NavMeshParams params = new NavMeshParams();
params.tileHeight = ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
params.tileWidth = ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET;
params.orig[0] = 0;
params.orig[1] = 0;
params.orig[2] = 0;
params.maxTiles = 1000;
params.maxPolys = 100000;
this.navMesh = new NavMesh(params, NavMeshConstructor.RECAST_VERTS_PER_POLY);
}
/**
* Adds a tile to the pathfinder
* @param tile The file
*/
public void addTile(MeshData tile){
lock.lock();
long ref = this.navMesh.addTile(tile, 0, 0);
meshRefMap.put(tile,ref);
lock.unlock();
}
/**
* Removes a tile from the navmesh
* @param tile The tile
*/
public void removeTile(MeshData tile){
lock.lock();
this.navMesh.removeTile(MAX_STRAIGHT_PATH_POINTS);
lock.unlock();
}
/** /**
* Solves for a path * Solves for a path
* @param mesh The navmesh * @param mesh The navmesh
@ -36,6 +91,7 @@ public class Pathfinder {
* @return The set of points to path along * @return The set of points to path along
*/ */
public List<Vector3d> solve(MeshData mesh, Vector3d startPos, Vector3d endPos){ public List<Vector3d> solve(MeshData mesh, Vector3d startPos, Vector3d endPos){
lock.lock();
List<Vector3d> rVal = new LinkedList<Vector3d>(); List<Vector3d> rVal = new LinkedList<Vector3d>();
if(mesh == null){ if(mesh == null){
@ -43,8 +99,7 @@ public class Pathfinder {
} }
//construct objects //construct objects
NavMesh navMesh = new NavMesh(mesh,6,0); NavMeshQuery query = new NavMeshQuery(this.navMesh);
NavMeshQuery query = new NavMeshQuery(navMesh);
QueryFilter filter = new DefaultQueryFilter(); QueryFilter filter = new DefaultQueryFilter();
//convert points to correct datatypes //convert points to correct datatypes
@ -91,7 +146,7 @@ public class Pathfinder {
message = "Failed to solve for path -- invalid param!\n" + message = "Failed to solve for path -- invalid param!\n" +
"Message: " + pathResult.message + "\n" + "Message: " + pathResult.message + "\n" +
"Status: " + pathResult.status + "\n" + "Status: " + pathResult.status + "\n" +
Pathfinder.checkInvalidParam(navMesh,startRef,endRef,startArr,endArr) + "\n" + Pathfinder.checkInvalidParam(this.navMesh,startRef,endRef,startArr,endArr) + "\n" +
"" ""
; ;
} }
@ -112,6 +167,8 @@ public class Pathfinder {
rVal.add(new Vector3d(pathItem.getPos()[0],pathItem.getPos()[1],pathItem.getPos()[2])); rVal.add(new Vector3d(pathItem.getPos()[0],pathItem.getPos()[1],pathItem.getPos()[2]));
} }
lock.unlock();
return rVal; return rVal;
} }