package electrosphere.server.pathfinding; import org.recast4j.detour.MeshData; import org.recast4j.detour.NavMeshBuilder; import org.recast4j.detour.NavMeshDataCreateParams; import org.recast4j.recast.AreaModification; import org.recast4j.recast.PolyMesh; import org.recast4j.recast.PolyMeshDetail; import org.recast4j.recast.RecastBuilder; import org.recast4j.recast.RecastBuilder.RecastBuilderResult; import org.recast4j.recast.RecastConstants.PartitionType; import org.recast4j.recast.RecastBuilderConfig; import org.recast4j.recast.RecastConfig; import org.recast4j.recast.geom.SingleTrimeshInputGeomProvider; import electrosphere.client.terrain.data.TerrainChunkData; /** * Constructor methods for nav meshes */ public class NavMeshConstructor { /** * Size of a recast cell */ static final float RECAST_CELL_SIZE = 1.0f; /** * Height of a recast cell */ static final float RECAST_CELL_HEIGHT = 1.0f; /** * Size of a recast agent */ static final float RECAST_AGENT_SIZE = 1.0f; /** * Height of a recast agent */ static final float RECAST_AGENT_HEIGHT = 1.0f; /** * Maximum height a recast agent can climb */ static final float RECAST_AGENT_MAX_CLIMB = 0.1f; /** * Maximum slope a recast agent can handle */ static final float RECAST_AGENT_MAX_SLOPE = 0.4f; /** * Minimum size of a recast region */ static final int RECAST_MIN_REGION_SIZE = 1; /** * Merge size of a recast region */ static final int RECAST_REGION_MERGE_SIZE = 1; static final float RECAST_REGION_EDGE_MAX_LEN = 1.0f; static final float RECAST_REGION_EDGE_MAX_ERROR = 1.0f; static final int RECAST_VERTS_PER_POLY = 3; static final float RECAST_DETAIL_SAMPLE_DIST = 0.1f; static final float RECAST_DETAIL_SAMPLE_MAX_ERROR = 0.1f; /** * Constructs a navmesh * @param terrainChunk The terrain chunk * @return the MeshData */ public static MeshData constructNavmesh(TerrainChunkData terrainChunkData){ MeshData rVal = null; try { RecastConfig recastConfig = new RecastConfig( PartitionType.WATERSHED, RECAST_CELL_SIZE, RECAST_CELL_HEIGHT, RECAST_AGENT_HEIGHT, RECAST_AGENT_SIZE, RECAST_AGENT_MAX_CLIMB, RECAST_AGENT_MAX_SLOPE, RECAST_MIN_REGION_SIZE, RECAST_REGION_MERGE_SIZE, RECAST_REGION_EDGE_MAX_LEN, RECAST_REGION_EDGE_MAX_ERROR, RECAST_VERTS_PER_POLY, RECAST_DETAIL_SAMPLE_DIST, RECAST_DETAIL_SAMPLE_MAX_ERROR, new AreaModification(0) ); SingleTrimeshInputGeomProvider geomProvider = new SingleTrimeshInputGeomProvider(terrainChunkData.getVertices(), terrainChunkData.getFaceElements()); RecastBuilderConfig recastBuilderConfig = new RecastBuilderConfig(recastConfig, geomProvider.getMeshBoundsMin(), geomProvider.getMeshBoundsMax()); RecastBuilder recastBuilder = new RecastBuilder(); RecastBuilderResult recastBuilderResult = recastBuilder.build(geomProvider, recastBuilderConfig); PolyMesh polyMesh = recastBuilderResult.getMesh(); for(int i = 0; i < polyMesh.npolys; i++){ polyMesh.flags[i] = 1; } //set params NavMeshDataCreateParams params = new NavMeshDataCreateParams(); params.verts = polyMesh.verts; params.vertCount = polyMesh.nverts; params.polys = polyMesh.polys; params.polyAreas = polyMesh.areas; params.polyFlags = polyMesh.flags; params.polyCount = polyMesh.npolys; params.nvp = polyMesh.nvp; params.walkableHeight = RECAST_AGENT_HEIGHT; params.walkableRadius = RECAST_AGENT_SIZE; params.walkableClimb = RECAST_AGENT_MAX_CLIMB; params.bmin = polyMesh.bmin; params.bmax = polyMesh.bmax; params.cs = RECAST_CELL_SIZE; params.ch = RECAST_CELL_HEIGHT; params.buildBvTree = true; PolyMeshDetail polyMeshDetail = recastBuilderResult.getMeshDetail(); if(polyMeshDetail != null){ params.detailMeshes = polyMeshDetail.meshes; params.detailVerts = polyMeshDetail.verts; params.detailVertsCount = polyMeshDetail.nverts; params.detailTris = polyMeshDetail.tris; params.detailTriCount = polyMeshDetail.ntris; } // params.offMeshConVerts = new float[6]; // params.offMeshConVerts[0] = 0.1f; // params.offMeshConVerts[1] = 0.2f; // params.offMeshConVerts[2] = 0.3f; // params.offMeshConVerts[3] = 0.4f; // params.offMeshConVerts[4] = 0.5f; // params.offMeshConVerts[5] = 0.6f; // params.offMeshConRad = new float[1]; // params.offMeshConRad[0] = 0.1f; // params.offMeshConDir = new int[1]; // params.offMeshConDir[0] = 1; // params.offMeshConAreas = new int[1]; // params.offMeshConAreas[0] = 2; // params.offMeshConFlags = new int[1]; // params.offMeshConFlags[0] = 12; // params.offMeshConUserID = new int[1]; // params.offMeshConUserID[0] = 0x4567; // params.offMeshConCount = 1; //actually build rVal = NavMeshBuilder.createNavMeshData(params); } catch (Exception e){ e.printStackTrace(); } return rVal; } }