1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 18:45:38 +00:00

Store BulletShape source file name and content hash

This commit is contained in:
elsid 2021-11-10 20:24:17 +01:00
parent d914cda347
commit d7041613ef
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
14 changed files with 130 additions and 4 deletions

View file

@ -335,6 +335,7 @@ namespace
MOCK_METHOD(void, setUseSkinning, (bool), (override)); MOCK_METHOD(void, setUseSkinning, (bool), (override));
MOCK_METHOD(bool, getUseSkinning, (), (const, override)); MOCK_METHOD(bool, getUseSkinning, (), (const, override));
MOCK_METHOD(std::string, getFilename, (), (const, override)); MOCK_METHOD(std::string, getFilename, (), (const, override));
MOCK_METHOD(std::uint64_t, getHash, (), (const, override));
MOCK_METHOD(unsigned int, getVersion, (), (const, override)); MOCK_METHOD(unsigned int, getVersion, (), (const, override));
MOCK_METHOD(unsigned int, getUserVersion, (), (const, override)); MOCK_METHOD(unsigned int, getUserVersion, (), (const, override));
MOCK_METHOD(unsigned int, getBethVersion, (), (const, override)); MOCK_METHOD(unsigned int, getBethVersion, (), (const, override));
@ -381,6 +382,7 @@ namespace
), ),
btVector3(4, 8, 12) btVector3(4, 8, 12)
}; };
const std::uint64_t mHash = 42;
TestBulletNifLoader() TestBulletNifLoader()
{ {
@ -411,6 +413,8 @@ namespace
mNiTriStripsData.vertices = {osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0)}; mNiTriStripsData.vertices = {osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0)};
mNiTriStripsData.strips = {{0, 1, 2, 3}}; mNiTriStripsData.strips = {{0, 1, 2, 3}};
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData); mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
EXPECT_CALL(mNifFile, getHash()).WillOnce(Return(mHash));
} }
}; };
@ -423,6 +427,8 @@ namespace
Resource::BulletShape expected; Resource::BulletShape expected;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
EXPECT_EQ(result->mFileName, "test.nif");
EXPECT_EQ(result->mFileHash, mHash);
} }
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root) TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)

View file

@ -93,7 +93,7 @@ add_component_dir (esmterrain
add_component_dir (misc add_component_dir (misc
constants utf8stream stringops resourcehelpers rng messageformatparser weakcache thread constants utf8stream stringops resourcehelpers rng messageformatparser weakcache thread
compression compression osguservalues
) )
add_component_dir (debug add_component_dir (debug
@ -106,7 +106,7 @@ IF(NOT WIN32 AND NOT APPLE)
ENDIF() ENDIF()
add_component_dir (files add_component_dir (files
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager escape linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager escape
lowlevelfile constrainedfilestream memorystream lowlevelfile constrainedfilestream memorystream hash
) )
add_component_dir (compiler add_component_dir (compiler

36
components/files/hash.cpp Normal file
View file

@ -0,0 +1,36 @@
#include "hash.hpp"
#include <components/misc/hash.hpp>
#include <cstdint>
#include <functional>
#include <istream>
#include <string>
namespace Files
{
std::uint64_t getHash(const std::string& fileName, std::istream& stream)
{
std::uint64_t hash = std::hash<std::string> {}(fileName);
try
{
const auto start = stream.tellg();
const auto exceptions = stream.exceptions();
stream.exceptions(std::ios_base::badbit);
while (stream)
{
std::uint64_t value = 0;
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
Misc::hashCombine(hash, value);
}
stream.exceptions(exceptions);
stream.clear();
stream.seekg(start);
}
catch (const std::exception& e)
{
throw std::runtime_error("Error while reading \"" + fileName + "\" to get hash: " + std::string(e.what()));
}
return hash;
}
}

13
components/files/hash.hpp Normal file
View file

@ -0,0 +1,13 @@
#ifndef COMPONENTS_FILES_HASH_H
#define COMPONENTS_FILES_HASH_H
#include <cstdint>
#include <istream>
#include <string>
namespace Files
{
std::uint64_t getHash(const std::string& fileName, std::istream& stream);
}
#endif

View file

@ -0,0 +1,6 @@
#include "osguservalues.hpp"
namespace Misc
{
const std::string OsgUserValues::sFileHash = "fileHash";
}

View file

@ -0,0 +1,14 @@
#ifndef OPENMW_COMPONENTS_MISC_OSGUSERVALUES_H
#define OPENMW_COMPONENTS_MISC_OSGUSERVALUES_H
#include <string>
namespace Misc
{
struct OsgUserValues
{
static const std::string sFileHash;
};
}
#endif

View file

@ -1,6 +1,8 @@
#include "niffile.hpp" #include "niffile.hpp"
#include "effect.hpp" #include "effect.hpp"
#include <components/files/hash.hpp>
#include <array> #include <array>
#include <map> #include <map>
#include <sstream> #include <sstream>
@ -156,6 +158,8 @@ std::string NIFFile::printVersion(unsigned int version)
void NIFFile::parse(Files::IStreamPtr stream) void NIFFile::parse(Files::IStreamPtr stream)
{ {
hash = Files::getHash(filename, *stream);
NIFStream nif (this, stream); NIFStream nif (this, stream);
// Check the header string // Check the header string

View file

@ -34,6 +34,8 @@ struct File
virtual std::string getFilename() const = 0; virtual std::string getFilename() const = 0;
virtual std::uint64_t getHash() const = 0;
virtual unsigned int getVersion() const = 0; virtual unsigned int getVersion() const = 0;
virtual unsigned int getUserVersion() const = 0; virtual unsigned int getUserVersion() const = 0;
@ -50,6 +52,7 @@ class NIFFile final : public File
/// File name, used for error messages and opening the file /// File name, used for error messages and opening the file
std::string filename; std::string filename;
std::uint64_t hash = 0;
/// Record list /// Record list
std::vector<Record*> records; std::vector<Record*> records;
@ -141,6 +144,8 @@ public:
/// Get the name of the file /// Get the name of the file
std::string getFilename() const override { return filename; } std::string getFilename() const override { return filename; }
std::uint64_t getHash() const override { return hash; }
/// Get the version of the NIF format used /// Get the version of the NIF format used
unsigned int getVersion() const override { return ver; } unsigned int getVersion() const override { return ver; }

View file

@ -166,6 +166,8 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
mStaticMesh.reset(); mStaticMesh.reset();
mAvoidStaticMesh.reset(); mAvoidStaticMesh.reset();
mShape->mFileHash = nif.getHash();
const size_t numRoots = nif.numRoots(); const size_t numRoots = nif.numRoots();
std::vector<const Nif::Node*> roots; std::vector<const Nif::Node*> roots;
for (size_t i = 0; i < numRoots; ++i) for (size_t i = 0; i < numRoots; ++i)
@ -178,6 +180,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
roots.emplace_back(node); roots.emplace_back(node);
} }
const std::string filename = nif.getFilename(); const std::string filename = nif.getFilename();
mShape->mFileName = filename;
if (roots.empty()) if (roots.empty())
{ {
warn("Found no root nodes in NIF file " + filename); warn("Found no root nodes in NIF file " + filename);

View file

@ -17,6 +17,7 @@
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/resource/imagemanager.hpp> #include <components/resource/imagemanager.hpp>
#include <components/sceneutil/util.hpp> #include <components/sceneutil/util.hpp>
#include <components/misc/osguservalues.hpp>
// particle // particle
#include <osgParticle/ParticleSystem> #include <osgParticle/ParticleSystem>
@ -325,6 +326,10 @@ namespace NifOsg
if (!textkeys->mTextKeys.empty()) if (!textkeys->mTextKeys.empty())
created->getOrCreateUserDataContainer()->addUserObject(textkeys); created->getOrCreateUserDataContainer()->addUserObject(textkeys);
const std::uint64_t nifHash = nif->getHash();
created->setUserValue(Misc::OsgUserValues::sFileHash,
std::string(reinterpret_cast<const char*>(&nifHash), sizeof(nifHash)));
return created; return created;
} }

View file

@ -74,6 +74,8 @@ BulletShape::BulletShape(const BulletShape &copy, const osg::CopyOp &copyop)
, mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape.get())) , mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape.get()))
, mCollisionBox(copy.mCollisionBox) , mCollisionBox(copy.mCollisionBox)
, mAnimatedShapes(copy.mAnimatedShapes) , mAnimatedShapes(copy.mAnimatedShapes)
, mFileName(copy.mFileName)
, mFileHash(copy.mFileHash)
{ {
} }

View file

@ -12,6 +12,11 @@
class btCollisionShape; class btCollisionShape;
namespace NifBullet
{
class BulletNifLoader;
}
namespace Resource namespace Resource
{ {
struct DeleteCollisionShape struct DeleteCollisionShape
@ -47,6 +52,9 @@ namespace Resource
// we store the node's record index mapped to the child index of the shape in the btCompoundShape. // we store the node's record index mapped to the child index of the shape in the btCompoundShape.
std::map<int, int> mAnimatedShapes; std::map<int, int> mAnimatedShapes;
std::string mFileName;
std::uint64_t mFileHash = 0;
void setLocalScaling(const btVector3& scale); void setLocalScaling(const btVector3& scale);
bool isAnimated() const { return !mAnimatedShapes.empty(); } bool isAnimated() const { return !mAnimatedShapes.empty(); }
@ -60,6 +68,8 @@ namespace Resource
public: public:
BulletShapeInstance(osg::ref_ptr<const BulletShape> source); BulletShapeInstance(osg::ref_ptr<const BulletShape> source);
const osg::ref_ptr<const BulletShape>& getSource() const { return mSource; }
private: private:
osg::ref_ptr<const BulletShape> mSource; osg::ref_ptr<const BulletShape> mSource;
}; };

View file

@ -1,5 +1,7 @@
#include "bulletshapemanager.hpp" #include "bulletshapemanager.hpp"
#include <cstring>
#include <osg/NodeVisitor> #include <osg/NodeVisitor>
#include <osg/TriangleFunctor> #include <osg/TriangleFunctor>
#include <osg/Transform> #include <osg/Transform>
@ -10,6 +12,7 @@
#include <components/misc/pathhelpers.hpp> #include <components/misc/pathhelpers.hpp>
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#include <components/misc/osguservalues.hpp>
#include <components/nifbullet/bulletnifloader.hpp> #include <components/nifbullet/bulletnifloader.hpp>
@ -162,6 +165,15 @@ osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &
if (!shape) if (!shape)
return osg::ref_ptr<BulletShape>(); return osg::ref_ptr<BulletShape>();
} }
if (shape != nullptr)
{
shape->mFileName = normalized;
std::string fileHash;
constNode->getUserValue(Misc::OsgUserValues::sFileHash, fileHash);
if (!fileHash.empty())
std::memcpy(&shape->mFileHash, fileHash.data(), std::min(fileHash.size(), sizeof(shape->mFileHash)));
}
} }
mCache->addEntryToObjectCache(normalized, shape); mCache->addEntryToObjectCache(normalized, shape);

View file

@ -21,6 +21,7 @@
#include <components/misc/pathhelpers.hpp> #include <components/misc/pathhelpers.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/misc/algorithm.hpp> #include <components/misc/algorithm.hpp>
#include <components/misc/osguservalues.hpp>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
@ -34,6 +35,8 @@
#include <components/shader/shadervisitor.hpp> #include <components/shader/shadervisitor.hpp>
#include <components/shader/shadermanager.hpp> #include <components/shader/shadermanager.hpp>
#include <components/files/hash.hpp>
#include "imagemanager.hpp" #include "imagemanager.hpp"
#include "niffilemanager.hpp" #include "niffilemanager.hpp"
#include "objectcache.hpp" #include "objectcache.hpp"
@ -502,7 +505,10 @@ namespace Resource
options->setReadFileCallback(new ImageReadCallback(imageManager)); options->setReadFileCallback(new ImageReadCallback(imageManager));
if (ext == "dae") options->setOptionString("daeUseSequencedTextureUnits"); if (ext == "dae") options->setOptionString("daeUseSequencedTextureUnits");
osgDB::ReaderWriter::ReadResult result = reader->readNode(*vfs->get(normalizedFilename), options); Files::IStreamPtr stream = vfs->get(normalizedFilename);
const std::uint64_t fileHash = Files::getHash(normalizedFilename, *stream);
osgDB::ReaderWriter::ReadResult result = reader->readNode(*stream, options);
if (!result.success()) if (!result.success())
{ {
std::stringstream errormsg; std::stringstream errormsg;
@ -528,8 +534,12 @@ namespace Resource
result.getNode()->getOrCreateStateSet()->addUniform(new osg::Uniform("useFalloff", false)); result.getNode()->getOrCreateStateSet()->addUniform(new osg::Uniform("useFalloff", false));
} }
auto node = result.getNode();
return result.getNode(); node->setUserValue(Misc::OsgUserValues::sFileHash,
std::string(reinterpret_cast<const char*>(&fileHash), sizeof(fileHash)));
return node;
} }
} }