mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 07:45:39 +00:00
Store BulletShape source file name and content hash
This commit is contained in:
parent
d914cda347
commit
d7041613ef
14 changed files with 130 additions and 4 deletions
|
@ -335,6 +335,7 @@ namespace
|
|||
MOCK_METHOD(void, setUseSkinning, (bool), (override));
|
||||
MOCK_METHOD(bool, getUseSkinning, (), (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, getUserVersion, (), (const, override));
|
||||
MOCK_METHOD(unsigned int, getBethVersion, (), (const, override));
|
||||
|
@ -381,6 +382,7 @@ namespace
|
|||
),
|
||||
btVector3(4, 8, 12)
|
||||
};
|
||||
const std::uint64_t mHash = 42;
|
||||
|
||||
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.strips = {{0, 1, 2, 3}};
|
||||
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
|
||||
|
||||
EXPECT_CALL(mNifFile, getHash()).WillOnce(Return(mHash));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -423,6 +427,8 @@ namespace
|
|||
Resource::BulletShape expected;
|
||||
|
||||
EXPECT_EQ(*result, expected);
|
||||
EXPECT_EQ(result->mFileName, "test.nif");
|
||||
EXPECT_EQ(result->mFileHash, mHash);
|
||||
}
|
||||
|
||||
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)
|
||||
|
|
|
@ -93,7 +93,7 @@ add_component_dir (esmterrain
|
|||
|
||||
add_component_dir (misc
|
||||
constants utf8stream stringops resourcehelpers rng messageformatparser weakcache thread
|
||||
compression
|
||||
compression osguservalues
|
||||
)
|
||||
|
||||
add_component_dir (debug
|
||||
|
@ -106,7 +106,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
ENDIF()
|
||||
add_component_dir (files
|
||||
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager escape
|
||||
lowlevelfile constrainedfilestream memorystream
|
||||
lowlevelfile constrainedfilestream memorystream hash
|
||||
)
|
||||
|
||||
add_component_dir (compiler
|
||||
|
|
36
components/files/hash.cpp
Normal file
36
components/files/hash.cpp
Normal 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
13
components/files/hash.hpp
Normal 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
|
6
components/misc/osguservalues.cpp
Normal file
6
components/misc/osguservalues.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "osguservalues.hpp"
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
const std::string OsgUserValues::sFileHash = "fileHash";
|
||||
}
|
14
components/misc/osguservalues.hpp
Normal file
14
components/misc/osguservalues.hpp
Normal 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
|
|
@ -1,6 +1,8 @@
|
|||
#include "niffile.hpp"
|
||||
#include "effect.hpp"
|
||||
|
||||
#include <components/files/hash.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
@ -156,6 +158,8 @@ std::string NIFFile::printVersion(unsigned int version)
|
|||
|
||||
void NIFFile::parse(Files::IStreamPtr stream)
|
||||
{
|
||||
hash = Files::getHash(filename, *stream);
|
||||
|
||||
NIFStream nif (this, stream);
|
||||
|
||||
// Check the header string
|
||||
|
|
|
@ -34,6 +34,8 @@ struct File
|
|||
|
||||
virtual std::string getFilename() const = 0;
|
||||
|
||||
virtual std::uint64_t getHash() const = 0;
|
||||
|
||||
virtual unsigned int getVersion() 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
|
||||
std::string filename;
|
||||
std::uint64_t hash = 0;
|
||||
|
||||
/// Record list
|
||||
std::vector<Record*> records;
|
||||
|
@ -141,6 +144,8 @@ public:
|
|||
/// Get the name of the file
|
||||
std::string getFilename() const override { return filename; }
|
||||
|
||||
std::uint64_t getHash() const override { return hash; }
|
||||
|
||||
/// Get the version of the NIF format used
|
||||
unsigned int getVersion() const override { return ver; }
|
||||
|
||||
|
|
|
@ -166,6 +166,8 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
|||
mStaticMesh.reset();
|
||||
mAvoidStaticMesh.reset();
|
||||
|
||||
mShape->mFileHash = nif.getHash();
|
||||
|
||||
const size_t numRoots = nif.numRoots();
|
||||
std::vector<const Nif::Node*> roots;
|
||||
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);
|
||||
}
|
||||
const std::string filename = nif.getFilename();
|
||||
mShape->mFileName = filename;
|
||||
if (roots.empty())
|
||||
{
|
||||
warn("Found no root nodes in NIF file " + filename);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
#include <components/misc/osguservalues.hpp>
|
||||
|
||||
// particle
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
@ -325,6 +326,10 @@ namespace NifOsg
|
|||
if (!textkeys->mTextKeys.empty())
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ BulletShape::BulletShape(const BulletShape ©, const osg::CopyOp ©op)
|
|||
, mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape.get()))
|
||||
, mCollisionBox(copy.mCollisionBox)
|
||||
, mAnimatedShapes(copy.mAnimatedShapes)
|
||||
, mFileName(copy.mFileName)
|
||||
, mFileHash(copy.mFileHash)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
class btCollisionShape;
|
||||
|
||||
namespace NifBullet
|
||||
{
|
||||
class BulletNifLoader;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
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.
|
||||
std::map<int, int> mAnimatedShapes;
|
||||
|
||||
std::string mFileName;
|
||||
std::uint64_t mFileHash = 0;
|
||||
|
||||
void setLocalScaling(const btVector3& scale);
|
||||
|
||||
bool isAnimated() const { return !mAnimatedShapes.empty(); }
|
||||
|
@ -60,6 +68,8 @@ namespace Resource
|
|||
public:
|
||||
BulletShapeInstance(osg::ref_ptr<const BulletShape> source);
|
||||
|
||||
const osg::ref_ptr<const BulletShape>& getSource() const { return mSource; }
|
||||
|
||||
private:
|
||||
osg::ref_ptr<const BulletShape> mSource;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "bulletshapemanager.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/TriangleFunctor>
|
||||
#include <osg/Transform>
|
||||
|
@ -10,6 +12,7 @@
|
|||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/misc/osguservalues.hpp>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
||||
|
@ -162,6 +165,15 @@ osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &
|
|||
if (!shape)
|
||||
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);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
#include <components/misc/osguservalues.hpp>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
|
@ -34,6 +35,8 @@
|
|||
#include <components/shader/shadervisitor.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include <components/files/hash.hpp>
|
||||
|
||||
#include "imagemanager.hpp"
|
||||
#include "niffilemanager.hpp"
|
||||
#include "objectcache.hpp"
|
||||
|
@ -502,7 +505,10 @@ namespace Resource
|
|||
options->setReadFileCallback(new ImageReadCallback(imageManager));
|
||||
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())
|
||||
{
|
||||
std::stringstream errormsg;
|
||||
|
@ -528,8 +534,12 @@ namespace Resource
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue