From 1cb03e2c5f64c2100e042b5cf785581b2eaa444b Mon Sep 17 00:00:00 2001 From: ikpil Date: Tue, 22 Aug 2023 23:48:04 +0900 Subject: [PATCH] draw temp obstacles --- .../{ObstacleState.cs => DtObstacleState.cs} | 2 +- src/DotRecast.Detour.TileCache/DtTileCache.cs | 124 +++++++++--------- .../DtTileCacheObstacle.cs | 2 +- .../Tools/ObstacleSampleTool.cs | 36 +++++ .../Tools/RcObstacleTool.cs | 11 +- 5 files changed, 110 insertions(+), 65 deletions(-) rename src/DotRecast.Detour.TileCache/{ObstacleState.cs => DtObstacleState.cs} (97%) diff --git a/src/DotRecast.Detour.TileCache/ObstacleState.cs b/src/DotRecast.Detour.TileCache/DtObstacleState.cs similarity index 97% rename from src/DotRecast.Detour.TileCache/ObstacleState.cs rename to src/DotRecast.Detour.TileCache/DtObstacleState.cs index 476590f..a28296b 100644 --- a/src/DotRecast.Detour.TileCache/ObstacleState.cs +++ b/src/DotRecast.Detour.TileCache/DtObstacleState.cs @@ -20,7 +20,7 @@ freely, subject to the following restrictions: namespace DotRecast.Detour.TileCache { - public enum ObstacleState + public enum DtObstacleState { DT_OBSTACLE_EMPTY, DT_OBSTACLE_PROCESSING, diff --git a/src/DotRecast.Detour.TileCache/DtTileCache.cs b/src/DotRecast.Detour.TileCache/DtTileCache.cs index d3203d7..26acff8 100644 --- a/src/DotRecast.Detour.TileCache/DtTileCache.cs +++ b/src/DotRecast.Detour.TileCache/DtTileCache.cs @@ -27,27 +27,15 @@ namespace DotRecast.Detour.TileCache { 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 int m_tileLutMask; + private DtCompressedTile m_nextFreeTile; // < Freelist of tiles. + private readonly DtCompressedTile[] m_tiles; // < List of tiles. // TODO: (PP) replace with list - /// < Tile hash lookup mask. - private readonly DtCompressedTile[] m_posLookup; - - /// < 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 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 DtTileCacheParams m_params; @@ -65,6 +53,38 @@ namespace DotRecast.Detour.TileCache private readonly DtTileCacheBuilder builder = new DtTileCacheBuilder(); 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 a, long v) { return a.Contains(v); @@ -110,37 +130,6 @@ namespace DotRecast.Detour.TileCache 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) { @@ -429,13 +418,28 @@ namespace DotRecast.Detour.TileCache m_nextFreeObstacle = o.next; } - o.state = ObstacleState.DT_OBSTACLE_PROCESSING; + o.state = DtObstacleState.DT_OBSTACLE_PROCESSING; o.touched.Clear(); o.pending.Clear(); o.next = null; 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 QueryTiles(RcVec3f bmin, RcVec3f bmax) { List results = new List(); @@ -516,7 +520,7 @@ namespace DotRecast.Detour.TileCache else if (req.action == ObstacleRequestAction.REQUEST_REMOVE) { // Prepare to remove obstacle. - ob.state = ObstacleState.DT_OBSTACLE_REMOVING; + ob.state = DtObstacleState.DT_OBSTACLE_REMOVING; // Add tiles to update list. ob.pending.Clear(); foreach (long j in ob.touched) @@ -546,8 +550,8 @@ namespace DotRecast.Detour.TileCache for (int i = 0; i < m_obstacles.Count; ++i) { DtTileCacheObstacle ob = m_obstacles[i]; - if (ob.state == ObstacleState.DT_OBSTACLE_PROCESSING - || ob.state == ObstacleState.DT_OBSTACLE_REMOVING) + if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSING + || ob.state == DtObstacleState.DT_OBSTACLE_REMOVING) { // Remove handled tile from pending list. ob.pending.Remove(refs); @@ -555,13 +559,13 @@ namespace DotRecast.Detour.TileCache // If all pending tiles processed, change state. 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. ob.salt = (ob.salt + 1) & ((1 << 16) - 1); if (ob.salt == 0) @@ -605,7 +609,7 @@ namespace DotRecast.Detour.TileCache for (int i = 0; i < m_obstacles.Count; ++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; } @@ -690,7 +694,7 @@ namespace DotRecast.Detour.TileCache 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) { diff --git a/src/DotRecast.Detour.TileCache/DtTileCacheObstacle.cs b/src/DotRecast.Detour.TileCache/DtTileCacheObstacle.cs index def2e0d..dca70e9 100644 --- a/src/DotRecast.Detour.TileCache/DtTileCacheObstacle.cs +++ b/src/DotRecast.Detour.TileCache/DtTileCacheObstacle.cs @@ -37,7 +37,7 @@ namespace DotRecast.Detour.TileCache public List touched = new List(); public readonly List pending = new List(); public int salt; - public ObstacleState state = ObstacleState.DT_OBSTACLE_EMPTY; + public DtObstacleState state = DtObstacleState.DT_OBSTACLE_EMPTY; public DtTileCacheObstacle next; public DtTileCacheObstacle(int index) diff --git a/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs b/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs index e5edbec..6a94ad3 100644 --- a/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs @@ -1,4 +1,5 @@ using DotRecast.Core; +using DotRecast.Detour.TileCache; using DotRecast.Detour.TileCache.Io.Compress; using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Toolset; @@ -75,10 +76,45 @@ public class ObstacleSampleTool : ISampleTool 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) { + var tc = _tool.GetTileCache(); + if (null != tc) + tc.Update(); } public void HandleClickRay(RcVec3f start, RcVec3f direction, bool shift) diff --git a/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs index 591328f..4e027a7 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs @@ -44,13 +44,18 @@ namespace DotRecast.Recast.Toolset.Tools //_tc.RemoveObstacle(refs); } - public void AddTempObstacle(RcVec3f p) + public long AddTempObstacle(RcVec3f p) { if (null == _tc) - return; + return 0; 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)