added DtNavMesh.Init()

This commit is contained in:
ikpil 2024-05-12 22:05:19 +09:00
parent 40306a5302
commit 47be4eca70
18 changed files with 108 additions and 69 deletions

View File

@ -8,9 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Added RcSpans UnitTest
- Added DtNavMesh.Init() interface
### Fixed
### Changed
- RcRecast, DtDetour
### Removed
### Special Thanks
- [@Doprez](https://github.com/Doprez)

View File

@ -224,9 +224,13 @@ namespace DotRecast.Detour.Dynamic
{
if (_dirty)
{
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
DtNavMesh navMesh = new DtNavMesh();
navMesh.Init(navMeshParams, MAX_VERTS_PER_POLY);
foreach (var t in _tiles.Values)
{
t.AddTo(navMesh);
}
_navMesh = navMesh;
_dirty = false;

View File

@ -168,12 +168,12 @@ namespace DotRecast.Detour.Dynamic
option.buildBvTree = true;
option.offMeshConCount = 0;
option.offMeshConVerts = new float[0];
option.offMeshConRad = new float[0];
option.offMeshConDir = new int[0];
option.offMeshConAreas = new int[0];
option.offMeshConFlags = new int[0];
option.offMeshConUserID = new int[0];
option.offMeshConVerts = Array.Empty<float>();
option.offMeshConRad = Array.Empty<float>();
option.offMeshConDir = Array.Empty<int>();
option.offMeshConAreas = Array.Empty<int>();
option.offMeshConFlags = Array.Empty<int>();
option.offMeshConUserID = Array.Empty<int>();
return option;
}
@ -181,7 +181,7 @@ namespace DotRecast.Detour.Dynamic
{
if (meshData != null)
{
id = navMesh.AddTile(meshData, 0, 0);
navMesh.AddTile(meshData, 0, 0, out var id);
}
else
{

View File

@ -1,6 +1,5 @@
using DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
namespace DotRecast.Detour.Extras.Jumplink
@ -36,7 +35,14 @@ namespace DotRecast.Detour.Extras.Jumplink
option.cs = r.Mesh.cs;
option.ch = r.Mesh.ch;
option.buildBvTree = true;
return new DtNavMeshQuery(new DtNavMesh(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
var mesh = new DtNavMesh();
var status = mesh.Init(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0);
if (status.Failed())
{
return null;
}
return new DtNavMeshQuery(mesh);
}

View File

@ -78,7 +78,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
int nodeCount = buffer.GetInt();
DtPoly[] nodes = new DtPoly[nodeCount];
DtPolyDetail[] detailNodes = new DtPolyDetail[nodeCount];
float[] detailVerts = new float[0];
float[] detailVerts = Array.Empty<float>();
int[] detailTris = new int[4 * nodeCount];
int vertMask = GetVertMask(vertsCount);
float ymin = float.PositiveInfinity;

View File

@ -65,10 +65,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
option.orig.X = -0.5f * graphMeta.forcedBoundsSize.x + graphMeta.forcedBoundsCenter.x;
option.orig.Y = -0.5f * graphMeta.forcedBoundsSize.y + graphMeta.forcedBoundsCenter.y;
option.orig.Z = -0.5f * graphMeta.forcedBoundsSize.z + graphMeta.forcedBoundsCenter.z;
DtNavMesh mesh = new DtNavMesh(option, 3);
DtNavMesh mesh = new DtNavMesh();
mesh.Init(option, 3);
foreach (DtMeshData t in graphMeshData.tiles)
{
mesh.AddTile(t, 0, 0);
mesh.AddTile(t, 0, 0, out _);
}
meshes[graphIndex] = mesh;

View File

@ -672,7 +672,7 @@ namespace DotRecast.Detour.TileCache
// Add new tile, or leave the location empty. if (navData) { // Let the
if (meshData != null)
{
m_navmesh.AddTile(meshData, 0, 0);
m_navmesh.AddTile(meshData, 0, 0, out var result);
}
}

View File

@ -69,7 +69,8 @@ namespace DotRecast.Detour.TileCache.Io
header.numTiles = bb.GetInt();
header.meshParams = paramReader.Read(bb);
header.cacheParams = ReadCacheParams(bb, cCompatibility);
DtNavMesh mesh = new DtNavMesh(header.meshParams, maxVertPerPoly);
DtNavMesh mesh = new DtNavMesh();
mesh.Init(header.meshParams, maxVertPerPoly);
IRcCompressor comp = _compFactory.Create(cCompatibility ? 0 : 1);
DtTileCacheStorageParams storageParams = new DtTileCacheStorageParams(bb.Order(), cCompatibility);
DtTileCache tc = new DtTileCache(header.cacheParams, storageParams, mesh, comp, meshProcessor);

View File

@ -29,29 +29,23 @@ namespace DotRecast.Detour
public class DtNavMesh
{
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 float m_tileWidth; // < 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_tileLutMask; // < Tile hash lookup mask.
private DtNavMeshParams m_params; //< Current initialization params. TODO: do not store this info twice.
private RcVec3f m_orig; // < Origin of the tile (0,0)
private float m_tileWidth; // < Dimensions of each tile.
private float m_tileHeight; // < Dimensions of each tile.
private int m_maxTiles; // < Max number of tiles.
private int m_tileLutMask; // < Tile hash lookup mask.
private readonly Dictionary<int, List<DtMeshTile>> m_posLookup; //< Tile hash lookup.
private readonly LinkedList<DtMeshTile> m_nextFree; //< Freelist of tiles.
private readonly DtMeshTile[] m_tiles; //< List of tiles.
private Dictionary<int, List<DtMeshTile>> m_posLookup; //< Tile hash lookup.
private LinkedList<DtMeshTile> m_nextFree; //< Freelist of tiles.
private DtMeshTile[] m_tiles; //< List of tiles.
/** The maximum number of vertices per navigation polygon. */
private readonly int m_maxVertPerPoly;
private int m_maxVertPerPoly;
private int m_tileCount;
public DtNavMesh(DtMeshData data, int maxVertsPerPoly, int flags)
: this(GetNavMeshParams(data), maxVertsPerPoly)
{
AddTile(data, flags, 0);
}
public DtNavMesh(DtNavMeshParams option, int maxVertsPerPoly)
public DtStatus Init(DtNavMeshParams option, int maxVertsPerPoly)
{
m_params = option;
m_orig = option.orig;
@ -70,6 +64,18 @@ namespace DotRecast.Detour
m_tiles[i].salt = 1;
m_nextFree.AddLast(m_tiles[i]);
}
return DtStatus.DT_SUCCESS;
}
public DtStatus Init(DtMeshData data, int maxVertsPerPoly, int flags)
{
var option = GetNavMeshParams(data);
DtStatus status = Init(option, maxVertsPerPoly);
if (status.Failed())
return status;
return AddTile(data, flags, 0, out _);
}
private static DtNavMeshParams GetNavMeshParams(DtMeshData data)
@ -328,30 +334,20 @@ namespace DotRecast.Detour
}
}
public long UpdateTile(DtMeshData data, int flags)
public DtStatus UpdateTile(DtMeshData data, int flags)
{
long refs = GetTileRefAt(data.header.x, data.header.y, data.header.layer);
refs = RemoveTile(refs);
return AddTile(data, flags, refs);
return AddTile(data, flags, refs, out _);
}
/// Adds a tile to the navigation mesh.
/// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
/// @param[in] dataSize Data size of the new tile mesh.
/// @param[in] flags Tile flags. (See: #dtTileFlags)
/// @param[in] lastRef The desired reference for the tile. (When reloading a
/// tile.) [opt] [Default: 0]
/// @param[out] result The tile reference. (If the tile was succesfully
/// added.) [opt]
/// @return The status flags for the operation.
/// @par
///
/// The add operation will fail if the data is in the wrong format, the
/// allocated tile
/// The add operation will fail if the data is in the wrong format, the allocated tile
/// space is full, or there is a tile already at the specified reference.
///
/// The lastRef parameter is used to restore a tile with the same tile
/// reference it had previously used. In this case the #long's for the
/// reference it had previously used. In this case the #dtPolyRef's for the
/// tile will be restored to the same values they were before the tile was
/// removed.
///
@ -361,15 +357,24 @@ namespace DotRecast.Detour
/// removed from this nav mesh.
///
/// @see dtCreateNavMeshData, #removeTile
public long AddTile(DtMeshData data, int flags, long lastRef)
/// Adds a tile to the navigation mesh.
/// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
/// @param[in] dataSize Data size of the new tile mesh.
/// @param[in] flags Tile flags. (See: #dtTileFlags)
/// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0]
/// @param[out] result The tile reference. (If the tile was succesfully added.) [opt]
/// @return The status flags for the operation.
public DtStatus AddTile(DtMeshData data, int flags, long lastRef, out long result)
{
result = 0;
// Make sure the data is in right format.
DtMeshHeader header = data.header;
// Make sure the location is free.
if (GetTileAt(header.x, header.y, header.layer) != null)
{
throw new Exception("Tile already exists");
return DtStatus.DT_FAILURE | DtStatus.DT_ALREADY_OCCUPIED;
}
// Allocate a tile.
@ -392,7 +397,7 @@ namespace DotRecast.Detour
int tileIndex = DecodePolyIdTile(lastRef);
if (tileIndex >= m_maxTiles)
{
throw new Exception("Tile index too high");
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
}
// Try to find the specific tile id from the free list.
@ -401,7 +406,7 @@ namespace DotRecast.Detour
if (!m_nextFree.Remove(target))
{
// Could not find the correct location.
throw new Exception("Could not find tile");
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
}
tile = target;
@ -409,6 +414,12 @@ namespace DotRecast.Detour
tile.salt = DecodePolyIdSalt(lastRef);
}
// Make sure we could allocate a tile.
if (null == tile)
{
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
}
tile.data = data;
tile.flags = flags;
tile.links.Clear();
@ -461,7 +472,8 @@ namespace DotRecast.Detour
}
}
return GetTileRef(tile);
result = GetTileRef(tile);
return DtStatus.DT_SUCCESS;
}
/// Removes the specified tile from the navigation mesh.

View File

@ -68,7 +68,8 @@ namespace DotRecast.Detour.Io
}
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
DtNavMesh mesh = new DtNavMesh(header.option, header.maxVertsPerPoly);
DtNavMesh mesh = new DtNavMesh();
mesh.Init(header.option, header.maxVertsPerPoly);
ReadTiles(bb, is32Bit, ref header, cCompatibility, mesh);
return mesh;
}
@ -133,7 +134,7 @@ namespace DotRecast.Detour.Io
}
DtMeshData data = meshReader.Read(bb, mesh.GetMaxVertsPerPoly(), is32Bit);
mesh.AddTile(data, i, tileHeader.tileRef);
mesh.AddTile(data, i, tileHeader.tileRef, out _);
}
}

View File

@ -73,7 +73,14 @@ namespace DotRecast.Recast.Toolset.Builder
private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly)
{
return new DtNavMesh(meshData, vertsPerPoly, 0);
var mesh = new DtNavMesh();
var status = mesh.Init(meshData, vertsPerPoly, 0);
if (status.Failed())
{
return null;
}
return mesh;
}
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg, bool keepInterResults)

View File

@ -115,8 +115,9 @@ namespace DotRecast.Recast.Toolset.Builder
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
DtNavMesh navMesh = new DtNavMesh(navMeshParams, vertsPerPoly);
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
DtNavMesh navMesh = new DtNavMesh();
navMesh.Init(navMeshParams, vertsPerPoly);
meshData.ForEach(md => navMesh.AddTile(md, 0, 0, out _));
return navMesh;
}

View File

@ -141,7 +141,8 @@ namespace DotRecast.Recast.Toolset.Tools
navMeshParams.maxTiles = 256; // ..
navMeshParams.maxPolys = 16384;
var navMesh = new DtNavMesh(navMeshParams, 6);
var navMesh = new DtNavMesh();
navMesh.Init(navMeshParams, 6);
var comp = _comp.Create(cCompatibility ? 0 : 1);
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
DtTileCache tc = new DtTileCache(option, storageParams, navMesh, comp, _proc);

View File

@ -25,7 +25,6 @@ using NUnit.Framework;
namespace DotRecast.Detour.Crowd.Test;
public class AbstractCrowdTest
{
protected readonly long[] startRefs =
@ -64,7 +63,8 @@ public class AbstractCrowdTest
public void SetUp()
{
nmd = new RecastTestMeshBuilder().GetMeshData();
navmesh = new DtNavMesh(nmd, 6, 0);
navmesh = new DtNavMesh();
navmesh.Init(nmd, 6, 0);
query = new DtNavMeshQuery(navmesh);
DtCrowdConfig config = new DtCrowdConfig(0.6f);
crowd = new DtCrowd(config, navmesh);

View File

@ -21,7 +21,6 @@ using NUnit.Framework;
namespace DotRecast.Detour.Test;
public abstract class AbstractDetourTest
{
protected static readonly long[] startRefs =
@ -64,6 +63,8 @@ public abstract class AbstractDetourTest
protected DtNavMesh CreateNavMesh()
{
return new DtNavMesh(new RecastTestMeshBuilder().GetMeshData(), 6, 0);
var mesh = new DtNavMesh();
mesh.Init(new RecastTestMeshBuilder().GetMeshData(), 6, 0);
return mesh;
}
}

View File

@ -28,7 +28,6 @@ using NUnit.Framework;
namespace DotRecast.Detour.Test.Io;
public class MeshSetReaderWriterTest
{
private readonly DtMeshSetWriter writer = new DtMeshSetWriter();
@ -66,7 +65,8 @@ public class MeshSetReaderWriterTest
header.option.maxTiles = m_maxTiles;
header.option.maxPolys = m_maxPolysPerTile;
header.numTiles = 0;
DtNavMesh mesh = new DtNavMesh(header.option, 6);
DtNavMesh mesh = new DtNavMesh();
mesh.Init(header.option, 6);
RcVec3f bmin = geom.GetMeshBoundsMin();
RcVec3f bmax = geom.GetMeshBoundsMax();
@ -92,7 +92,7 @@ public class MeshSetReaderWriterTest
if (data != null)
{
mesh.RemoveTile(mesh.GetTileRefAt(x, y, 0));
mesh.AddTile(data, 0, 0);
mesh.AddTile(data, 0, 0, out _);
}
}
}

View File

@ -17,7 +17,6 @@ freely, subject to the following restrictions:
*/
using System.Collections.Generic;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using DotRecast.Recast.Geom;
@ -64,7 +63,8 @@ public class TestTiledNavMeshBuilder
navMeshParams.tileHeight = tileSize * cellSize;
navMeshParams.maxTiles = 128;
navMeshParams.maxPolys = 32768;
navMesh = new DtNavMesh(navMeshParams, 6);
navMesh = new DtNavMesh();
navMesh.Init(navMeshParams, 6);
// Build all tiles
RcConfig cfg = new RcConfig(true, tileSize, tileSize, RcConfig.CalcBorder(agentRadius, cellSize),
@ -119,7 +119,7 @@ public class TestTiledNavMeshBuilder
option.tileX = result.TileX;
option.tileZ = result.TileZ;
option.buildBvTree = true;
navMesh.AddTile(DtNavMeshBuilder.CreateNavMeshData(option), 0, 0);
navMesh.AddTile(DtNavMeshBuilder.CreateNavMeshData(option), 0, 0, out _);
}
}

View File

@ -64,7 +64,8 @@ public class AbstractTileCacheTest
navMeshParams.maxTiles = 256;
navMeshParams.maxPolys = 16384;
var navMesh = new DtNavMesh(navMeshParams, 6);
var navMesh = new DtNavMesh();
navMesh.Init(navMeshParams, 6);
var comp = DtTileCacheCompressorFactory.Shared.Create(cCompatibility ? 0 : 1);
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
var process = new TestTileCacheMeshProcess();