using DotRecast.Detour; using DotRecast.Recast.Geom; using DotRecast.Recast.Toolset.Geom; namespace DotRecast.Recast.Toolset.Builder { public static class DemoNavMeshBuilder { public static DtNavMeshCreateParams GetNavMeshCreateParams(IInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, RcBuilderResult rcResult) { RcPolyMesh pmesh = rcResult.GetMesh(); RcPolyMeshDetail dmesh = rcResult.GetMeshDetail(); DtNavMeshCreateParams option = new DtNavMeshCreateParams(); for (int i = 0; i < pmesh.npolys; ++i) { pmesh.flags[i] = 1; } option.verts = pmesh.verts; option.vertCount = pmesh.nverts; option.polys = pmesh.polys; option.polyAreas = pmesh.areas; option.polyFlags = pmesh.flags; option.polyCount = pmesh.npolys; option.nvp = pmesh.nvp; if (dmesh != null) { option.detailMeshes = dmesh.meshes; option.detailVerts = dmesh.verts; option.detailVertsCount = dmesh.nverts; option.detailTris = dmesh.tris; option.detailTriCount = dmesh.ntris; } option.walkableHeight = agentHeight; option.walkableRadius = agentRadius; option.walkableClimb = agentMaxClimb; option.bmin = pmesh.bmin; option.bmax = pmesh.bmax; option.cs = cellSize; option.ch = cellHeight; option.buildBvTree = true; var offMeshConnections = geom.GetOffMeshConnections(); option.offMeshConCount = offMeshConnections.Count; option.offMeshConVerts = new float[option.offMeshConCount * 6]; option.offMeshConRad = new float[option.offMeshConCount]; option.offMeshConDir = new int[option.offMeshConCount]; option.offMeshConAreas = new int[option.offMeshConCount]; option.offMeshConFlags = new int[option.offMeshConCount]; option.offMeshConUserID = new int[option.offMeshConCount]; for (int i = 0; i < option.offMeshConCount; i++) { RcOffMeshConnection offMeshCon = offMeshConnections[i]; for (int j = 0; j < 6; j++) { option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j]; } option.offMeshConRad[i] = offMeshCon.radius; option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0; option.offMeshConAreas[i] = offMeshCon.area; option.offMeshConFlags[i] = offMeshCon.flags; // option.offMeshConUserID[i] = offMeshCon.userId; } return option; } public static DtMeshData UpdateAreaAndFlags(DtMeshData meshData) { // Update poly flags from areas. for (int i = 0; i < meshData.polys.Length; ++i) { if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE) { meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND); } if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD) { meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK; } else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER) { meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM; } else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR) { meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR; } } return meshData; } } }