From 63e984ba24bc718cffe503cdf328ab0598eb6ec5 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 24 Sep 2024 00:14:18 +0200 Subject: [PATCH] Use normalized path in BulletShapeManager --- .../detournavigator/asyncnavmeshupdater.cpp | 3 +- apps/navmeshtool/worldspacedata.cpp | 3 +- apps/openmw/mwphysics/physicssystem.cpp | 14 ++- components/nifbullet/bulletnifloader.cpp | 4 +- components/resource/bulletshape.hpp | 5 +- components/resource/bulletshapemanager.cpp | 114 ++++++++---------- components/resource/bulletshapemanager.hpp | 13 +- components/resource/foreachbulletobject.cpp | 9 +- components/resource/multiobjectcache.cpp | 23 ++-- components/resource/multiobjectcache.hpp | 12 +- 10 files changed, 92 insertions(+), 108 deletions(-) diff --git a/apps/components_tests/detournavigator/asyncnavmeshupdater.cpp b/apps/components_tests/detournavigator/asyncnavmeshupdater.cpp index 14c2a3bfe4..ea9efc3df2 100644 --- a/apps/components_tests/detournavigator/asyncnavmeshupdater.cpp +++ b/apps/components_tests/detournavigator/asyncnavmeshupdater.cpp @@ -33,7 +33,8 @@ namespace { const ObjectId id(&shape); osg::ref_ptr bulletShape(new Resource::BulletShape); - bulletShape->mFileName = "test.nif"; + constexpr VFS::Path::NormalizedView test("test.nif"); + bulletShape->mFileName = test; bulletShape->mFileHash = "test_hash"; ObjectTransform objectTransform; std::fill(std::begin(objectTransform.mPosition.pos), std::end(objectTransform.mPosition.pos), 0.1f); diff --git a/apps/navmeshtool/worldspacedata.cpp b/apps/navmeshtool/worldspacedata.cpp index 3a4ff63329..077b43f72f 100644 --- a/apps/navmeshtool/worldspacedata.cpp +++ b/apps/navmeshtool/worldspacedata.cpp @@ -131,7 +131,8 @@ namespace NavMeshTool osg::ref_ptr shape = [&] { try { - return bulletShapeManager.getShape(Misc::ResourceHelpers::correctMeshPath(model)); + return bulletShapeManager.getShape( + VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(model))); } catch (const std::exception& e) { diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 20a9c38b0f..5601b486d0 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -412,9 +412,9 @@ namespace MWPhysics if (ptr.mRef->mData.mPhysicsPostponed) return; - std::string animationMesh = mesh; - if (ptr.getClass().useAnim()) - animationMesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS()); + const VFS::Path::Normalized animationMesh = ptr.getClass().useAnim() + ? Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS()) + : mesh; osg::ref_ptr shapeInstance = mShapeManager->getInstance(animationMesh); if (!shapeInstance || !shapeInstance->mCollisionShape) return; @@ -562,7 +562,8 @@ namespace MWPhysics void PhysicsSystem::addActor(const MWWorld::Ptr& ptr, const std::string& mesh) { - std::string animationMesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS()); + const VFS::Path::Normalized animationMesh + = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS()); osg::ref_ptr shape = mShapeManager->getShape(animationMesh); // Try to get shape from basic model as fallback for creatures @@ -570,7 +571,7 @@ namespace MWPhysics { if (animationMesh != mesh) { - shape = mShapeManager->getShape(mesh); + shape = mShapeManager->getShape(VFS::Path::toNormalized(mesh)); } } @@ -590,7 +591,8 @@ namespace MWPhysics int PhysicsSystem::addProjectile( const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius) { - osg::ref_ptr shapeInstance = mShapeManager->getInstance(mesh); + osg::ref_ptr shapeInstance + = mShapeManager->getInstance(VFS::Path::toNormalized(mesh)); assert(shapeInstance); float radius = computeRadius ? shapeInstance->mCollisionBox.mExtents.length() / 2.f : 1.f; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index bcda7efe70..6bf6ad89bb 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -53,7 +53,7 @@ namespace NifBullet mShape->mFileName = nif.getFilename(); if (roots.empty()) { - warn("Found no root nodes in NIF file " + mShape->mFileName); + warn("Found no root nodes in NIF file " + mShape->mFileName.value()); return mShape; } @@ -93,7 +93,7 @@ namespace NifBullet } else { - warn("Invalid Bounding Box node bounds in file " + mShape->mFileName); + warn("Invalid Bounding Box node bounds in file " + mShape->mFileName.value()); } return true; } diff --git a/components/resource/bulletshape.hpp b/components/resource/bulletshape.hpp index 0a1b98bf7c..d9aad0f092 100644 --- a/components/resource/bulletshape.hpp +++ b/components/resource/bulletshape.hpp @@ -1,7 +1,6 @@ #ifndef OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H #define OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H -#include #include #include @@ -12,6 +11,8 @@ #include #include +#include + class btCollisionShape; namespace NifBullet @@ -56,7 +57,7 @@ namespace Resource // we store the node's record index mapped to the child index of the shape in the btCompoundShape. std::map mAnimatedShapes; - std::string mFileName; + VFS::Path::Normalized mFileName; std::string mFileHash; VisualCollisionType mVisualCollisionType = VisualCollisionType::None; diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index 93c53d8cb0..345efc7fbd 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -106,93 +106,83 @@ namespace Resource { } - BulletShapeManager::~BulletShapeManager() {} + BulletShapeManager::~BulletShapeManager() = default; - osg::ref_ptr BulletShapeManager::getShape(const std::string& name) + osg::ref_ptr BulletShapeManager::getShape(VFS::Path::NormalizedView name) { - const VFS::Path::Normalized normalized(name); + if (osg::ref_ptr obj = mCache->getRefFromObjectCache(name)) + return osg::ref_ptr(static_cast(obj.get())); osg::ref_ptr shape; - osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); - if (obj) - shape = osg::ref_ptr(static_cast(obj.get())); + + if (Misc::getFileExtension(name.value()) == "nif") + { + NifBullet::BulletNifLoader loader; + shape = loader.load(*mNifFileManager->get(name)); + } else { - if (Misc::getFileExtension(normalized) == "nif") + // TODO: support .bullet shape files + + osg::ref_ptr constNode(mSceneManager->getTemplate(name)); + // const-trickery required because there is no const version of NodeVisitor + osg::ref_ptr node(const_cast(constNode.get())); + + // Check first if there's a custom collision node + unsigned int visitAllNodesMask = 0xffffffff; + SceneUtil::FindByNameVisitor nameFinder("Collision"); + nameFinder.setTraversalMask(visitAllNodesMask); + nameFinder.setNodeMaskOverride(visitAllNodesMask); + node->accept(nameFinder); + if (nameFinder.mFoundNode) { - NifBullet::BulletNifLoader loader; - shape = loader.load(*mNifFileManager->get(normalized)); + NodeToShapeVisitor visitor; + visitor.setTraversalMask(visitAllNodesMask); + visitor.setNodeMaskOverride(visitAllNodesMask); + nameFinder.mFoundNode->accept(visitor); + shape = visitor.getShape(); } - else + + // Generate a collision shape from the mesh + if (!shape) { - // TODO: support .bullet shape files - - osg::ref_ptr constNode(mSceneManager->getTemplate(normalized)); - osg::ref_ptr node(const_cast( - constNode.get())); // const-trickery required because there is no const version of NodeVisitor - - // Check first if there's a custom collision node - unsigned int visitAllNodesMask = 0xffffffff; - SceneUtil::FindByNameVisitor nameFinder("Collision"); - nameFinder.setTraversalMask(visitAllNodesMask); - nameFinder.setNodeMaskOverride(visitAllNodesMask); - node->accept(nameFinder); - if (nameFinder.mFoundNode) - { - NodeToShapeVisitor visitor; - visitor.setTraversalMask(visitAllNodesMask); - visitor.setNodeMaskOverride(visitAllNodesMask); - nameFinder.mFoundNode->accept(visitor); - shape = visitor.getShape(); - } - - // Generate a collision shape from the mesh + NodeToShapeVisitor visitor; + node->accept(visitor); + shape = visitor.getShape(); if (!shape) - { - NodeToShapeVisitor visitor; - node->accept(visitor); - shape = visitor.getShape(); - if (!shape) - return osg::ref_ptr(); - } - - if (shape != nullptr) - { - shape->mFileName = normalized; - constNode->getUserValue(Misc::OsgUserValues::sFileHash, shape->mFileHash); - } + return osg::ref_ptr(); } - mCache->addEntryToObjectCache(normalized, shape); + if (shape != nullptr) + { + shape->mFileName = name; + constNode->getUserValue(Misc::OsgUserValues::sFileHash, shape->mFileHash); + } } + + mCache->addEntryToObjectCache(name.value(), shape); + return shape; } - osg::ref_ptr BulletShapeManager::cacheInstance(const std::string& name) + osg::ref_ptr BulletShapeManager::cacheInstance(VFS::Path::NormalizedView name) { - const std::string normalized = VFS::Path::normalizeFilename(name); - - osg::ref_ptr instance = createInstance(normalized); - if (instance) - mInstanceCache->addEntryToObjectCache(normalized, instance.get()); + osg::ref_ptr instance = createInstance(name); + if (instance != nullptr) + mInstanceCache->addEntryToObjectCache(name, instance.get()); return instance; } - osg::ref_ptr BulletShapeManager::getInstance(const std::string& name) + osg::ref_ptr BulletShapeManager::getInstance(VFS::Path::NormalizedView name) { - const std::string normalized = VFS::Path::normalizeFilename(name); - - osg::ref_ptr obj = mInstanceCache->takeFromObjectCache(normalized); - if (obj.get()) + if (osg::ref_ptr obj = mInstanceCache->takeFromObjectCache(name)) return static_cast(obj.get()); - else - return createInstance(normalized); + return createInstance(name); } - osg::ref_ptr BulletShapeManager::createInstance(const std::string& name) + osg::ref_ptr BulletShapeManager::createInstance(VFS::Path::NormalizedView name) { - osg::ref_ptr shape = getShape(name); - if (shape) + if (osg::ref_ptr shape = getShape(name)) return makeInstance(std::move(shape)); return osg::ref_ptr(); } diff --git a/components/resource/bulletshapemanager.hpp b/components/resource/bulletshapemanager.hpp index a81296fdfd..3c5a495c77 100644 --- a/components/resource/bulletshapemanager.hpp +++ b/components/resource/bulletshapemanager.hpp @@ -1,11 +1,10 @@ #ifndef OPENMW_COMPONENTS_BULLETSHAPEMANAGER_H #define OPENMW_COMPONENTS_BULLETSHAPEMANAGER_H -#include -#include - #include +#include + #include "bulletshape.hpp" #include "resourcemanager.hpp" @@ -30,16 +29,16 @@ namespace Resource ~BulletShapeManager(); /// @note May return a null pointer if the object has no shape. - osg::ref_ptr getShape(const std::string& name); + osg::ref_ptr getShape(VFS::Path::NormalizedView name); /// Create an instance of the given shape and cache it for later use, so that future calls to getInstance() can /// simply return the cached instance instead of having to create a new one. /// @note The returned ref_ptr may be kept by the caller to ensure that the instance stays in cache for as long /// as needed. - osg::ref_ptr cacheInstance(const std::string& name); + osg::ref_ptr cacheInstance(VFS::Path::NormalizedView name); /// @note May return a null pointer if the object has no shape. - osg::ref_ptr getInstance(const std::string& name); + osg::ref_ptr getInstance(VFS::Path::NormalizedView name); /// @see ResourceManager::updateCache void updateCache(double referenceTime) override; @@ -49,7 +48,7 @@ namespace Resource void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; private: - osg::ref_ptr createInstance(const std::string& name); + osg::ref_ptr createInstance(VFS::Path::NormalizedView name); osg::ref_ptr mInstanceCache; SceneManager* mSceneManager; diff --git a/components/resource/foreachbulletobject.cpp b/components/resource/foreachbulletobject.cpp index b936e39a2a..9c205c8228 100644 --- a/components/resource/foreachbulletobject.cpp +++ b/components/resource/foreachbulletobject.cpp @@ -16,10 +16,6 @@ #include #include -#include -#include -#include -#include #include #include @@ -97,7 +93,7 @@ namespace Resource for (CellRef& cellRef : cellRefs) { - std::string model(getModel(esmData, cellRef.mRefId, cellRef.mType)); + VFS::Path::Normalized model(getModel(esmData, cellRef.mRefId, cellRef.mType)); if (model.empty()) continue; @@ -107,7 +103,8 @@ namespace Resource osg::ref_ptr shape = [&] { try { - return bulletShapeManager.getShape("meshes/" + model); + constexpr VFS::Path::NormalizedView prefix("meshes"); + return bulletShapeManager.getShape(prefix / model); } catch (const std::exception& e) { diff --git a/components/resource/multiobjectcache.cpp b/components/resource/multiobjectcache.cpp index 71500b0ceb..0be9be232e 100644 --- a/components/resource/multiobjectcache.cpp +++ b/components/resource/multiobjectcache.cpp @@ -6,11 +6,6 @@ namespace Resource { - - MultiObjectCache::MultiObjectCache() {} - - MultiObjectCache::~MultiObjectCache() {} - void MultiObjectCache::removeUnreferencedObjectsInCache() { std::vector> objectsToRemove; @@ -44,7 +39,7 @@ namespace Resource _objectCache.clear(); } - void MultiObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object) + void MultiObjectCache::addEntryToObjectCache(VFS::Path::NormalizedView filename, osg::Object* object) { if (!object) { @@ -52,23 +47,23 @@ namespace Resource return; } std::lock_guard lock(_objectCacheMutex); - _objectCache.insert(std::make_pair(filename, object)); + _objectCache.emplace(filename, object); } - osg::ref_ptr MultiObjectCache::takeFromObjectCache(const std::string& fileName) + osg::ref_ptr MultiObjectCache::takeFromObjectCache(VFS::Path::NormalizedView fileName) { std::lock_guard lock(_objectCacheMutex); ++mGet; - ObjectCacheMap::iterator found = _objectCache.find(fileName); - if (found == _objectCache.end()) - return osg::ref_ptr(); - else + const auto it = _objectCache.find(fileName); + if (it != _objectCache.end()) { - osg::ref_ptr object = std::move(found->second); - _objectCache.erase(found); + osg::ref_ptr object = std::move(it->second); + _objectCache.erase(it); ++mHit; return object; } + + return nullptr; } void MultiObjectCache::releaseGLObjects(osg::State* state) diff --git a/components/resource/multiobjectcache.hpp b/components/resource/multiobjectcache.hpp index 654a88b524..6e05f462f0 100644 --- a/components/resource/multiobjectcache.hpp +++ b/components/resource/multiobjectcache.hpp @@ -3,11 +3,12 @@ #include #include -#include #include #include +#include + #include "cachestats.hpp" namespace osg @@ -23,18 +24,15 @@ namespace Resource class MultiObjectCache : public osg::Referenced { public: - MultiObjectCache(); - ~MultiObjectCache(); - void removeUnreferencedObjectsInCache(); /** Remove all objects from the cache. */ void clear(); - void addEntryToObjectCache(const std::string& filename, osg::Object* object); + void addEntryToObjectCache(VFS::Path::NormalizedView filename, osg::Object* object); /** Take an Object from cache. Return nullptr if no object found. */ - osg::ref_ptr takeFromObjectCache(const std::string& fileName); + osg::ref_ptr takeFromObjectCache(VFS::Path::NormalizedView fileName); /** call releaseGLObjects on all objects attached to the object cache.*/ void releaseGLObjects(osg::State* state); @@ -42,7 +40,7 @@ namespace Resource CacheStats getStats() const; protected: - typedef std::multimap> ObjectCacheMap; + typedef std::multimap, std::less<>> ObjectCacheMap; ObjectCacheMap _objectCache; mutable std::mutex _objectCacheMutex;