mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 03:59:56 +00:00
Merge branch 'vfs_normalized_path_15' into 'master'
Use normalized path in BulletShapeManager and PreloadItem (#8138) See merge request OpenMW/openmw!4391
This commit is contained in:
commit
0590aa181d
12 changed files with 103 additions and 122 deletions
|
@ -33,7 +33,8 @@ namespace
|
|||
{
|
||||
const ObjectId id(&shape);
|
||||
osg::ref_ptr<Resource::BulletShape> 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);
|
||||
|
|
|
@ -131,7 +131,8 @@ namespace NavMeshTool
|
|||
osg::ref_ptr<const Resource::BulletShape> shape = [&] {
|
||||
try
|
||||
{
|
||||
return bulletShapeManager.getShape(Misc::ResourceHelpers::correctMeshPath(model));
|
||||
return bulletShapeManager.getShape(
|
||||
VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(model)));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
|
@ -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<Resource::BulletShapeInstance> 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<const Resource::BulletShape> 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<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
|
||||
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance
|
||||
= mShapeManager->getInstance(VFS::Path::toNormalized(mesh));
|
||||
assert(shapeInstance);
|
||||
float radius = computeRadius ? shapeInstance->mCollisionBox.mExtents.length() / 2.f : 1.f;
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ namespace MWRender
|
|||
if (!weaponNode->getNumChildren())
|
||||
{
|
||||
osg::ref_ptr<osg::Node> fallbackNode
|
||||
= mResourceSystem->getSceneManager()->getInstance(VFS::Path::toNormalized(mesh), weaponNode);
|
||||
= mResourceSystem->getSceneManager()->getInstance(mesh, weaponNode);
|
||||
resetControllers(fallbackNode);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/loadinglistener/reporter.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
@ -105,8 +106,8 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
std::string mesh;
|
||||
std::string kfname;
|
||||
VFS::Path::Normalized mesh;
|
||||
VFS::Path::Normalized kfname;
|
||||
for (std::string_view path : mMeshes)
|
||||
{
|
||||
if (mAbort)
|
||||
|
@ -121,19 +122,15 @@ namespace MWWorld
|
|||
if (!vfs.exists(mesh))
|
||||
continue;
|
||||
|
||||
size_t slashpos = mesh.find_last_of("/\\");
|
||||
if (slashpos != std::string::npos && slashpos != mesh.size() - 1)
|
||||
{
|
||||
if (Misc::StringUtils::toLower(mesh[slashpos + 1]) == 'x'
|
||||
&& Misc::StringUtils::ciEndsWith(mesh, ".nif"))
|
||||
if (Misc::getFileName(mesh).starts_with('x') && Misc::getFileExtension(mesh) == "nif")
|
||||
{
|
||||
kfname = mesh;
|
||||
kfname.replace(kfname.size() - 4, 4, ".kf");
|
||||
kfname.changeExtension("kf");
|
||||
if (vfs.exists(kfname))
|
||||
mPreloadedObjects.insert(mKeyframeManager->get(kfname));
|
||||
}
|
||||
}
|
||||
mPreloadedObjects.insert(mSceneManager->getTemplate(VFS::Path::toNormalized(mesh)));
|
||||
|
||||
mPreloadedObjects.insert(mSceneManager->getTemplate(mesh));
|
||||
if (mPreloadInstances)
|
||||
mPreloadedObjects.insert(mBulletShapeManager->cacheInstance(mesh));
|
||||
else
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H
|
||||
#define OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
|
@ -12,6 +11,8 @@
|
|||
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h>
|
||||
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
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<int, int> mAnimatedShapes;
|
||||
|
||||
std::string mFileName;
|
||||
VFS::Path::Normalized mFileName;
|
||||
std::string mFileHash;
|
||||
|
||||
VisualCollisionType mVisualCollisionType = VisualCollisionType::None;
|
||||
|
|
|
@ -106,30 +106,27 @@ namespace Resource
|
|||
{
|
||||
}
|
||||
|
||||
BulletShapeManager::~BulletShapeManager() {}
|
||||
BulletShapeManager::~BulletShapeManager() = default;
|
||||
|
||||
osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string& name)
|
||||
osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(VFS::Path::NormalizedView name)
|
||||
{
|
||||
const VFS::Path::Normalized normalized(name);
|
||||
if (osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(name))
|
||||
return osg::ref_ptr<BulletShape>(static_cast<BulletShape*>(obj.get()));
|
||||
|
||||
osg::ref_ptr<BulletShape> shape;
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
shape = osg::ref_ptr<BulletShape>(static_cast<BulletShape*>(obj.get()));
|
||||
else
|
||||
{
|
||||
if (Misc::getFileExtension(normalized) == "nif")
|
||||
|
||||
if (Misc::getFileExtension(name.value()) == "nif")
|
||||
{
|
||||
NifBullet::BulletNifLoader loader;
|
||||
shape = loader.load(*mNifFileManager->get(normalized));
|
||||
shape = loader.load(*mNifFileManager->get(name));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: support .bullet shape files
|
||||
|
||||
osg::ref_ptr<const osg::Node> constNode(mSceneManager->getTemplate(normalized));
|
||||
osg::ref_ptr<osg::Node> node(const_cast<osg::Node*>(
|
||||
constNode.get())); // const-trickery required because there is no const version of NodeVisitor
|
||||
osg::ref_ptr<const osg::Node> constNode(mSceneManager->getTemplate(name));
|
||||
// const-trickery required because there is no const version of NodeVisitor
|
||||
osg::ref_ptr<osg::Node> node(const_cast<osg::Node*>(constNode.get()));
|
||||
|
||||
// Check first if there's a custom collision node
|
||||
unsigned int visitAllNodesMask = 0xffffffff;
|
||||
|
@ -158,41 +155,34 @@ namespace Resource
|
|||
|
||||
if (shape != nullptr)
|
||||
{
|
||||
shape->mFileName = normalized;
|
||||
shape->mFileName = name;
|
||||
constNode->getUserValue(Misc::OsgUserValues::sFileHash, shape->mFileHash);
|
||||
}
|
||||
}
|
||||
|
||||
mCache->addEntryToObjectCache(normalized, shape);
|
||||
}
|
||||
mCache->addEntryToObjectCache(name.value(), shape);
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(const std::string& name)
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(VFS::Path::NormalizedView name)
|
||||
{
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> instance = createInstance(normalized);
|
||||
if (instance)
|
||||
mInstanceCache->addEntryToObjectCache(normalized, instance.get());
|
||||
osg::ref_ptr<BulletShapeInstance> instance = createInstance(name);
|
||||
if (instance != nullptr)
|
||||
mInstanceCache->addEntryToObjectCache(name, instance.get());
|
||||
return instance;
|
||||
}
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::getInstance(const std::string& name)
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::getInstance(VFS::Path::NormalizedView name)
|
||||
{
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mInstanceCache->takeFromObjectCache(normalized);
|
||||
if (obj.get())
|
||||
if (osg::ref_ptr<osg::Object> obj = mInstanceCache->takeFromObjectCache(name))
|
||||
return static_cast<BulletShapeInstance*>(obj.get());
|
||||
else
|
||||
return createInstance(normalized);
|
||||
return createInstance(name);
|
||||
}
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::string& name)
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(VFS::Path::NormalizedView name)
|
||||
{
|
||||
osg::ref_ptr<const BulletShape> shape = getShape(name);
|
||||
if (shape)
|
||||
if (osg::ref_ptr<const BulletShape> shape = getShape(name))
|
||||
return makeInstance(std::move(shape));
|
||||
return osg::ref_ptr<BulletShapeInstance>();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#ifndef OPENMW_COMPONENTS_BULLETSHAPEMANAGER_H
|
||||
#define OPENMW_COMPONENTS_BULLETSHAPEMANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#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<const BulletShape> getShape(const std::string& name);
|
||||
osg::ref_ptr<const BulletShape> 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<BulletShapeInstance> cacheInstance(const std::string& name);
|
||||
osg::ref_ptr<BulletShapeInstance> cacheInstance(VFS::Path::NormalizedView name);
|
||||
|
||||
/// @note May return a null pointer if the object has no shape.
|
||||
osg::ref_ptr<BulletShapeInstance> getInstance(const std::string& name);
|
||||
osg::ref_ptr<BulletShapeInstance> 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<BulletShapeInstance> createInstance(const std::string& name);
|
||||
osg::ref_ptr<BulletShapeInstance> createInstance(VFS::Path::NormalizedView name);
|
||||
|
||||
osg::ref_ptr<MultiObjectCache> mInstanceCache;
|
||||
SceneManager* mSceneManager;
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
#include <osg/ref_ptr>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -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<const Resource::BulletShape> shape = [&] {
|
||||
try
|
||||
{
|
||||
return bulletShapeManager.getShape("meshes/" + model);
|
||||
constexpr VFS::Path::NormalizedView prefix("meshes");
|
||||
return bulletShapeManager.getShape(prefix / model);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
|
@ -6,11 +6,6 @@
|
|||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
MultiObjectCache::MultiObjectCache() {}
|
||||
|
||||
MultiObjectCache::~MultiObjectCache() {}
|
||||
|
||||
void MultiObjectCache::removeUnreferencedObjectsInCache()
|
||||
{
|
||||
std::vector<osg::ref_ptr<osg::Object>> 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<std::mutex> lock(_objectCacheMutex);
|
||||
_objectCache.insert(std::make_pair(filename, object));
|
||||
_objectCache.emplace(filename, object);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(const std::string& fileName)
|
||||
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(VFS::Path::NormalizedView fileName)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||
++mGet;
|
||||
ObjectCacheMap::iterator found = _objectCache.find(fileName);
|
||||
if (found == _objectCache.end())
|
||||
return osg::ref_ptr<osg::Object>();
|
||||
else
|
||||
const auto it = _objectCache.find(fileName);
|
||||
if (it != _objectCache.end())
|
||||
{
|
||||
osg::ref_ptr<osg::Object> object = std::move(found->second);
|
||||
_objectCache.erase(found);
|
||||
osg::ref_ptr<osg::Object> object = std::move(it->second);
|
||||
_objectCache.erase(it);
|
||||
++mHit;
|
||||
return object;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MultiObjectCache::releaseGLObjects(osg::State* state)
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include <osg/Referenced>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#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<osg::Object> takeFromObjectCache(const std::string& fileName);
|
||||
osg::ref_ptr<osg::Object> 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<std::string, osg::ref_ptr<osg::Object>> ObjectCacheMap;
|
||||
typedef std::multimap<VFS::Path::Normalized, osg::ref_ptr<osg::Object>, std::less<>> ObjectCacheMap;
|
||||
|
||||
ObjectCacheMap _objectCache;
|
||||
mutable std::mutex _objectCacheMutex;
|
||||
|
|
Loading…
Reference in a new issue