diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 0683a43bc1..49339ebdff 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -38,8 +38,14 @@ namespace DetourNavigator return stream << "failed"; case UpdateNavMeshStatus::lost: return stream << "lost"; + case UpdateNavMeshStatus::cached: + return stream << "cached"; + case UpdateNavMeshStatus::unchanged: + return stream << "unchanged"; + case UpdateNavMeshStatus::restored: + return stream << "restored"; } - return stream << "unknown"; + return stream << "unknown(" << static_cast(value) << ")"; } AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager, diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index beee95113c..7c7dcf1864 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -559,6 +559,7 @@ namespace DetourNavigator } auto cachedNavMeshData = navMeshTilesCache.get(agentHalfExtents, changedTile, *recastMesh, offMeshConnections); + bool cached = static_cast(cachedNavMeshData); if (!cachedNavMeshData) { @@ -584,6 +585,7 @@ namespace DetourNavigator { cachedNavMeshData = navMeshTilesCache.get(agentHalfExtents, changedTile, *recastMesh, offMeshConnections); + cached = static_cast(cachedNavMeshData); } if (!cachedNavMeshData) @@ -593,6 +595,8 @@ namespace DetourNavigator } } - return navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData)); + const auto updateStatus = navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData)); + + return UpdateNavMeshStatusBuilder(updateStatus).cached(cached).getResult(); } } diff --git a/components/detournavigator/navmeshcacheitem.hpp b/components/detournavigator/navmeshcacheitem.hpp index f133413971..76f74f2667 100644 --- a/components/detournavigator/navmeshcacheitem.hpp +++ b/components/detournavigator/navmeshcacheitem.hpp @@ -22,6 +22,9 @@ namespace DetourNavigator replaced = removed | added, failed = 1 << 2, lost = removed | failed, + cached = 1 << 3, + unchanged = replaced | cached, + restored = added | cached, }; inline bool isSuccess(UpdateNavMeshStatus value) @@ -34,6 +37,9 @@ namespace DetourNavigator public: UpdateNavMeshStatusBuilder() = default; + explicit UpdateNavMeshStatusBuilder(UpdateNavMeshStatus value) + : mResult(value) {} + UpdateNavMeshStatusBuilder removed(bool value) { if (value) @@ -61,6 +67,15 @@ namespace DetourNavigator return *this; } + UpdateNavMeshStatusBuilder cached(bool value) + { + if (value) + set(UpdateNavMeshStatus::cached); + else + unset(UpdateNavMeshStatus::cached); + return *this; + } + UpdateNavMeshStatus getResult() const { return mResult; @@ -143,7 +158,7 @@ namespace DetourNavigator UpdateNavMeshStatus removeTile(const TilePosition& position) { - const auto removed = dtStatusSucceed(removeTileImpl(position)); + const auto removed = removeTileImpl(position); if (removed) removeUsedTile(position); return UpdateNavMeshStatusBuilder().removed(removed).getResult(); @@ -181,13 +196,15 @@ namespace DetourNavigator return mImpl->addTile(data, size, doNotTransferOwnership, lastRef, result); } - dtStatus removeTileImpl(const TilePosition& position) + bool removeTileImpl(const TilePosition& position) { const int layer = 0; const auto tileRef = mImpl->getTileRefAt(position.x(), position.y(), layer); + if (tileRef == 0) + return false; unsigned char** const data = nullptr; int* const dataSize = nullptr; - return mImpl->removeTile(tileRef, data, dataSize); + return dtStatusSucceed(mImpl->removeTile(tileRef, data, dataSize)); } }; diff --git a/components/detournavigator/navmeshtilescache.cpp b/components/detournavigator/navmeshtilescache.cpp index 466d2e708d..f554cd4143 100644 --- a/components/detournavigator/navmeshtilescache.cpp +++ b/components/detournavigator/navmeshtilescache.cpp @@ -9,42 +9,32 @@ namespace DetourNavigator { namespace { - inline std::string makeNavMeshKey(const RecastMesh& recastMesh, + inline std::vector makeNavMeshKey(const RecastMesh& recastMesh, const std::vector& offMeshConnections) { - std::string result; - result.reserve( - recastMesh.getIndices().size() * sizeof(int) - + recastMesh.getVertices().size() * sizeof(float) - + recastMesh.getAreaTypes().size() * sizeof(AreaType) - + recastMesh.getWater().size() * sizeof(RecastMesh::Water) - + offMeshConnections.size() * sizeof(OffMeshConnection) - ); - std::copy( - reinterpret_cast(recastMesh.getIndices().data()), - reinterpret_cast(recastMesh.getIndices().data() + recastMesh.getIndices().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getVertices().data()), - reinterpret_cast(recastMesh.getVertices().data() + recastMesh.getVertices().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getAreaTypes().data()), - reinterpret_cast(recastMesh.getAreaTypes().data() + recastMesh.getAreaTypes().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getWater().data()), - reinterpret_cast(recastMesh.getWater().data() + recastMesh.getWater().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(offMeshConnections.data()), - reinterpret_cast(offMeshConnections.data() + offMeshConnections.size()), - std::back_inserter(result) - ); + const std::size_t indicesSize = recastMesh.getIndices().size() * sizeof(int); + const std::size_t verticesSize = recastMesh.getVertices().size() * sizeof(float); + const std::size_t areaTypesSize = recastMesh.getAreaTypes().size() * sizeof(AreaType); + const std::size_t waterSize = recastMesh.getWater().size() * sizeof(RecastMesh::Water); + const std::size_t offMeshConnectionsSize = offMeshConnections.size() * sizeof(OffMeshConnection); + + std::vector result(indicesSize + verticesSize + areaTypesSize + waterSize + offMeshConnectionsSize); + unsigned char* dst = result.data(); + + std::memcpy(dst, recastMesh.getIndices().data(), indicesSize); + dst += indicesSize; + + std::memcpy(dst, recastMesh.getVertices().data(), verticesSize); + dst += verticesSize; + + std::memcpy(dst, recastMesh.getAreaTypes().data(), areaTypesSize); + dst += areaTypesSize; + + std::memcpy(dst, recastMesh.getWater().data(), waterSize); + dst += waterSize; + + std::memcpy(dst, offMeshConnections.data(), offMeshConnectionsSize); + return result; } } @@ -189,8 +179,8 @@ namespace DetourNavigator { struct CompareBytes { - const char* mRhsIt; - const char* mRhsEnd; + const unsigned char* mRhsIt; + const unsigned char* const mRhsEnd; template int operator ()(const std::vector& lhs) @@ -225,7 +215,7 @@ namespace DetourNavigator }; } - int NavMeshTilesCache::RecastMeshKeyView::compare(const std::string& other) const + int NavMeshTilesCache::RecastMeshKeyView::compare(const std::vector& other) const { CompareBytes compareBytes {other.data(), other.data() + other.size()}; diff --git a/components/detournavigator/navmeshtilescache.hpp b/components/detournavigator/navmeshtilescache.hpp index 57f57a56f8..064d9e185b 100644 --- a/components/detournavigator/navmeshtilescache.hpp +++ b/components/detournavigator/navmeshtilescache.hpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include namespace osg { @@ -33,10 +35,10 @@ namespace DetourNavigator std::atomic mUseCount; osg::Vec3f mAgentHalfExtents; TilePosition mChangedTile; - std::string mNavMeshKey; + std::vector mNavMeshKey; NavMeshData mNavMeshData; - Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, std::string navMeshKey) + Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, std::vector&& navMeshKey) : mUseCount(0) , mAgentHalfExtents(agentHalfExtents) , mChangedTile(changedTile) @@ -120,19 +122,32 @@ namespace DetourNavigator virtual ~KeyView() = default; - KeyView(const std::string& value) + KeyView(const std::vector& value) : mValue(&value) {} - const std::string& getValue() const + const std::vector& getValue() const { assert(mValue); return *mValue; } - virtual int compare(const std::string& other) const + virtual int compare(const std::vector& other) const { assert(mValue); - return mValue->compare(other); + + const auto valueSize = mValue->size(); + const auto otherSize = other.size(); + + if (const auto result = std::memcmp(mValue->data(), other.data(), std::min(valueSize, otherSize))) + return result; + + if (valueSize < otherSize) + return -1; + + if (valueSize > otherSize) + return 1; + + return 0; } virtual bool isLess(const KeyView& other) const @@ -147,7 +162,7 @@ namespace DetourNavigator } private: - const std::string* mValue = nullptr; + const std::vector* mValue = nullptr; }; class RecastMeshKeyView : public KeyView @@ -156,7 +171,7 @@ namespace DetourNavigator RecastMeshKeyView(const RecastMesh& recastMesh, const std::vector& offMeshConnections) : mRecastMesh(recastMesh), mOffMeshConnections(offMeshConnections) {} - int compare(const std::string& other) const override; + int compare(const std::vector& other) const override; bool isLess(const KeyView& other) const override {