draw temp obstacles

This commit is contained in:
ikpil 2023-08-22 23:48:04 +09:00
parent 1c2d211075
commit 1cb03e2c5f
5 changed files with 110 additions and 65 deletions

View File

@ -20,7 +20,7 @@ freely, subject to the following restrictions:
namespace DotRecast.Detour.TileCache namespace DotRecast.Detour.TileCache
{ {
public enum ObstacleState public enum DtObstacleState
{ {
DT_OBSTACLE_EMPTY, DT_OBSTACLE_EMPTY,
DT_OBSTACLE_PROCESSING, DT_OBSTACLE_PROCESSING,

View File

@ -27,27 +27,15 @@ namespace DotRecast.Detour.TileCache
{ {
public class DtTileCache public class DtTileCache
{ {
private int m_tileLutSize; private int m_tileLutSize; // < Tile hash lookup size (must be pot).
private int m_tileLutMask; // < Tile hash lookup mask.
private readonly DtCompressedTile[] m_posLookup; // < Tile hash lookup.
/// < Tile hash lookup size (must be pot). private DtCompressedTile m_nextFreeTile; // < Freelist of tiles.
private int m_tileLutMask; private readonly DtCompressedTile[] m_tiles; // < List of tiles. // TODO: (PP) replace with list
/// < Tile hash lookup mask. private readonly int m_saltBits; // < Number of salt bits in the tile ID.
private readonly DtCompressedTile[] m_posLookup; private readonly int m_tileBits; // < Number of tile bits in the tile ID.
/// < Tile hash lookup.
private DtCompressedTile m_nextFreeTile;
/// < Freelist of tiles.
private readonly DtCompressedTile[] m_tiles;
/// < List of tiles. // TODO: (PP) replace with list
private readonly int m_saltBits;
/// < Number of salt bits in the tile ID.
private readonly int m_tileBits;
/// < Number of tile bits in the tile ID.
private readonly DtNavMesh m_navmesh; private readonly DtNavMesh m_navmesh;
private readonly DtTileCacheParams m_params; private readonly DtTileCacheParams m_params;
@ -65,6 +53,38 @@ namespace DotRecast.Detour.TileCache
private readonly DtTileCacheBuilder builder = new DtTileCacheBuilder(); private readonly DtTileCacheBuilder builder = new DtTileCacheBuilder();
private readonly DtTileCacheLayerHeaderReader tileReader = new DtTileCacheLayerHeaderReader(); private readonly DtTileCacheLayerHeaderReader tileReader = new DtTileCacheLayerHeaderReader();
public DtTileCache(DtTileCacheParams option, DtTileCacheStorageParams storageParams, DtNavMesh navmesh, IRcCompressor tcomp, IDtTileCacheMeshProcess tmprocs)
{
m_params = option;
m_storageParams = storageParams;
m_navmesh = navmesh;
m_tcomp = tcomp;
m_tmproc = tmprocs;
m_tileLutSize = DtUtils.NextPow2(m_params.maxTiles / 4);
if (m_tileLutSize == 0)
{
m_tileLutSize = 1;
}
m_tileLutMask = m_tileLutSize - 1;
m_tiles = new DtCompressedTile[m_params.maxTiles];
m_posLookup = new DtCompressedTile[m_tileLutSize];
for (int i = m_params.maxTiles - 1; i >= 0; --i)
{
m_tiles[i] = new DtCompressedTile(i);
m_tiles[i].next = m_nextFreeTile;
m_nextFreeTile = m_tiles[i];
}
m_tileBits = DtUtils.Ilog2(DtUtils.NextPow2(m_params.maxTiles));
m_saltBits = Math.Min(31, 32 - m_tileBits);
if (m_saltBits < 10)
{
throw new Exception("Too few salt bits: " + m_saltBits);
}
}
private bool Contains(List<long> a, long v) private bool Contains(List<long> a, long v)
{ {
return a.Contains(v); return a.Contains(v);
@ -110,37 +130,6 @@ namespace DotRecast.Detour.TileCache
return (int)(refs & tileMask); return (int)(refs & tileMask);
} }
public DtTileCache(DtTileCacheParams option, DtTileCacheStorageParams storageParams, DtNavMesh navmesh, IRcCompressor tcomp, IDtTileCacheMeshProcess tmprocs)
{
m_params = option;
m_storageParams = storageParams;
m_navmesh = navmesh;
m_tcomp = tcomp;
m_tmproc = tmprocs;
m_tileLutSize = DtUtils.NextPow2(m_params.maxTiles / 4);
if (m_tileLutSize == 0)
{
m_tileLutSize = 1;
}
m_tileLutMask = m_tileLutSize - 1;
m_tiles = new DtCompressedTile[m_params.maxTiles];
m_posLookup = new DtCompressedTile[m_tileLutSize];
for (int i = m_params.maxTiles - 1; i >= 0; --i)
{
m_tiles[i] = new DtCompressedTile(i);
m_tiles[i].next = m_nextFreeTile;
m_nextFreeTile = m_tiles[i];
}
m_tileBits = DtUtils.Ilog2(DtUtils.NextPow2(m_params.maxTiles));
m_saltBits = Math.Min(31, 32 - m_tileBits);
if (m_saltBits < 10)
{
throw new Exception("Too few salt bits: " + m_saltBits);
}
}
public DtCompressedTile GetTileByRef(long refs) public DtCompressedTile GetTileByRef(long refs)
{ {
@ -429,13 +418,28 @@ namespace DotRecast.Detour.TileCache
m_nextFreeObstacle = o.next; m_nextFreeObstacle = o.next;
} }
o.state = ObstacleState.DT_OBSTACLE_PROCESSING; o.state = DtObstacleState.DT_OBSTACLE_PROCESSING;
o.touched.Clear(); o.touched.Clear();
o.pending.Clear(); o.pending.Clear();
o.next = null; o.next = null;
return o; return o;
} }
public int GetObstacleCount()
{
return m_obstacles.Count;
}
public DtTileCacheObstacle GetObstacle(int i)
{
if (0 > i || i >= m_obstacles.Count)
{
return null;
}
return m_obstacles[i];
}
private List<long> QueryTiles(RcVec3f bmin, RcVec3f bmax) private List<long> QueryTiles(RcVec3f bmin, RcVec3f bmax)
{ {
List<long> results = new List<long>(); List<long> results = new List<long>();
@ -516,7 +520,7 @@ namespace DotRecast.Detour.TileCache
else if (req.action == ObstacleRequestAction.REQUEST_REMOVE) else if (req.action == ObstacleRequestAction.REQUEST_REMOVE)
{ {
// Prepare to remove obstacle. // Prepare to remove obstacle.
ob.state = ObstacleState.DT_OBSTACLE_REMOVING; ob.state = DtObstacleState.DT_OBSTACLE_REMOVING;
// Add tiles to update list. // Add tiles to update list.
ob.pending.Clear(); ob.pending.Clear();
foreach (long j in ob.touched) foreach (long j in ob.touched)
@ -546,8 +550,8 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < m_obstacles.Count; ++i) for (int i = 0; i < m_obstacles.Count; ++i)
{ {
DtTileCacheObstacle ob = m_obstacles[i]; DtTileCacheObstacle ob = m_obstacles[i];
if (ob.state == ObstacleState.DT_OBSTACLE_PROCESSING if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSING
|| ob.state == ObstacleState.DT_OBSTACLE_REMOVING) || ob.state == DtObstacleState.DT_OBSTACLE_REMOVING)
{ {
// Remove handled tile from pending list. // Remove handled tile from pending list.
ob.pending.Remove(refs); ob.pending.Remove(refs);
@ -555,13 +559,13 @@ namespace DotRecast.Detour.TileCache
// If all pending tiles processed, change state. // If all pending tiles processed, change state.
if (0 == ob.pending.Count) if (0 == ob.pending.Count)
{ {
if (ob.state == ObstacleState.DT_OBSTACLE_PROCESSING) if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSING)
{ {
ob.state = ObstacleState.DT_OBSTACLE_PROCESSED; ob.state = DtObstacleState.DT_OBSTACLE_PROCESSED;
} }
else if (ob.state == ObstacleState.DT_OBSTACLE_REMOVING) else if (ob.state == DtObstacleState.DT_OBSTACLE_REMOVING)
{ {
ob.state = ObstacleState.DT_OBSTACLE_EMPTY; ob.state = DtObstacleState.DT_OBSTACLE_EMPTY;
// Update salt, salt should never be zero. // Update salt, salt should never be zero.
ob.salt = (ob.salt + 1) & ((1 << 16) - 1); ob.salt = (ob.salt + 1) & ((1 << 16) - 1);
if (ob.salt == 0) if (ob.salt == 0)
@ -605,7 +609,7 @@ namespace DotRecast.Detour.TileCache
for (int i = 0; i < m_obstacles.Count; ++i) for (int i = 0; i < m_obstacles.Count; ++i)
{ {
DtTileCacheObstacle ob = m_obstacles[i]; DtTileCacheObstacle ob = m_obstacles[i];
if (ob.state == ObstacleState.DT_OBSTACLE_EMPTY || ob.state == ObstacleState.DT_OBSTACLE_REMOVING) if (ob.state == DtObstacleState.DT_OBSTACLE_EMPTY || ob.state == DtObstacleState.DT_OBSTACLE_REMOVING)
{ {
continue; continue;
} }
@ -690,7 +694,7 @@ namespace DotRecast.Detour.TileCache
bmax.z = header.bmin.z + (header.maxy + 1) * cs; bmax.z = header.bmin.z + (header.maxy + 1) * cs;
} }
void GetObstacleBounds(DtTileCacheObstacle ob, ref RcVec3f bmin, ref RcVec3f bmax) public void GetObstacleBounds(DtTileCacheObstacle ob, ref RcVec3f bmin, ref RcVec3f bmax)
{ {
if (ob.type == TileCacheObstacleType.CYLINDER) if (ob.type == TileCacheObstacleType.CYLINDER)
{ {

View File

@ -37,7 +37,7 @@ namespace DotRecast.Detour.TileCache
public List<long> touched = new List<long>(); public List<long> touched = new List<long>();
public readonly List<long> pending = new List<long>(); public readonly List<long> pending = new List<long>();
public int salt; public int salt;
public ObstacleState state = ObstacleState.DT_OBSTACLE_EMPTY; public DtObstacleState state = DtObstacleState.DT_OBSTACLE_EMPTY;
public DtTileCacheObstacle next; public DtTileCacheObstacle next;
public DtTileCacheObstacle(int index) public DtTileCacheObstacle(int index)

View File

@ -1,4 +1,5 @@
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Detour.TileCache;
using DotRecast.Detour.TileCache.Io.Compress; using DotRecast.Detour.TileCache.Io.Compress;
using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset;
@ -75,10 +76,45 @@ public class ObstacleSampleTool : ISampleTool
public void HandleRender(NavMeshRenderer renderer) public void HandleRender(NavMeshRenderer renderer)
{ {
DrawObstacles(renderer.GetDebugDraw());
}
private void DrawObstacles(RecastDebugDraw dd)
{
var tc = _tool.GetTileCache();
if (null == tc)
return;
// Draw obstacles
for (int i = 0; i < tc.GetObstacleCount(); ++i)
{
var ob = tc.GetObstacle(i);
if (ob.state == DtObstacleState.DT_OBSTACLE_EMPTY)
continue;
RcVec3f bmin = RcVec3f.Zero;
RcVec3f bmax = RcVec3f.Zero;
tc.GetObstacleBounds(ob, ref bmin, ref bmax);
int col = 0;
if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSING)
col = DebugDraw.DuRGBA(255, 255, 0, 128);
else if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSED)
col = DebugDraw.DuRGBA(255, 192, 0, 192);
else if (ob.state == DtObstacleState.DT_OBSTACLE_REMOVING)
col = DebugDraw.DuRGBA(220, 0, 0, 128);
dd.DebugDrawCylinder(bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2], col);
dd.DebugDrawCylinderWire(bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2], DebugDraw.DuDarkenCol(col), 2);
}
} }
public void HandleUpdate(float dt) public void HandleUpdate(float dt)
{ {
var tc = _tool.GetTileCache();
if (null != tc)
tc.Update();
} }
public void HandleClickRay(RcVec3f start, RcVec3f direction, bool shift) public void HandleClickRay(RcVec3f start, RcVec3f direction, bool shift)

View File

@ -44,13 +44,18 @@ namespace DotRecast.Recast.Toolset.Tools
//_tc.RemoveObstacle(refs); //_tc.RemoveObstacle(refs);
} }
public void AddTempObstacle(RcVec3f p) public long AddTempObstacle(RcVec3f p)
{ {
if (null == _tc) if (null == _tc)
return; return 0;
p.y -= 0.5f; p.y -= 0.5f;
_tc.AddObstacle(p, 1.0f, 2.0f); return _tc.AddObstacle(p, 1.0f, 2.0f);
}
public DtTileCache GetTileCache()
{
return _tc;
} }
public DtTileCache CreateTileCache(IInputGeomProvider geom, RcNavMeshBuildSettings setting, RcByteOrder order, bool cCompatibility) public DtTileCache CreateTileCache(IInputGeomProvider geom, RcNavMeshBuildSettings setting, RcByteOrder order, bool cCompatibility)