From 2d0e2f852551f0152e114e4ca70bf287be8c9196 Mon Sep 17 00:00:00 2001 From: ikpil Date: Sat, 21 Sep 2024 02:54:01 +0900 Subject: [PATCH] Fix dynamic mesh bounds calculation #77 recast4j - https://github.com/recast4j/recast4j/issues/203 - https://github.com/recast4j/recast4j/pull/204 --- CHANGELOG.md | 2 ++ DotRecast.sln | 12 +++++----- .../DtDynamicNavMesh.cs | 18 +++++++++----- .../Io/DtVoxelFile.cs | 20 +++++++++------- src/DotRecast.Recast.Demo/DemoSample.cs | 9 ++++++- src/DotRecast.Recast.Demo/RecastDemo.cs | 6 ++--- .../Tools/DynamicUpdateSampleTool.cs | 24 ++++++++++++++++--- .../Tools/ObstacleSampleTool.cs | 2 +- .../Builder/NavMeshBuildResult.cs | 14 ++++++++++- .../Builder/SoloNavMeshBuilder.cs | 2 +- .../Builder/TileNavMeshBuilder.cs | 11 +++++---- .../RcNavMeshBuildSettings.cs | 2 +- .../Tools/RcDynamicUpdateTool.cs | 14 +++++++++-- .../Tools/RcObstacleTool.cs | 2 +- 14 files changed, 98 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c3a06..d09eff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix raycast shortcuts ([@Sarofc](https://github.com/Sarofc)) [#72](https://github.com/ikpil/DotRecast/issues/72) +- Fix dynamic mesh bounds calculation ([@ppiastucki](https://github.com/ppiastucki)) [#77](https://github.com/ikpil/DotRecast/issues/77) + - issuer : [@OhJeongrok](https://github.com/OhJeongrok) ### Changed - Changed data structure of 'neis' from List to byte[] for optimized memory usage and improved access speed in `DtLayerMonotoneRegion` diff --git a/DotRecast.sln b/DotRecast.sln index 5a437de..581b760 100644 --- a/DotRecast.sln +++ b/DotRecast.sln @@ -123,18 +123,18 @@ Global {FFE40BBF-843B-41FA-8504-F4ABD166762E} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} {38933A87-4568-40A5-A3DA-E2445E8C2B99} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} {C19E4BFA-63A0-4815-9815-869A9DC52DBC} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} - {88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} - {554CB5BD-D58A-4856-BFE1-666A62C9BEA3} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {FA7EF26A-BA47-43FD-86F8-0A33CFDF643F} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} - {F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {53AF87DA-37F8-4504-B623-B2113F4438CA} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} - {67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {17E4F2F0-FC27-416E-9CB6-9F2CAAC49C9D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} - {7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {DEB16B90-CCD4-497E-A2E9-4CC66FD7EF47} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} - {3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {023E1E6A-4895-4573-89AE-3D5D8E0B39C8} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} {DF987948-8C23-4337-AF83-D87D6407518D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD} + {88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} + {554CB5BD-D58A-4856-BFE1-666A62C9BEA3} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} + {F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} + {67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} + {7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} + {3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {10395C8F-DFBD-4263-8A20-EA3500A6E55A} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} {D1EFC625-D095-4208-98A2-112B73CB40B0} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73} EndGlobalSection diff --git a/src/DotRecast.Detour.Dynamic/DtDynamicNavMesh.cs b/src/DotRecast.Detour.Dynamic/DtDynamicNavMesh.cs index 277b755..82a0104 100644 --- a/src/DotRecast.Detour.Dynamic/DtDynamicNavMesh.cs +++ b/src/DotRecast.Detour.Dynamic/DtDynamicNavMesh.cs @@ -167,7 +167,7 @@ namespace DotRecast.Detour.Dynamic { foreach (var tile in tiles) Rebuild(tile); - + return UpdateNavMesh(); } @@ -188,17 +188,17 @@ namespace DotRecast.Detour.Dynamic return _tiles.Values; } - int minx = (int)MathF.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth); - int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight); - int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth); - int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight); + int minx = (int)MathF.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth) - 1; + int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight) - 1; + int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth) + 1; + int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight) + 1; List tiles = new List(); for (int z = minz; z <= maxz; ++z) { for (int x = minx; x <= maxx; ++x) { DtDynamicTile tile = GetTileAt(x, z); - if (tile != null) + if (tile != null && IntersectsXZ(tile, bounds)) { tiles.Add(tile); } @@ -208,6 +208,12 @@ namespace DotRecast.Detour.Dynamic return tiles; } + private bool IntersectsXZ(DtDynamicTile tile, float[] bounds) + { + return tile.voxelTile.boundsMin.X <= bounds[3] && tile.voxelTile.boundsMax.X >= bounds[0] && + tile.voxelTile.boundsMin.Z <= bounds[5] && tile.voxelTile.boundsMax.Z >= bounds[2]; + } + private List GetTilesByCollider(long cid) { return _tiles.Values.Where(t => t.ContainsCollider(cid)).ToList(); diff --git a/src/DotRecast.Detour.Dynamic/Io/DtVoxelFile.cs b/src/DotRecast.Detour.Dynamic/Io/DtVoxelFile.cs index aa89808..7f152e4 100644 --- a/src/DotRecast.Detour.Dynamic/Io/DtVoxelFile.cs +++ b/src/DotRecast.Detour.Dynamic/Io/DtVoxelFile.cs @@ -78,7 +78,7 @@ namespace DotRecast.Detour.Dynamic.Io walkbableAreaMod, buildMeshDetail); } - public static DtVoxelFile From(RcConfig config, List results) + public static DtVoxelFile From(RcConfig config, IList results) { DtVoxelFile f = new DtVoxelFile(); f.version = 1; @@ -109,13 +109,14 @@ namespace DotRecast.Detour.Dynamic.Io }; foreach (RcBuilderResult r in results) { + float pad = r.SolidHeightfiled.borderSize * r.SolidHeightfiled.cs; f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled)); - f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X); + f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X + pad); f.bounds[1] = Math.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y); - f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z); - f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X); + f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z + pad); + f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X - pad); f.bounds[4] = Math.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y); - f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z); + f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z - pad); } return f; @@ -155,12 +156,13 @@ namespace DotRecast.Detour.Dynamic.Io { RcHeightfield heightfield = vt.Heightfield(); f.tiles.Add(new DtVoxelTile(vt.tileX, vt.tileZ, heightfield)); - f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.X); + float pad = vt.borderSize * vt.cellSize; + f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.X + pad); f.bounds[1] = Math.Min(f.bounds[1], vt.boundsMin.Y); - f.bounds[2] = Math.Min(f.bounds[2], vt.boundsMin.Z); - f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X); + f.bounds[2] = Math.Min(f.bounds[2], vt.boundsMin.Z + pad); + f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X - pad); f.bounds[4] = Math.Max(f.bounds[4], vt.boundsMax.Y); - f.bounds[5] = Math.Max(f.bounds[5], vt.boundsMax.Z); + f.bounds[5] = Math.Max(f.bounds[5], vt.boundsMax.Z - pad); } return f; diff --git a/src/DotRecast.Recast.Demo/DemoSample.cs b/src/DotRecast.Recast.Demo/DemoSample.cs index f87f4cb..be365d2 100644 --- a/src/DotRecast.Recast.Demo/DemoSample.cs +++ b/src/DotRecast.Recast.Demo/DemoSample.cs @@ -32,6 +32,7 @@ namespace DotRecast.Recast.Demo private DtNavMesh _navMesh; private DtNavMeshQuery _navMeshQuery; private readonly RcNavMeshBuildSettings _settings; + private RcConfig _cfg; private IList _recastResults; private bool _changed; @@ -56,6 +57,11 @@ namespace DotRecast.Recast.Demo return _geom; } + public RcConfig GetRecastConfig() + { + return _cfg; + } + public IList GetRecastResults() { return _recastResults; @@ -86,9 +92,10 @@ namespace DotRecast.Recast.Demo _changed = changed; } - public void Update(DemoInputGeomProvider geom, IList recastResults, DtNavMesh navMesh) + public void Update(DemoInputGeomProvider geom, RcConfig cfg, IList recastResults, DtNavMesh navMesh) { _geom = geom; + _cfg = cfg; _recastResults = recastResults; _navMesh = navMesh; SetQuery(navMesh); diff --git a/src/DotRecast.Recast.Demo/RecastDemo.cs b/src/DotRecast.Recast.Demo/RecastDemo.cs index 26c26ca..e5d42df 100644 --- a/src/DotRecast.Recast.Demo/RecastDemo.cs +++ b/src/DotRecast.Recast.Demo/RecastDemo.cs @@ -320,7 +320,7 @@ public class RecastDemo : IRecastDemoChannel if (null != mesh) { - _sample.Update(_sample.GetInputGeom(), ImmutableArray.Empty, mesh); + _sample.Update(_sample.GetInputGeom(), _sample.GetRecastConfig(), ImmutableArray.Empty, mesh); _toolsetView.SetEnabled(true); } } @@ -684,7 +684,7 @@ public class RecastDemo : IRecastDemoChannel { var geom = LoadInputMesh(args.FilePath); - _sample.Update(geom, ImmutableArray.Empty, null); + _sample.Update(geom, null, ImmutableArray.Empty, null); } private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args) @@ -719,7 +719,7 @@ public class RecastDemo : IRecastDemoChannel return; } - _sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh); + _sample.Update(_sample.GetInputGeom(), buildResult.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh); _sample.SetChanged(false); settingsView.SetBuildTime((RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond); //settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList()); diff --git a/src/DotRecast.Recast.Demo/Tools/DynamicUpdateSampleTool.cs b/src/DotRecast.Recast.Demo/Tools/DynamicUpdateSampleTool.cs index 54dfd25..c3d33cf 100644 --- a/src/DotRecast.Recast.Demo/Tools/DynamicUpdateSampleTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/DynamicUpdateSampleTool.cs @@ -25,6 +25,7 @@ using DotRecast.Core; using DotRecast.Core.Collections; using DotRecast.Core.Numerics; using DotRecast.Detour.Dynamic; +using DotRecast.Detour.Dynamic.Io; using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset.Tools; using DotRecast.Recast.Demo.Draw; @@ -117,8 +118,16 @@ public class DynamicUpdateSampleTool : ISampleTool if (mode == RcDynamicUpdateToolMode.BUILD) { const string loadVoxelPopupStrId = "Load Voxels Popup"; - + bool isLoadVoxelPopup = true; + if (_sample.GetRecastResults() != null && _sample.GetRecastConfig() != null) + { + if (ImGui.Button("Import Voxels")) + { + Copy(); + } + } + if (ImGui.Button("Load Voxels...")) { ImGui.OpenPopup(loadVoxelPopupStrId); @@ -410,7 +419,7 @@ public class DynamicUpdateSampleTool : ISampleTool { buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond; var dynaMesh = _tool.GetDynamicNavMesh(); - _sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh()); + _sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh()); _sample.SetChanged(false); } } @@ -420,6 +429,15 @@ public class DynamicUpdateSampleTool : ISampleTool } } + private void Copy() + { + if (_sample.GetRecastResults() != null && _sample.GetRecastConfig() != null) + { + var dynaMesh = _tool.Copy(_sample.GetRecastConfig(), _sample.GetRecastResults()); + UpdateFrom(dynaMesh.config); + BuildDynaMesh(); + } + } private void Load(string filename) { @@ -457,7 +475,7 @@ public class DynamicUpdateSampleTool : ISampleTool } buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond; - _sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh()); + _sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh()); } private void UpdateTo(DtDynamicNavMeshConfig config) diff --git a/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs b/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs index ae4ee66..8661122 100644 --- a/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/ObstacleSampleTool.cs @@ -32,7 +32,7 @@ public class ObstacleSampleTool : ISampleTool var buildResult = _tool.Build(geom, settings, RcByteOrder.LITTLE_ENDIAN, true); if (buildResult.Success) { - _sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh); + _sample.Update(_sample.GetInputGeom(), buildResult.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh); } } diff --git a/src/DotRecast.Recast.Toolset/Builder/NavMeshBuildResult.cs b/src/DotRecast.Recast.Toolset/Builder/NavMeshBuildResult.cs index b4f1ce2..a86f222 100644 --- a/src/DotRecast.Recast.Toolset/Builder/NavMeshBuildResult.cs +++ b/src/DotRecast.Recast.Toolset/Builder/NavMeshBuildResult.cs @@ -7,6 +7,7 @@ namespace DotRecast.Recast.Toolset.Builder public class NavMeshBuildResult { public readonly bool Success; + public readonly RcConfig Cfg; public readonly IList RecastBuilderResults; public readonly DtNavMesh NavMesh; @@ -17,11 +18,22 @@ namespace DotRecast.Recast.Toolset.Builder NavMesh = null; } - public NavMeshBuildResult(IList recastBuilderResults, DtNavMesh navMesh) + // for solo + public NavMeshBuildResult(RcConfig cfg, IList recastBuilderResults, DtNavMesh navMesh) { Success = true; + Cfg = cfg; RecastBuilderResults = recastBuilderResults; NavMesh = navMesh; } + + // for tiles + public NavMeshBuildResult(RcConfig cfg, IList recastBuilderResults) + { + Success = true; + Cfg = cfg; + RecastBuilderResults = recastBuilderResults; + NavMesh = null; + } } } \ No newline at end of file diff --git a/src/DotRecast.Recast.Toolset/Builder/SoloNavMeshBuilder.cs b/src/DotRecast.Recast.Toolset/Builder/SoloNavMeshBuilder.cs index 4d01aec..401802c 100644 --- a/src/DotRecast.Recast.Toolset/Builder/SoloNavMeshBuilder.cs +++ b/src/DotRecast.Recast.Toolset/Builder/SoloNavMeshBuilder.cs @@ -69,7 +69,7 @@ namespace DotRecast.Recast.Toolset.Builder } var navMesh = BuildNavMesh(meshData, vertsPerPoly); - return new NavMeshBuildResult(RcImmutableArray.Create(rcResult), navMesh); + return new NavMeshBuildResult(cfg, RcImmutableArray.Create(rcResult), navMesh); } private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly) diff --git a/src/DotRecast.Recast.Toolset/Builder/TileNavMeshBuilder.cs b/src/DotRecast.Recast.Toolset/Builder/TileNavMeshBuilder.cs index befe1b2..e328985 100644 --- a/src/DotRecast.Recast.Toolset/Builder/TileNavMeshBuilder.cs +++ b/src/DotRecast.Recast.Toolset/Builder/TileNavMeshBuilder.cs @@ -58,7 +58,7 @@ namespace DotRecast.Recast.Toolset.Builder bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans, bool keepInterResults, bool buildAll) { - List results = BuildRecastResult( + NavMeshBuildResult result = BuildRecastResult( geom, tileSize, partitionType, @@ -72,12 +72,12 @@ namespace DotRecast.Recast.Toolset.Builder keepInterResults, buildAll ); - var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, results); + var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result.RecastBuilderResults); var tileNavMesh = BuildNavMesh(geom, tileMeshData, cellSize, tileSize, vertsPerPoly); - return new NavMeshBuildResult(results, tileNavMesh); + return new NavMeshBuildResult(result.Cfg, result.RecastBuilderResults, tileNavMesh); } - public List BuildRecastResult(IInputGeomProvider geom, + public NavMeshBuildResult BuildRecastResult(IInputGeomProvider geom, int tileSize, RcPartition partitionType, float cellSize, float cellHeight, @@ -102,7 +102,8 @@ namespace DotRecast.Recast.Toolset.Builder filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true); RcBuilder rcBuilder = new RcBuilder(); - return rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory); + var results = rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory); + return new NavMeshBuildResult(cfg, results); } public DtNavMesh BuildNavMesh(IInputGeomProvider geom, List meshData, float cellSize, int tileSize, int vertsPerPoly) diff --git a/src/DotRecast.Recast.Toolset/RcNavMeshBuildSettings.cs b/src/DotRecast.Recast.Toolset/RcNavMeshBuildSettings.cs index ea70e2b..64f4985 100644 --- a/src/DotRecast.Recast.Toolset/RcNavMeshBuildSettings.cs +++ b/src/DotRecast.Recast.Toolset/RcNavMeshBuildSettings.cs @@ -32,7 +32,7 @@ namespace DotRecast.Recast.Toolset public bool tiled = false; public int tileSize = 32; - public bool keepInterResults = false; + public bool keepInterResults = true; // full memory public bool buildAll = true; } } \ No newline at end of file diff --git a/src/DotRecast.Recast.Toolset/Tools/RcDynamicUpdateTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcDynamicUpdateTool.cs index 9be7417..a27cb40 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcDynamicUpdateTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcDynamicUpdateTool.cs @@ -141,6 +141,16 @@ namespace DotRecast.Recast.Toolset.Tools return colliderWithGizmo; } + public DtDynamicNavMesh Copy(RcConfig cfg, IList results) + { + var voxelFile = DtVoxelFile.From(cfg, results); + dynaMesh = new DtDynamicNavMesh(voxelFile); + dynaMesh.config.keepIntermediateResults = true; + colliderGizmos.Clear(); + + return dynaMesh; + } + public DtDynamicNavMesh Load(string filename, IRcCompressor compressor) { using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); @@ -184,7 +194,7 @@ namespace DotRecast.Recast.Toolset.Tools (1f - 2 * (float)random.NextDouble()) ); a = RcVec3f.Normalize(a); - + float len = 1f + (float)random.NextDouble() * 20f; a.X *= len; a.Y *= len; @@ -235,7 +245,7 @@ namespace DotRecast.Recast.Toolset.Tools RcVec3f baseUp = new RcVec3f(0, 1, 0); RcVec3f forward = new RcVec3f((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble())); forward = RcVec3f.Normalize(forward); - + RcVec3f side = RcVec3f.Cross(forward, baseUp); DtBoxCollider @base = new DtBoxCollider(baseCenter, Detour.Dynamic.Colliders.DtBoxCollider.GetHalfEdges(baseUp, forward, baseExtent), SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, walkableClimb); diff --git a/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs b/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs index b26fc87..53b4b88 100644 --- a/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs +++ b/src/DotRecast.Recast.Toolset/Tools/RcObstacleTool.cs @@ -78,7 +78,7 @@ namespace DotRecast.Recast.Toolset.Tools _tc.BuildNavMeshTile(refs); } - return new NavMeshBuildResult(RcImmutableArray.Empty, _tc.GetNavMesh()); + return new NavMeshBuildResult(cfg, RcImmutableArray.Empty, _tc.GetNavMesh()); } public void ClearAllTempObstacles()