From 17891c2d43388faa7e20926509839050bf82cc86 Mon Sep 17 00:00:00 2001 From: ikpil Date: Wed, 7 Jun 2023 23:19:25 +0900 Subject: [PATCH] for unity3d --- .../Builder/AbstractNavMeshBuilder.cs | 97 -------- .../Builder/SampleAreaModifications.cs | 66 ----- .../Builder/SoloNavMeshBuilder.cs | 72 ------ .../Builder/TileNavMeshBuilder.cs | 137 ----------- src/DotRecast.Recast.Demo/Draw/DebugDraw.cs | 2 +- .../Draw/NavMeshRenderer.cs | 4 +- .../Draw/RecastDebugDraw.cs | 2 +- .../Geom/DemoInputGeomProvider.cs | 226 ----------------- src/DotRecast.Recast.Demo/RecastDemo.cs | 14 +- src/DotRecast.Recast.Demo/Sample.cs | 2 +- .../Tools/ConvexVolumeTool.cs | 4 +- .../Tools/CrowdProfilingTool.cs | 2 +- src/DotRecast.Recast.Demo/Tools/CrowdTool.cs | 5 +- .../Tools/DemoObjImporter.cs | 2 +- .../Tools/DynamicUpdateTool.cs | 4 +- .../Tools/JumpLinkBuilderTool.cs | 4 +- .../Tools/OffMeshConnectionTool.cs | 4 +- .../Tools/TestNavmeshTool.cs | 2 +- src/DotRecast.Recast.Demo/UI/ToolsView.cs | 1 + .../Builder/AbstractNavMeshBuilder.cs | 98 ++++++++ .../Builder/SampleAreaModifications.cs | 68 ++++++ .../Builder/SoloNavMeshBuilder.cs | 73 ++++++ .../Builder/TileNavMeshBuilder.cs | 138 +++++++++++ .../Geom/DemoInputGeomProvider.cs | 228 ++++++++++++++++++ .../Geom/DemoOffMeshConnection.cs | 45 ++-- src/DotRecast.Recast/PolyMesh.cs | 1 + src/DotRecast.Recast/PolyUtils.cs | 1 + 27 files changed, 658 insertions(+), 644 deletions(-) delete mode 100644 src/DotRecast.Recast.Demo/Builder/AbstractNavMeshBuilder.cs delete mode 100644 src/DotRecast.Recast.Demo/Builder/SampleAreaModifications.cs delete mode 100644 src/DotRecast.Recast.Demo/Builder/SoloNavMeshBuilder.cs delete mode 100644 src/DotRecast.Recast.Demo/Builder/TileNavMeshBuilder.cs delete mode 100644 src/DotRecast.Recast.Demo/Geom/DemoInputGeomProvider.cs create mode 100644 src/DotRecast.Recast.DemoTool/Builder/AbstractNavMeshBuilder.cs create mode 100644 src/DotRecast.Recast.DemoTool/Builder/SampleAreaModifications.cs create mode 100644 src/DotRecast.Recast.DemoTool/Builder/SoloNavMeshBuilder.cs create mode 100644 src/DotRecast.Recast.DemoTool/Builder/TileNavMeshBuilder.cs create mode 100644 src/DotRecast.Recast.DemoTool/Geom/DemoInputGeomProvider.cs rename src/{DotRecast.Recast.Demo => DotRecast.Recast.DemoTool}/Geom/DemoOffMeshConnection.cs (58%) diff --git a/src/DotRecast.Recast.Demo/Builder/AbstractNavMeshBuilder.cs b/src/DotRecast.Recast.Demo/Builder/AbstractNavMeshBuilder.cs deleted file mode 100644 index 3c4b175..0000000 --- a/src/DotRecast.Recast.Demo/Builder/AbstractNavMeshBuilder.cs +++ /dev/null @@ -1,97 +0,0 @@ -using DotRecast.Detour; -using DotRecast.Recast.Demo.Geom; - -namespace DotRecast.Recast.Demo.Builder; - -public abstract class AbstractNavMeshBuilder -{ - protected NavMeshDataCreateParams GetNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize, - float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb, - RecastBuilderResult rcResult) - { - PolyMesh m_pmesh = rcResult.GetMesh(); - PolyMeshDetail m_dmesh = rcResult.GetMeshDetail(); - NavMeshDataCreateParams option = new NavMeshDataCreateParams(); - for (int i = 0; i < m_pmesh.npolys; ++i) - { - m_pmesh.flags[i] = 1; - } - - option.verts = m_pmesh.verts; - option.vertCount = m_pmesh.nverts; - option.polys = m_pmesh.polys; - option.polyAreas = m_pmesh.areas; - option.polyFlags = m_pmesh.flags; - option.polyCount = m_pmesh.npolys; - option.nvp = m_pmesh.nvp; - if (m_dmesh != null) - { - option.detailMeshes = m_dmesh.meshes; - option.detailVerts = m_dmesh.verts; - option.detailVertsCount = m_dmesh.nverts; - option.detailTris = m_dmesh.tris; - option.detailTriCount = m_dmesh.ntris; - } - - option.walkableHeight = m_agentHeight; - option.walkableRadius = m_agentRadius; - option.walkableClimb = m_agentMaxClimb; - option.bmin = m_pmesh.bmin; - option.bmax = m_pmesh.bmax; - option.cs = m_cellSize; - option.ch = m_cellHeight; - option.buildBvTree = true; - - option.offMeshConCount = m_geom.GetOffMeshConnections().Count; - option.offMeshConVerts = new float[option.offMeshConCount * 6]; - option.offMeshConRad = new float[option.offMeshConCount]; - option.offMeshConDir = new int[option.offMeshConCount]; - option.offMeshConAreas = new int[option.offMeshConCount]; - option.offMeshConFlags = new int[option.offMeshConCount]; - option.offMeshConUserID = new int[option.offMeshConCount]; - for (int i = 0; i < option.offMeshConCount; i++) - { - DemoOffMeshConnection offMeshCon = m_geom.GetOffMeshConnections()[i]; - for (int j = 0; j < 6; j++) - { - option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j]; - } - - option.offMeshConRad[i] = offMeshCon.radius; - option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0; - option.offMeshConAreas[i] = offMeshCon.area; - option.offMeshConFlags[i] = offMeshCon.flags; - } - - return option; - } - - protected MeshData UpdateAreaAndFlags(MeshData meshData) - { - // Update poly flags from areas. - for (int i = 0; i < meshData.polys.Length; ++i) - { - if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE) - { - meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND); - } - - if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND - || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS - || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD) - { - meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK; - } - else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER) - { - meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM; - } - else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR) - { - meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR; - } - } - - return meshData; - } -} \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/Builder/SampleAreaModifications.cs b/src/DotRecast.Recast.Demo/Builder/SampleAreaModifications.cs deleted file mode 100644 index 50a21ab..0000000 --- a/src/DotRecast.Recast.Demo/Builder/SampleAreaModifications.cs +++ /dev/null @@ -1,66 +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. -*/ - -using System.Collections.Immutable; -using System.Linq; - -namespace DotRecast.Recast.Demo.Builder; - -public class SampleAreaModifications -{ - public const int SAMPLE_POLYAREA_TYPE_GROUND = 0x0; - public const int SAMPLE_POLYAREA_TYPE_WATER = 0x1; - public const int SAMPLE_POLYAREA_TYPE_ROAD = 0x2; - public const int SAMPLE_POLYAREA_TYPE_DOOR = 0x3; - public const int SAMPLE_POLYAREA_TYPE_GRASS = 0x4; - public const int SAMPLE_POLYAREA_TYPE_JUMP = 0x5; - public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6; - public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f; - - public static readonly AreaModification SAMPLE_AREAMOD_WALKABLE = new(SAMPLE_POLYAREA_TYPE_WALKABLE); - public static readonly AreaModification SAMPLE_AREAMOD_GROUND = new(SAMPLE_POLYAREA_TYPE_GROUND); - public static readonly AreaModification SAMPLE_AREAMOD_WATER = new(SAMPLE_POLYAREA_TYPE_WATER); - public static readonly AreaModification SAMPLE_AREAMOD_ROAD = new(SAMPLE_POLYAREA_TYPE_ROAD); - public static readonly AreaModification SAMPLE_AREAMOD_GRASS = new(SAMPLE_POLYAREA_TYPE_GRASS); - public static readonly AreaModification SAMPLE_AREAMOD_DOOR = new(SAMPLE_POLYAREA_TYPE_DOOR); - public static readonly AreaModification SAMPLE_AREAMOD_JUMP = new(SAMPLE_POLYAREA_TYPE_JUMP); - - public static readonly ImmutableArray Values = ImmutableArray.Create( - SAMPLE_AREAMOD_WALKABLE, - SAMPLE_AREAMOD_GROUND, - SAMPLE_AREAMOD_WATER, - SAMPLE_AREAMOD_ROAD, - SAMPLE_AREAMOD_GRASS, - SAMPLE_AREAMOD_DOOR, - SAMPLE_AREAMOD_JUMP - ); - - public static AreaModification OfValue(int value) - { - return Values.FirstOrDefault(x => x.Value == value, SAMPLE_AREAMOD_GRASS); - } - - public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road) - public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water). - public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors. - public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump. - public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon - public static readonly int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities. -} \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/Builder/SoloNavMeshBuilder.cs b/src/DotRecast.Recast.Demo/Builder/SoloNavMeshBuilder.cs deleted file mode 100644 index 6418283..0000000 --- a/src/DotRecast.Recast.Demo/Builder/SoloNavMeshBuilder.cs +++ /dev/null @@ -1,72 +0,0 @@ -/* -recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org - -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. -*/ - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using DotRecast.Detour; -using DotRecast.Recast.Demo.Geom; - -namespace DotRecast.Recast.Demo.Builder; - -public class SoloNavMeshBuilder : AbstractNavMeshBuilder -{ - public Tuple, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType, - float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, - float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, - int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, - bool filterLedgeSpans, bool filterWalkableLowHeightSpans) - { - RecastBuilderResult rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight, - agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError, - vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans, - filterWalkableLowHeightSpans); - return Tuple.Create(ImmutableArray.Create(rcResult) as IList, - BuildNavMesh( - BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult), - vertsPerPoly)); - } - - private NavMesh BuildNavMesh(MeshData meshData, int vertsPerPoly) - { - return new NavMesh(meshData, vertsPerPoly, 0); - } - - private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, float cellSize, - float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, float agentMaxSlope, - int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, int vertsPerPoly, - float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans, - bool filterWalkableLowHeightSpans) - { - RecastConfig cfg = new RecastConfig(partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, - filterLedgeSpans, filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, regionMinSize, - regionMergeSize, edgeMaxLen, edgeMaxError, vertsPerPoly, detailSampleDist, detailSampleMaxError, - SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true); - RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax()); - RecastBuilder rcBuilder = new RecastBuilder(); - return rcBuilder.Build(geom, bcfg); - } - - private MeshData BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight, - float agentRadius, float agentMaxClimb, RecastBuilderResult result) - { - NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, - agentMaxClimb, result); - return UpdateAreaAndFlags(NavMeshBuilder.CreateNavMeshData(option)); - } -} \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/Builder/TileNavMeshBuilder.cs b/src/DotRecast.Recast.Demo/Builder/TileNavMeshBuilder.cs deleted file mode 100644 index 121a1f7..0000000 --- a/src/DotRecast.Recast.Demo/Builder/TileNavMeshBuilder.cs +++ /dev/null @@ -1,137 +0,0 @@ -/* -recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org - -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. -*/ - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using DotRecast.Core; -using DotRecast.Detour; -using DotRecast.Recast.Demo.Geom; -using static DotRecast.Core.RcMath; - -namespace DotRecast.Recast.Demo.Builder; - -public class TileNavMeshBuilder : AbstractNavMeshBuilder -{ - public TileNavMeshBuilder() - { - } - - public Tuple, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType, - float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, - float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, - int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, - bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize) - { - List rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight, - agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError, - vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans, - filterWalkableLowHeightSpans, tileSize); - return Tuple.Create((IList)rcResult, - BuildNavMesh(geom, - BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult), - cellSize, tileSize, vertsPerPoly)); - } - - private List BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, - float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, - float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, - int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, - bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize) - { - RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.CalcBorder(agentRadius, cellSize), - partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, filterLedgeSpans, - filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, - regionMinSize * regionMinSize * cellSize * cellSize, - regionMergeSize * regionMergeSize * cellSize * cellSize, edgeMaxLen, edgeMaxError, vertsPerPoly, - true, detailSampleDist, detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE); - RecastBuilder rcBuilder = new RecastBuilder(); - return rcBuilder.BuildTiles(geom, cfg, Task.Factory); - } - - private NavMesh BuildNavMesh(DemoInputGeomProvider geom, List meshData, float cellSize, int tileSize, - int vertsPerPoly) - { - NavMeshParams navMeshParams = new NavMeshParams(); - navMeshParams.orig.x = geom.GetMeshBoundsMin().x; - navMeshParams.orig.y = geom.GetMeshBoundsMin().y; - navMeshParams.orig.z = geom.GetMeshBoundsMin().z; - navMeshParams.tileWidth = tileSize * cellSize; - navMeshParams.tileHeight = tileSize * cellSize; - - // Snprintf(text, 64, "Tiles %d x %d", tw, th); - - navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize); - navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize); - NavMesh navMesh = new NavMesh(navMeshParams, vertsPerPoly); - meshData.ForEach(md => navMesh.AddTile(md, 0, 0)); - return navMesh; - } - - public int GetMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize) - { - int tileBits = GetTileBits(geom, cellSize, tileSize); - return 1 << tileBits; - } - - public int GetMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize) - { - int polyBits = 22 - GetTileBits(geom, cellSize, tileSize); - return 1 << polyBits; - } - - private int GetTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize) - { - Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); - int tw = (gw + tileSize - 1) / tileSize; - int th = (gh + tileSize - 1) / tileSize; - int tileBits = Math.Min(DetourCommon.Ilog2(DetourCommon.NextPow2(tw * th)), 14); - return tileBits; - } - - public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize) - { - Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); - int tw = (gw + tileSize - 1) / tileSize; - int th = (gh + tileSize - 1) / tileSize; - return new int[] { tw, th }; - } - - private List BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight, - float agentRadius, float agentMaxClimb, List results) - { - // Add tiles to nav mesh - List meshData = new(); - foreach (RecastBuilderResult result in results) - { - int x = result.tileX; - int z = result.tileZ; - NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, - agentRadius, agentMaxClimb, result); - option.tileX = x; - option.tileZ = z; - MeshData md = NavMeshBuilder.CreateNavMeshData(option); - if (md != null) - { - meshData.Add(UpdateAreaAndFlags(md)); - } - } - - return meshData; - } -} diff --git a/src/DotRecast.Recast.Demo/Draw/DebugDraw.cs b/src/DotRecast.Recast.Demo/Draw/DebugDraw.cs index 485bc65..994ea96 100644 --- a/src/DotRecast.Recast.Demo/Draw/DebugDraw.cs +++ b/src/DotRecast.Recast.Demo/Draw/DebugDraw.cs @@ -20,7 +20,7 @@ freely, subject to the following restrictions: using System; using DotRecast.Core; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using Silk.NET.OpenGL; namespace DotRecast.Recast.Demo.Draw; diff --git a/src/DotRecast.Recast.Demo/Draw/NavMeshRenderer.cs b/src/DotRecast.Recast.Demo/Draw/NavMeshRenderer.cs index b16f56d..9a35517 100644 --- a/src/DotRecast.Recast.Demo/Draw/NavMeshRenderer.cs +++ b/src/DotRecast.Recast.Demo/Draw/NavMeshRenderer.cs @@ -21,8 +21,8 @@ freely, subject to the following restrictions: using System.Collections.Generic; using DotRecast.Core; using DotRecast.Detour; -using DotRecast.Recast.Demo.Builder; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Builder; +using DotRecast.Recast.DemoTool.Geom; using DotRecast.Recast.Demo.UI; namespace DotRecast.Recast.Demo.Draw; diff --git a/src/DotRecast.Recast.Demo/Draw/RecastDebugDraw.cs b/src/DotRecast.Recast.Demo/Draw/RecastDebugDraw.cs index 5a95606..5f1a897 100644 --- a/src/DotRecast.Recast.Demo/Draw/RecastDebugDraw.cs +++ b/src/DotRecast.Recast.Demo/Draw/RecastDebugDraw.cs @@ -24,7 +24,7 @@ using System.Numerics; using DotRecast.Core; using DotRecast.Detour; using DotRecast.Detour.QueryResults; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using Silk.NET.OpenGL; namespace DotRecast.Recast.Demo.Draw; diff --git a/src/DotRecast.Recast.Demo/Geom/DemoInputGeomProvider.cs b/src/DotRecast.Recast.Demo/Geom/DemoInputGeomProvider.cs deleted file mode 100644 index 079d3de..0000000 --- a/src/DotRecast.Recast.Demo/Geom/DemoInputGeomProvider.cs +++ /dev/null @@ -1,226 +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. -*/ - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using DotRecast.Core; -using DotRecast.Recast.Geom; - -namespace DotRecast.Recast.Demo.Geom; - -public class DemoInputGeomProvider : IInputGeomProvider -{ - public readonly float[] vertices; - public readonly int[] faces; - public readonly float[] normals; - private readonly RcVec3f bmin; - private readonly RcVec3f bmax; - private readonly List _convexVolumes = new(); - private readonly List offMeshConnections = new(); - private readonly TriMesh _mesh; - - public DemoInputGeomProvider(List vertexPositions, List meshFaces) : - this(MapVertices(vertexPositions), MapFaces(meshFaces)) - { - } - - private static int[] MapFaces(List meshFaces) - { - int[] faces = new int[meshFaces.Count]; - for (int i = 0; i < faces.Length; i++) - { - faces[i] = meshFaces[i]; - } - - return faces; - } - - private static float[] MapVertices(List vertexPositions) - { - float[] vertices = new float[vertexPositions.Count]; - for (int i = 0; i < vertices.Length; i++) - { - vertices[i] = vertexPositions[i]; - } - - return vertices; - } - - public DemoInputGeomProvider(float[] vertices, int[] faces) - { - this.vertices = vertices; - this.faces = faces; - normals = new float[faces.Length]; - CalculateNormals(); - bmin = RcVec3f.Zero; - bmax = RcVec3f.Zero; - RcVec3f.Copy(ref bmin, vertices, 0); - RcVec3f.Copy(ref bmax, vertices, 0); - for (int i = 1; i < vertices.Length / 3; i++) - { - bmin.Min(vertices, i * 3); - bmax.Max(vertices, i * 3); - } - - _mesh = new TriMesh(vertices, faces); - } - - public RcVec3f GetMeshBoundsMin() - { - return bmin; - } - - public RcVec3f GetMeshBoundsMax() - { - return bmax; - } - - public void CalculateNormals() - { - for (int i = 0; i < faces.Length; i += 3) - { - int v0 = faces[i] * 3; - int v1 = faces[i + 1] * 3; - int v2 = faces[i + 2] * 3; - RcVec3f e0 = new RcVec3f(); - RcVec3f e1 = new RcVec3f(); - for (int j = 0; j < 3; ++j) - { - e0[j] = vertices[v1 + j] - vertices[v0 + j]; - e1[j] = vertices[v2 + j] - vertices[v0 + j]; - } - - normals[i] = e0.y * e1.z - e0.z * e1.y; - normals[i + 1] = e0.z * e1.x - e0.x * e1.z; - normals[i + 2] = e0.x * e1.y - e0.y * e1.x; - float d = (float)Math.Sqrt(normals[i] * normals[i] + normals[i + 1] * normals[i + 1] + normals[i + 2] * normals[i + 2]); - if (d > 0) - { - d = 1.0f / d; - normals[i] *= d; - normals[i + 1] *= d; - normals[i + 2] *= d; - } - } - } - - public IList ConvexVolumes() - { - return _convexVolumes; - } - - public IEnumerable Meshes() - { - return ImmutableArray.Create(_mesh); - } - - public List GetOffMeshConnections() - { - return offMeshConnections; - } - - public void AddOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags) - { - offMeshConnections.Add(new DemoOffMeshConnection(start, end, radius, bidir, area, flags)); - } - - public void RemoveOffMeshConnections(Predicate filter) - { - //offMeshConnections.RetainAll(offMeshConnections.Stream().Filter(c -> !filter.Test(c)).Collect(ToList())); - offMeshConnections.RemoveAll(filter); // TODO : 확인 필요 - } - - public float? RaycastMesh(RcVec3f src, RcVec3f dst) - { - // Prune hit ray. - if (!Intersections.IsectSegAABB(src, dst, bmin, bmax, out var btmin, out var btmax)) - { - return null; - } - - float[] p = new float[2]; - float[] q = new float[2]; - p[0] = src.x + (dst.x - src.x) * btmin; - p[1] = src.z + (dst.z - src.z) * btmin; - q[0] = src.x + (dst.x - src.x) * btmax; - q[1] = src.z + (dst.z - src.z) * btmax; - - List chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q); - if (0 == chunks.Count) - { - return null; - } - - float tmin = 1.0f; - bool hit = false; - foreach (ChunkyTriMeshNode chunk in chunks) - { - int[] tris = chunk.tris; - for (int j = 0; j < chunk.tris.Length; j += 3) - { - RcVec3f v1 = RcVec3f.Of( - vertices[tris[j] * 3], - vertices[tris[j] * 3 + 1], - vertices[tris[j] * 3 + 2] - ); - RcVec3f v2 = RcVec3f.Of( - vertices[tris[j + 1] * 3], - vertices[tris[j + 1] * 3 + 1], - vertices[tris[j + 1] * 3 + 2] - ); - RcVec3f v3 = RcVec3f.Of( - vertices[tris[j + 2] * 3], - vertices[tris[j + 2] * 3 + 1], - vertices[tris[j + 2] * 3 + 2] - ); - float? t = Intersections.IntersectSegmentTriangle(src, dst, v1, v2, v3); - if (null != t) - { - if (t.Value < tmin) - { - tmin = t.Value; - } - - hit = true; - } - } - } - - return hit ? tmin : null; - } - - - public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod) - { - ConvexVolume volume = new ConvexVolume(); - volume.verts = verts; - volume.hmin = minh; - volume.hmax = maxh; - volume.areaMod = areaMod; - _convexVolumes.Add(volume); - } - - public void ClearConvexVolumes() - { - _convexVolumes.Clear(); - } -} \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/RecastDemo.cs b/src/DotRecast.Recast.Demo/RecastDemo.cs index ed41406..4de0193 100644 --- a/src/DotRecast.Recast.Demo/RecastDemo.cs +++ b/src/DotRecast.Recast.Demo/RecastDemo.cs @@ -35,9 +35,9 @@ using DotRecast.Core; using DotRecast.Detour; using DotRecast.Detour.Extras.Unity.Astar; using DotRecast.Detour.Io; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using DotRecast.Recast.Demo.Tools; using DotRecast.Recast.Demo.UI; using static DotRecast.Core.RcMath; @@ -385,10 +385,12 @@ public class RecastDemo var renderGl = _gl.GetStringS(GLEnum.Renderer); var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion); - Logger.Debug(vendor); - Logger.Debug(version); - Logger.Debug(renderGl); - Logger.Debug(glslString); + var workingDirectory = Directory.GetCurrentDirectory(); + Logger.Information($"working directory - {workingDirectory}"); + Logger.Information(vendor); + Logger.Information(version); + Logger.Information(renderGl); + Logger.Information(glslString); DemoInputGeomProvider geom = LoadInputMesh(Loader.ToBytes("nav_test.obj")); diff --git a/src/DotRecast.Recast.Demo/Sample.cs b/src/DotRecast.Recast.Demo/Sample.cs index 520f1ab..4602bd2 100644 --- a/src/DotRecast.Recast.Demo/Sample.cs +++ b/src/DotRecast.Recast.Demo/Sample.cs @@ -21,7 +21,7 @@ freely, subject to the following restrictions: using System.Collections.Generic; using DotRecast.Detour; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using DotRecast.Recast.Demo.UI; diff --git a/src/DotRecast.Recast.Demo/Tools/ConvexVolumeTool.cs b/src/DotRecast.Recast.Demo/Tools/ConvexVolumeTool.cs index 43175c1..230fa71 100644 --- a/src/DotRecast.Recast.Demo/Tools/ConvexVolumeTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/ConvexVolumeTool.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; using Silk.NET.Windowing; using DotRecast.Core; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using ImGuiNET; using static DotRecast.Recast.Demo.Draw.DebugDraw; using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives; diff --git a/src/DotRecast.Recast.Demo/Tools/CrowdProfilingTool.cs b/src/DotRecast.Recast.Demo/Tools/CrowdProfilingTool.cs index 76669ce..dbd1152 100644 --- a/src/DotRecast.Recast.Demo/Tools/CrowdProfilingTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/CrowdProfilingTool.cs @@ -24,7 +24,7 @@ using DotRecast.Core; using DotRecast.Detour; using DotRecast.Detour.Crowd; using DotRecast.Detour.QueryResults; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; using ImGuiNET; using Silk.NET.Windowing; diff --git a/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs b/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs index 225e69e..85a8b93 100644 --- a/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs @@ -1,6 +1,7 @@ /* Copyright (c) 2009-2010 Mikko Mononen memon@inside.org recast4j copyright (c) 2021 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 @@ -26,9 +27,9 @@ using DotRecast.Detour; using DotRecast.Detour.Crowd; using DotRecast.Detour.Crowd.Tracking; using DotRecast.Detour.QueryResults; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using ImGuiNET; using static DotRecast.Recast.Demo.Draw.DebugDraw; using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives; diff --git a/src/DotRecast.Recast.Demo/Tools/DemoObjImporter.cs b/src/DotRecast.Recast.Demo/Tools/DemoObjImporter.cs index 74de7e2..2b8730b 100644 --- a/src/DotRecast.Recast.Demo/Tools/DemoObjImporter.cs +++ b/src/DotRecast.Recast.Demo/Tools/DemoObjImporter.cs @@ -1,6 +1,6 @@ using System; using System.IO; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; namespace DotRecast.Recast.Demo.Tools; diff --git a/src/DotRecast.Recast.Demo/Tools/DynamicUpdateTool.cs b/src/DotRecast.Recast.Demo/Tools/DynamicUpdateTool.cs index f823753..bcdf803 100644 --- a/src/DotRecast.Recast.Demo/Tools/DynamicUpdateTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/DynamicUpdateTool.cs @@ -30,9 +30,9 @@ using DotRecast.Core; using DotRecast.Detour.Dynamic; using DotRecast.Detour.Dynamic.Colliders; using DotRecast.Detour.Dynamic.Io; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using DotRecast.Recast.Demo.Tools.Gizmos; using DotRecast.Recast.Demo.UI; using ImGuiNET; diff --git a/src/DotRecast.Recast.Demo/Tools/JumpLinkBuilderTool.cs b/src/DotRecast.Recast.Demo/Tools/JumpLinkBuilderTool.cs index 68e5a67..d003208 100644 --- a/src/DotRecast.Recast.Demo/Tools/JumpLinkBuilderTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/JumpLinkBuilderTool.cs @@ -21,9 +21,9 @@ using System.Linq; using DotRecast.Core; using Silk.NET.Windowing; using DotRecast.Detour.Extras.Jumplink; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using ImGuiNET; using static DotRecast.Core.RcMath; using static DotRecast.Recast.Demo.Draw.DebugDraw; diff --git a/src/DotRecast.Recast.Demo/Tools/OffMeshConnectionTool.cs b/src/DotRecast.Recast.Demo/Tools/OffMeshConnectionTool.cs index 4ef68de..0be4941 100644 --- a/src/DotRecast.Recast.Demo/Tools/OffMeshConnectionTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/OffMeshConnectionTool.cs @@ -21,9 +21,9 @@ freely, subject to the following restrictions: using System; using Silk.NET.Windowing; using DotRecast.Core; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; -using DotRecast.Recast.Demo.Geom; +using DotRecast.Recast.DemoTool.Geom; using ImGuiNET; using static DotRecast.Recast.Demo.Draw.DebugDraw; diff --git a/src/DotRecast.Recast.Demo/Tools/TestNavmeshTool.cs b/src/DotRecast.Recast.Demo/Tools/TestNavmeshTool.cs index cc347e6..181e503 100644 --- a/src/DotRecast.Recast.Demo/Tools/TestNavmeshTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/TestNavmeshTool.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using DotRecast.Core; using DotRecast.Detour; using DotRecast.Detour.QueryResults; -using DotRecast.Recast.Demo.Builder; +using DotRecast.Recast.DemoTool.Builder; using DotRecast.Recast.Demo.Draw; using ImGuiNET; using static DotRecast.Core.RcMath; diff --git a/src/DotRecast.Recast.Demo/UI/ToolsView.cs b/src/DotRecast.Recast.Demo/UI/ToolsView.cs index 30c47c3..41c9554 100644 --- a/src/DotRecast.Recast.Demo/UI/ToolsView.cs +++ b/src/DotRecast.Recast.Demo/UI/ToolsView.cs @@ -1,6 +1,7 @@ /* Copyright (c) 2009-2010 Mikko Mononen memon@inside.org recast4j copyright (c) 2021 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 diff --git a/src/DotRecast.Recast.DemoTool/Builder/AbstractNavMeshBuilder.cs b/src/DotRecast.Recast.DemoTool/Builder/AbstractNavMeshBuilder.cs new file mode 100644 index 0000000..ac25c31 --- /dev/null +++ b/src/DotRecast.Recast.DemoTool/Builder/AbstractNavMeshBuilder.cs @@ -0,0 +1,98 @@ +using DotRecast.Detour; +using DotRecast.Recast.DemoTool.Geom; + +namespace DotRecast.Recast.DemoTool.Builder +{ + public abstract class AbstractNavMeshBuilder + { + protected NavMeshDataCreateParams GetNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize, + float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb, + RecastBuilderResult rcResult) + { + PolyMesh m_pmesh = rcResult.GetMesh(); + PolyMeshDetail m_dmesh = rcResult.GetMeshDetail(); + NavMeshDataCreateParams option = new NavMeshDataCreateParams(); + for (int i = 0; i < m_pmesh.npolys; ++i) + { + m_pmesh.flags[i] = 1; + } + + option.verts = m_pmesh.verts; + option.vertCount = m_pmesh.nverts; + option.polys = m_pmesh.polys; + option.polyAreas = m_pmesh.areas; + option.polyFlags = m_pmesh.flags; + option.polyCount = m_pmesh.npolys; + option.nvp = m_pmesh.nvp; + if (m_dmesh != null) + { + option.detailMeshes = m_dmesh.meshes; + option.detailVerts = m_dmesh.verts; + option.detailVertsCount = m_dmesh.nverts; + option.detailTris = m_dmesh.tris; + option.detailTriCount = m_dmesh.ntris; + } + + option.walkableHeight = m_agentHeight; + option.walkableRadius = m_agentRadius; + option.walkableClimb = m_agentMaxClimb; + option.bmin = m_pmesh.bmin; + option.bmax = m_pmesh.bmax; + option.cs = m_cellSize; + option.ch = m_cellHeight; + option.buildBvTree = true; + + option.offMeshConCount = m_geom.GetOffMeshConnections().Count; + option.offMeshConVerts = new float[option.offMeshConCount * 6]; + option.offMeshConRad = new float[option.offMeshConCount]; + option.offMeshConDir = new int[option.offMeshConCount]; + option.offMeshConAreas = new int[option.offMeshConCount]; + option.offMeshConFlags = new int[option.offMeshConCount]; + option.offMeshConUserID = new int[option.offMeshConCount]; + for (int i = 0; i < option.offMeshConCount; i++) + { + DemoOffMeshConnection offMeshCon = m_geom.GetOffMeshConnections()[i]; + for (int j = 0; j < 6; j++) + { + option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j]; + } + + option.offMeshConRad[i] = offMeshCon.radius; + option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0; + option.offMeshConAreas[i] = offMeshCon.area; + option.offMeshConFlags[i] = offMeshCon.flags; + } + + return option; + } + + protected MeshData UpdateAreaAndFlags(MeshData meshData) + { + // Update poly flags from areas. + for (int i = 0; i < meshData.polys.Length; ++i) + { + if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE) + { + meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND); + } + + if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND + || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS + || meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD) + { + meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK; + } + else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER) + { + meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM; + } + else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR) + { + meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR; + } + } + + return meshData; + } + } +} \ No newline at end of file diff --git a/src/DotRecast.Recast.DemoTool/Builder/SampleAreaModifications.cs b/src/DotRecast.Recast.DemoTool/Builder/SampleAreaModifications.cs new file mode 100644 index 0000000..b99186c --- /dev/null +++ b/src/DotRecast.Recast.DemoTool/Builder/SampleAreaModifications.cs @@ -0,0 +1,68 @@ +/* +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. +*/ + +using System.Collections.Immutable; +using System.Linq; + +namespace DotRecast.Recast.DemoTool.Builder +{ + + public class SampleAreaModifications + { + public const int SAMPLE_POLYAREA_TYPE_GROUND = 0x0; + public const int SAMPLE_POLYAREA_TYPE_WATER = 0x1; + public const int SAMPLE_POLYAREA_TYPE_ROAD = 0x2; + public const int SAMPLE_POLYAREA_TYPE_DOOR = 0x3; + public const int SAMPLE_POLYAREA_TYPE_GRASS = 0x4; + public const int SAMPLE_POLYAREA_TYPE_JUMP = 0x5; + public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6; + public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f; + + public static readonly AreaModification SAMPLE_AREAMOD_WALKABLE = new AreaModification(SAMPLE_POLYAREA_TYPE_WALKABLE); + public static readonly AreaModification SAMPLE_AREAMOD_GROUND = new AreaModification(SAMPLE_POLYAREA_TYPE_GROUND); + public static readonly AreaModification SAMPLE_AREAMOD_WATER = new AreaModification(SAMPLE_POLYAREA_TYPE_WATER); + public static readonly AreaModification SAMPLE_AREAMOD_ROAD = new AreaModification(SAMPLE_POLYAREA_TYPE_ROAD); + public static readonly AreaModification SAMPLE_AREAMOD_GRASS = new AreaModification(SAMPLE_POLYAREA_TYPE_GRASS); + public static readonly AreaModification SAMPLE_AREAMOD_DOOR = new AreaModification(SAMPLE_POLYAREA_TYPE_DOOR); + public static readonly AreaModification SAMPLE_AREAMOD_JUMP = new AreaModification(SAMPLE_POLYAREA_TYPE_JUMP); + + public static readonly ImmutableArray Values = ImmutableArray.Create( + SAMPLE_AREAMOD_WALKABLE, + SAMPLE_AREAMOD_GROUND, + SAMPLE_AREAMOD_WATER, + SAMPLE_AREAMOD_ROAD, + SAMPLE_AREAMOD_GRASS, + SAMPLE_AREAMOD_DOOR, + SAMPLE_AREAMOD_JUMP + ); + + public static AreaModification OfValue(int value) + { + return Values.FirstOrDefault(x => x.Value == value) ?? SAMPLE_AREAMOD_GRASS; + } + + public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road) + public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water). + public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors. + public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump. + public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon + public static readonly int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities. + } +} \ No newline at end of file diff --git a/src/DotRecast.Recast.DemoTool/Builder/SoloNavMeshBuilder.cs b/src/DotRecast.Recast.DemoTool/Builder/SoloNavMeshBuilder.cs new file mode 100644 index 0000000..f885b25 --- /dev/null +++ b/src/DotRecast.Recast.DemoTool/Builder/SoloNavMeshBuilder.cs @@ -0,0 +1,73 @@ +/* +recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org + +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. +*/ + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using DotRecast.Detour; +using DotRecast.Recast.DemoTool.Geom; + +namespace DotRecast.Recast.DemoTool.Builder +{ + public class SoloNavMeshBuilder : AbstractNavMeshBuilder + { + public Tuple, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType, + float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, + float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, + int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, + bool filterLedgeSpans, bool filterWalkableLowHeightSpans) + { + RecastBuilderResult rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight, + agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError, + vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans, + filterWalkableLowHeightSpans); + return Tuple.Create(ImmutableArray.Create(rcResult) as IList, + BuildNavMesh( + BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult), + vertsPerPoly)); + } + + private NavMesh BuildNavMesh(MeshData meshData, int vertsPerPoly) + { + return new NavMesh(meshData, vertsPerPoly, 0); + } + + private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, float cellSize, + float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, float agentMaxSlope, + int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, int vertsPerPoly, + float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans, + bool filterWalkableLowHeightSpans) + { + RecastConfig cfg = new RecastConfig(partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, + filterLedgeSpans, filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, regionMinSize, + regionMergeSize, edgeMaxLen, edgeMaxError, vertsPerPoly, detailSampleDist, detailSampleMaxError, + SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true); + RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax()); + RecastBuilder rcBuilder = new RecastBuilder(); + return rcBuilder.Build(geom, bcfg); + } + + private MeshData BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight, + float agentRadius, float agentMaxClimb, RecastBuilderResult result) + { + NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, + agentMaxClimb, result); + return UpdateAreaAndFlags(NavMeshBuilder.CreateNavMeshData(option)); + } + } +} \ No newline at end of file diff --git a/src/DotRecast.Recast.DemoTool/Builder/TileNavMeshBuilder.cs b/src/DotRecast.Recast.DemoTool/Builder/TileNavMeshBuilder.cs new file mode 100644 index 0000000..5280ed2 --- /dev/null +++ b/src/DotRecast.Recast.DemoTool/Builder/TileNavMeshBuilder.cs @@ -0,0 +1,138 @@ +/* +recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org + +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. +*/ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using DotRecast.Core; +using DotRecast.Detour; +using DotRecast.Recast.DemoTool.Geom; +using static DotRecast.Core.RcMath; + +namespace DotRecast.Recast.DemoTool.Builder +{ + public class TileNavMeshBuilder : AbstractNavMeshBuilder + { + public TileNavMeshBuilder() + { + } + + public Tuple, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType, + float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, + float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, + int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, + bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize) + { + List rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight, + agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError, + vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans, + filterWalkableLowHeightSpans, tileSize); + return Tuple.Create((IList)rcResult, + BuildNavMesh(geom, + BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult), + cellSize, tileSize, vertsPerPoly)); + } + + private List BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, + float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, + float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, + int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, + bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize) + { + RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.CalcBorder(agentRadius, cellSize), + partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, filterLedgeSpans, + filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, + regionMinSize * regionMinSize * cellSize * cellSize, + regionMergeSize * regionMergeSize * cellSize * cellSize, edgeMaxLen, edgeMaxError, vertsPerPoly, + true, detailSampleDist, detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE); + RecastBuilder rcBuilder = new RecastBuilder(); + return rcBuilder.BuildTiles(geom, cfg, Task.Factory); + } + + private NavMesh BuildNavMesh(DemoInputGeomProvider geom, List meshData, float cellSize, int tileSize, + int vertsPerPoly) + { + NavMeshParams navMeshParams = new NavMeshParams(); + navMeshParams.orig.x = geom.GetMeshBoundsMin().x; + navMeshParams.orig.y = geom.GetMeshBoundsMin().y; + navMeshParams.orig.z = geom.GetMeshBoundsMin().z; + navMeshParams.tileWidth = tileSize * cellSize; + navMeshParams.tileHeight = tileSize * cellSize; + + // Snprintf(text, 64, "Tiles %d x %d", tw, th); + + navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize); + navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize); + NavMesh navMesh = new NavMesh(navMeshParams, vertsPerPoly); + meshData.ForEach(md => navMesh.AddTile(md, 0, 0)); + return navMesh; + } + + public int GetMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize) + { + int tileBits = GetTileBits(geom, cellSize, tileSize); + return 1 << tileBits; + } + + public int GetMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize) + { + int polyBits = 22 - GetTileBits(geom, cellSize, tileSize); + return 1 << polyBits; + } + + private int GetTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize) + { + Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); + int tw = (gw + tileSize - 1) / tileSize; + int th = (gh + tileSize - 1) / tileSize; + int tileBits = Math.Min(DetourCommon.Ilog2(DetourCommon.NextPow2(tw * th)), 14); + return tileBits; + } + + public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize) + { + Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh); + int tw = (gw + tileSize - 1) / tileSize; + int th = (gh + tileSize - 1) / tileSize; + return new int[] { tw, th }; + } + + private List BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight, + float agentRadius, float agentMaxClimb, List results) + { + // Add tiles to nav mesh + List meshData = new List(); + foreach (RecastBuilderResult result in results) + { + int x = result.tileX; + int z = result.tileZ; + NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, + agentRadius, agentMaxClimb, result); + option.tileX = x; + option.tileZ = z; + MeshData md = NavMeshBuilder.CreateNavMeshData(option); + if (md != null) + { + meshData.Add(UpdateAreaAndFlags(md)); + } + } + + return meshData; + } + } +} \ No newline at end of file diff --git a/src/DotRecast.Recast.DemoTool/Geom/DemoInputGeomProvider.cs b/src/DotRecast.Recast.DemoTool/Geom/DemoInputGeomProvider.cs new file mode 100644 index 0000000..e89a961 --- /dev/null +++ b/src/DotRecast.Recast.DemoTool/Geom/DemoInputGeomProvider.cs @@ -0,0 +1,228 @@ +/* +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. +*/ + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using DotRecast.Core; +using DotRecast.Recast.Geom; + +namespace DotRecast.Recast.DemoTool.Geom +{ + public class DemoInputGeomProvider : IInputGeomProvider + { + public readonly float[] vertices; + public readonly int[] faces; + public readonly float[] normals; + private readonly RcVec3f bmin; + private readonly RcVec3f bmax; + private readonly List _convexVolumes = new List(); + private readonly List offMeshConnections = new List(); + private readonly TriMesh _mesh; + + public DemoInputGeomProvider(List vertexPositions, List meshFaces) : + this(MapVertices(vertexPositions), MapFaces(meshFaces)) + { + } + + private static int[] MapFaces(List meshFaces) + { + int[] faces = new int[meshFaces.Count]; + for (int i = 0; i < faces.Length; i++) + { + faces[i] = meshFaces[i]; + } + + return faces; + } + + private static float[] MapVertices(List vertexPositions) + { + float[] vertices = new float[vertexPositions.Count]; + for (int i = 0; i < vertices.Length; i++) + { + vertices[i] = vertexPositions[i]; + } + + return vertices; + } + + public DemoInputGeomProvider(float[] vertices, int[] faces) + { + this.vertices = vertices; + this.faces = faces; + normals = new float[faces.Length]; + CalculateNormals(); + bmin = RcVec3f.Zero; + bmax = RcVec3f.Zero; + RcVec3f.Copy(ref bmin, vertices, 0); + RcVec3f.Copy(ref bmax, vertices, 0); + for (int i = 1; i < vertices.Length / 3; i++) + { + bmin.Min(vertices, i * 3); + bmax.Max(vertices, i * 3); + } + + _mesh = new TriMesh(vertices, faces); + } + + public RcVec3f GetMeshBoundsMin() + { + return bmin; + } + + public RcVec3f GetMeshBoundsMax() + { + return bmax; + } + + public void CalculateNormals() + { + for (int i = 0; i < faces.Length; i += 3) + { + int v0 = faces[i] * 3; + int v1 = faces[i + 1] * 3; + int v2 = faces[i + 2] * 3; + RcVec3f e0 = new RcVec3f(); + RcVec3f e1 = new RcVec3f(); + for (int j = 0; j < 3; ++j) + { + e0[j] = vertices[v1 + j] - vertices[v0 + j]; + e1[j] = vertices[v2 + j] - vertices[v0 + j]; + } + + normals[i] = e0.y * e1.z - e0.z * e1.y; + normals[i + 1] = e0.z * e1.x - e0.x * e1.z; + normals[i + 2] = e0.x * e1.y - e0.y * e1.x; + float d = (float)Math.Sqrt(normals[i] * normals[i] + normals[i + 1] * normals[i + 1] + normals[i + 2] * normals[i + 2]); + if (d > 0) + { + d = 1.0f / d; + normals[i] *= d; + normals[i + 1] *= d; + normals[i + 2] *= d; + } + } + } + + public IList ConvexVolumes() + { + return _convexVolumes; + } + + public IEnumerable Meshes() + { + return ImmutableArray.Create(_mesh); + } + + public List GetOffMeshConnections() + { + return offMeshConnections; + } + + public void AddOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags) + { + offMeshConnections.Add(new DemoOffMeshConnection(start, end, radius, bidir, area, flags)); + } + + public void RemoveOffMeshConnections(Predicate filter) + { + //offMeshConnections.RetainAll(offMeshConnections.Stream().Filter(c -> !filter.Test(c)).Collect(ToList())); + offMeshConnections.RemoveAll(filter); // TODO : 확인 필요 + } + + public float? RaycastMesh(RcVec3f src, RcVec3f dst) + { + // Prune hit ray. + if (!Intersections.IsectSegAABB(src, dst, bmin, bmax, out var btmin, out var btmax)) + { + return null; + } + + float[] p = new float[2]; + float[] q = new float[2]; + p[0] = src.x + (dst.x - src.x) * btmin; + p[1] = src.z + (dst.z - src.z) * btmin; + q[0] = src.x + (dst.x - src.x) * btmax; + q[1] = src.z + (dst.z - src.z) * btmax; + + List chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q); + if (0 == chunks.Count) + { + return null; + } + + float? tmin = 1.0f; + bool hit = false; + foreach (ChunkyTriMeshNode chunk in chunks) + { + int[] tris = chunk.tris; + for (int j = 0; j < chunk.tris.Length; j += 3) + { + RcVec3f v1 = RcVec3f.Of( + vertices[tris[j] * 3], + vertices[tris[j] * 3 + 1], + vertices[tris[j] * 3 + 2] + ); + RcVec3f v2 = RcVec3f.Of( + vertices[tris[j + 1] * 3], + vertices[tris[j + 1] * 3 + 1], + vertices[tris[j + 1] * 3 + 2] + ); + RcVec3f v3 = RcVec3f.Of( + vertices[tris[j + 2] * 3], + vertices[tris[j + 2] * 3 + 1], + vertices[tris[j + 2] * 3 + 2] + ); + float? t = Intersections.IntersectSegmentTriangle(src, dst, v1, v2, v3); + if (null != t) + { + if (t.Value < tmin) + { + tmin = t.Value; + } + + hit = true; + } + } + } + + return hit + ? tmin + : null; + } + + + public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod) + { + ConvexVolume volume = new ConvexVolume(); + volume.verts = verts; + volume.hmin = minh; + volume.hmax = maxh; + volume.areaMod = areaMod; + _convexVolumes.Add(volume); + } + + public void ClearConvexVolumes() + { + _convexVolumes.Clear(); + } + } +} \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/Geom/DemoOffMeshConnection.cs b/src/DotRecast.Recast.DemoTool/Geom/DemoOffMeshConnection.cs similarity index 58% rename from src/DotRecast.Recast.Demo/Geom/DemoOffMeshConnection.cs rename to src/DotRecast.Recast.DemoTool/Geom/DemoOffMeshConnection.cs index ee83cd2..16d9caa 100644 --- a/src/DotRecast.Recast.Demo/Geom/DemoOffMeshConnection.cs +++ b/src/DotRecast.Recast.DemoTool/Geom/DemoOffMeshConnection.cs @@ -20,28 +20,29 @@ freely, subject to the following restrictions: using DotRecast.Core; -namespace DotRecast.Recast.Demo.Geom; - -public class DemoOffMeshConnection +namespace DotRecast.Recast.DemoTool.Geom { - public readonly float[] verts; - public readonly float radius; - public readonly bool bidir; - public readonly int area; - public readonly int flags; - - public DemoOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags) + public class DemoOffMeshConnection { - verts = new float[6]; - verts[0] = start.x; - verts[1] = start.y; - verts[2] = start.z; - verts[3] = end.x; - verts[4] = end.y; - verts[5] = end.z; - this.radius = radius; - this.bidir = bidir; - this.area = area; - this.flags = flags; + public readonly float[] verts; + public readonly float radius; + public readonly bool bidir; + public readonly int area; + public readonly int flags; + + public DemoOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags) + { + verts = new float[6]; + verts[0] = start.x; + verts[1] = start.y; + verts[2] = start.z; + verts[3] = end.x; + verts[4] = end.y; + verts[5] = end.z; + this.radius = radius; + this.bidir = bidir; + this.area = area; + this.flags = flags; + } } -} +} \ No newline at end of file diff --git a/src/DotRecast.Recast/PolyMesh.cs b/src/DotRecast.Recast/PolyMesh.cs index c6b2a07..f937794 100644 --- a/src/DotRecast.Recast/PolyMesh.cs +++ b/src/DotRecast.Recast/PolyMesh.cs @@ -1,6 +1,7 @@ /* Copyright (c) 2009-2010 Mikko Mononen memon@inside.org Recast4J Copyright (c) 2015 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 diff --git a/src/DotRecast.Recast/PolyUtils.cs b/src/DotRecast.Recast/PolyUtils.cs index 64baabd..7aa61bd 100644 --- a/src/DotRecast.Recast/PolyUtils.cs +++ b/src/DotRecast.Recast/PolyUtils.cs @@ -1,6 +1,7 @@ /* Copyright (c) 2009-2010 Mikko Mononen memon@inside.org recast4j copyright (c) 2021 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