2023-03-14 08:02:43 +03:00
|
|
|
/*
|
|
|
|
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.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using DotRecast.Core;
|
|
|
|
using DotRecast.Detour.Extras.Unity.Astar;
|
|
|
|
using DotRecast.Detour.Io;
|
2023-04-23 08:13:10 +03:00
|
|
|
using DotRecast.Detour.QueryResults;
|
2023-03-14 08:02:43 +03:00
|
|
|
using NUnit.Framework;
|
|
|
|
|
|
|
|
namespace DotRecast.Detour.Extras.Test.Unity.Astar;
|
|
|
|
|
2023-04-25 17:22:44 +03:00
|
|
|
[Parallelizable]
|
2023-03-16 19:48:49 +03:00
|
|
|
public class UnityAStarPathfindingImporterTest
|
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
[Test]
|
2023-05-05 02:44:48 +03:00
|
|
|
public void Test_v4_0_6()
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-05-05 02:44:48 +03:00
|
|
|
NavMesh mesh = LoadNavMesh("graph.zip");
|
2023-03-29 18:59:00 +03:00
|
|
|
Vector3f startPos = Vector3f.Of(8.200293f, 2.155071f, -26.176147f);
|
|
|
|
Vector3f endPos = Vector3f.Of(11.971109f, 0.000000f, 8.663261f);
|
2023-05-05 02:44:48 +03:00
|
|
|
Result<List<long>> path = FindPath(mesh, startPos, endPos);
|
2023-03-14 08:02:43 +03:00
|
|
|
Assert.That(path.status, Is.EqualTo(Status.SUCCSESS));
|
|
|
|
Assert.That(path.result.Count, Is.EqualTo(57));
|
2023-05-05 02:44:48 +03:00
|
|
|
SaveMesh(mesh, "v4_0_6");
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
2023-05-05 02:44:48 +03:00
|
|
|
public void Test_v4_1_16()
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-05-05 02:44:48 +03:00
|
|
|
NavMesh mesh = LoadNavMesh("graph_v4_1_16.zip");
|
2023-03-29 18:59:00 +03:00
|
|
|
Vector3f startPos = Vector3f.Of(22.93f, -2.37f, -5.11f);
|
|
|
|
Vector3f endPos = Vector3f.Of(16.81f, -2.37f, 25.52f);
|
2023-05-05 02:44:48 +03:00
|
|
|
Result<List<long>> path = FindPath(mesh, startPos, endPos);
|
|
|
|
Assert.That(path.status.IsSuccess(), Is.True);
|
2023-03-14 08:02:43 +03:00
|
|
|
Assert.That(path.result.Count, Is.EqualTo(15));
|
2023-05-05 02:44:48 +03:00
|
|
|
SaveMesh(mesh, "v4_1_16");
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
2023-05-05 02:44:48 +03:00
|
|
|
public void TestBoundsTree()
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-05-05 02:44:48 +03:00
|
|
|
NavMesh mesh = LoadNavMesh("test_boundstree.zip");
|
2023-03-29 18:59:00 +03:00
|
|
|
Vector3f position = Vector3f.Of(387.52988f, 19.997f, 368.86282f);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
int[] tilePos = mesh.CalcTileLoc(position);
|
|
|
|
long tileRef = mesh.GetTileRefAt(tilePos[0], tilePos[1], 0);
|
|
|
|
MeshTile tile = mesh.GetTileByRef(tileRef);
|
2023-03-14 08:02:43 +03:00
|
|
|
MeshData data = tile.data;
|
|
|
|
BVNode[] bvNodes = data.bvTree;
|
|
|
|
data.bvTree = null; // set BV-Tree empty to get 'clear' search poly without BV
|
2023-05-05 02:44:48 +03:00
|
|
|
FindNearestPolyResult clearResult = GetNearestPolys(mesh, position)[0]; // check poly to exists
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
// restore BV-Tree and try search again
|
|
|
|
// important aspect in that test: BV result must equals result without BV
|
|
|
|
// if poly not found or found other poly - tile bounds is wrong!
|
|
|
|
data.bvTree = bvNodes;
|
2023-05-05 02:44:48 +03:00
|
|
|
FindNearestPolyResult bvResult = GetNearestPolys(mesh, position)[0];
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
Assert.That(bvResult.GetNearestRef(), Is.EqualTo(clearResult.GetNearestRef()));
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
private NavMesh LoadNavMesh(string filename)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
var filepath = Loader.ToRPath(filename);
|
2023-04-29 13:48:19 +03:00
|
|
|
using var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
// Import the graphs
|
|
|
|
UnityAStarPathfindingImporter importer = new UnityAStarPathfindingImporter();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
NavMesh[] meshes = importer.Load(fs);
|
2023-03-14 08:02:43 +03:00
|
|
|
return meshes[0];
|
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
private Result<List<long>> FindPath(NavMesh mesh, Vector3f startPos, Vector3f endPos)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
// Perform a simple pathfinding
|
|
|
|
NavMeshQuery query = new NavMeshQuery(mesh);
|
2023-05-05 03:06:43 +03:00
|
|
|
IQueryFilter filter = new DefaultQueryFilter();
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
FindNearestPolyResult[] polys = GetNearestPolys(mesh, startPos, endPos);
|
|
|
|
return query.FindPath(polys[0].GetNearestRef(), polys[1].GetNearestRef(), startPos, endPos, filter);
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
private FindNearestPolyResult[] GetNearestPolys(NavMesh mesh, params Vector3f[] positions)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
NavMeshQuery query = new NavMeshQuery(mesh);
|
2023-05-05 03:06:43 +03:00
|
|
|
IQueryFilter filter = new DefaultQueryFilter();
|
2023-03-29 18:59:00 +03:00
|
|
|
Vector3f extents = Vector3f.Of(0.1f, 0.1f, 0.1f);
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
FindNearestPolyResult[] results = new FindNearestPolyResult[positions.Length];
|
2023-03-16 19:48:49 +03:00
|
|
|
for (int i = 0; i < results.Length; i++)
|
|
|
|
{
|
2023-03-29 18:59:00 +03:00
|
|
|
Vector3f position = positions[i];
|
2023-05-05 02:44:48 +03:00
|
|
|
Result<FindNearestPolyResult> result = query.FindNearestPoly(position, extents, filter);
|
2023-04-28 17:22:09 +03:00
|
|
|
Assert.That(result.Succeeded(), Is.True);
|
2023-05-05 02:44:48 +03:00
|
|
|
Assert.That(result.result.GetNearestPos(), Is.Not.EqualTo(Vector3f.Zero), "Nearest start position is null!");
|
2023-03-14 08:02:43 +03:00
|
|
|
results[i] = result.result;
|
|
|
|
}
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-03-14 08:02:43 +03:00
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
private void SaveMesh(NavMesh mesh, string filePostfix)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
// Set the flag to RecastDemo work properly
|
2023-05-05 02:44:48 +03:00
|
|
|
for (int i = 0; i < mesh.GetTileCount(); i++)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-05-05 02:44:48 +03:00
|
|
|
foreach (Poly p in mesh.GetTile(i).data.polys)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-03-14 08:02:43 +03:00
|
|
|
p.flags = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save the mesh as recast file,
|
|
|
|
MeshSetWriter writer = new MeshSetWriter();
|
|
|
|
string filename = $"all_tiles_navmesh_{filePostfix}.bin";
|
|
|
|
string filepath = Path.Combine("test-output", filename);
|
|
|
|
using var fs = new FileStream(filename, FileMode.Create);
|
|
|
|
using var os = new BinaryWriter(fs);
|
2023-05-05 02:44:48 +03:00
|
|
|
writer.Write(os, mesh, ByteOrder.LITTLE_ENDIAN, true);
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
2023-04-29 07:29:40 +03:00
|
|
|
}
|