rename RcRecast, DtDetour

This commit is contained in:
ikpil 2024-05-12 01:11:03 +09:00
parent 3f750ba499
commit 40306a5302
43 changed files with 411 additions and 408 deletions

View File

@ -1,11 +1,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using DotRecast.Recast; using DotRecast.Recast;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Detour.Extras.Jumplink namespace DotRecast.Detour.Extras.Jumplink
{ {
using static RcRecast;
public class EdgeExtractor public class EdgeExtractor
{ {
public JumpEdge[] ExtractEdges(RcPolyMesh mesh) public JumpEdge[] ExtractEdges(RcPolyMesh mesh)

View File

@ -22,6 +22,8 @@ using DotRecast.Core;
namespace DotRecast.Detour.Extras.Unity.Astar namespace DotRecast.Detour.Extras.Unity.Astar
{ {
using static DtDetour;
public class GraphMeshDataReader : ZipBinaryReader public class GraphMeshDataReader : ZipBinaryReader
{ {
public const float INT_PRECISION_FACTOR = 1000f; public const float INT_PRECISION_FACTOR = 1000f;
@ -116,8 +118,8 @@ namespace DotRecast.Detour.Extras.Unity.Astar
tiles[tileIndex].detailVerts = detailVerts; tiles[tileIndex].detailVerts = detailVerts;
tiles[tileIndex].detailTris = detailTris; tiles[tileIndex].detailTris = detailTris;
DtMeshHeader header = new DtMeshHeader(); DtMeshHeader header = new DtMeshHeader();
header.magic = DtNavMesh.DT_NAVMESH_MAGIC; header.magic = DT_NAVMESH_MAGIC;
header.version = DtNavMesh.DT_NAVMESH_VERSION; header.version = DT_NAVMESH_VERSION;
header.x = x; header.x = x;
header.y = z; header.y = z;
header.polyCount = nodeCount; header.polyCount = nodeCount;

View File

@ -21,6 +21,8 @@ using System.Collections.Generic;
namespace DotRecast.Detour.Extras.Unity.Astar namespace DotRecast.Detour.Extras.Unity.Astar
{ {
using static DtDetour;
public class LinkBuilder public class LinkBuilder
{ {
// Process connections and transform them into recast neighbour flags // Process connections and transform them into recast neighbour flags
@ -65,19 +67,19 @@ namespace DotRecast.Detour.Extras.Unity.Astar
{ {
if (neighbourTile.header.bmin.X > tile.header.bmin.X) if (neighbourTile.header.bmin.X > tile.header.bmin.X)
{ {
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.X, 0)] = DtNavMesh.DT_EXT_LINK; node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.X, 0)] = DT_EXT_LINK;
} }
else if (neighbourTile.header.bmin.X < tile.header.bmin.X) else if (neighbourTile.header.bmin.X < tile.header.bmin.X)
{ {
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.X, 0)] = DtNavMesh.DT_EXT_LINK | 4; node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.X, 0)] = DT_EXT_LINK | 4;
} }
else if (neighbourTile.header.bmin.Z > tile.header.bmin.Z) else if (neighbourTile.header.bmin.Z > tile.header.bmin.Z)
{ {
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 2; node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.Z, 2)] = DT_EXT_LINK | 2;
} }
else else
{ {
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 6; node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DT_EXT_LINK | 6;
} }
} }
} }

View File

@ -26,6 +26,8 @@ using DotRecast.Detour.TileCache.Io;
namespace DotRecast.Detour.TileCache namespace DotRecast.Detour.TileCache
{ {
using static DtDetour;
public class DtTileCache public class DtTileCache
{ {
private int m_tileLutSize; // < Tile hash lookup size (must be pot). private int m_tileLutSize; // < Tile hash lookup size (must be pot).
@ -160,7 +162,7 @@ namespace DotRecast.Detour.TileCache
List<long> tiles = new List<long>(); List<long> tiles = new List<long>();
// Find tile based on hash. // Find tile based on hash.
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask); int h = ComputeTileHash(tx, ty, m_tileLutMask);
DtCompressedTile tile = m_posLookup[h]; DtCompressedTile tile = m_posLookup[h];
while (tile != null) while (tile != null)
{ {
@ -178,7 +180,7 @@ namespace DotRecast.Detour.TileCache
DtCompressedTile GetTileAt(int tx, int ty, int tlayer) DtCompressedTile GetTileAt(int tx, int ty, int tlayer)
{ {
// Find tile based on hash. // Find tile based on hash.
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask); int h = ComputeTileHash(tx, ty, m_tileLutMask);
DtCompressedTile tile = m_posLookup[h]; DtCompressedTile tile = m_posLookup[h];
while (tile != null) while (tile != null)
{ {
@ -266,7 +268,7 @@ namespace DotRecast.Detour.TileCache
} }
// Insert tile into the position lut. // Insert tile into the position lut.
int h = DtNavMesh.ComputeTileHash(header.tx, header.ty, m_tileLutMask); int h = ComputeTileHash(header.tx, header.ty, m_tileLutMask);
tile.next = m_posLookup[h]; tile.next = m_posLookup[h];
m_posLookup[h] = tile; m_posLookup[h] = tile;
@ -305,7 +307,7 @@ namespace DotRecast.Detour.TileCache
} }
// Remove tile from hash lookup. // Remove tile from hash lookup.
int h = DtNavMesh.ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask); int h = ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
DtCompressedTile prev = null; DtCompressedTile prev = null;
DtCompressedTile cur = m_posLookup[h]; DtCompressedTile cur = m_posLookup[h];
while (cur != null) while (cur != null)

View File

@ -0,0 +1,176 @@
using DotRecast.Core.Numerics;
namespace DotRecast.Detour
{
public static class DtDetour
{
/** A magic number used to detect compatibility of navigation tile data. */
public const int DT_NAVMESH_MAGIC = 'D' << 24 | 'N' << 16 | 'A' << 8 | 'V';
/** A version number used to detect compatibility of navigation tile data. */
public const int DT_NAVMESH_VERSION = 7;
public const int DT_NAVMESH_VERSION_RECAST4J_FIRST = 0x8807;
public const int DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK = 0x8808;
public const int DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE = 0x8809;
public const int DT_NAVMESH_VERSION_RECAST4J_LAST = 0x8809;
/** A magic number used to detect the compatibility of navigation tile states. */
public const int DT_NAVMESH_STATE_MAGIC = 'D' << 24 | 'N' << 16 | 'M' << 8 | 'S';
/** A version number used to detect compatibility of navigation tile states. */
public const int DT_NAVMESH_STATE_VERSION = 1;
public const int DT_SALT_BITS = 16;
public const int DT_TILE_BITS = 28;
public const int DT_POLY_BITS = 20;
/// A flag that indicates that an entity links to an external entity.
/// (E.g. A polygon edge is a portal that links to another polygon.)
public const int DT_EXT_LINK = 0x8000;
/// A value that indicates the entity does not link to anything.
public const int DT_NULL_LINK = unchecked((int)0xffffffff);
/// A flag that indicates that an off-mesh connection can be traversed in
/// both directions. (Is bidirectional.)
public const int DT_OFFMESH_CON_BIDIR = 1;
/// The maximum number of user defined area ids.
public const int DT_MAX_AREAS = 64;
/// Limit raycasting during any angle pahfinding
/// The limit is given as a multiple of the character radius
public const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f;
/// @{
/// @name Encoding and Decoding
/// These functions are generally meant for internal use only.
/// Derives a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] salt The tile's salt value.
/// @param[in] it The index of the tile.
/// @param[in] ip The index of the polygon within the tile.
public static long EncodePolyId(int salt, int it, int ip)
{
return (((long)salt) << (DT_POLY_BITS + DT_TILE_BITS)) | ((long)it << DT_POLY_BITS) | (long)ip;
}
/// Decodes a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference to decode.
/// @param[out] salt The tile's salt value.
/// @param[out] it The index of the tile.
/// @param[out] ip The index of the polygon within the tile.
/// @see #encodePolyId
public static void DecodePolyId(long refs, out int salt, out int it, out int ip)
{
long saltMask = (1L << DT_SALT_BITS) - 1;
long tileMask = (1L << DT_TILE_BITS) - 1;
long polyMask = (1L << DT_POLY_BITS) - 1;
salt = (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
it = (int)((refs >> DT_POLY_BITS) & tileMask);
ip = (int)(refs & polyMask);
}
/// Extracts a tile's salt value from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
public static int DecodePolyIdSalt(long refs)
{
long saltMask = (1L << DT_SALT_BITS) - 1;
return (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
}
/// Extracts the tile's index from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
public static int DecodePolyIdTile(long refs)
{
long tileMask = (1L << DT_TILE_BITS) - 1;
return (int)((refs >> DT_POLY_BITS) & tileMask);
}
/// Extracts the polygon's index (within its tile) from the specified
/// polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
public static int DecodePolyIdPoly(long refs)
{
long polyMask = (1L << DT_POLY_BITS) - 1;
return (int)(refs & polyMask);
}
public static int ComputeTileHash(int x, int y, int mask)
{
uint h1 = 0x8da6b343; // Large multiplicative constants;
uint h2 = 0xd8163841; // here arbitrarily chosen primes
uint n = h1 * (uint)x + h2 * (uint)y;
return (int)(n & mask);
}
public static float GetSlabCoord(float[] verts, int va, int side)
{
if (side == 0 || side == 4)
{
return verts[va];
}
else if (side == 2 || side == 6)
{
return verts[va + 2];
}
return 0;
}
public static void CalcSlabEndPoints(float[] verts, int va, int vb, ref RcVec2f bmin, ref RcVec2f bmax, int side)
{
if (side == 0 || side == 4)
{
if (verts[va + 2] < verts[vb + 2])
{
bmin.X = verts[va + 2];
bmin.Y = verts[va + 1];
bmax.X = verts[vb + 2];
bmax.Y = verts[vb + 1];
}
else
{
bmin.X = verts[vb + 2];
bmin.Y = verts[vb + 1];
bmax.X = verts[va + 2];
bmax.Y = verts[va + 1];
}
}
else if (side == 2 || side == 6)
{
if (verts[va + 0] < verts[vb + 0])
{
bmin.X = verts[va + 0];
bmin.Y = verts[va + 1];
bmax.X = verts[vb + 0];
bmax.Y = verts[vb + 1];
}
else
{
bmin.X = verts[vb + 0];
bmin.Y = verts[vb + 1];
bmax.X = verts[va + 0];
bmax.Y = verts[va + 1];
}
}
}
/// Get flags for edge in detail triangle.
/// @param[in] triFlags The flags for the triangle (last component of detail vertices above).
/// @param[in] edgeIndex The index of the first vertex of the edge. For instance, if 0,
/// returns flags for edge AB.
public static int GetDetailTriEdgeFlags(int triFlags, int edgeIndex)
{
return (triFlags >> (edgeIndex * 2)) & 0x3;
}
}
}

View File

@ -22,6 +22,8 @@ using System.Collections.Generic;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
/** /**
* Defines a navigation mesh tile. * Defines a navigation mesh tile.
*/ */
@ -41,7 +43,7 @@ namespace DotRecast.Detour
public readonly List<DtLink> links = new List<DtLink>(); public readonly List<DtLink> links = new List<DtLink>();
/** Index to the next free link. */ /** Index to the next free link. */
public int linksFreeList = DtNavMesh.DT_NULL_LINK; // FIXME: Remove public int linksFreeList = DT_NULL_LINK; // FIXME: Remove
/** Tile flags. (See: #dtTileFlags) */ /** Tile flags. (See: #dtTileFlags) */
public int flags; public int flags;

View File

@ -25,56 +25,19 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
public class DtNavMesh public class DtNavMesh
{ {
/** A magic number used to detect compatibility of navigation tile data. */
public const int DT_NAVMESH_MAGIC = 'D' << 24 | 'N' << 16 | 'A' << 8 | 'V';
/** A version number used to detect compatibility of navigation tile data. */
public const int DT_NAVMESH_VERSION = 7;
public const int DT_NAVMESH_VERSION_RECAST4J_FIRST = 0x8807;
public const int DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK = 0x8808;
public const int DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE = 0x8809;
public const int DT_NAVMESH_VERSION_RECAST4J_LAST = 0x8809;
/** A magic number used to detect the compatibility of navigation tile states. */
public const int DT_NAVMESH_STATE_MAGIC = 'D' << 24 | 'N' << 16 | 'M' << 8 | 'S';
/** A version number used to detect compatibility of navigation tile states. */
public const int DT_NAVMESH_STATE_VERSION = 1;
public const int DT_SALT_BITS = 16;
public const int DT_TILE_BITS = 28;
public const int DT_POLY_BITS = 20;
/// A flag that indicates that an entity links to an external entity.
/// (E.g. A polygon edge is a portal that links to another polygon.)
public const int DT_EXT_LINK = 0x8000;
/// A value that indicates the entity does not link to anything.
public const int DT_NULL_LINK = unchecked((int)0xffffffff);
/// A flag that indicates that an off-mesh connection can be traversed in
/// both directions. (Is bidirectional.)
public const int DT_OFFMESH_CON_BIDIR = 1;
/// The maximum number of user defined area ids.
public const int DT_MAX_AREAS = 64;
/// Limit raycasting during any angle pahfinding
/// The limit is given as a multiple of the character radius
public const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f;
private readonly DtNavMeshParams m_params; //< Current initialization params. TODO: do not store this info twice. private readonly DtNavMeshParams m_params; //< Current initialization params. TODO: do not store this info twice.
private readonly RcVec3f m_orig; // < Origin of the tile (0,0) private readonly RcVec3f m_orig; // < Origin of the tile (0,0)
private readonly float m_tileWidth;// < Dimensions of each tile. private readonly float m_tileWidth; // < Dimensions of each tile.
private readonly float m_tileHeight; // < Dimensions of each tile. private readonly float m_tileHeight; // < Dimensions of each tile.
private readonly int m_maxTiles; // < Max number of tiles. private readonly int m_maxTiles; // < Max number of tiles.
private readonly int m_tileLutMask; // < Tile hash lookup mask. private readonly int m_tileLutMask; // < Tile hash lookup mask.
private readonly Dictionary<int, List<DtMeshTile>> m_posLookup = new Dictionary<int, List<DtMeshTile>>(); //< Tile hash lookup. private readonly Dictionary<int, List<DtMeshTile>> m_posLookup; //< Tile hash lookup.
private readonly LinkedList<DtMeshTile> m_nextFree = new LinkedList<DtMeshTile>(); //< Freelist of tiles. private readonly LinkedList<DtMeshTile> m_nextFree; //< Freelist of tiles.
private readonly DtMeshTile[] m_tiles; //< List of tiles. private readonly DtMeshTile[] m_tiles; //< List of tiles.
/** The maximum number of vertices per navigation polygon. */ /** The maximum number of vertices per navigation polygon. */
@ -98,6 +61,8 @@ namespace DotRecast.Detour
m_maxTiles = option.maxTiles; m_maxTiles = option.maxTiles;
m_maxVertPerPoly = maxVertsPerPoly; m_maxVertPerPoly = maxVertsPerPoly;
m_tileLutMask = Math.Max(1, DtUtils.NextPow2(option.maxTiles)) - 1; m_tileLutMask = Math.Max(1, DtUtils.NextPow2(option.maxTiles)) - 1;
m_posLookup = new Dictionary<int, List<DtMeshTile>>();
m_nextFree = new LinkedList<DtMeshTile>();
m_tiles = new DtMeshTile[m_maxTiles]; m_tiles = new DtMeshTile[m_maxTiles];
for (int i = 0; i < m_maxTiles; i++) for (int i = 0; i < m_maxTiles; i++)
{ {
@ -155,67 +120,6 @@ namespace DotRecast.Detour
return EncodePolyId(tile.salt, it, 0); return EncodePolyId(tile.salt, it, 0);
} }
/// @{
/// @name Encoding and Decoding
/// These functions are generally meant for internal use only.
/// Derives a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] salt The tile's salt value.
/// @param[in] it The index of the tile.
/// @param[in] ip The index of the polygon within the tile.
public static long EncodePolyId(int salt, int it, int ip)
{
return (((long)salt) << (DT_POLY_BITS + DT_TILE_BITS)) | ((long)it << DT_POLY_BITS) | (long)ip;
}
/// Decodes a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference to decode.
/// @param[out] salt The tile's salt value.
/// @param[out] it The index of the tile.
/// @param[out] ip The index of the polygon within the tile.
/// @see #encodePolyId
static void DecodePolyId(long refs, out int salt, out int it, out int ip)
{
long saltMask = (1L << DT_SALT_BITS) - 1;
long tileMask = (1L << DT_TILE_BITS) - 1;
long polyMask = (1L << DT_POLY_BITS) - 1;
salt = (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
it = (int)((refs >> DT_POLY_BITS) & tileMask);
ip = (int)(refs & polyMask);
}
/// Extracts a tile's salt value from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
static int DecodePolyIdSalt(long refs)
{
long saltMask = (1L << DT_SALT_BITS) - 1;
return (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
}
/// Extracts the tile's index from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
public static int DecodePolyIdTile(long refs)
{
long tileMask = (1L << DT_TILE_BITS) - 1;
return (int)((refs >> DT_POLY_BITS) & tileMask);
}
/// Extracts the polygon's index (within its tile) from the specified
/// polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
static int DecodePolyIdPoly(long refs)
{
long polyMask = (1L << DT_POLY_BITS) - 1;
return (int)(refs & polyMask);
}
private int AllocLink(DtMeshTile tile) private int AllocLink(DtMeshTile tile)
{ {
if (tile.linksFreeList == DT_NULL_LINK) if (tile.linksFreeList == DT_NULL_LINK)
@ -509,7 +413,7 @@ namespace DotRecast.Detour
tile.flags = flags; tile.flags = flags;
tile.links.Clear(); tile.links.Clear();
tile.polyLinks = new int[data.polys.Length]; tile.polyLinks = new int[data.polys.Length];
Array.Fill(tile.polyLinks, DtNavMesh.DT_NULL_LINK); Array.Fill(tile.polyLinks, DT_NULL_LINK);
// Insert tile into the position lut. // Insert tile into the position lut.
GetTileListByPos(header.x, header.y).Add(tile); GetTileListByPos(header.x, header.y).Add(tile);
@ -622,7 +526,7 @@ namespace DotRecast.Detour
tile.flags = 0; tile.flags = 0;
tile.links.Clear(); tile.links.Clear();
tile.linksFreeList = DtNavMesh.DT_NULL_LINK; tile.linksFreeList = DT_NULL_LINK;
// Update salt, salt should never be zero. // Update salt, salt should never be zero.
tile.salt = (tile.salt + 1) & ((1 << DT_SALT_BITS) - 1); tile.salt = (tile.salt + 1) & ((1 << DT_SALT_BITS) - 1);
@ -956,59 +860,7 @@ namespace DotRecast.Detour
return n; return n;
} }
static float GetSlabCoord(float[] verts, int va, int side) private bool OverlapSlabs(RcVec2f amin, RcVec2f amax, RcVec2f bmin, RcVec2f bmax, float px, float py)
{
if (side == 0 || side == 4)
{
return verts[va];
}
else if (side == 2 || side == 6)
{
return verts[va + 2];
}
return 0;
}
static void CalcSlabEndPoints(float[] verts, int va, int vb, ref RcVec2f bmin, ref RcVec2f bmax, int side)
{
if (side == 0 || side == 4)
{
if (verts[va + 2] < verts[vb + 2])
{
bmin.X = verts[va + 2];
bmin.Y = verts[va + 1];
bmax.X = verts[vb + 2];
bmax.Y = verts[vb + 1];
}
else
{
bmin.X = verts[vb + 2];
bmin.Y = verts[vb + 1];
bmax.X = verts[va + 2];
bmax.Y = verts[va + 1];
}
}
else if (side == 2 || side == 6)
{
if (verts[va + 0] < verts[vb + 0])
{
bmin.X = verts[va + 0];
bmin.Y = verts[va + 1];
bmax.X = verts[vb + 0];
bmax.Y = verts[vb + 1];
}
else
{
bmin.X = verts[vb + 0];
bmin.Y = verts[vb + 1];
bmax.X = verts[va + 0];
bmax.Y = verts[va + 1];
}
}
}
bool OverlapSlabs(RcVec2f amin, RcVec2f amax, RcVec2f bmin, RcVec2f bmax, float px, float py)
{ {
// Check for horizontal overlap. // Check for horizontal overlap.
// The segment is shrunken a little so that slabs which touch // The segment is shrunken a little so that slabs which touch
@ -1496,14 +1348,6 @@ namespace DotRecast.Detour
return EncodePolyId(tile.salt, tile.index, 0); return EncodePolyId(tile.salt, tile.index, 0);
} }
public static int ComputeTileHash(int x, int y, int mask)
{
uint h1 = 0x8da6b343; // Large multiplicative constants;
uint h2 = 0xd8163841; // here arbitrarily chosen primes
uint n = h1 * (uint)x + h2 * (uint)y;
return (int)(n & mask);
}
/// Gets the endpoints for an off-mesh connection, ordered by "direction of travel". /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
/// @param[in] prevRef The reference of the polygon before the connection. /// @param[in] prevRef The reference of the polygon before the connection.
/// @param[in] polyRef The reference of the off-mesh connection polygon. /// @param[in] polyRef The reference of the off-mesh connection polygon.
@ -1745,20 +1589,6 @@ namespace DotRecast.Detour
return center; return center;
} }
/**
* Get flags for edge in detail triangle.
*
* @param triFlags
* The flags for the triangle (last component of detail vertices above).
* @param edgeIndex
* The index of the first vertex of the edge. For instance, if 0,
* @return flags for edge AB.
*/
public static int GetDetailTriEdgeFlags(int triFlags, int edgeIndex)
{
return (triFlags >> (edgeIndex * 2)) & 0x3;
}
private List<DtMeshTile> GetTileListByPos(int x, int z) private List<DtMeshTile> GetTileListByPos(int x, int z)
{ {
var tileHash = ComputeTileHash(x, z, m_tileLutMask); var tileHash = ComputeTileHash(x, z, m_tileLutMask);

View File

@ -24,6 +24,8 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
public static class DtNavMeshBuilder public static class DtNavMeshBuilder
{ {
const int MESH_NULL_IDX = 0xffff; const int MESH_NULL_IDX = 0xffff;
@ -424,8 +426,8 @@ namespace DotRecast.Detour
DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount]; DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount];
// Store header // Store header
header.magic = DtNavMesh.DT_NAVMESH_MAGIC; header.magic = DT_NAVMESH_MAGIC;
header.version = DtNavMesh.DT_NAVMESH_VERSION; header.version = DT_NAVMESH_VERSION;
header.x = option.tileX; header.x = option.tileX;
header.y = option.tileZ; header.y = option.tileZ;
header.layer = option.tileLayer; header.layer = option.tileLayer;
@ -497,13 +499,13 @@ namespace DotRecast.Detour
if (dir == 0xf) // Border if (dir == 0xf) // Border
p.neis[j] = 0; p.neis[j] = 0;
else if (dir == 0) // Portal x- else if (dir == 0) // Portal x-
p.neis[j] = DtNavMesh.DT_EXT_LINK | 4; p.neis[j] = DT_EXT_LINK | 4;
else if (dir == 1) // Portal z+ else if (dir == 1) // Portal z+
p.neis[j] = DtNavMesh.DT_EXT_LINK | 2; p.neis[j] = DT_EXT_LINK | 2;
else if (dir == 2) // Portal x+ else if (dir == 2) // Portal x+
p.neis[j] = DtNavMesh.DT_EXT_LINK | 0; p.neis[j] = DT_EXT_LINK | 0;
else if (dir == 3) // Portal z- else if (dir == 3) // Portal z-
p.neis[j] = DtNavMesh.DT_EXT_LINK | 6; p.neis[j] = DT_EXT_LINK | 6;
} }
else else
{ {
@ -622,7 +624,7 @@ namespace DotRecast.Detour
} }
con.rad = option.offMeshConRad[i]; con.rad = option.offMeshConRad[i];
con.flags = option.offMeshConDir[i] != 0 ? DtNavMesh.DT_OFFMESH_CON_BIDIR : 0; con.flags = option.offMeshConDir[i] != 0 ? DT_OFFMESH_CON_BIDIR : 0;
con.side = offMeshConClass[i * 2 + 1]; con.side = offMeshConClass[i * 2 + 1];
if (option.offMeshConUserID != null) if (option.offMeshConUserID != null)
con.userId = option.offMeshConUserID[i]; con.userId = option.offMeshConUserID[i];

View File

@ -26,6 +26,8 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
public class DtNavMeshQuery public class DtNavMeshQuery
{ {
/// < Add a vertex at every polygon edge crossing. /// < Add a vertex at every polygon edge crossing.
@ -300,7 +302,7 @@ namespace DotRecast.Detour
parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id; parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id;
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -775,7 +777,7 @@ namespace DotRecast.Detour
// so it is enough to compute it from the first tile. // so it is enough to compute it from the first tile.
DtMeshTile tile = m_nav.GetTileByRef(startRef); DtMeshTile tile = m_nav.GetTileByRef(startRef);
float agentRadius = tile.data.header.walkableRadius; float agentRadius = tile.data.header.walkableRadius;
raycastLimitSqr = RcMath.Sqr(agentRadius * DtNavMesh.DT_RAY_CAST_LIMIT_PROPORTIONS); raycastLimitSqr = RcMath.Sqr(agentRadius * DT_RAY_CAST_LIMIT_PROPORTIONS);
} }
if (startRef == endRef) if (startRef == endRef)
@ -851,7 +853,7 @@ namespace DotRecast.Detour
} }
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
long neighbourRef = bestTile.links[i].refs; long neighbourRef = bestTile.links[i].refs;
@ -1046,7 +1048,7 @@ namespace DotRecast.Detour
// so it is enough to compute it from the first tile. // so it is enough to compute it from the first tile.
DtMeshTile tile = m_nav.GetTileByRef(startRef); DtMeshTile tile = m_nav.GetTileByRef(startRef);
float agentRadius = tile.data.header.walkableRadius; float agentRadius = tile.data.header.walkableRadius;
m_query.raycastLimitSqr = RcMath.Sqr(agentRadius * DtNavMesh.DT_RAY_CAST_LIMIT_PROPORTIONS); m_query.raycastLimitSqr = RcMath.Sqr(agentRadius * DT_RAY_CAST_LIMIT_PROPORTIONS);
} }
if (startRef == endRef) if (startRef == endRef)
@ -1172,7 +1174,7 @@ namespace DotRecast.Detour
} }
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
long neighbourRef = bestTile.links[i].refs; long neighbourRef = bestTile.links[i].refs;
@ -1862,10 +1864,10 @@ namespace DotRecast.Detour
// Find links to neighbours. // Find links to neighbours.
int nneis = 0; int nneis = 0;
if ((curPoly.neis[j] & DtNavMesh.DT_EXT_LINK) != 0) if ((curPoly.neis[j] & DT_EXT_LINK) != 0)
{ {
// Tile border. // Tile border.
for (int k = curTile.polyLinks[curPoly.index]; k != DtNavMesh.DT_NULL_LINK; k = curTile.links[k].next) for (int k = curTile.polyLinks[curPoly.index]; k != DT_NULL_LINK; k = curTile.links[k].next)
{ {
DtLink link = curTile.links[k]; DtLink link = curTile.links[k];
if (link.edge == j) if (link.edge == j)
@ -1960,7 +1962,8 @@ namespace DotRecast.Detour
visited[n++] = node.id; visited[n++] = node.id;
if (n >= maxVisitedSize) if (n >= maxVisitedSize)
{ {
status |= DtStatus.DT_BUFFER_TOO_SMALL;; status |= DtStatus.DT_BUFFER_TOO_SMALL;
;
break; break;
} }
@ -2010,7 +2013,7 @@ namespace DotRecast.Detour
// Find the link that points to the 'to' polygon. // Find the link that points to the 'to' polygon.
DtLink link = null; DtLink link = null;
for (int i = fromTile.polyLinks[fromPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = fromTile.links[i].next) for (int i = fromTile.polyLinks[fromPoly.index]; i != DT_NULL_LINK; i = fromTile.links[i].next)
{ {
if (fromTile.links[i].refs == to) if (fromTile.links[i].refs == to)
{ {
@ -2028,7 +2031,7 @@ namespace DotRecast.Detour
if (fromPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) if (fromPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
// Find link that points to first vertex. // Find link that points to first vertex.
for (int i = fromTile.polyLinks[fromPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = fromTile.links[i].next) for (int i = fromTile.polyLinks[fromPoly.index]; i != DT_NULL_LINK; i = fromTile.links[i].next)
{ {
if (fromTile.links[i].refs == to) if (fromTile.links[i].refs == to)
{ {
@ -2050,7 +2053,7 @@ namespace DotRecast.Detour
if (toPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) if (toPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
for (int i = toTile.polyLinks[toPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = toTile.links[i].next) for (int i = toTile.polyLinks[toPoly.index]; i != DT_NULL_LINK; i = toTile.links[i].next)
{ {
if (toTile.links[i].refs == from) if (toTile.links[i].refs == from)
{ {
@ -2326,7 +2329,7 @@ namespace DotRecast.Detour
// Follow neighbours. // Follow neighbours.
long nextRef = 0; long nextRef = 0;
for (int i = tile.polyLinks[poly.index]; i != DtNavMesh.DT_NULL_LINK; i = tile.links[i].next) for (int i = tile.polyLinks[poly.index]; i != DT_NULL_LINK; i = tile.links[i].next)
{ {
DtLink link = tile.links[i]; DtLink link = tile.links[i];
@ -2567,7 +2570,7 @@ namespace DotRecast.Detour
resultParent.Add(parentRef); resultParent.Add(parentRef);
resultCost.Add(bestNode.total); resultCost.Add(bestNode.total);
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2744,7 +2747,7 @@ namespace DotRecast.Detour
resultParent.Add(parentRef); resultParent.Add(parentRef);
resultCost.Add(bestNode.total); resultCost.Add(bestNode.total);
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2899,7 +2902,7 @@ namespace DotRecast.Detour
long curRef = curNode.id; long curRef = curNode.id;
m_nav.GetTileAndPolyByRefUnsafe(curRef, out var curTile, out var curPoly); m_nav.GetTileAndPolyByRefUnsafe(curRef, out var curTile, out var curPoly);
for (int i = curTile.polyLinks[curPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = curTile.links[i].next) for (int i = curTile.polyLinks[curPoly.index]; i != DT_NULL_LINK; i = curTile.links[i].next)
{ {
DtLink link = curTile.links[i]; DtLink link = curTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2967,7 +2970,7 @@ namespace DotRecast.Detour
// Connected polys do not overlap. // Connected polys do not overlap.
bool connected = false; bool connected = false;
for (int k = curTile.polyLinks[curPoly.index]; k != DtNavMesh.DT_NULL_LINK; k = curTile.links[k].next) for (int k = curTile.polyLinks[curPoly.index]; k != DT_NULL_LINK; k = curTile.links[k].next)
{ {
if (curTile.links[k].refs == pastRef) if (curTile.links[k].refs == pastRef)
{ {
@ -3073,10 +3076,10 @@ namespace DotRecast.Detour
{ {
// Skip non-solid edges. // Skip non-solid edges.
ints.Clear(); ints.Clear();
if ((poly.neis[j] & DtNavMesh.DT_EXT_LINK) != 0) if ((poly.neis[j] & DT_EXT_LINK) != 0)
{ {
// Tile border. // Tile border.
for (int k = tile.polyLinks[poly.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next) for (int k = tile.polyLinks[poly.index]; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
DtLink link = tile.links[k]; DtLink link = tile.links[k];
if (link.edge == j) if (link.edge == j)
@ -3240,11 +3243,11 @@ namespace DotRecast.Detour
for (int i = 0, j = bestPoly.vertCount - 1; i < bestPoly.vertCount; j = i++) for (int i = 0, j = bestPoly.vertCount - 1; i < bestPoly.vertCount; j = i++)
{ {
// Skip non-solid edges. // Skip non-solid edges.
if ((bestPoly.neis[j] & DtNavMesh.DT_EXT_LINK) != 0) if ((bestPoly.neis[j] & DT_EXT_LINK) != 0)
{ {
// Tile border. // Tile border.
bool solid = true; bool solid = true;
for (int k = bestTile.polyLinks[bestPoly.index]; k != DtNavMesh.DT_NULL_LINK; k = bestTile.links[k].next) for (int k = bestTile.polyLinks[bestPoly.index]; k != DT_NULL_LINK; k = bestTile.links[k].next)
{ {
DtLink link = bestTile.links[k]; DtLink link = bestTile.links[k];
if (link.edge == j) if (link.edge == j)
@ -3300,7 +3303,7 @@ namespace DotRecast.Detour
bestvi = RcVecUtils.Create(bestTile.data.verts, vi); bestvi = RcVecUtils.Create(bestTile.data.verts, vi);
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DtNavMesh.DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;

View File

@ -24,6 +24,8 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
public static class DtPathUtils public static class DtPathUtils
{ {
private const int MAX_STEER_POINTS = 3; private const int MAX_STEER_POINTS = 3;
@ -107,7 +109,7 @@ namespace DotRecast.Detour
} }
for (int k = tile.polyLinks[poly.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next) for (int k = tile.polyLinks[poly.index]; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
DtLink link = tile.links[k]; DtLink link = tile.links[k];
if (link.refs != 0) if (link.refs != 0)

View File

@ -23,6 +23,8 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour;
/** /**
* <b>The Default Implementation</b> * <b>The Default Implementation</b>
* *
@ -50,7 +52,7 @@ namespace DotRecast.Detour
*/ */
public class DtQueryDefaultFilter : IDtQueryFilter public class DtQueryDefaultFilter : IDtQueryFilter
{ {
private readonly float[] m_areaCost = new float[DtNavMesh.DT_MAX_AREAS]; //< Cost per area type. (Used by default implementation.) private readonly float[] m_areaCost = new float[DT_MAX_AREAS]; //< Cost per area type. (Used by default implementation.)
private int m_includeFlags; //< Flags for polygons that can be visited. (Used by default implementation.) private int m_includeFlags; //< Flags for polygons that can be visited. (Used by default implementation.)
private int m_excludeFlags; //< Flags for polygons that should not be visited. (Used by default implementation.) private int m_excludeFlags; //< Flags for polygons that should not be visited. (Used by default implementation.)
@ -58,7 +60,7 @@ namespace DotRecast.Detour
{ {
m_includeFlags = 0xffff; m_includeFlags = 0xffff;
m_excludeFlags = 0; m_excludeFlags = 0;
for (int i = 0; i < DtNavMesh.DT_MAX_AREAS; ++i) for (int i = 0; i < DT_MAX_AREAS; ++i)
{ {
m_areaCost[i] = 1.0f; m_areaCost[i] = 1.0f;
} }
@ -68,12 +70,12 @@ namespace DotRecast.Detour
{ {
m_includeFlags = includeFlags; m_includeFlags = includeFlags;
m_excludeFlags = excludeFlags; m_excludeFlags = excludeFlags;
for (int i = 0; i < Math.Min(DtNavMesh.DT_MAX_AREAS, areaCost.Length); ++i) for (int i = 0; i < Math.Min(DT_MAX_AREAS, areaCost.Length); ++i)
{ {
m_areaCost[i] = areaCost[i]; m_areaCost[i] = areaCost[i];
} }
for (int i = areaCost.Length; i < DtNavMesh.DT_MAX_AREAS; ++i) for (int i = areaCost.Length; i < DT_MAX_AREAS; ++i)
{ {
m_areaCost[i] = 1.0f; m_areaCost[i] = 1.0f;
} }

View File

@ -21,6 +21,8 @@ using DotRecast.Core;
namespace DotRecast.Detour.Io namespace DotRecast.Detour.Io
{ {
using static DtDetour;
public class DtMeshDataReader public class DtMeshDataReader
{ {
public const int DT_POLY_DETAIL_SIZE = 10; public const int DT_POLY_DETAIL_SIZE = 10;
@ -53,10 +55,10 @@ namespace DotRecast.Detour.Io
DtMeshHeader header = new DtMeshHeader(); DtMeshHeader header = new DtMeshHeader();
data.header = header; data.header = header;
header.magic = buf.GetInt(); header.magic = buf.GetInt();
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC) if (header.magic != DT_NAVMESH_MAGIC)
{ {
header.magic = IOUtils.SwapEndianness(header.magic); header.magic = IOUtils.SwapEndianness(header.magic);
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC) if (header.magic != DT_NAVMESH_MAGIC)
{ {
throw new IOException("Invalid magic"); throw new IOException("Invalid magic");
} }
@ -65,16 +67,16 @@ namespace DotRecast.Detour.Io
} }
header.version = buf.GetInt(); header.version = buf.GetInt();
if (header.version != DtNavMesh.DT_NAVMESH_VERSION) if (header.version != DT_NAVMESH_VERSION)
{ {
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_FIRST if (header.version < DT_NAVMESH_VERSION_RECAST4J_FIRST
|| header.version > DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST) || header.version > DT_NAVMESH_VERSION_RECAST4J_LAST)
{ {
throw new IOException("Invalid version " + header.version); throw new IOException("Invalid version " + header.version);
} }
} }
bool cCompatibility = header.version == DtNavMesh.DT_NAVMESH_VERSION; bool cCompatibility = header.version == DT_NAVMESH_VERSION;
header.x = buf.GetInt(); header.x = buf.GetInt();
header.y = buf.GetInt(); header.y = buf.GetInt();
header.layer = buf.GetInt(); header.layer = buf.GetInt();
@ -141,7 +143,7 @@ namespace DotRecast.Detour.Io
for (int i = 0; i < polys.Length; i++) for (int i = 0; i < polys.Length; i++)
{ {
polys[i] = new DtPoly(i, maxVertPerPoly); polys[i] = new DtPoly(i, maxVertPerPoly);
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK) if (header.version < DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
{ {
buf.GetInt(); // polys[i].firstLink buf.GetInt(); // polys[i].firstLink
} }
@ -200,7 +202,7 @@ namespace DotRecast.Detour.Io
for (int i = 0; i < nodes.Length; i++) for (int i = 0; i < nodes.Length; i++)
{ {
nodes[i] = new DtBVNode(); nodes[i] = new DtBVNode();
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE) if (header.version < DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE)
{ {
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
{ {

View File

@ -21,13 +21,15 @@ using DotRecast.Core;
namespace DotRecast.Detour.Io namespace DotRecast.Detour.Io
{ {
using static DtDetour;
public class DtMeshDataWriter : DtWriter public class DtMeshDataWriter : DtWriter
{ {
public void Write(BinaryWriter stream, DtMeshData data, RcByteOrder order, bool cCompatibility) public void Write(BinaryWriter stream, DtMeshData data, RcByteOrder order, bool cCompatibility)
{ {
DtMeshHeader header = data.header; DtMeshHeader header = data.header;
Write(stream, header.magic, order); Write(stream, header.magic, order);
Write(stream, cCompatibility ? DtNavMesh.DT_NAVMESH_VERSION : DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST, order); Write(stream, cCompatibility ? DT_NAVMESH_VERSION : DT_NAVMESH_VERSION_RECAST4J_LAST, order);
Write(stream, header.x, order); Write(stream, header.x, order);
Write(stream, header.y, order); Write(stream, header.y, order);
Write(stream, header.layer, order); Write(stream, header.layer, order);

View File

@ -22,6 +22,8 @@ using DotRecast.Core;
namespace DotRecast.Detour.Io namespace DotRecast.Detour.Io
{ {
using static DtDetour;
public class DtMeshSetReader public class DtMeshSetReader
{ {
private readonly DtMeshDataReader meshReader = new DtMeshDataReader(); private readonly DtMeshDataReader meshReader = new DtMeshDataReader();
@ -147,7 +149,7 @@ namespace DotRecast.Detour.Io
int salt = ((refs >> (m_polyBits + m_tileBits)) & saltMask); int salt = ((refs >> (m_polyBits + m_tileBits)) & saltMask);
int it = ((refs >> m_polyBits) & tileMask); int it = ((refs >> m_polyBits) & tileMask);
int ip = refs & polyMask; int ip = refs & polyMask;
return DtNavMesh.EncodePolyId(salt, it, ip); return EncodePolyId(salt, it, ip);
} }
} }
} }

View File

@ -23,14 +23,14 @@ using DotRecast.Core.Numerics;
using DotRecast.Detour; using DotRecast.Detour;
using DotRecast.Recast.Toolset.Builder; using DotRecast.Recast.Toolset.Builder;
using DotRecast.Recast.Toolset.Geom; using DotRecast.Recast.Toolset.Geom;
using static DotRecast.Recast.RcCommons; using static DotRecast.Recast.RcRecast;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
public class NavMeshRenderer public class NavMeshRenderer
{ {
private readonly RecastDebugDraw _debugDraw; private readonly RecastDebugDraw _debugDraw;
private readonly int _navMeshDrawFlags = RecastDebugDraw.DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DRAWNAVMESH_CLOSEDLIST; private readonly int _navMeshDrawFlags = RecastDebugDraw.DU_DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DU_DRAWNAVMESH_CLOSEDLIST;
public NavMeshRenderer(RecastDebugDraw debugDraw) public NavMeshRenderer(RecastDebugDraw debugDraw)
{ {

View File

@ -22,16 +22,20 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using DotRecast.Detour; using DotRecast.Detour;
using DotRecast.Detour.Crowd;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Recast.Toolset.Builder; using DotRecast.Recast.Toolset.Builder;
using Silk.NET.OpenGL; using Silk.NET.OpenGL;
namespace DotRecast.Recast.Demo.Draw; namespace DotRecast.Recast.Demo.Draw;
using static DtDetour;
public class RecastDebugDraw : DebugDraw public class RecastDebugDraw : DebugDraw
{ {
public static readonly int DRAWNAVMESH_OFFMESHCONS = 0x01; public static readonly int DU_DRAWNAVMESH_OFFMESHCONS = 0x01;
public static readonly int DRAWNAVMESH_CLOSEDLIST = 0x02; public static readonly int DU_DRAWNAVMESH_CLOSEDLIST = 0x02;
public static readonly int DRAWNAVMESH_COLOR_TILES = 0x04; public static readonly int DU_DRAWNAVMESH_COLOR_TILES = 0x04;
public RecastDebugDraw(GL gl) : base(gl) public RecastDebugDraw(GL gl) : base(gl)
{ {
@ -101,7 +105,7 @@ public class RecastDebugDraw : DebugDraw
public void DebugDrawNavMeshWithClosedList(DtNavMesh mesh, DtNavMeshQuery query, int flags) public void DebugDrawNavMeshWithClosedList(DtNavMesh mesh, DtNavMeshQuery query, int flags)
{ {
DtNavMeshQuery q = (flags & DRAWNAVMESH_CLOSEDLIST) != 0 ? query : null; DtNavMeshQuery q = (flags & DU_DRAWNAVMESH_CLOSEDLIST) != 0 ? query : null;
for (int i = 0; i < mesh.GetMaxTiles(); ++i) for (int i = 0; i < mesh.GetMaxTiles(); ++i)
{ {
DtMeshTile tile = mesh.GetTile(i); DtMeshTile tile = mesh.GetTile(i);
@ -116,7 +120,7 @@ public class RecastDebugDraw : DebugDraw
{ {
long @base = mesh.GetPolyRefBase(tile); long @base = mesh.GetPolyRefBase(tile);
int tileNum = DtNavMesh.DecodePolyIdTile(@base); int tileNum = DecodePolyIdTile(@base);
int tileColor = DuIntToCol(tileNum, 128); int tileColor = DuIntToCol(tileNum, 128);
DepthMask(false); DepthMask(false);
Begin(DebugDrawPrimitives.TRIS); Begin(DebugDrawPrimitives.TRIS);
@ -135,7 +139,7 @@ public class RecastDebugDraw : DebugDraw
} }
else else
{ {
if ((flags & DRAWNAVMESH_COLOR_TILES) != 0) if ((flags & DU_DRAWNAVMESH_COLOR_TILES) != 0)
{ {
col = tileColor; col = tileColor;
} }
@ -163,7 +167,7 @@ public class RecastDebugDraw : DebugDraw
// Draw outer poly boundaries // Draw outer poly boundaries
DrawPolyBoundaries(tile, DuRGBA(0, 48, 64, 220), 2.5f, false); DrawPolyBoundaries(tile, DuRGBA(0, 48, 64, 220), 2.5f, false);
if ((flags & DRAWNAVMESH_OFFMESHCONS) != 0) if ((flags & DU_DRAWNAVMESH_OFFMESHCONS) != 0)
{ {
Begin(DebugDrawPrimitives.LINES, 2.0f); Begin(DebugDrawPrimitives.LINES, 2.0f);
for (int i = 0; i < tile.data.header.polyCount; ++i) for (int i = 0; i < tile.data.header.polyCount; ++i)
@ -198,7 +202,7 @@ public class RecastDebugDraw : DebugDraw
// Check to see if start and end end-points have links. // Check to see if start and end end-points have links.
bool startSet = false; bool startSet = false;
bool endSet = false; bool endSet = false;
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next) for (int k = tile.polyLinks[p.index]; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
if (tile.links[k].edge == 0) if (tile.links[k].edge == 0)
{ {
@ -319,10 +323,10 @@ public class RecastDebugDraw : DebugDraw
continue; continue;
} }
if ((p.neis[j] & DtNavMesh.DT_EXT_LINK) != 0) if ((p.neis[j] & DT_EXT_LINK) != 0)
{ {
bool con = false; bool con = false;
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next) for (int k = tile.polyLinks[p.index]; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
if (tile.links[k].edge == j) if (tile.links[k].edge == j)
{ {
@ -394,7 +398,7 @@ public class RecastDebugDraw : DebugDraw
for (int m = 0, n = 2; m < 3; n = m++) for (int m = 0, n = 2; m < 3; n = m++)
{ {
if ((DtNavMesh.GetDetailTriEdgeFlags(tile.data.detailTris[t + 3], n) & DtDetailTriEdgeFlags.DT_DETAIL_EDGE_BOUNDARY) == 0) if ((GetDetailTriEdgeFlags(tile.data.detailTris[t + 3], n) & DtDetailTriEdgeFlags.DT_DETAIL_EDGE_BOUNDARY) == 0)
continue; continue;
if (((tile.data.detailTris[t + 3] >> (n * 2)) & 0x3) == 0) if (((tile.data.detailTris[t + 3] >> (n * 2)) & 0x3) == 0)
@ -498,7 +502,7 @@ public class RecastDebugDraw : DebugDraw
{ {
color = DuRGBA(0, 192, 255, 64); color = DuRGBA(0, 192, 255, 64);
} }
else if (area == RcConstants.RC_NULL_AREA) else if (area == RcRecast.RC_NULL_AREA)
{ {
color = DuRGBA(0, 0, 0, 64); color = DuRGBA(0, 0, 0, 64);
} }
@ -670,7 +674,7 @@ public class RecastDebugDraw : DebugDraw
int v3 = c.rverts[j * 4 + 3]; int v3 = c.rverts[j * 4 + 3];
float off = 0; float off = 0;
int colv = color; int colv = color;
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0) if ((v3 & RcRecast.RC_BORDER_VERTEX) != 0)
{ {
colv = DuRGBA(255, 255, 255, a); colv = DuRGBA(255, 255, 255, a);
off = ch * 2; off = ch * 2;
@ -717,7 +721,7 @@ public class RecastDebugDraw : DebugDraw
int vb0 = c.verts[j * 4]; int vb0 = c.verts[j * 4];
int vb1 = c.verts[j * 4 + 1]; int vb1 = c.verts[j * 4 + 1];
int vb2 = c.verts[j * 4 + 2]; int vb2 = c.verts[j * 4 + 2];
int col = (va3 & RcConstants.RC_AREA_BORDER) != 0 ? bcolor : color; int col = (va3 & RcRecast.RC_AREA_BORDER) != 0 ? bcolor : color;
float fx = orig.X + va0 * cs; float fx = orig.X + va0 * cs;
float fy = orig.Y + (va1 + 1 + (i & 1)) * ch; float fy = orig.Y + (va1 + 1 + (i & 1)) * ch;
@ -748,7 +752,7 @@ public class RecastDebugDraw : DebugDraw
int v3 = c.verts[j * 4 + 3]; int v3 = c.verts[j * 4 + 3];
float off = 0; float off = 0;
int colv = color; int colv = color;
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0) if ((v3 & RcRecast.RC_BORDER_VERTEX) != 0)
{ {
colv = DuRGBA(255, 255, 255, a); colv = DuRGBA(255, 255, 255, a);
off = ch * 2; off = ch * 2;
@ -828,7 +832,7 @@ public class RecastDebugDraw : DebugDraw
{ {
fcol[0] = DuRGBA(64, 128, 160, 255); fcol[0] = DuRGBA(64, 128, 160, 255);
} }
else if (s.area == RcConstants.RC_NULL_AREA) else if (s.area == RcRecast.RC_NULL_AREA)
{ {
fcol[0] = DuRGBA(64, 64, 64, 255); fcol[0] = DuRGBA(64, 64, 64, 255);
} }
@ -950,7 +954,7 @@ public class RecastDebugDraw : DebugDraw
{ {
color = DuRGBA(0, 192, 255, 64); color = DuRGBA(0, 192, 255, 64);
} }
else if (area == RcConstants.RC_NULL_AREA) else if (area == RcRecast.RC_NULL_AREA)
{ {
color = DuRGBA(0, 0, 0, 64); color = DuRGBA(0, 0, 0, 64);
} }
@ -962,7 +966,7 @@ public class RecastDebugDraw : DebugDraw
int[] vi = new int[3]; int[] vi = new int[3];
for (int j = 2; j < nvp; ++j) for (int j = 2; j < nvp; ++j)
{ {
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX) if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
{ {
break; break;
} }
@ -993,7 +997,7 @@ public class RecastDebugDraw : DebugDraw
int p = i * nvp * 2; int p = i * nvp * 2;
for (int j = 0; j < nvp; ++j) for (int j = 0; j < nvp; ++j)
{ {
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX) if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
{ {
break; break;
} }
@ -1003,7 +1007,7 @@ public class RecastDebugDraw : DebugDraw
continue; continue;
} }
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.RC_MESH_NULL_IDX) ? 0 : j + 1; int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] }; int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
for (int k = 0; k < 2; ++k) for (int k = 0; k < 2; ++k)
@ -1027,7 +1031,7 @@ public class RecastDebugDraw : DebugDraw
int p = i * nvp * 2; int p = i * nvp * 2;
for (int j = 0; j < nvp; ++j) for (int j = 0; j < nvp; ++j)
{ {
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX) if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
{ {
break; break;
} }
@ -1037,7 +1041,7 @@ public class RecastDebugDraw : DebugDraw
continue; continue;
} }
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.RC_MESH_NULL_IDX) ? 0 : j + 1; int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] }; int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
int col = colb; int col = colb;
@ -1328,7 +1332,7 @@ public class RecastDebugDraw : DebugDraw
for (int side = 0; side < 8; ++side) for (int side = 0; side < 8; ++side)
{ {
int m = DtNavMesh.DT_EXT_LINK | (short)side; int m = DT_EXT_LINK | (short)side;
for (int i = 0; i < tile.data.header.polyCount; ++i) for (int i = 0; i < tile.data.header.polyCount; ++i)
{ {

View File

@ -462,7 +462,7 @@ public class RecastDemo : IRecastDemoChannel
var settings = _sample.GetSettings(); var settings = _sample.GetSettings();
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin(); RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax(); RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh); RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
settingsView.SetVoxels(gw, gh); settingsView.SetVoxels(gw, gh);
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize)); settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize)); settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));

View File

@ -158,7 +158,7 @@ namespace DotRecast.Recast.Toolset.Builder
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize) private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
{ {
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
int tw = (gw + tileSize - 1) / tileSize; int tw = (gw + tileSize - 1) / tileSize;
int th = (gh + tileSize - 1) / tileSize; int th = (gh + tileSize - 1) / tileSize;
int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14); int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14);
@ -167,7 +167,7 @@ namespace DotRecast.Recast.Toolset.Builder
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize) public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
{ {
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
int tw = (gw + tileSize - 1) / tileSize; int tw = (gw + tileSize - 1) / tileSize;
int th = (gh + tileSize - 1) / tileSize; int th = (gh + tileSize - 1) / tileSize;
return new int[] { tw, th }; return new int[] { tw, th };

View File

@ -42,7 +42,7 @@ namespace DotRecast.Recast.Toolset.Tools
// Init cache // Init cache
var bmin = geom.GetMeshBoundsMin(); var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax(); var bmax = geom.GetMeshBoundsMax();
RcCommons.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh); RcRecast.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
int ts = setting.tileSize; int ts = setting.tileSize;
int tw = (gw + ts - 1) / ts; int tw = (gw + ts - 1) / ts;
int th = (gh + ts - 1) / ts; int th = (gh + ts - 1) / ts;

View File

@ -23,7 +23,7 @@ namespace DotRecast.Recast.Toolset.Tools
var bmin = geom.GetMeshBoundsMin(); var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax(); var bmax = geom.GetMeshBoundsMax();
int gw = 0, gh = 0; int gw = 0, gh = 0;
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh); RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
int ts = settings.tileSize; int ts = settings.tileSize;
int tw = (gw + ts - 1) / ts; int tw = (gw + ts - 1) / ts;
@ -47,7 +47,7 @@ namespace DotRecast.Recast.Toolset.Tools
var bmin = geom.GetMeshBoundsMin(); var bmin = geom.GetMeshBoundsMin();
var bmax = geom.GetMeshBoundsMax(); var bmax = geom.GetMeshBoundsMax();
int gw = 0, gh = 0; int gw = 0, gh = 0;
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh); RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
int ts = settings.tileSize; int ts = settings.tileSize;
int tw = (gw + ts - 1) / ts; int tw = (gw + ts - 1) / ts;

View File

@ -25,8 +25,7 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants; using static RcRecast;
using static RcCommons;
public static class RcAreas public static class RcAreas
{ {

View File

@ -30,7 +30,7 @@ using DotRecast.Recast.Geom;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcCommons; using static RcRecast;
using static RcAreas; using static RcAreas;
public class RcBuilder public class RcBuilder

View File

@ -92,7 +92,7 @@ namespace DotRecast.Recast
} }
else else
{ {
RcCommons.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height); RcRecast.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
} }
} }
} }

View File

@ -20,17 +20,14 @@ freely, subject to the following restrictions:
using System; using System;
using System.Linq; using System.Linq;
using DotRecast.Core; using DotRecast.Core;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcCommons; using static RcRecast;
public static class RcCompacts public static class RcCompacts
{ {
private const int MAX_HEIGHT = RcConstants.RC_SPAN_MAX_HEIGHT; private const int MAX_HEIGHT = RC_SPAN_MAX_HEIGHT;
/// @} /// @}
/// @name Compact Heightfield Functions /// @name Compact Heightfield Functions

View File

@ -1,93 +0,0 @@
/*
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
namespace DotRecast.Recast
{
public static class RcConstants
{
/// Represents the null area.
/// When a data element is given this value it is considered to no longer be
/// assigned to a usable area. (E.g. It is un-walkable.)
public const int RC_NULL_AREA = 0;
/// The default area id used to indicate a walkable polygon.
/// This is also the maximum allowed area id, and the only non-null area id
/// recognized by some steps in the build process.
public const int RC_WALKABLE_AREA = 63;
/// The value returned by #rcGetCon if the specified direction is not connected
/// to another span. (Has no neighbor.)
public const int RC_NOT_CONNECTED = 0x3f;
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
public const int RC_SPAN_HEIGHT_BITS = 20;
/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
public const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1;
/// The number of spans allocated per span spool.
/// @see rcSpanPool
public const int RC_SPANS_PER_POOL = 2048;
/// Heighfield border flag.
/// If a heightfield region ID has this bit set, then the region is a border
/// region and its spans are considered unwalkable.
/// (Used during the region and contour build process.)
/// @see rcCompactSpan::reg
public const int RC_BORDER_REG = 0x8000;
/// Polygon touches multiple regions.
/// If a polygon has this region ID it was merged with or created
/// from polygons of different regions during the polymesh
/// build step that removes redundant border vertices.
/// (Used during the polymesh and detail polymesh build processes)
/// @see rcPolyMesh::regs
public const int RC_MULTIPLE_REGS = 0;
// Border vertex flag.
/// If a region ID has this bit set, then the associated element lies on
/// a tile border. If a contour vertex's region ID has this bit set, the
/// vertex will later be removed in order to match the segments and vertices
/// at tile boundaries.
/// (Used during the build process.)
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
public const int RC_BORDER_VERTEX = 0x10000;
/// Area border flag.
/// If a region ID has this bit set, then the associated element lies on
/// the border of an area.
/// (Used during the region and contour build process.)
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
public const int RC_AREA_BORDER = 0x20000;
/// Applied to the region id field of contour vertices in order to extract the region id.
/// The region id field of a vertex may have several flags applied to it. So the
/// fields value can't be used directly.
/// @see rcContour::verts, rcContour::rverts
public const int RC_CONTOUR_REG_MASK = 0xffff;
/// A value which indicates an invalid index within a mesh.
/// @note This does not necessarily indicate an error.
/// @see rcPolyMesh::polys
public const int RC_MESH_NULL_IDX = 0xffff;
public const int RC_LOG_WARNING = 1;
}
}

View File

@ -24,8 +24,8 @@ using DotRecast.Core;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants;
using static RcCommons; using static RcRecast;
public static class RcContours public static class RcContours
{ {

View File

@ -20,11 +20,11 @@ freely, subject to the following restrictions:
using System; using System;
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcRecast;
public static class RcFilledVolumeRasterization public static class RcFilledVolumeRasterization
{ {
private const float EPSILON = 0.00001f; private const float EPSILON = 0.00001f;

View File

@ -23,8 +23,8 @@ using DotRecast.Core;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants;
using static RcCommons; using static RcRecast;
public static class RcFilters public static class RcFilters
{ {

View File

@ -25,12 +25,12 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants;
using static RcCommons; using static RcRecast;
public static class RcLayers public static class RcLayers
{ {
const int RC_MAX_LAYERS = RcConstants.RC_NOT_CONNECTED; const int RC_MAX_LAYERS = RcRecast.RC_NOT_CONNECTED;
const int RC_MAX_NEIS = 16; const int RC_MAX_NEIS = 16;

View File

@ -22,11 +22,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcCommons; using static RcRecast;
public static class RcMeshDetails public static class RcMeshDetails
@ -35,7 +35,7 @@ namespace DotRecast.Recast
public const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts). public const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
public const int MAX_VERTS_PER_EDGE = 32; public const int MAX_VERTS_PER_EDGE = 32;
public const int RC_UNSET_HEIGHT = RcConstants.RC_SPAN_MAX_HEIGHT; public const int RC_UNSET_HEIGHT = RcRecast.RC_SPAN_MAX_HEIGHT;
public const int EV_UNDEF = -1; public const int EV_UNDEF = -1;
public const int EV_HULL = -2; public const int EV_HULL = -2;

View File

@ -24,7 +24,7 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants; using static RcRecast;
public static class RcMeshs public static class RcMeshs
{ {

View File

@ -21,10 +21,12 @@ freely, subject to the following restrictions:
using System; using System;
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using static DotRecast.Recast.RcConstants;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcRecast;
public static class RcRasterizations public static class RcRasterizations
{ {
/// Check whether two bounding boxes overlap /// Check whether two bounding boxes overlap

View File

@ -24,10 +24,76 @@ using DotRecast.Core.Numerics;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants; public static class RcRecast
public static class RcCommons
{ {
/// Represents the null area.
/// When a data element is given this value it is considered to no longer be
/// assigned to a usable area. (E.g. It is un-walkable.)
public const int RC_NULL_AREA = 0;
/// The default area id used to indicate a walkable polygon.
/// This is also the maximum allowed area id, and the only non-null area id
/// recognized by some steps in the build process.
public const int RC_WALKABLE_AREA = 63;
/// The value returned by #rcGetCon if the specified direction is not connected
/// to another span. (Has no neighbor.)
public const int RC_NOT_CONNECTED = 0x3f;
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
public const int RC_SPAN_HEIGHT_BITS = 20;
/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
public const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1;
/// The number of spans allocated per span spool.
/// @see rcSpanPool
public const int RC_SPANS_PER_POOL = 2048;
/// Heighfield border flag.
/// If a heightfield region ID has this bit set, then the region is a border
/// region and its spans are considered unwalkable.
/// (Used during the region and contour build process.)
/// @see rcCompactSpan::reg
public const int RC_BORDER_REG = 0x8000;
/// Polygon touches multiple regions.
/// If a polygon has this region ID it was merged with or created
/// from polygons of different regions during the polymesh
/// build step that removes redundant border vertices.
/// (Used during the polymesh and detail polymesh build processes)
/// @see rcPolyMesh::regs
public const int RC_MULTIPLE_REGS = 0;
// Border vertex flag.
/// If a region ID has this bit set, then the associated element lies on
/// a tile border. If a contour vertex's region ID has this bit set, the
/// vertex will later be removed in order to match the segments and vertices
/// at tile boundaries.
/// (Used during the build process.)
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
public const int RC_BORDER_VERTEX = 0x10000;
/// Area border flag.
/// If a region ID has this bit set, then the associated element lies on
/// the border of an area.
/// (Used during the region and contour build process.)
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
public const int RC_AREA_BORDER = 0x20000;
/// Applied to the region id field of contour vertices in order to extract the region id.
/// The region id field of a vertex may have several flags applied to it. So the
/// fields value can't be used directly.
/// @see rcContour::verts, rcContour::rverts
public const int RC_CONTOUR_REG_MASK = 0xffff;
/// A value which indicates an invalid index within a mesh.
/// @note This does not necessarily indicate an error.
/// @see rcPolyMesh::polys
public const int RC_MESH_NULL_IDX = 0xffff;
public const int RC_LOG_WARNING = 1;
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, }; private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 }; private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 }; private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 };

View File

@ -25,8 +25,8 @@ using DotRecast.Core;
namespace DotRecast.Recast namespace DotRecast.Recast
{ {
using static RcConstants;
using static RcCommons; using static RcRecast;
public static class RcRegions public static class RcRegions
{ {

View File

@ -28,7 +28,7 @@ namespace DotRecast.Recast
public RcSpanPool() public RcSpanPool()
{ {
items = new RcSpan[RcConstants.RC_SPANS_PER_POOL]; items = new RcSpan[RcRecast.RC_SPANS_PER_POOL];
for (int i = 0; i < items.Length; ++i) for (int i = 0; i < items.Length; ++i)
{ {
items[i] = new RcSpan(); items[i] = new RcSpan();

View File

@ -55,7 +55,7 @@ namespace DotRecast.Recast
{ {
int[] tris = node.tris; int[] tris = node.tris;
int ntris = tris.Length / 3; int ntris = tris.Length / 3;
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb); RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
} }
} }
@ -63,7 +63,7 @@ namespace DotRecast.Recast
{ {
int[] tris = geom.GetTris(); int[] tris = geom.GetTris();
int ntris = tris.Length / 3; int ntris = tris.Length / 3;
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb); RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
} }
} }

View File

@ -70,7 +70,7 @@ public class MeshSetReaderWriterTest
RcVec3f bmin = geom.GetMeshBoundsMin(); RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax(); RcVec3f bmax = geom.GetMeshBoundsMax();
RcCommons.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th); RcRecast.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
for (int y = 0; y < th; ++y) for (int y = 0; y < th; ++y)
{ {
for (int x = 0; x < tw; ++x) for (int x = 0; x < tw; ++x)

View File

@ -21,6 +21,7 @@ using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
using static DtDetour;
public class NavMeshBuilderTest public class NavMeshBuilderTest
{ {
@ -57,7 +58,7 @@ public class NavMeshBuilderTest
Assert.That(nmd.offMeshCons[0].rad, Is.EqualTo(0.1f)); Assert.That(nmd.offMeshCons[0].rad, Is.EqualTo(0.1f));
Assert.That(nmd.offMeshCons[0].poly, Is.EqualTo(118)); Assert.That(nmd.offMeshCons[0].poly, Is.EqualTo(118));
Assert.That(nmd.offMeshCons[0].flags, Is.EqualTo(DtNavMesh.DT_OFFMESH_CON_BIDIR)); Assert.That(nmd.offMeshCons[0].flags, Is.EqualTo(DT_OFFMESH_CON_BIDIR));
Assert.That(nmd.offMeshCons[0].side, Is.EqualTo(0xFF)); Assert.That(nmd.offMeshCons[0].side, Is.EqualTo(0xFF));
Assert.That(nmd.offMeshCons[0].userId, Is.EqualTo(0x4567)); Assert.That(nmd.offMeshCons[0].userId, Is.EqualTo(0x4567));
Assert.That(nmd.polys[118].vertCount, Is.EqualTo(2)); Assert.That(nmd.polys[118].vertCount, Is.EqualTo(2));

View File

@ -44,7 +44,7 @@ public class AbstractTileCacheTest
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility) public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
{ {
DtTileCacheParams option = new DtTileCacheParams(); DtTileCacheParams option = new DtTileCacheParams();
RcCommons.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th); RcRecast.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
option.ch = m_cellHeight; option.ch = m_cellHeight;
option.cs = m_cellSize; option.cs = m_cellSize;
option.orig = geom.GetMeshBoundsMin(); option.orig = geom.GetMeshBoundsMin();

View File

@ -73,7 +73,7 @@ public class TestTileLayerBuilder : DtTileCacheLayerBuilder
RcVec3f bmin = geom.GetMeshBoundsMin(); RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax(); RcVec3f bmax = geom.GetMeshBoundsMax();
RcCommons.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th); RcRecast.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
} }
public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads) public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads)

View File

@ -24,7 +24,7 @@ using NUnit.Framework;
namespace DotRecast.Recast.Test; namespace DotRecast.Recast.Test;
using static RcConstants;
public class RecastLayersTest public class RecastLayersTest

View File

@ -25,10 +25,9 @@ using NUnit.Framework;
namespace DotRecast.Recast.Test; namespace DotRecast.Recast.Test;
using static RcConstants; using static RcRecast;
using static RcAreas; using static RcAreas;
public class RecastSoloMeshTest public class RecastSoloMeshTest
{ {
private const float m_cellSize = 0.3f; private const float m_cellSize = 0.3f;
@ -139,7 +138,7 @@ public class RecastSoloMeshTest
// Find triangles which are walkable based on their slope and rasterize them. // Find triangles which are walkable based on their slope and rasterize them.
// If your input data is multiple meshes, you can transform them here, calculate // If your input data is multiple meshes, you can transform them here, calculate
// the are type for each of the meshes and rasterize them. // the are type for each of the meshes and rasterize them.
int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcRecast.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(m_ctx, verts, tris, m_triareas, ntris, m_solid, cfg.WalkableClimb); RcRasterizations.RasterizeTriangles(m_ctx, verts, tris, m_triareas, ntris, m_solid, cfg.WalkableClimb);
} }

View File

@ -21,8 +21,7 @@ using DotRecast.Core;
namespace DotRecast.Recast.Test; namespace DotRecast.Recast.Test;
using static RcConstants; using static RcRecast;
public class RecastTest public class RecastTest
{ {
@ -39,18 +38,18 @@ public class RecastTest
RcContext ctx = new RcContext(); RcContext ctx = new RcContext();
{ {
int[] areas = { 42 }; int[] areas = { 42 };
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas); RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA"); Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
} }
{ {
int[] areas = { 42 }; int[] areas = { 42 };
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas); RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's"); Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
} }
{ {
int[] areas = { 42 }; int[] areas = { 42 };
walkableSlopeAngle = 0; walkableSlopeAngle = 0;
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas); RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable."); Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
} }
} }