From c296685e3218d1842b95f1b7d0309668ae70b86c Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Mon, 5 Aug 2024 23:29:58 -0400 Subject: [PATCH] Moved navmesh into its own object and started serialization & deserialization of nav mesh --- Nuake/src/AI/NavManager.cpp | 15 +++- Nuake/src/AI/NavManager.h | 4 +- Nuake/src/AI/NavMesh.cpp | 165 ++++++++++++++++++++++++++++++++++++ Nuake/src/AI/NavMesh.h | 30 +++++++ 4 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 Nuake/src/AI/NavMesh.cpp create mode 100644 Nuake/src/AI/NavMesh.h diff --git a/Nuake/src/AI/NavManager.cpp b/Nuake/src/AI/NavManager.cpp index 01cb9d12..a3f0e716 100644 --- a/Nuake/src/AI/NavManager.cpp +++ b/Nuake/src/AI/NavManager.cpp @@ -13,6 +13,7 @@ #include "src/Core/Maths.h" #include "src/AI/RecastConfig.h" +#include "NavMesh.h" namespace Nuake { @@ -31,7 +32,7 @@ namespace Nuake { m_Meshes.push_back({ mesh, transform }); } - void NavManager::BuildNavMesh(const RecastConfig& config) + Ref NavManager::BuildNavMesh(const RecastConfig& config) { // Merge all meshes togheter std::vector vertices; @@ -277,7 +278,16 @@ namespace Nuake { Logger::Log("Could not init Detour navmesh query", "NavManager", CRITICAL); } + Ref navMesh = CreateRef(m_DetourNavMesh, m_DetourNavQuery); + + const std::string& deserializedNavMesh = navMesh->Serialize().dump(4); + Logger::Log(deserializedNavMesh, "debug", VERBOSE); + + Ref navMesh2 = CreateRef(); + navMesh->Deserialize(json::parse(deserializedNavMesh)); m_Meshes.clear(); + + return navMesh; } void NavManager::DrawNavMesh() @@ -345,9 +355,6 @@ namespace Nuake { } } } - - } - } \ No newline at end of file diff --git a/Nuake/src/AI/NavManager.h b/Nuake/src/AI/NavManager.h index 0aca9cea..21aaef01 100644 --- a/Nuake/src/AI/NavManager.h +++ b/Nuake/src/AI/NavManager.h @@ -1,6 +1,8 @@ #pragma once #include "src/Core/Core.h" #include "src/Rendering/Mesh/Mesh.h" +#include "src/AI/NavMesh.h" + #include "NavMeshDebugDrawer.h" class rcContext; @@ -30,7 +32,7 @@ namespace Nuake { void Initialize(); void PushMesh(const Ref& mesh, const Matrix4& transform); - void BuildNavMesh(const RecastConfig& config); + Ref BuildNavMesh(const RecastConfig& config); void DrawNavMesh(); diff --git a/Nuake/src/AI/NavMesh.cpp b/Nuake/src/AI/NavMesh.cpp new file mode 100644 index 00000000..12fcdf16 --- /dev/null +++ b/Nuake/src/AI/NavMesh.cpp @@ -0,0 +1,165 @@ +#include "NavMesh.h" +#include "Recast.h" +#include "src/Core/String.h" +#include +#include "DetourNavMeshQuery.h" +#include + +namespace Nuake { + + struct NavMeshTileHeader + { + dtTileRef tileRef; + int dataSize; + }; + + struct NavMeshSetHeader + { + int magic; + int version; + int numTiles; + dtNavMeshParams params; + }; + + NavMesh::NavMesh(dtNavMesh* navMesh, dtNavMeshQuery* navMeshQuery) + { + m_DetourNavMesh = navMesh; + m_DetourNavQuery = navMeshQuery; + } + + int NavMesh::FindNearestPolygon(const Vector3& searchPosition, const Vector3& searchBox) + { + float nearestPoint[3]; + float searchPos[3] = { searchPosition.x, searchPosition.y, searchPosition.z }; + float searchExtent[3] = { searchBox.x, searchBox.y, searchBox.z}; + + dtQueryFilter filter; + filter.setIncludeFlags(1); + + dtPolyRef resultPoly = 0; + dtStatus status = m_DetourNavQuery->findNearestPoly(searchPos, searchExtent, &filter, &resultPoly, nearestPoint); + return resultPoly; + } + + std::vector NavMesh::FindPath(int polyStart, int polyEnd, const Vector3& nearestPointStart, const Vector3& nearestPointEnd, const int maxPoly) + { + dtNavMesh* mesh = dtAllocNavMesh(); + + return std::vector(); + } + + json NavMesh::Serialize() + { + BEGIN_SERIALIZE(); + + // Get number of tiles + nlohmann::json headerJson; + headerJson["magic"] = 1337; + headerJson["version"] = 1; + + int numTiles = 0; + const auto* navMesh = m_DetourNavMesh; + for (int i = 0; i < m_DetourNavMesh->getMaxTiles(); i++) + { + const dtMeshTile* tile = navMesh->getTile(i); + if (!tile || !tile->header || !tile->dataSize) continue; + numTiles++; + } + + const dtNavMeshParams* params = navMesh->getParams(); + if (params) + { + nlohmann::json paramsJson; + paramsJson["orig[0]"] = params->orig[0]; + paramsJson["orig[1]"] = params->orig[1]; + paramsJson["orig[2]"] = params->orig[2]; + paramsJson["tileWidth"] = params->tileWidth; + paramsJson["tileHeight"] = params->tileHeight; + paramsJson["maxTiles"] = params->maxTiles; + paramsJson["maxPolys"] = params->maxPolys; + + headerJson["params"] = paramsJson; + } + + headerJson["numTiles"] = numTiles; + + std::vector tilesJson; + for (int i = 0; i < m_DetourNavMesh->getMaxTiles(); i++) + { + const dtMeshTile* tile = navMesh->getTile(i); + if (!tile || !tile->header || !tile->dataSize) continue; + + nlohmann::json tileJson; + tileJson["tileRef"] = m_DetourNavMesh->getTileRef(tile); + tileJson["dataSize"] = tile->dataSize; + + // Serialize tile data as base64 + std::vector tileData(tile->data, tile->data + tile->dataSize); + tileJson["data"] = String::Base64Encode(tileData); + + tilesJson.push_back(tileJson); + } + + j["header"] = headerJson; + j["tiles"] = tilesJson; + + END_SERIALIZE(); + } + + bool NavMesh::Deserialize(const json& j) + { + if (j.contains("header")) + { + int magicNumber = j["header"]["magic"]; + int version = j["header"]["version"]; + int numTiles = j["header"]["numTiles"]; + } + + + //dtStatus status = mesh->init(&header.params); + dtNavMesh* mesh = dtAllocNavMesh(); + + dtNavMeshParams params; + params.orig[0] = j["header"]["params"]["orig[0]"].get(); + params.orig[1] = j["header"]["params"]["orig[1]"].get(); + params.orig[2] = j["header"]["params"]["orig[2]"].get(); + params.tileWidth = j["header"]["params"]["tileWidth"].get(); + params.tileHeight = j["header"]["params"]["tileHeight"].get(); + params.maxTiles = j["header"]["params"]["maxTiles"].get(); + params.maxPolys = j["header"]["params"]["maxPolys"].get(); + + dtStatus status = mesh->init(¶ms); + if (dtStatusFailed(status)) + { + return false; + } + + for (const auto& tileJson : j["tiles"]) + { + auto dataSize = tileJson["dataSize"].get(); + std::string base64Data = tileJson["data"].get(); + + // Decode Base64 data + std::vector tileData = String::Base64Decode(base64Data); + + if (dataSize != tileData.size()) + { + Logger::Log("Tile data size mismatch", "navmesh", CRITICAL); + continue; + } + + auto data = new uint8_t[dataSize]; + std::memcpy(data, tileData.data(), dataSize); + + mesh->addTile(data, dataSize, DT_TILE_FREE_DATA, tileJson["tileRef"].get(), 0); + } + + return true; + } + + NavMesh::~NavMesh() + { + delete m_DetourNavMesh; + delete m_DetourNavQuery; + } +} \ No newline at end of file diff --git a/Nuake/src/AI/NavMesh.h b/Nuake/src/AI/NavMesh.h new file mode 100644 index 00000000..2d30b2b3 --- /dev/null +++ b/Nuake/src/AI/NavMesh.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "src/Resource/Serializable.h" +#include +#include + +namespace Nuake { + + class NavMesh : ISerializable { + + public: + NavMesh(dtNavMesh* navMesh, dtNavMeshQuery* navMeshQuery); + NavMesh() = default; + ~NavMesh(); + + // Query + int FindNearestPolygon(const Vector3 & searchPosition, const Vector3 & searchBox); + + std::vector FindPath(int polyStart, int polyEnd, const Vector3& nearestPointStart, const Vector3& nearestPointEnd, const int maxPoly); + + json Serialize() override; + bool Deserialize(const json& j) override; + + private: + const dtMeshTile* GetTile(int i) const; + + dtNavMesh* m_DetourNavMesh; + dtNavMeshQuery* m_DetourNavQuery; + }; +} \ No newline at end of file