Merge branch 'restrict_navmesh_cache_writes' into 'master'

Do not write shapes to navmeshdb when writing is disabled (#6498)

Closes #6498

See merge request OpenMW/openmw!1486
This commit is contained in:
psi29a 2021-12-17 07:28:53 +00:00
commit 844266b58e
7 changed files with 133 additions and 17 deletions

View file

@ -89,7 +89,8 @@ namespace DetourNavigator
{
if (db == nullptr)
return nullptr;
return std::make_unique<DbWorker>(updater, std::move(db), TileVersion(settings.mNavMeshVersion), settings.mRecast);
return std::make_unique<DbWorker>(updater, std::move(db), TileVersion(settings.mNavMeshVersion),
settings.mRecast, settings.mWriteToNavMeshDb);
}
void updateJobs(std::deque<JobIt>& jobs, TilePosition playerTile, int maxTiles)
@ -704,11 +705,12 @@ namespace DetourNavigator
}
DbWorker::DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db,
TileVersion version, const RecastSettings& recastSettings)
TileVersion version, const RecastSettings& recastSettings, bool writeToDb)
: mUpdater(updater)
, mRecastSettings(recastSettings)
, mDb(std::move(db))
, mVersion(version)
, mWriteToDb(writeToDb)
, mNextTileId(mDb->getMaxTileId() + 1)
, mNextShapeId(mDb->getMaxShapeId() + 1)
, mThread([this] { run(); })
@ -799,12 +801,23 @@ namespace DetourNavigator
if (job->mInput.empty())
{
Log(Debug::Debug) << "Serializing input for job " << job->mId;
const ShapeId shapeId = mNextShapeId;
const std::vector<DbRefGeometryObject> objects = makeDbRefGeometryObjects(job->mRecastMesh->getMeshSources(),
[&] (const MeshSource& v) { return resolveMeshSource(*mDb, v, mNextShapeId); });
if (shapeId != mNextShapeId)
++mWrites;
job->mInput = serialize(mRecastSettings, *job->mRecastMesh, objects);
if (mWriteToDb)
{
const ShapeId shapeId = mNextShapeId;
const auto objects = makeDbRefGeometryObjects(job->mRecastMesh->getMeshSources(),
[&] (const MeshSource& v) { return resolveMeshSource(*mDb, v, mNextShapeId); });
if (shapeId != mNextShapeId)
++mWrites;
job->mInput = serialize(mRecastSettings, *job->mRecastMesh, objects);
}
else
{
const auto objects = makeDbRefGeometryObjects(job->mRecastMesh->getMeshSources(),
[&] (const MeshSource& v) { return resolveMeshSource(*mDb, v); });
if (!objects.has_value())
return;
job->mInput = serialize(mRecastSettings, *job->mRecastMesh, *objects);
}
}
job->mCachedTileData = mDb->getTileData(job->mWorldspace, job->mChangedTile, job->mInput);

View file

@ -136,7 +136,7 @@ namespace DetourNavigator
};
DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db,
TileVersion version, const RecastSettings& recastSettings);
TileVersion version, const RecastSettings& recastSettings, bool writeToDb);
~DbWorker();
@ -153,6 +153,7 @@ namespace DetourNavigator
const RecastSettings& mRecastSettings;
const std::unique_ptr<NavMeshDb> mDb;
const TileVersion mVersion;
const bool mWriteToDb;
TileId mNextTileId;
ShapeId mNextShapeId;
DbJobQueue mQueue;

View file

@ -4,10 +4,14 @@
#include "objecttransform.hpp"
#include "recastmesh.hpp"
#include <components/misc/typetraits.hpp>
#include <algorithm>
#include <cstdint>
#include <tuple>
#include <vector>
#include <optional>
#include <type_traits>
namespace DetourNavigator
{
@ -28,16 +32,27 @@ namespace DetourNavigator
};
template <class ResolveMeshSource>
inline std::vector<DbRefGeometryObject> makeDbRefGeometryObjects(const std::vector<MeshSource>& meshSources,
ResolveMeshSource&& resolveMeshSource)
inline auto makeDbRefGeometryObjects(const std::vector<MeshSource>& meshSources, ResolveMeshSource&& resolveMeshSource)
-> std::conditional_t<
Misc::isOptional<std::decay_t<decltype(resolveMeshSource(meshSources.front()))>>,
std::optional<std::vector<DbRefGeometryObject>>,
std::vector<DbRefGeometryObject>
>
{
std::vector<DbRefGeometryObject> result;
result.reserve(meshSources.size());
std::transform(meshSources.begin(), meshSources.end(), std::back_inserter(result),
[&] (const MeshSource& meshSource)
for (const MeshSource& meshSource : meshSources)
{
const auto shapeId = resolveMeshSource(meshSource);
if constexpr (Misc::isOptional<std::decay_t<decltype(shapeId)>>)
{
return DbRefGeometryObject {resolveMeshSource(meshSource), meshSource.mObjectTransform};
});
if (!shapeId.has_value())
return std::nullopt;
result.push_back(DbRefGeometryObject {*shapeId, meshSource.mObjectTransform});
}
else
result.push_back(DbRefGeometryObject {shapeId, meshSource.mObjectTransform});
}
std::sort(result.begin(), result.end());
return result;
}

View file

@ -5,12 +5,21 @@
#include <components/debug/debuglog.hpp>
#include <cassert>
#include <optional>
namespace DetourNavigator
{
namespace
{
ShapeId getShapeId(NavMeshDb& db, const std::string& name, ShapeType type, const std::string& hash, ShapeId& nextShapeId)
std::optional<ShapeId> findShapeId(NavMeshDb& db, const std::string& name, ShapeType type,
const std::string& hash)
{
const Sqlite3::ConstBlob hashData {hash.data(), static_cast<int>(hash.size())};
return db.findShapeId(name, type, hashData);
}
ShapeId getShapeId(NavMeshDb& db, const std::string& name, ShapeType type,
const std::string& hash, ShapeId& nextShapeId)
{
const Sqlite3::ConstBlob hashData {hash.data(), static_cast<int>(hash.size())};
if (const auto existingShapeId = db.findShapeId(name, type, hashData))
@ -37,4 +46,18 @@ namespace DetourNavigator
return ShapeId(0);
}
}
std::optional<ShapeId> resolveMeshSource(NavMeshDb& db, const MeshSource& source)
{
switch (source.mAreaType)
{
case AreaType_null:
return findShapeId(db, source.mShape->mFileName, ShapeType::Avoid, source.mShape->mFileHash);
case AreaType_ground:
return findShapeId(db, source.mShape->mFileName, ShapeType::Collision, source.mShape->mFileHash);
default:
Log(Debug::Warning) << "Trying to resolve recast mesh source with unsupported area type: " << source.mAreaType;
return std::nullopt;
}
}
}

View file

@ -3,11 +3,15 @@
#include "navmeshdb.hpp"
#include <optional>
namespace DetourNavigator
{
struct MeshSource;
ShapeId resolveMeshSource(NavMeshDb& db, const MeshSource& source, ShapeId& nextShapeId);
std::optional<ShapeId> resolveMeshSource(NavMeshDb& db, const MeshSource& source);
}
#endif

View file

@ -0,0 +1,19 @@
#ifndef OPENMW_COMPONENTS_MISC_TYPETRAITS_H
#define OPENMW_COMPONENTS_MISC_TYPETRAITS_H
#include <optional>
#include <type_traits>
namespace Misc
{
template <class T>
struct IsOptional : std::false_type {};
template <class T>
struct IsOptional<std::optional<T>> : std::true_type {};
template <class T>
inline constexpr bool isOptional = IsOptional<T>::value;
}
#endif