mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-13 19:36:44 +00:00
Merge branch 'nifosg_tests' into 'master'
Add tests for NifOsg::Loader See merge request OpenMW/openmw!2421
This commit is contained in:
commit
aed0ad6b83
38 changed files with 927 additions and 658 deletions
|
@ -50,7 +50,9 @@ void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::p
|
||||||
if (isNIF(name))
|
if (isNIF(name))
|
||||||
{
|
{
|
||||||
// std::cout << "Decoding: " << name << std::endl;
|
// std::cout << "Decoding: " << name << std::endl;
|
||||||
Nif::NIFFile temp_nif(myManager.get(name), archivePath / name);
|
Nif::NIFFile file(archivePath / name);
|
||||||
|
Nif::Reader reader(file);
|
||||||
|
reader.parse(myManager.get(name));
|
||||||
}
|
}
|
||||||
else if (isBSA(name))
|
else if (isBSA(name))
|
||||||
{
|
{
|
||||||
|
@ -120,7 +122,7 @@ int main(int argc, char** argv)
|
||||||
if (!parseOptions(argc, argv, files))
|
if (!parseOptions(argc, argv, files))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Nif::NIFFile::setLoadUnsupportedFiles(true);
|
Nif::Reader::setLoadUnsupportedFiles(true);
|
||||||
// std::cout << "Reading Files" << std::endl;
|
// std::cout << "Reading Files" << std::endl;
|
||||||
for (const auto& path : files)
|
for (const auto& path : files)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +131,9 @@ int main(int argc, char** argv)
|
||||||
if (isNIF(path))
|
if (isNIF(path))
|
||||||
{
|
{
|
||||||
// std::cout << "Decoding: " << name << std::endl;
|
// std::cout << "Decoding: " << name << std::endl;
|
||||||
Nif::NIFFile temp_nif(Files::openConstrainedFileStream(path), path);
|
Nif::NIFFile file(path);
|
||||||
|
Nif::Reader reader(file);
|
||||||
|
reader.parse(Files::openConstrainedFileStream(path));
|
||||||
}
|
}
|
||||||
else if (isBSA(path))
|
else if (isBSA(path))
|
||||||
{
|
{
|
||||||
|
|
|
@ -616,7 +616,7 @@ namespace MWRender
|
||||||
MWBase::Environment::get().getWindowManager()->setCullMask(mask);
|
MWBase::Environment::get().getWindowManager()->setCullMask(mask);
|
||||||
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
|
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
|
||||||
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
|
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
|
||||||
Nif::NIFFile::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
|
Nif::Reader::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
|
||||||
|
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
mStateUpdater->setFogEnd(mViewDistance);
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ file(GLOB UNITTEST_SRC_FILES
|
||||||
fx/technique.cpp
|
fx/technique.cpp
|
||||||
|
|
||||||
esm3/readerscache.cpp
|
esm3/readerscache.cpp
|
||||||
|
|
||||||
|
nifosg/testnifloader.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
|
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
|
||||||
|
|
72
apps/openmw_test_suite/nif/node.hpp
Normal file
72
apps/openmw_test_suite/nif/node.hpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#ifndef OPENMW_TEST_SUITE_NIF_NODE_H
|
||||||
|
#define OPENMW_TEST_SUITE_NIF_NODE_H
|
||||||
|
|
||||||
|
#include <components/nif/data.hpp>
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
|
||||||
|
namespace Nif::Testing
|
||||||
|
{
|
||||||
|
inline void init(Transformation& value)
|
||||||
|
{
|
||||||
|
value = Transformation::getIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(Extra& value)
|
||||||
|
{
|
||||||
|
value.next = ExtraPtr(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(Named& value)
|
||||||
|
{
|
||||||
|
value.extra = ExtraPtr(nullptr);
|
||||||
|
value.extralist = ExtraList();
|
||||||
|
value.controller = ControllerPtr(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(Node& value)
|
||||||
|
{
|
||||||
|
init(static_cast<Named&>(value));
|
||||||
|
value.flags = 0;
|
||||||
|
init(value.trafo);
|
||||||
|
value.hasBounds = false;
|
||||||
|
value.isBone = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(NiGeometry& value)
|
||||||
|
{
|
||||||
|
init(static_cast<Node&>(value));
|
||||||
|
value.data = NiGeometryDataPtr(nullptr);
|
||||||
|
value.skin = NiSkinInstancePtr(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(NiTriShape& value)
|
||||||
|
{
|
||||||
|
init(static_cast<NiGeometry&>(value));
|
||||||
|
value.recType = RC_NiTriShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(NiTriStrips& value)
|
||||||
|
{
|
||||||
|
init(static_cast<NiGeometry&>(value));
|
||||||
|
value.recType = RC_NiTriStrips;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(NiSkinInstance& value)
|
||||||
|
{
|
||||||
|
value.data = NiSkinDataPtr(nullptr);
|
||||||
|
value.root = NodePtr(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void init(Controller& value)
|
||||||
|
{
|
||||||
|
value.next = ControllerPtr(nullptr);
|
||||||
|
value.flags = 0;
|
||||||
|
value.frequency = 0;
|
||||||
|
value.phase = 0;
|
||||||
|
value.timeStart = 0;
|
||||||
|
value.timeStop = 0;
|
||||||
|
value.target = NamedPtr(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "../nif/node.hpp"
|
||||||
|
|
||||||
#include <components/bullethelpers/processtrianglecallback.hpp>
|
#include <components/bullethelpers/processtrianglecallback.hpp>
|
||||||
#include <components/nif/data.hpp>
|
#include <components/nif/data.hpp>
|
||||||
#include <components/nif/extra.hpp>
|
#include <components/nif/extra.hpp>
|
||||||
|
@ -260,71 +262,9 @@ static bool operator==(const btCollisionShape& lhs, const btCollisionShape& rhs)
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
using namespace Nif::Testing;
|
||||||
using NifBullet::BulletNifLoader;
|
using NifBullet::BulletNifLoader;
|
||||||
|
|
||||||
void init(Nif::Transformation& value)
|
|
||||||
{
|
|
||||||
value = Nif::Transformation::getIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::Extra& value)
|
|
||||||
{
|
|
||||||
value.next = Nif::ExtraPtr(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::Named& value)
|
|
||||||
{
|
|
||||||
value.extra = Nif::ExtraPtr(nullptr);
|
|
||||||
value.extralist = Nif::ExtraList();
|
|
||||||
value.controller = Nif::ControllerPtr(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::Node& value)
|
|
||||||
{
|
|
||||||
init(static_cast<Nif::Named&>(value));
|
|
||||||
value.flags = 0;
|
|
||||||
init(value.trafo);
|
|
||||||
value.hasBounds = false;
|
|
||||||
value.parents.push_back(nullptr);
|
|
||||||
value.isBone = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::NiGeometry& value)
|
|
||||||
{
|
|
||||||
init(static_cast<Nif::Node&>(value));
|
|
||||||
value.data = Nif::NiGeometryDataPtr(nullptr);
|
|
||||||
value.skin = Nif::NiSkinInstancePtr(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::NiTriShape& value)
|
|
||||||
{
|
|
||||||
init(static_cast<Nif::NiGeometry&>(value));
|
|
||||||
value.recType = Nif::RC_NiTriShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::NiTriStrips& value)
|
|
||||||
{
|
|
||||||
init(static_cast<Nif::NiGeometry&>(value));
|
|
||||||
value.recType = Nif::RC_NiTriStrips;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::NiSkinInstance& value)
|
|
||||||
{
|
|
||||||
value.data = Nif::NiSkinDataPtr(nullptr);
|
|
||||||
value.root = Nif::NodePtr(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Nif::Controller& value)
|
|
||||||
{
|
|
||||||
value.next = Nif::ControllerPtr(nullptr);
|
|
||||||
value.flags = 0;
|
|
||||||
value.frequency = 0;
|
|
||||||
value.phase = 0;
|
|
||||||
value.timeStart = 0;
|
|
||||||
value.timeStop = 0;
|
|
||||||
value.target = Nif::NamedPtr(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy(const btTransform& src, Nif::Transformation& dst)
|
void copy(const btTransform& src, Nif::Transformation& dst)
|
||||||
{
|
{
|
||||||
dst.pos = osg::Vec3f(src.getOrigin().x(), src.getOrigin().y(), src.getOrigin().z());
|
dst.pos = osg::Vec3f(src.getOrigin().x(), src.getOrigin().y(), src.getOrigin().z());
|
||||||
|
@ -333,31 +273,9 @@ namespace
|
||||||
dst.rotation.mValues[column][row] = src.getBasis().getRow(row)[column];
|
dst.rotation.mValues[column][row] = src.getBasis().getRow(row)[column];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NifFileMock : Nif::File
|
|
||||||
{
|
|
||||||
MOCK_METHOD(Nif::Record*, getRecord, (std::size_t), (const, override));
|
|
||||||
MOCK_METHOD(std::size_t, numRecords, (), (const, override));
|
|
||||||
MOCK_METHOD(Nif::Record*, getRoot, (std::size_t), (const, override));
|
|
||||||
MOCK_METHOD(std::size_t, numRoots, (), (const, override));
|
|
||||||
MOCK_METHOD(std::string, getString, (uint32_t), (const, override));
|
|
||||||
MOCK_METHOD(void, setUseSkinning, (bool), (override));
|
|
||||||
MOCK_METHOD(bool, getUseSkinning, (), (const, override));
|
|
||||||
MOCK_METHOD(std::filesystem::path, getFilename, (), (const, override));
|
|
||||||
MOCK_METHOD(std::string, getHash, (), (const, override));
|
|
||||||
MOCK_METHOD(unsigned int, getVersion, (), (const, override));
|
|
||||||
MOCK_METHOD(unsigned int, getUserVersion, (), (const, override));
|
|
||||||
MOCK_METHOD(unsigned int, getBethVersion, (), (const, override));
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RecordMock : Nif::Record
|
|
||||||
{
|
|
||||||
MOCK_METHOD(void, read, (Nif::NIFStream * nif), (override));
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TestBulletNifLoader : Test
|
struct TestBulletNifLoader : Test
|
||||||
{
|
{
|
||||||
BulletNifLoader mLoader;
|
BulletNifLoader mLoader;
|
||||||
const StrictMock<const NifFileMock> mNifFile;
|
|
||||||
Nif::Node mNode;
|
Nif::Node mNode;
|
||||||
Nif::Node mNode2;
|
Nif::Node mNode2;
|
||||||
Nif::NiNode mNiNode;
|
Nif::NiNode mNiNode;
|
||||||
|
@ -412,16 +330,15 @@ namespace
|
||||||
= { osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0) };
|
= { 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));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_zero_num_roots_should_return_default)
|
TEST_F(TestBulletNifLoader, for_zero_num_roots_should_return_default)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(0));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -432,10 +349,11 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)
|
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(nullptr));
|
file.mRoots.push_back(nullptr);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -444,10 +362,11 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default)
|
TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode));
|
file.mRoots.push_back(&mNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -458,10 +377,11 @@ namespace
|
||||||
{
|
{
|
||||||
mNode.recType = Nif::RC_RootCollisionNode;
|
mNode.recType = Nif::RC_RootCollisionNode;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode));
|
file.mRoots.push_back(&mNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -470,10 +390,11 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_default_root_nif_node_and_filename_starting_with_x_should_return_default)
|
TEST_F(TestBulletNifLoader, for_default_root_nif_node_and_filename_starting_with_x_should_return_default)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode));
|
file.mRoots.push_back(&mNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -489,10 +410,11 @@ namespace
|
||||||
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
||||||
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode));
|
file.mRoots.push_back(&mNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -515,10 +437,11 @@ namespace
|
||||||
mNode.parents.push_back(&mNiNode);
|
mNode.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -547,10 +470,11 @@ namespace
|
||||||
mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6);
|
mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -585,10 +509,11 @@ namespace
|
||||||
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
|
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -623,10 +548,11 @@ namespace
|
||||||
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
|
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(4, 5, 6);
|
expected.mCollisionBox.mExtents = osg::Vec3f(4, 5, 6);
|
||||||
|
@ -647,10 +573,11 @@ namespace
|
||||||
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
||||||
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode));
|
file.mRoots.push_back(&mNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -661,10 +588,11 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_shape_with_triangle_mesh_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_shape_with_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape));
|
file.mRoots.push_back(&mNiTriShape);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -682,10 +610,11 @@ namespace
|
||||||
mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3);
|
||||||
mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape));
|
file.mRoots.push_back(&mNiTriShape);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
|
||||||
|
@ -699,10 +628,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -719,10 +649,11 @@ namespace
|
||||||
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
mNiTriShape.parents.push_back(&mNiNode2);
|
mNiTriShape.parents.push_back(&mNiNode2);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -739,10 +670,11 @@ namespace
|
||||||
mNiNode.children
|
mNiNode.children
|
||||||
= Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) }));
|
= Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
|
triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
|
||||||
|
@ -760,10 +692,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -779,10 +712,11 @@ namespace
|
||||||
copy(mTransform, mNiTriShape.trafo);
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
mNiTriShape.trafo.scale = 3;
|
mNiTriShape.trafo.scale = 3;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape));
|
file.mRoots.push_back(&mNiTriShape);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -806,10 +740,11 @@ namespace
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
mNiNode.trafo.scale = 4;
|
mNiNode.trafo.scale = 4;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -840,10 +775,11 @@ namespace
|
||||||
Nif::NodePtr(&mNiTriShape2),
|
Nif::NodePtr(&mNiTriShape2),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -876,10 +812,11 @@ namespace
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
mNiNode.trafo.scale = 4;
|
mNiNode.trafo.scale = 4;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -912,10 +849,11 @@ namespace
|
||||||
}));
|
}));
|
||||||
mNiNode.trafo.scale = 4;
|
mNiNode.trafo.scale = 4;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(
|
triangles->addTriangle(
|
||||||
|
@ -943,11 +881,12 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriShape2));
|
file.mRoots.push_back(&mNiTriShape2);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -974,10 +913,11 @@ namespace
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
mNiNode.recType = Nif::RC_AvoidNode;
|
mNiNode.recType = Nif::RC_AvoidNode;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -993,10 +933,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1011,10 +952,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1030,10 +972,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1054,10 +997,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1077,10 +1021,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1101,10 +1046,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1131,10 +1077,11 @@ namespace
|
||||||
mNiNode.children = Nif::NodeList(
|
mNiNode.children = Nif::NodeList(
|
||||||
std::vector<Nif::NodePtr>({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) }));
|
std::vector<Nif::NodePtr>({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1154,10 +1101,11 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1177,10 +1125,11 @@ namespace
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) }));
|
||||||
mNiNode.recType = Nif::RC_NiNode;
|
mNiNode.recType = Nif::RC_NiNode;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1194,10 +1143,11 @@ namespace
|
||||||
{
|
{
|
||||||
mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
|
mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape));
|
file.mRoots.push_back(&mNiTriShape);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1206,10 +1156,11 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape)
|
TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1224,10 +1175,11 @@ namespace
|
||||||
{
|
{
|
||||||
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriShapeData);
|
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriShapeData);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1238,10 +1190,11 @@ namespace
|
||||||
{
|
{
|
||||||
mNiTriStripsData.strips.clear();
|
mNiTriStripsData.strips.clear();
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1252,10 +1205,11 @@ namespace
|
||||||
{
|
{
|
||||||
mNiTriStripsData.strips.front() = { 0, 1 };
|
mNiTriStripsData.strips.front() = { 0, 1 };
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1269,10 +1223,11 @@ namespace
|
||||||
mNiNode.recType = Nif::RC_AvoidNode;
|
mNiNode.recType = Nif::RC_AvoidNode;
|
||||||
mNiTriStripsData.strips.front() = { 0, 1 };
|
mNiTriStripsData.strips.front() = { 0, 1 };
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("test.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1285,10 +1240,11 @@ namespace
|
||||||
mNiTriStrips.parents.push_back(&mNiNode);
|
mNiTriStrips.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriStrips) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriStrips) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
const Resource::BulletShape expected;
|
const Resource::BulletShape expected;
|
||||||
|
|
||||||
|
@ -1301,11 +1257,12 @@ namespace
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriStrips));
|
file.mRoots.push_back(&mNiTriStrips);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
@ -1330,11 +1287,12 @@ namespace
|
||||||
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
|
||||||
mNiNode2.trafo.scale = 3;
|
mNiNode2.trafo.scale = 3;
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
Nif::NIFFile file("xtest.nif");
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
file.mRoots.push_back(&mNiNode);
|
||||||
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiNode2));
|
file.mRoots.push_back(&mNiNode2);
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
file.mHash = mHash;
|
||||||
const auto result = mLoader.load(mNifFile);
|
|
||||||
|
const auto result = mLoader.load(file);
|
||||||
|
|
||||||
std::unique_ptr<btTriangleMesh> triangles1(new btTriangleMesh(false));
|
std::unique_ptr<btTriangleMesh> triangles1(new btTriangleMesh(false));
|
||||||
triangles1->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
triangles1->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
|
231
apps/openmw_test_suite/nifosg/testnifloader.cpp
Normal file
231
apps/openmw_test_suite/nifosg/testnifloader.cpp
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
#include "../nif/node.hpp"
|
||||||
|
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
#include <components/nif/property.hpp>
|
||||||
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
#include <components/resource/imagemanager.hpp>
|
||||||
|
#include <components/sceneutil/serialize.hpp>
|
||||||
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
#include <osgDB/Registry>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace testing;
|
||||||
|
using namespace NifOsg;
|
||||||
|
using namespace Nif::Testing;
|
||||||
|
|
||||||
|
struct BaseNifOsgLoaderTest
|
||||||
|
{
|
||||||
|
VFS::Manager mVfs{ false };
|
||||||
|
Resource::ImageManager mImageManager{ &mVfs };
|
||||||
|
const osgDB::ReaderWriter* mReaderWriter = osgDB::Registry::instance()->getReaderWriterForExtension("osgt");
|
||||||
|
osg::ref_ptr<osgDB::Options> mOptions = new osgDB::Options;
|
||||||
|
|
||||||
|
BaseNifOsgLoaderTest()
|
||||||
|
{
|
||||||
|
SceneUtil::registerSerializers();
|
||||||
|
|
||||||
|
if (mReaderWriter == nullptr)
|
||||||
|
throw std::runtime_error("osgt reader writer is not found");
|
||||||
|
|
||||||
|
mOptions->setPluginStringData("fileType", "Ascii");
|
||||||
|
mOptions->setPluginStringData("WriteImageHint", "UseExternal");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string serialize(const osg::Node& node) const
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
mReaderWriter->writeNode(node, stream, mOptions);
|
||||||
|
std::string result;
|
||||||
|
for (std::string line; std::getline(stream, line);)
|
||||||
|
{
|
||||||
|
if (line.starts_with('#'))
|
||||||
|
continue;
|
||||||
|
boost::trim_right(line);
|
||||||
|
result += line;
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NifOsgLoaderTest : Test, BaseNifOsgLoaderTest
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(NifOsgLoaderTest, shouldLoadFileWithDefaultNode)
|
||||||
|
{
|
||||||
|
Nif::Node node;
|
||||||
|
init(node);
|
||||||
|
Nif::NIFFile file("test.nif");
|
||||||
|
file.mRoots.push_back(&node);
|
||||||
|
auto result = Loader::load(file, &mImageManager);
|
||||||
|
EXPECT_EQ(serialize(*result), R"(
|
||||||
|
osg::Group {
|
||||||
|
UniqueID 1
|
||||||
|
DataVariance STATIC
|
||||||
|
UserDataContainer TRUE {
|
||||||
|
osg::DefaultUserDataContainer {
|
||||||
|
UniqueID 2
|
||||||
|
UDC_UserObjects 1 {
|
||||||
|
osg::StringValueObject {
|
||||||
|
UniqueID 3
|
||||||
|
Name "fileHash"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Children 1 {
|
||||||
|
osg::Group {
|
||||||
|
UniqueID 4
|
||||||
|
DataVariance STATIC
|
||||||
|
UserDataContainer TRUE {
|
||||||
|
osg::DefaultUserDataContainer {
|
||||||
|
UniqueID 5
|
||||||
|
UDC_UserObjects 1 {
|
||||||
|
osg::UIntValueObject {
|
||||||
|
UniqueID 6
|
||||||
|
Name "recIndex"
|
||||||
|
Value 4294967295
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string formatOsgNodeForShaderProperty(std::string_view shaderPrefix)
|
||||||
|
{
|
||||||
|
static constexpr const char format[] = R"(
|
||||||
|
osg::Group {
|
||||||
|
UniqueID 1
|
||||||
|
DataVariance STATIC
|
||||||
|
UserDataContainer TRUE {
|
||||||
|
osg::DefaultUserDataContainer {
|
||||||
|
UniqueID 2
|
||||||
|
UDC_UserObjects 1 {
|
||||||
|
osg::StringValueObject {
|
||||||
|
UniqueID 3
|
||||||
|
Name "fileHash"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Children 1 {
|
||||||
|
osg::Group {
|
||||||
|
UniqueID 4
|
||||||
|
DataVariance STATIC
|
||||||
|
UserDataContainer TRUE {
|
||||||
|
osg::DefaultUserDataContainer {
|
||||||
|
UniqueID 5
|
||||||
|
UDC_UserObjects 3 {
|
||||||
|
osg::UIntValueObject {
|
||||||
|
UniqueID 6
|
||||||
|
Name "recIndex"
|
||||||
|
Value 4294967295
|
||||||
|
}
|
||||||
|
osg::StringValueObject {
|
||||||
|
UniqueID 7
|
||||||
|
Name "shaderPrefix"
|
||||||
|
Value "%s"
|
||||||
|
}
|
||||||
|
osg::BoolValueObject {
|
||||||
|
UniqueID 8
|
||||||
|
Name "shaderRequired"
|
||||||
|
Value TRUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateSet TRUE {
|
||||||
|
osg::StateSet {
|
||||||
|
UniqueID 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
return (boost::format(format) % shaderPrefix).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShaderPrefixParams
|
||||||
|
{
|
||||||
|
unsigned int mShaderType;
|
||||||
|
std::string_view mExpectedShaderPrefix;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NifOsgLoaderBSShaderPrefixTest : TestWithParam<ShaderPrefixParams>, BaseNifOsgLoaderTest
|
||||||
|
{
|
||||||
|
static constexpr std::array sParams = {
|
||||||
|
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Default), "nv_default" },
|
||||||
|
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_NoLighting), "nv_nolighting" },
|
||||||
|
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Tile), "nv_default" },
|
||||||
|
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "nv_default" },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(NifOsgLoaderBSShaderPrefixTest, shouldAddShaderPrefix)
|
||||||
|
{
|
||||||
|
Nif::Node node;
|
||||||
|
init(node);
|
||||||
|
Nif::BSShaderPPLightingProperty property;
|
||||||
|
property.recType = Nif::RC_BSShaderPPLightingProperty;
|
||||||
|
property.textureSet = nullptr;
|
||||||
|
property.controller = nullptr;
|
||||||
|
property.type = GetParam().mShaderType;
|
||||||
|
node.props.push_back(Nif::RecordPtrT<Nif::Property>(&property));
|
||||||
|
Nif::NIFFile file("test.nif");
|
||||||
|
file.mRoots.push_back(&node);
|
||||||
|
auto result = Loader::load(file, &mImageManager);
|
||||||
|
EXPECT_EQ(serialize(*result), formatOsgNodeForShaderProperty(GetParam().mExpectedShaderPrefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(Params, NifOsgLoaderBSShaderPrefixTest, ValuesIn(NifOsgLoaderBSShaderPrefixTest::sParams));
|
||||||
|
|
||||||
|
struct NifOsgLoaderBSLightingShaderPrefixTest : TestWithParam<ShaderPrefixParams>, BaseNifOsgLoaderTest
|
||||||
|
{
|
||||||
|
static constexpr std::array sParams = {
|
||||||
|
ShaderPrefixParams{
|
||||||
|
static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Default), "nv_default" },
|
||||||
|
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Cloud), "nv_default" },
|
||||||
|
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "nv_default" },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(NifOsgLoaderBSLightingShaderPrefixTest, shouldAddShaderPrefix)
|
||||||
|
{
|
||||||
|
Nif::Node node;
|
||||||
|
init(node);
|
||||||
|
Nif::BSLightingShaderProperty property;
|
||||||
|
property.recType = Nif::RC_BSLightingShaderProperty;
|
||||||
|
property.mTextureSet = nullptr;
|
||||||
|
property.controller = nullptr;
|
||||||
|
property.type = GetParam().mShaderType;
|
||||||
|
node.props.push_back(Nif::RecordPtrT<Nif::Property>(&property));
|
||||||
|
Nif::NIFFile file("test.nif");
|
||||||
|
file.mRoots.push_back(&node);
|
||||||
|
auto result = Loader::load(file, &mImageManager);
|
||||||
|
EXPECT_EQ(serialize(*result), formatOsgNodeForShaderProperty(GetParam().mExpectedShaderPrefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
Params, NifOsgLoaderBSLightingShaderPrefixTest, ValuesIn(NifOsgLoaderBSLightingShaderPrefixTest::sParams));
|
||||||
|
}
|
|
@ -19,14 +19,14 @@ namespace Nif
|
||||||
if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0))
|
if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0))
|
||||||
extra.read(nif);
|
extra.read(nif);
|
||||||
else
|
else
|
||||||
extralist.read(nif);
|
readRecordList(nif, extralist);
|
||||||
controller.read(nif);
|
controller.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Named::post(NIFFile* nif)
|
void Named::post(Reader& nif)
|
||||||
{
|
{
|
||||||
extra.post(nif);
|
extra.post(nif);
|
||||||
extralist.post(nif);
|
postRecordList(nif, extralist);
|
||||||
controller.post(nif);
|
controller.post(nif);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Nif
|
||||||
unsigned int recordSize{ 0u };
|
unsigned int recordSize{ 0u };
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override { next.post(nif); }
|
void post(Reader& nif) override { next.post(nif); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Controller : public Record
|
struct Controller : public Record
|
||||||
|
@ -43,7 +43,7 @@ namespace Nif
|
||||||
NamedPtr target;
|
NamedPtr target;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
bool isActive() const { return flags & Flag_Active; }
|
bool isActive() const { return flags & Flag_Active; }
|
||||||
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); }
|
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); }
|
||||||
|
@ -58,7 +58,7 @@ namespace Nif
|
||||||
ControllerPtr controller;
|
ControllerPtr controller;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
using NiSequenceStreamHelper = Named;
|
using NiSequenceStreamHelper = Named;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Nif
|
||||||
/* bool mPersistRenderData = */ nif->getBoolean();
|
/* bool mPersistRenderData = */ nif->getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSourceTexture::post(NIFFile* nif)
|
void NiSourceTexture::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Named::post(nif);
|
Named::post(nif);
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
|
@ -59,7 +59,7 @@ namespace Nif
|
||||||
controller.read(nif);
|
controller.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiParticleModifier::post(NIFFile* nif)
|
void NiParticleModifier::post(Reader& nif)
|
||||||
{
|
{
|
||||||
next.post(nif);
|
next.post(nif);
|
||||||
controller.post(nif);
|
controller.post(nif);
|
||||||
|
@ -78,7 +78,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiParticleColorModifier::post(NIFFile* nif)
|
void NiParticleColorModifier::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiParticleModifier::post(nif);
|
NiParticleModifier::post(nif);
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace Nif
|
||||||
unsigned int alpha;
|
unsigned int alpha;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSShaderTextureSet : public Record
|
struct BSShaderTextureSet : public Record
|
||||||
|
@ -89,7 +89,7 @@ namespace Nif
|
||||||
ControllerPtr controller;
|
ControllerPtr controller;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiParticleGrowFade : public NiParticleModifier
|
struct NiParticleGrowFade : public NiParticleModifier
|
||||||
|
@ -105,7 +105,7 @@ namespace Nif
|
||||||
NiColorDataPtr data;
|
NiColorDataPtr data;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiGravity : public NiParticleModifier
|
struct NiGravity : public NiParticleModifier
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Nif
|
||||||
target.read(nif);
|
target.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::post(NIFFile* nif)
|
void Controller::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Record::post(nif);
|
Record::post(nif);
|
||||||
next.post(nif);
|
next.post(nif);
|
||||||
|
@ -44,7 +44,7 @@ namespace Nif
|
||||||
mInterpolator.read(nif);
|
mInterpolator.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSingleInterpController::post(NIFFile* nif)
|
void NiSingleInterpController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
mInterpolator.post(nif);
|
mInterpolator.post(nif);
|
||||||
|
@ -104,7 +104,7 @@ namespace Nif
|
||||||
nif->getChar();
|
nif->getChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiParticleSystemController::post(NIFFile* nif)
|
void NiParticleSystemController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
Controller::post(nif);
|
||||||
emitter.post(nif);
|
emitter.post(nif);
|
||||||
|
@ -128,7 +128,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMaterialColorController::post(NIFFile* nif)
|
void NiMaterialColorController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiPoint3InterpController::post(nif);
|
NiPoint3InterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
|
@ -142,7 +142,7 @@ namespace Nif
|
||||||
target.read(nif);
|
target.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiLookAtController::post(NIFFile* nif)
|
void NiLookAtController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
Controller::post(nif);
|
||||||
target.post(nif);
|
target.post(nif);
|
||||||
|
@ -160,7 +160,7 @@ namespace Nif
|
||||||
floatData.read(nif);
|
floatData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPathController::post(NIFFile* nif)
|
void NiPathController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
Controller::post(nif);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiUVController::post(NIFFile* nif)
|
void NiUVController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Controller::post(nif);
|
Controller::post(nif);
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
|
@ -189,7 +189,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiKeyframeController::post(NIFFile* nif)
|
void NiKeyframeController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::post(nif);
|
NiSingleInterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
|
@ -206,10 +206,10 @@ namespace Nif
|
||||||
mExtraTargets = targets;
|
mExtraTargets = targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMultiTargetTransformController::post(NIFFile* nif)
|
void NiMultiTargetTransformController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
mExtraTargets.post(nif);
|
postRecordList(nif, mExtraTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiAlphaController::read(NIFStream* nif)
|
void NiAlphaController::read(NIFStream* nif)
|
||||||
|
@ -219,7 +219,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiAlphaController::post(NIFFile* nif)
|
void NiAlphaController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::post(nif);
|
NiFloatInterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
|
@ -232,7 +232,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiRollController::post(NIFFile* nif)
|
void NiRollController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiSingleInterpController::post(nif);
|
NiSingleInterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
|
@ -251,7 +251,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||||
{
|
{
|
||||||
mInterpolators.read(nif);
|
readRecordList(nif, mInterpolators);
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() > 9)
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() > 9)
|
||||||
{
|
{
|
||||||
unsigned int numUnknown = nif->getUInt();
|
unsigned int numUnknown = nif->getUInt();
|
||||||
|
@ -275,11 +275,11 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiGeomMorpherController::post(NIFFile* nif)
|
void NiGeomMorpherController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiInterpController::post(nif);
|
NiInterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
mInterpolators.post(nif);
|
postRecordList(nif, mInterpolators);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiVisController::read(NIFStream* nif)
|
void NiVisController::read(NIFStream* nif)
|
||||||
|
@ -289,7 +289,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiVisController::post(NIFFile* nif)
|
void NiVisController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiBoolInterpController::post(nif);
|
NiBoolInterpController::post(nif);
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
|
@ -304,13 +304,13 @@ namespace Nif
|
||||||
timeStart = nif->getFloat();
|
timeStart = nif->getFloat();
|
||||||
mDelta = nif->getFloat();
|
mDelta = nif->getFloat();
|
||||||
}
|
}
|
||||||
mSources.read(nif);
|
readRecordList(nif, mSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiFlipController::post(NIFFile* nif)
|
void NiFlipController::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiFloatInterpController::post(nif);
|
NiFloatInterpController::post(nif);
|
||||||
mSources.post(nif);
|
postRecordList(nif, mSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkBlendController::read(NIFStream* nif)
|
void bhkBlendController::read(NIFStream* nif)
|
||||||
|
@ -334,7 +334,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPoint3Interpolator::post(NIFFile* nif)
|
void NiPoint3Interpolator::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiBoolInterpolator::post(NIFFile* nif)
|
void NiBoolInterpolator::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +356,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiFloatInterpolator::post(NIFFile* nif)
|
void NiFloatInterpolator::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiTransformInterpolator::post(NIFFile* nif)
|
void NiTransformInterpolator::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ namespace Nif
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiColorInterpolator::post(NIFFile* nif)
|
void NiColorInterpolator::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace Nif
|
||||||
NiInterpolatorPtr mInterpolator;
|
NiInterpolatorPtr mInterpolator;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for controllers that use a NiFloatInterpolator to animate their target.
|
// Base class for controllers that use a NiFloatInterpolator to animate their target.
|
||||||
|
@ -116,7 +116,7 @@ namespace Nif
|
||||||
NiParticleModifierPtr colliders;
|
NiParticleModifierPtr colliders;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; }
|
bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; }
|
||||||
bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; }
|
bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; }
|
||||||
|
@ -129,7 +129,7 @@ namespace Nif
|
||||||
unsigned int mTargetColor;
|
unsigned int mTargetColor;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiPathController : public Controller
|
struct NiPathController : public Controller
|
||||||
|
@ -152,7 +152,7 @@ namespace Nif
|
||||||
short followAxis;
|
short followAxis;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiLookAtController : public Controller
|
struct NiLookAtController : public Controller
|
||||||
|
@ -161,7 +161,7 @@ namespace Nif
|
||||||
unsigned short lookAtFlags{ 0 };
|
unsigned short lookAtFlags{ 0 };
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiUVController : public Controller
|
struct NiUVController : public Controller
|
||||||
|
@ -170,7 +170,7 @@ namespace Nif
|
||||||
unsigned int uvSet;
|
unsigned int uvSet;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiKeyframeController : public NiSingleInterpController
|
struct NiKeyframeController : public NiSingleInterpController
|
||||||
|
@ -178,7 +178,7 @@ namespace Nif
|
||||||
NiKeyframeDataPtr mData;
|
NiKeyframeDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiMultiTargetTransformController : public NiInterpController
|
struct NiMultiTargetTransformController : public NiInterpController
|
||||||
|
@ -186,7 +186,7 @@ namespace Nif
|
||||||
NodeList mExtraTargets;
|
NodeList mExtraTargets;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiAlphaController : public NiFloatInterpController
|
struct NiAlphaController : public NiFloatInterpController
|
||||||
|
@ -194,7 +194,7 @@ namespace Nif
|
||||||
NiFloatDataPtr mData;
|
NiFloatDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiRollController : public NiSingleInterpController
|
struct NiRollController : public NiSingleInterpController
|
||||||
|
@ -202,7 +202,7 @@ namespace Nif
|
||||||
NiFloatDataPtr mData;
|
NiFloatDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiGeomMorpherController : public NiInterpController
|
struct NiGeomMorpherController : public NiInterpController
|
||||||
|
@ -214,7 +214,7 @@ namespace Nif
|
||||||
std::vector<float> mWeights;
|
std::vector<float> mWeights;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiVisController : public NiBoolInterpController
|
struct NiVisController : public NiBoolInterpController
|
||||||
|
@ -222,7 +222,7 @@ namespace Nif
|
||||||
NiVisDataPtr mData;
|
NiVisDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiFlipController : public NiFloatInterpController
|
struct NiFlipController : public NiFloatInterpController
|
||||||
|
@ -232,7 +232,7 @@ namespace Nif
|
||||||
NiSourceTextureList mSources;
|
NiSourceTextureList mSources;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bhkBlendController : public Controller
|
struct bhkBlendController : public Controller
|
||||||
|
@ -255,7 +255,7 @@ namespace Nif
|
||||||
osg::Vec3f defaultVal;
|
osg::Vec3f defaultVal;
|
||||||
NiPosDataPtr data;
|
NiPosDataPtr data;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBoolInterpolator : public NiInterpolator
|
struct NiBoolInterpolator : public NiInterpolator
|
||||||
|
@ -263,7 +263,7 @@ namespace Nif
|
||||||
char defaultVal;
|
char defaultVal;
|
||||||
NiBoolDataPtr data;
|
NiBoolDataPtr data;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiFloatInterpolator : public NiInterpolator
|
struct NiFloatInterpolator : public NiInterpolator
|
||||||
|
@ -271,7 +271,7 @@ namespace Nif
|
||||||
float defaultVal;
|
float defaultVal;
|
||||||
NiFloatDataPtr data;
|
NiFloatDataPtr data;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiTransformInterpolator : public NiInterpolator
|
struct NiTransformInterpolator : public NiInterpolator
|
||||||
|
@ -282,7 +282,7 @@ namespace Nif
|
||||||
NiKeyframeDataPtr data;
|
NiKeyframeDataPtr data;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiColorInterpolator : public NiInterpolator
|
struct NiColorInterpolator : public NiInterpolator
|
||||||
|
@ -290,7 +290,7 @@ namespace Nif
|
||||||
osg::Vec4f defaultVal;
|
osg::Vec4f defaultVal;
|
||||||
NiColorDataPtr data;
|
NiColorDataPtr data;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
#include "nifkey.hpp"
|
#include "nifkey.hpp"
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
void NiSkinInstance::read(NIFStream* nif)
|
void NiSkinInstance::read(NIFStream* nif)
|
||||||
|
@ -10,28 +13,27 @@ namespace Nif
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 101))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 101))
|
||||||
partitions.read(nif);
|
partitions.read(nif);
|
||||||
root.read(nif);
|
root.read(nif);
|
||||||
bones.read(nif);
|
readRecordList(nif, bones);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSkinInstance::post(NIFFile* nif)
|
void NiSkinInstance::post(Reader& nif)
|
||||||
{
|
{
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
partitions.post(nif);
|
partitions.post(nif);
|
||||||
root.post(nif);
|
root.post(nif);
|
||||||
bones.post(nif);
|
postRecordList(nif, bones);
|
||||||
|
|
||||||
if (data.empty() || root.empty())
|
if (data.empty() || root.empty())
|
||||||
nif->fail("NiSkinInstance missing root or data");
|
throw Nif::Exception("NiSkinInstance missing root or data", nif.getFilename());
|
||||||
|
|
||||||
size_t bnum = bones.length();
|
if (bones.size() != data->bones.size())
|
||||||
if (bnum != data->bones.size())
|
throw Nif::Exception("Mismatch in NiSkinData bone count", nif.getFilename());
|
||||||
nif->fail("Mismatch in NiSkinData bone count");
|
|
||||||
|
|
||||||
for (size_t i = 0; i < bnum; i++)
|
for (auto& bone : bones)
|
||||||
{
|
{
|
||||||
if (bones[i].empty())
|
if (bone.empty())
|
||||||
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
throw Nif::Exception("Oops: Missing bone! Don't know how to handle this.", nif.getFilename());
|
||||||
bones[i]->setBone();
|
bone->setBone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +303,7 @@ namespace Nif
|
||||||
nif->getUChars(data, numPixels * numFaces);
|
nif->getUChars(data, numPixels * numFaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPixelData::post(NIFFile* nif)
|
void NiPixelData::post(Reader& nif)
|
||||||
{
|
{
|
||||||
palette.post(nif);
|
palette.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -357,7 +359,7 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSkinData::post(NIFFile* nif)
|
void NiSkinData::post(Reader& nif)
|
||||||
{
|
{
|
||||||
partitions.post(nif);
|
partitions.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +472,8 @@ namespace Nif
|
||||||
{
|
{
|
||||||
palette = nif->getString();
|
palette = nif->getString();
|
||||||
if (nif->getUInt() != palette.size())
|
if (nif->getUInt() != palette.size())
|
||||||
nif->file->warn("Failed size check in NiStringPalette");
|
Log(Debug::Warning) << "NIFFile Warning: Failed size check in NiStringPalette. File: "
|
||||||
|
<< nif->getFile().getFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiBoolData::read(NIFStream* nif)
|
void NiBoolData::read(NIFStream* nif)
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace Nif
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiColorData : public Record
|
struct NiColorData : public Record
|
||||||
|
@ -169,7 +169,7 @@ namespace Nif
|
||||||
NodeList bones;
|
NodeList bones;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSDismemberSkinInstance : public NiSkinInstance
|
struct BSDismemberSkinInstance : public NiSkinInstance
|
||||||
|
@ -198,7 +198,7 @@ namespace Nif
|
||||||
NiSkinPartitionPtr partitions;
|
NiSkinPartitionPtr partitions;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiSkinPartition : public Record
|
struct NiSkinPartition : public Record
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace Nif
|
||||||
nif->skip(2); // Unknown short
|
nif->skip(2); // Unknown short
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiTextureEffect::post(NIFFile* nif)
|
void NiTextureEffect::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiDynamicEffect::post(nif);
|
NiDynamicEffect::post(nif);
|
||||||
texture.post(nif);
|
texture.post(nif);
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace Nif
|
||||||
CoordGenType coordGenType;
|
CoordGenType coordGenType;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
bool wrapT() const { return clamp & 1; }
|
bool wrapT() const { return clamp & 1; }
|
||||||
bool wrapS() const { return (clamp >> 1) & 1; }
|
bool wrapS() const { return (clamp >> 1) & 1; }
|
||||||
|
|
21
components/nif/exception.hpp
Normal file
21
components/nif/exception.hpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_NIF_EXCEPTION_HPP
|
||||||
|
#define OPENMW_COMPONENTS_NIF_EXCEPTION_HPP
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <components/files/conversion.hpp>
|
||||||
|
|
||||||
|
namespace Nif
|
||||||
|
{
|
||||||
|
struct Exception : std::runtime_error
|
||||||
|
{
|
||||||
|
explicit Exception(const std::string& message, const std::filesystem::path& path)
|
||||||
|
: std::runtime_error("NIFFile Error: " + message + " when reading " + Files::pathToUnicodeString(path))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,6 +15,7 @@
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
#include "effect.hpp"
|
#include "effect.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
#include "extra.hpp"
|
#include "extra.hpp"
|
||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
#include "property.hpp"
|
#include "property.hpp"
|
||||||
|
@ -22,11 +23,16 @@
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Open a NIF stream. The name is used for error messages.
|
Reader::Reader(NIFFile& file)
|
||||||
NIFFile::NIFFile(Files::IStreamPtr&& stream, const std::filesystem::path& name)
|
: ver(file.mVersion)
|
||||||
: filename(name)
|
, userVer(file.mUserVersion)
|
||||||
|
, bethVer(file.mBethVersion)
|
||||||
|
, filename(file.mPath)
|
||||||
|
, hash(file.mHash)
|
||||||
|
, records(file.mRecords)
|
||||||
|
, roots(file.mRoots)
|
||||||
|
, mUseSkinning(file.mUseSkinning)
|
||||||
{
|
{
|
||||||
parse(std::move(stream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeType, RecordType recordType>
|
template <typename NodeType, RecordType recordType>
|
||||||
|
@ -172,7 +178,7 @@ namespace Nif
|
||||||
/// Make the factory map used for parsing the file
|
/// Make the factory map used for parsing the file
|
||||||
static const std::map<std::string, CreateRecord> factories = makeFactory();
|
static const std::map<std::string, CreateRecord> factories = makeFactory();
|
||||||
|
|
||||||
std::string NIFFile::printVersion(unsigned int version)
|
std::string Reader::printVersion(unsigned int version)
|
||||||
{
|
{
|
||||||
int major = (version >> 24) & 0xFF;
|
int major = (version >> 24) & 0xFF;
|
||||||
int minor = (version >> 16) & 0xFF;
|
int minor = (version >> 16) & 0xFF;
|
||||||
|
@ -184,12 +190,12 @@ namespace Nif
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFFile::parse(Files::IStreamPtr&& stream)
|
void Reader::parse(Files::IStreamPtr&& stream)
|
||||||
{
|
{
|
||||||
const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream);
|
const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream);
|
||||||
hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t));
|
hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t));
|
||||||
|
|
||||||
NIFStream nif(this, std::move(stream));
|
NIFStream nif(*this, std::move(stream));
|
||||||
|
|
||||||
// Check the header string
|
// Check the header string
|
||||||
std::string head = nif.getVersionString();
|
std::string head = nif.getVersionString();
|
||||||
|
@ -200,7 +206,7 @@ namespace Nif
|
||||||
const bool supportedHeader = std::any_of(verStrings.begin(), verStrings.end(),
|
const bool supportedHeader = std::any_of(verStrings.begin(), verStrings.end(),
|
||||||
[&](const std::string& verString) { return head.compare(0, verString.size(), verString) == 0; });
|
[&](const std::string& verString) { return head.compare(0, verString.size(), verString) == 0; });
|
||||||
if (!supportedHeader)
|
if (!supportedHeader)
|
||||||
fail("Invalid NIF header: " + head);
|
throw Nif::Exception("Invalid NIF header: " + head, filename);
|
||||||
|
|
||||||
// Get BCD version
|
// Get BCD version
|
||||||
ver = nif.getUInt();
|
ver = nif.getUInt();
|
||||||
|
@ -208,15 +214,16 @@ namespace Nif
|
||||||
// It's not used by Morrowind assets but Morrowind supports it.
|
// It's not used by Morrowind assets but Morrowind supports it.
|
||||||
static const std::array<uint32_t, 2> supportedVers = {
|
static const std::array<uint32_t, 2> supportedVers = {
|
||||||
NIFStream::generateVersion(4, 0, 0, 0),
|
NIFStream::generateVersion(4, 0, 0, 0),
|
||||||
VER_MW,
|
NIFFile::VER_MW,
|
||||||
};
|
};
|
||||||
const bool supportedVersion = std::find(supportedVers.begin(), supportedVers.end(), ver) != supportedVers.end();
|
const bool supportedVersion = std::find(supportedVers.begin(), supportedVers.end(), ver) != supportedVers.end();
|
||||||
if (!supportedVersion)
|
if (!supportedVersion)
|
||||||
{
|
{
|
||||||
if (sLoadUnsupportedFiles)
|
if (sLoadUnsupportedFiles)
|
||||||
warn("Unsupported NIF version: " + printVersion(ver) + ". Proceed with caution!");
|
Log(Debug::Warning) << " NIFFile Warning: Unsupported NIF version: " << printVersion(ver)
|
||||||
|
<< ". Proceed with caution! File: " << filename;
|
||||||
else
|
else
|
||||||
fail("Unsupported NIF version: " + printVersion(ver));
|
throw Nif::Exception("Unsupported NIF version: " + printVersion(ver), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NIF data endianness
|
// NIF data endianness
|
||||||
|
@ -224,7 +231,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
unsigned char endianness = nif.getChar();
|
unsigned char endianness = nif.getChar();
|
||||||
if (endianness == 0)
|
if (endianness == 0)
|
||||||
fail("Big endian NIF files are unsupported");
|
throw Nif::Exception("Big endian NIF files are unsupported", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// User version
|
// User version
|
||||||
|
@ -237,19 +244,19 @@ namespace Nif
|
||||||
|
|
||||||
// Bethesda stream header
|
// Bethesda stream header
|
||||||
// It contains Bethesda format version and (useless) export information
|
// It contains Bethesda format version and (useless) export information
|
||||||
if (ver == VER_OB_OLD
|
if (ver == NIFFile::VER_OB_OLD
|
||||||
|| (userVer >= 3
|
|| (userVer >= 3
|
||||||
&& ((ver == VER_OB || ver == VER_BGS)
|
&& ((ver == NIFFile::VER_OB || ver == NIFFile::VER_BGS)
|
||||||
|| (ver >= NIFStream::generateVersion(10, 1, 0, 0) && ver <= NIFStream::generateVersion(20, 0, 0, 4)
|
|| (ver >= NIFStream::generateVersion(10, 1, 0, 0) && ver <= NIFStream::generateVersion(20, 0, 0, 4)
|
||||||
&& userVer <= 11))))
|
&& userVer <= 11))))
|
||||||
{
|
{
|
||||||
bethVer = nif.getUInt();
|
bethVer = nif.getUInt();
|
||||||
nif.getExportString(); // Author
|
nif.getExportString(); // Author
|
||||||
if (bethVer > BETHVER_FO4)
|
if (bethVer > NIFFile::BETHVER_FO4)
|
||||||
nif.getUInt(); // Unknown
|
nif.getUInt(); // Unknown
|
||||||
nif.getExportString(); // Process script
|
nif.getExportString(); // Process script
|
||||||
nif.getExportString(); // Export script
|
nif.getExportString(); // Export script
|
||||||
if (bethVer == BETHVER_FO4)
|
if (bethVer == NIFFile::BETHVER_FO4)
|
||||||
nif.getExportString(); // Max file path
|
nif.getExportString(); // Max file path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,24 +303,19 @@ namespace Nif
|
||||||
{
|
{
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
error << "Record number " << i << " out of " << recNum << " is blank.";
|
error << "Record number " << i << " out of " << recNum << " is blank.";
|
||||||
fail(error.str());
|
throw Nif::Exception(error.str(), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record separator. Some Havok records in Oblivion do not have it.
|
// Record separator. Some Havok records in Oblivion do not have it.
|
||||||
if (hasRecordSeparators && rec.compare(0, 3, "bhk"))
|
if (hasRecordSeparators && rec.compare(0, 3, "bhk"))
|
||||||
{
|
|
||||||
if (nif.getInt())
|
if (nif.getInt())
|
||||||
{
|
Log(Debug::Warning) << "NIFFile Warning: Record number " << i << " out of " << recNum
|
||||||
std::stringstream warning;
|
<< " is preceded by a non-zero separator. File: " << filename;
|
||||||
warning << "Record number " << i << " out of " << recNum << " is preceded by a non-zero separator.";
|
|
||||||
warn(warning.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto entry = factories.find(rec);
|
const auto entry = factories.find(rec);
|
||||||
|
|
||||||
if (entry == factories.end())
|
if (entry == factories.end())
|
||||||
fail("Unknown record type " + rec);
|
throw Nif::Exception("Unknown record type " + rec, filename);
|
||||||
|
|
||||||
r = entry->second();
|
r = entry->second();
|
||||||
|
|
||||||
|
@ -343,45 +345,31 @@ namespace Nif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
roots[i] = nullptr;
|
roots[i] = nullptr;
|
||||||
warn("Root " + std::to_string(i + 1) + " does not point to a record: index " + std::to_string(idx));
|
Log(Debug::Warning) << "NIFFile Warning: Root " << i + 1 << " does not point to a record: index " << idx
|
||||||
|
<< ". File: " << filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once parsing is done, do post-processing.
|
// Once parsing is done, do post-processing.
|
||||||
for (const auto& record : records)
|
for (const auto& record : records)
|
||||||
record->post(this);
|
record->post(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFFile::setUseSkinning(bool skinning)
|
void Reader::setUseSkinning(bool skinning)
|
||||||
{
|
{
|
||||||
mUseSkinning = skinning;
|
mUseSkinning = skinning;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NIFFile::getUseSkinning() const
|
std::atomic_bool Reader::sLoadUnsupportedFiles = false;
|
||||||
{
|
|
||||||
return mUseSkinning;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::atomic_bool NIFFile::sLoadUnsupportedFiles = false;
|
void Reader::setLoadUnsupportedFiles(bool load)
|
||||||
|
|
||||||
void NIFFile::setLoadUnsupportedFiles(bool load)
|
|
||||||
{
|
{
|
||||||
sLoadUnsupportedFiles = load;
|
sLoadUnsupportedFiles = load;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFFile::warn(const std::string& msg) const
|
std::string Reader::getString(std::uint32_t index) const
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << " NIFFile Warning: " << msg << "\nFile: " << filename;
|
if (index == std::numeric_limits<std::uint32_t>::max())
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] void NIFFile::fail(const std::string& msg) const
|
|
||||||
{
|
|
||||||
throw std::runtime_error(" NIFFile Error: " + msg + "\nFile: " + Files::pathToUnicodeString(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NIFFile::getString(uint32_t index) const
|
|
||||||
{
|
|
||||||
if (index == std::numeric_limits<uint32_t>::max())
|
|
||||||
return std::string();
|
return std::string();
|
||||||
return strings.at(index);
|
return strings.at(index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,72 +14,8 @@
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
struct File
|
struct NIFFile
|
||||||
{
|
{
|
||||||
virtual ~File() = default;
|
|
||||||
|
|
||||||
virtual Record* getRecord(size_t index) const = 0;
|
|
||||||
|
|
||||||
virtual size_t numRecords() const = 0;
|
|
||||||
|
|
||||||
virtual Record* getRoot(size_t index = 0) const = 0;
|
|
||||||
|
|
||||||
virtual size_t numRoots() const = 0;
|
|
||||||
|
|
||||||
virtual std::string getString(uint32_t index) const = 0;
|
|
||||||
|
|
||||||
virtual void setUseSkinning(bool skinning) = 0;
|
|
||||||
|
|
||||||
virtual bool getUseSkinning() const = 0;
|
|
||||||
|
|
||||||
virtual std::filesystem::path getFilename() const = 0;
|
|
||||||
|
|
||||||
virtual std::string getHash() const = 0;
|
|
||||||
|
|
||||||
virtual unsigned int getVersion() const = 0;
|
|
||||||
|
|
||||||
virtual unsigned int getUserVersion() const = 0;
|
|
||||||
|
|
||||||
virtual unsigned int getBethVersion() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NIFFile final : public File
|
|
||||||
{
|
|
||||||
/// File version, user version, Bethesda version
|
|
||||||
unsigned int ver = 0;
|
|
||||||
unsigned int userVer = 0;
|
|
||||||
unsigned int bethVer = 0;
|
|
||||||
|
|
||||||
/// File name, used for error messages and opening the file
|
|
||||||
std::filesystem::path filename;
|
|
||||||
std::string hash;
|
|
||||||
|
|
||||||
/// Record list
|
|
||||||
std::vector<std::unique_ptr<Record>> records;
|
|
||||||
|
|
||||||
/// Root list. This is a select portion of the pointers from records
|
|
||||||
std::vector<Record*> roots;
|
|
||||||
|
|
||||||
/// String table
|
|
||||||
std::vector<std::string> strings;
|
|
||||||
|
|
||||||
bool mUseSkinning = false;
|
|
||||||
|
|
||||||
static std::atomic_bool sLoadUnsupportedFiles;
|
|
||||||
|
|
||||||
/// Parse the file
|
|
||||||
void parse(Files::IStreamPtr&& stream);
|
|
||||||
|
|
||||||
/// Get the file's version in a human readable form
|
|
||||||
///\returns A string containing a human readable NIF version number
|
|
||||||
std::string printVersion(unsigned int version);
|
|
||||||
|
|
||||||
/// Private Copy Constructor
|
|
||||||
NIFFile(NIFFile const&);
|
|
||||||
///\overload
|
|
||||||
void operator=(NIFFile const&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// For generic versions NIFStream::generateVersion() is used instead
|
// For generic versions NIFStream::generateVersion() is used instead
|
||||||
enum NIFVersion
|
enum NIFVersion
|
||||||
{
|
{
|
||||||
|
@ -94,51 +30,119 @@ namespace Nif
|
||||||
BETHVER_FO4 = 130 // Fallout 4
|
BETHVER_FO4 = 130 // Fallout 4
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Used if file parsing fails
|
/// File version, user version, Bethesda version
|
||||||
[[noreturn]] void fail(const std::string& msg) const;
|
unsigned int mVersion = 0;
|
||||||
|
unsigned int mUserVersion = 0;
|
||||||
|
unsigned int mBethVersion = 0;
|
||||||
|
|
||||||
/// Used when something goes wrong, but not catastrophically so
|
/// File name, used for error messages and opening the file
|
||||||
void warn(const std::string& msg) const;
|
std::filesystem::path mPath;
|
||||||
|
std::string mHash;
|
||||||
|
|
||||||
/// Open a NIF stream. The name is used for error messages.
|
/// Record list
|
||||||
NIFFile(Files::IStreamPtr&& stream, const std::filesystem::path& name);
|
std::vector<std::unique_ptr<Record>> mRecords;
|
||||||
|
|
||||||
/// Get a given record
|
/// Root list. This is a select portion of the pointers from records
|
||||||
Record* getRecord(size_t index) const override { return records.at(index).get(); }
|
std::vector<Record*> mRoots;
|
||||||
/// Number of records
|
|
||||||
size_t numRecords() const override { return records.size(); }
|
bool mUseSkinning = false;
|
||||||
|
|
||||||
|
explicit NIFFile(const std::filesystem::path& path)
|
||||||
|
: mPath(path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileView(const NIFFile& file)
|
||||||
|
: mFile(&file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a given root
|
/// Get a given root
|
||||||
Record* getRoot(size_t index = 0) const override
|
const Record* getRoot(std::size_t index) const { return mFile->mRoots.at(index); }
|
||||||
{
|
|
||||||
Record* res = roots.at(index);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
/// Number of roots
|
/// Number of roots
|
||||||
size_t numRoots() const override { return roots.size(); }
|
std::size_t numRoots() const { return mFile->mRoots.size(); }
|
||||||
|
|
||||||
|
/// Get the name of the file
|
||||||
|
const std::filesystem::path& getFilename() const { return mFile->mPath; }
|
||||||
|
|
||||||
|
const std::string& getHash() const { return mFile->mHash; }
|
||||||
|
|
||||||
|
/// Get the version of the NIF format used
|
||||||
|
unsigned int getVersion() const { return mFile->mVersion; }
|
||||||
|
|
||||||
|
/// Get the user version of the NIF format used
|
||||||
|
unsigned int getUserVersion() const { return mFile->mUserVersion; }
|
||||||
|
|
||||||
|
/// Get the Bethesda version of the NIF format used
|
||||||
|
unsigned int getBethVersion() const { return mFile->mBethVersion; }
|
||||||
|
|
||||||
|
bool getUseSkinning() const { return mFile->mUseSkinning; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const NIFFile* mFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Reader
|
||||||
|
{
|
||||||
|
/// File version, user version, Bethesda version
|
||||||
|
unsigned int& ver;
|
||||||
|
unsigned int& userVer;
|
||||||
|
unsigned int& bethVer;
|
||||||
|
|
||||||
|
/// File name, used for error messages and opening the file
|
||||||
|
std::filesystem::path& filename;
|
||||||
|
std::string& hash;
|
||||||
|
|
||||||
|
/// Record list
|
||||||
|
std::vector<std::unique_ptr<Record>>& records;
|
||||||
|
|
||||||
|
/// Root list. This is a select portion of the pointers from records
|
||||||
|
std::vector<Record*>& roots;
|
||||||
|
|
||||||
|
/// String table
|
||||||
|
std::vector<std::string> strings;
|
||||||
|
|
||||||
|
bool& mUseSkinning;
|
||||||
|
|
||||||
|
static std::atomic_bool sLoadUnsupportedFiles;
|
||||||
|
|
||||||
|
/// Get the file's version in a human readable form
|
||||||
|
///\returns A string containing a human readable NIF version number
|
||||||
|
std::string printVersion(unsigned int version);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Open a NIF stream. The name is used for error messages.
|
||||||
|
explicit Reader(NIFFile& file);
|
||||||
|
|
||||||
|
/// Parse the file
|
||||||
|
void parse(Files::IStreamPtr&& stream);
|
||||||
|
|
||||||
|
/// Get a given record
|
||||||
|
Record* getRecord(size_t index) const { return records.at(index).get(); }
|
||||||
|
|
||||||
/// Get a given string from the file's string table
|
/// Get a given string from the file's string table
|
||||||
std::string getString(uint32_t index) const override;
|
std::string getString(uint32_t index) const;
|
||||||
|
|
||||||
/// Set whether there is skinning contained in this NIF file.
|
/// Set whether there is skinning contained in this NIF file.
|
||||||
/// @note This is just a hint for users of the NIF file and has no effect on the loading procedure.
|
/// @note This is just a hint for users of the NIF file and has no effect on the loading procedure.
|
||||||
void setUseSkinning(bool skinning) override;
|
void setUseSkinning(bool skinning);
|
||||||
|
|
||||||
bool getUseSkinning() const override;
|
|
||||||
|
|
||||||
/// Get the name of the file
|
/// Get the name of the file
|
||||||
std::filesystem::path getFilename() const override { return filename; }
|
std::filesystem::path getFilename() const { return filename; }
|
||||||
|
|
||||||
std::string 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 { return ver; }
|
||||||
|
|
||||||
/// Get the user version of the NIF format used
|
/// Get the user version of the NIF format used
|
||||||
unsigned int getUserVersion() const override { return userVer; }
|
unsigned int getUserVersion() const { return userVer; }
|
||||||
|
|
||||||
/// Get the Bethesda version of the NIF format used
|
/// Get the Bethesda version of the NIF format used
|
||||||
unsigned int getBethVersion() const override { return bethVer; }
|
unsigned int getBethVersion() const { return bethVer; }
|
||||||
|
|
||||||
static void setLoadUnsupportedFiles(bool load);
|
static void setLoadUnsupportedFiles(bool load);
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "exception.hpp"
|
||||||
#include "niffile.hpp"
|
#include "niffile.hpp"
|
||||||
#include "nifstream.hpp"
|
#include "nifstream.hpp"
|
||||||
|
|
||||||
|
@ -112,7 +113,8 @@ namespace Nif
|
||||||
}
|
}
|
||||||
else if (count != 0)
|
else if (count != 0)
|
||||||
{
|
{
|
||||||
nif->file->fail("Unhandled interpolation type: " + std::to_string(mInterpolationType));
|
throw Nif::Exception("Unhandled interpolation type: " + std::to_string(mInterpolationType),
|
||||||
|
nif->getFile().getFilename());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,20 +34,20 @@ namespace Nif
|
||||||
/// Read in a string, either from the string table using the index or from the stream using the specified length
|
/// Read in a string, either from the string table using the index or from the stream using the specified length
|
||||||
std::string NIFStream::getString()
|
std::string NIFStream::getString()
|
||||||
{
|
{
|
||||||
return getVersion() < generateVersion(20, 1, 0, 1) ? getSizedString() : file->getString(getUInt());
|
return getVersion() < generateVersion(20, 1, 0, 1) ? getSizedString() : file.getString(getUInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience utility functions: get the versions of the currently read file
|
// Convenience utility functions: get the versions of the currently read file
|
||||||
unsigned int NIFStream::getVersion() const
|
unsigned int NIFStream::getVersion() const
|
||||||
{
|
{
|
||||||
return file->getVersion();
|
return file.getVersion();
|
||||||
}
|
}
|
||||||
unsigned int NIFStream::getUserVersion() const
|
unsigned int NIFStream::getUserVersion() const
|
||||||
{
|
{
|
||||||
return file->getBethVersion();
|
return file.getBethVersion();
|
||||||
}
|
}
|
||||||
unsigned int NIFStream::getBethVersion() const
|
unsigned int NIFStream::getBethVersion() const
|
||||||
{
|
{
|
||||||
return file->getBethVersion();
|
return file.getBethVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
class NIFFile;
|
class Reader;
|
||||||
|
|
||||||
template <std::size_t numInstances, typename T>
|
template <std::size_t numInstances, typename T>
|
||||||
inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest)
|
inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest)
|
||||||
|
@ -59,18 +59,20 @@ namespace Nif
|
||||||
|
|
||||||
class NIFStream
|
class NIFStream
|
||||||
{
|
{
|
||||||
|
const Reader& file;
|
||||||
|
|
||||||
/// Input stream
|
/// Input stream
|
||||||
Files::IStreamPtr inp;
|
Files::IStreamPtr inp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NIFFile* const file;
|
explicit NIFStream(const Reader& file, Files::IStreamPtr&& inp)
|
||||||
|
: file(file)
|
||||||
NIFStream(NIFFile* file, Files::IStreamPtr&& inp)
|
, inp(std::move(inp))
|
||||||
: inp(std::move(inp))
|
|
||||||
, file(file)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Reader& getFile() const { return file; }
|
||||||
|
|
||||||
void skip(size_t size) { inp->ignore(size); }
|
void skip(size_t size) { inp->ignore(size); }
|
||||||
|
|
||||||
char getChar() { return readLittleEndianType<char>(inp); }
|
char getChar() { return readLittleEndianType<char>(inp); }
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/misc/algorithm.hpp>
|
#include <components/misc/algorithm.hpp>
|
||||||
|
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
#include "property.hpp"
|
#include "property.hpp"
|
||||||
|
|
||||||
|
@ -68,7 +69,8 @@ namespace Nif
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
nif->file->fail("Unhandled NiBoundingVolume type: " + std::to_string(type));
|
throw Nif::Exception(
|
||||||
|
"Unhandled NiBoundingVolume type: " + std::to_string(type), nif->getFile().getFilename());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +84,7 @@ namespace Nif
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
||||||
velocity = nif->getVector3();
|
velocity = nif->getVector3();
|
||||||
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
||||||
props.read(nif);
|
readRecordList(nif, props);
|
||||||
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
||||||
hasBounds = nif->getBoolean();
|
hasBounds = nif->getBoolean();
|
||||||
|
@ -97,10 +99,10 @@ namespace Nif
|
||||||
isBone = false;
|
isBone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::post(NIFFile* nif)
|
void Node::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Named::post(nif);
|
Named::post(nif);
|
||||||
props.post(nif);
|
postRecordList(nif, props);
|
||||||
collision.post(nif);
|
collision.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +114,9 @@ namespace Nif
|
||||||
void NiNode::read(NIFStream* nif)
|
void NiNode::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
Node::read(nif);
|
Node::read(nif);
|
||||||
children.read(nif);
|
readRecordList(nif, children);
|
||||||
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
||||||
effects.read(nif);
|
readRecordList(nif, effects);
|
||||||
|
|
||||||
// Discard transformations for the root node, otherwise some meshes
|
// Discard transformations for the root node, otherwise some meshes
|
||||||
// occasionally get wrong orientation. Only for NiNode-s for now, but
|
// occasionally get wrong orientation. Only for NiNode-s for now, but
|
||||||
|
@ -126,17 +128,17 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiNode::post(NIFFile* nif)
|
void NiNode::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Node::post(nif);
|
Node::post(nif);
|
||||||
children.post(nif);
|
postRecordList(nif, children);
|
||||||
effects.post(nif);
|
postRecordList(nif, effects);
|
||||||
|
|
||||||
for (size_t i = 0; i < children.length(); i++)
|
for (auto& child : children)
|
||||||
{
|
{
|
||||||
// Why would a unique list of children contain empty refs?
|
// Why would a unique list of children contain empty refs?
|
||||||
if (!children[i].empty())
|
if (!child.empty())
|
||||||
children[i]->parents.push_back(this);
|
child->parents.push_back(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +176,7 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiGeometry::post(NIFFile* nif)
|
void NiGeometry::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Node::post(nif);
|
Node::post(nif);
|
||||||
data.post(nif);
|
data.post(nif);
|
||||||
|
@ -182,7 +184,7 @@ namespace Nif
|
||||||
shaderprop.post(nif);
|
shaderprop.post(nif);
|
||||||
alphaprop.post(nif);
|
alphaprop.post(nif);
|
||||||
if (recType != RC_NiParticles && !skin.empty())
|
if (recType != RC_NiParticles && !skin.empty())
|
||||||
nif->setUseSkinning(true);
|
nif.setUseSkinning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSLODTriShape::read(NIFStream* nif)
|
void BSLODTriShape::read(NIFStream* nif)
|
||||||
|
@ -269,7 +271,7 @@ namespace Nif
|
||||||
mSubSorter.read(nif);
|
mSubSorter.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiSortAdjustNode::post(NIFFile* nif)
|
void NiSortAdjustNode::post(Reader& nif)
|
||||||
{
|
{
|
||||||
NiNode::post(nif);
|
NiNode::post(nif);
|
||||||
mSubSorter.post(nif);
|
mSubSorter.post(nif);
|
||||||
|
|
|
@ -94,7 +94,7 @@ namespace Nif
|
||||||
NiCollisionObjectPtr collision;
|
NiCollisionObjectPtr collision;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
|
|
||||||
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
||||||
// NiNodes (or types derived from NiNodes) can be parents.
|
// NiNodes (or types derived from NiNodes) can be parents.
|
||||||
|
@ -126,7 +126,7 @@ namespace Nif
|
||||||
};
|
};
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiGeometry : Node
|
struct NiGeometry : Node
|
||||||
|
@ -154,7 +154,7 @@ namespace Nif
|
||||||
NiAlphaPropertyPtr alphaprop;
|
NiAlphaPropertyPtr alphaprop;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiTriShape : NiGeometry
|
struct NiTriShape : NiGeometry
|
||||||
|
@ -263,7 +263,7 @@ namespace Nif
|
||||||
NiAccumulatorPtr mSubSorter;
|
NiAccumulatorPtr mSubSorter;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBillboardNode : NiNode
|
struct NiBillboardNode : NiNode
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace Nif
|
||||||
mWorldObjectInfo.read(nif);
|
mWorldObjectInfo.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkWorldObject::post(NIFFile* nif)
|
void bhkWorldObject::post(Reader& nif)
|
||||||
{
|
{
|
||||||
mShape.post(nif);
|
mShape.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ namespace Nif
|
||||||
mShape.read(nif);
|
mShape.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkBvTreeShape::post(NIFFile* nif)
|
void bhkBvTreeShape::post(Reader& nif)
|
||||||
{
|
{
|
||||||
mShape.post(nif);
|
mShape.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -202,14 +202,14 @@ namespace Nif
|
||||||
mGrowBy = nif->getUInt();
|
mGrowBy = nif->getUInt();
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
||||||
mScale = nif->getVector4();
|
mScale = nif->getVector4();
|
||||||
mData.read(nif);
|
readRecordList(nif, mData);
|
||||||
unsigned int numFilters = nif->getUInt();
|
unsigned int numFilters = nif->getUInt();
|
||||||
nif->getUInts(mFilters, numFilters);
|
nif->getUInts(mFilters, numFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkNiTriStripsShape::post(NIFFile* nif)
|
void bhkNiTriStripsShape::post(Reader& nif)
|
||||||
{
|
{
|
||||||
mData.post(nif);
|
postRecordList(nif, mData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkPackedNiTriStripsShape::read(NIFStream* nif)
|
void bhkPackedNiTriStripsShape::read(NIFStream* nif)
|
||||||
|
@ -229,7 +229,7 @@ namespace Nif
|
||||||
mData.read(nif);
|
mData.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bhkPackedNiTriStripsShape::post(NIFFile* nif)
|
void bhkPackedNiTriStripsShape::post(Reader& nif)
|
||||||
{
|
{
|
||||||
mData.post(nif);
|
mData.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ namespace Nif
|
||||||
|
|
||||||
void bhkListShape::read(NIFStream* nif)
|
void bhkListShape::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
mSubshapes.read(nif);
|
readRecordList(nif, mSubshapes);
|
||||||
mHavokMaterial.read(nif);
|
mHavokMaterial.read(nif);
|
||||||
mChildShapeProperty.read(nif);
|
mChildShapeProperty.read(nif);
|
||||||
mChildFilterProperty.read(nif);
|
mChildFilterProperty.read(nif);
|
||||||
|
@ -315,7 +315,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
bhkEntity::read(nif);
|
bhkEntity::read(nif);
|
||||||
mInfo.read(nif);
|
mInfo.read(nif);
|
||||||
mConstraints.read(nif);
|
readRecordList(nif, mConstraints);
|
||||||
if (nif->getBethVersion() < 76)
|
if (nif->getBethVersion() < 76)
|
||||||
mBodyFlags = nif->getUInt();
|
mBodyFlags = nif->getUInt();
|
||||||
else
|
else
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
class NIFStream;
|
class NIFStream;
|
||||||
class NIFFile;
|
struct NIFFile;
|
||||||
|
|
||||||
/// Non-record data types
|
/// Non-record data types
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ namespace Nif
|
||||||
NodePtr mTarget;
|
NodePtr mTarget;
|
||||||
|
|
||||||
void read(NIFStream* nif) override { mTarget.read(nif); }
|
void read(NIFStream* nif) override { mTarget.read(nif); }
|
||||||
void post(NIFFile* nif) override { mTarget.post(nif); }
|
void post(Reader& nif) override { mTarget.post(nif); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bethesda Havok-specific collision object
|
// Bethesda Havok-specific collision object
|
||||||
|
@ -214,7 +214,7 @@ namespace Nif
|
||||||
bhkWorldObjectPtr mBody;
|
bhkWorldObjectPtr mBody;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override
|
void post(Reader& nif) override
|
||||||
{
|
{
|
||||||
NiCollisionObject::post(nif);
|
NiCollisionObject::post(nif);
|
||||||
mBody.post(nif);
|
mBody.post(nif);
|
||||||
|
@ -228,7 +228,7 @@ namespace Nif
|
||||||
HavokFilter mHavokFilter;
|
HavokFilter mHavokFilter;
|
||||||
bhkWorldObjectCInfo mWorldObjectInfo;
|
bhkWorldObjectCInfo mWorldObjectInfo;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract
|
// Abstract
|
||||||
|
@ -244,7 +244,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
bhkShapePtr mShape;
|
bhkShapePtr mShape;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// bhkBvTreeShape with Havok MOPP code
|
// bhkBvTreeShape with Havok MOPP code
|
||||||
|
@ -265,7 +265,7 @@ namespace Nif
|
||||||
NiTriStripsDataList mData;
|
NiTriStripsDataList mData;
|
||||||
std::vector<unsigned int> mFilters;
|
std::vector<unsigned int> mFilters;
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bethesda packed triangle strip-based Havok shape collection
|
// Bethesda packed triangle strip-based Havok shape collection
|
||||||
|
@ -278,7 +278,7 @@ namespace Nif
|
||||||
hkPackedNiTriStripsDataPtr mData;
|
hkPackedNiTriStripsDataPtr mData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// bhkPackedNiTriStripsShape data block
|
// bhkPackedNiTriStripsShape data block
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiTexturingProperty::Texture::post(NIFFile* nif)
|
void NiTexturingProperty::Texture::post(Reader& nif)
|
||||||
{
|
{
|
||||||
texture.post(nif);
|
texture.post(nif);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiTexturingProperty::post(NIFFile* nif)
|
void NiTexturingProperty::post(Reader& nif)
|
||||||
{
|
{
|
||||||
Property::post(nif);
|
Property::post(nif);
|
||||||
for (size_t i = 0; i < textures.size(); i++)
|
for (size_t i = 0; i < textures.size(); i++)
|
||||||
|
@ -134,7 +134,7 @@ namespace Nif
|
||||||
parallax.scale = nif->getFloat();
|
parallax.scale = nif->getFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSShaderPPLightingProperty::post(NIFFile* nif)
|
void BSShaderPPLightingProperty::post(Reader& nif)
|
||||||
{
|
{
|
||||||
BSShaderLightingProperty::post(nif);
|
BSShaderLightingProperty::post(nif);
|
||||||
textureSet.post(nif);
|
textureSet.post(nif);
|
||||||
|
@ -198,7 +198,7 @@ namespace Nif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSLightingShaderProperty::post(NIFFile* nif)
|
void BSLightingShaderProperty::post(Reader& nif)
|
||||||
{
|
{
|
||||||
BSShaderProperty::post(nif);
|
BSShaderProperty::post(nif);
|
||||||
mTextureSet.post(nif);
|
mTextureSet.post(nif);
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Nif
|
||||||
unsigned int clamp, uvSet;
|
unsigned int clamp, uvSet;
|
||||||
|
|
||||||
void read(NIFStream* nif);
|
void read(NIFStream* nif);
|
||||||
void post(NIFFile* nif);
|
void post(Reader& nif);
|
||||||
|
|
||||||
bool wrapT() const { return clamp & 1; }
|
bool wrapT() const { return clamp & 1; }
|
||||||
bool wrapS() const { return (clamp >> 1) & 1; }
|
bool wrapS() const { return (clamp >> 1) & 1; }
|
||||||
|
@ -97,7 +97,7 @@ namespace Nif
|
||||||
osg::Vec4f bumpMapMatrix;
|
osg::Vec4f bumpMapMatrix;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiFogProperty : public Property
|
struct NiFogProperty : public Property
|
||||||
|
@ -166,7 +166,7 @@ namespace Nif
|
||||||
ParallaxSettings parallax;
|
ParallaxSettings parallax;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSShaderNoLightingProperty : public BSShaderLightingProperty
|
struct BSShaderNoLightingProperty : public BSShaderLightingProperty
|
||||||
|
@ -212,7 +212,7 @@ namespace Nif
|
||||||
float mEmissiveMult, mSpecStrength;
|
float mEmissiveMult, mSpecStrength;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(NIFFile* nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiDitherProperty : public Property
|
struct NiDitherProperty : public Property
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
class NIFFile;
|
class Reader;
|
||||||
class NIFStream;
|
class NIFStream;
|
||||||
|
|
||||||
enum RecordType
|
enum RecordType
|
||||||
|
@ -164,7 +164,7 @@ namespace Nif
|
||||||
virtual void read(NIFStream* nif) = 0;
|
virtual void read(NIFStream* nif) = 0;
|
||||||
|
|
||||||
/// Does post-processing, after the entire tree is loaded
|
/// Does post-processing, after the entire tree is loaded
|
||||||
virtual void post(NIFFile* nif) {}
|
virtual void post(Reader& nif) {}
|
||||||
|
|
||||||
virtual ~Record() {}
|
virtual ~Record() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,13 +44,13 @@ namespace Nif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve index to pointer
|
/// Resolve index to pointer
|
||||||
void post(NIFFile* nif)
|
void post(Reader& nif)
|
||||||
{
|
{
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
ptr = nullptr;
|
ptr = nullptr;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Record* r = nif->getRecord(index);
|
Record* r = nif.getRecord(index);
|
||||||
// And cast it
|
// And cast it
|
||||||
ptr = dynamic_cast<X*>(r);
|
ptr = dynamic_cast<X*>(r);
|
||||||
assert(ptr != nullptr);
|
assert(ptr != nullptr);
|
||||||
|
@ -85,39 +85,28 @@ namespace Nif
|
||||||
implementation.
|
implementation.
|
||||||
*/
|
*/
|
||||||
template <class X>
|
template <class X>
|
||||||
class RecordListT
|
using RecordListT = std::vector<RecordPtrT<X>>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void readRecordList(NIFStream* nif, RecordListT<T>& list)
|
||||||
{
|
{
|
||||||
typedef RecordPtrT<X> Ptr;
|
const int length = nif->getInt();
|
||||||
std::vector<Ptr> list;
|
|
||||||
|
|
||||||
public:
|
if (length < 0)
|
||||||
RecordListT() = default;
|
throw std::runtime_error("Negative NIF record list length: " + std::to_string(length));
|
||||||
|
|
||||||
RecordListT(std::vector<Ptr> list)
|
list.resize(static_cast<std::size_t>(length));
|
||||||
: list(std::move(list))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(NIFStream* nif)
|
for (auto& value : list)
|
||||||
{
|
value.read(nif);
|
||||||
int len = nif->getInt();
|
}
|
||||||
list.resize(len);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < list.size(); i++)
|
template <class T>
|
||||||
list[i].read(nif);
|
void postRecordList(Reader& nif, RecordListT<T>& list)
|
||||||
}
|
{
|
||||||
|
for (auto& value : list)
|
||||||
void post(NIFFile* nif)
|
value.post(nif);
|
||||||
{
|
}
|
||||||
for (size_t i = 0; i < list.size(); i++)
|
|
||||||
list[i].post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Ptr& operator[](size_t index) const { return list.at(index); }
|
|
||||||
Ptr& operator[](size_t index) { return list.at(index); }
|
|
||||||
|
|
||||||
size_t length() const { return list.size(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Node;
|
struct Node;
|
||||||
struct Extra;
|
struct Extra;
|
||||||
|
|
|
@ -160,7 +160,7 @@ namespace
|
||||||
namespace NifBullet
|
namespace NifBullet
|
||||||
{
|
{
|
||||||
|
|
||||||
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(Nif::FileView nif)
|
||||||
{
|
{
|
||||||
mShape = new Resource::BulletShape;
|
mShape = new Resource::BulletShape;
|
||||||
|
|
||||||
|
@ -284,14 +284,9 @@ namespace NifBullet
|
||||||
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node))
|
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node))
|
||||||
{
|
{
|
||||||
const Nif::NodeList& list = ninode->children;
|
const Nif::NodeList& list = ninode->children;
|
||||||
for (size_t i = 0; i < list.length(); i++)
|
for (const auto& child : list)
|
||||||
{
|
if (!child.empty() && findBoundingBox(child.get(), filename))
|
||||||
if (!list[i].empty())
|
return true;
|
||||||
{
|
|
||||||
if (findBoundingBox(list[i].get(), filename))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -300,12 +295,11 @@ namespace NifBullet
|
||||||
{
|
{
|
||||||
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
|
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
|
||||||
{
|
{
|
||||||
const Nif::NodeList& list = ninode->children;
|
for (const auto& child : ninode->children)
|
||||||
for (size_t i = 0; i < list.length(); i++)
|
|
||||||
{
|
{
|
||||||
if (list[i].empty())
|
if (child.empty())
|
||||||
continue;
|
continue;
|
||||||
if (list[i].getPtr()->recType == Nif::RC_RootCollisionNode)
|
if (child.getPtr()->recType == Nif::RC_RootCollisionNode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,17 +310,16 @@ namespace NifBullet
|
||||||
{
|
{
|
||||||
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
|
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
|
||||||
{
|
{
|
||||||
const Nif::NodeList& list = ninode->children;
|
for (const auto& child : ninode->children)
|
||||||
for (size_t i = 0; i < list.length(); i++)
|
|
||||||
{
|
{
|
||||||
if (list[i].empty())
|
if (child.empty())
|
||||||
continue;
|
continue;
|
||||||
const Nif::Node* childNode = list[i].getPtr();
|
const Nif::Node* childNode = child.getPtr();
|
||||||
if (childNode->recType != Nif::RC_RootCollisionNode)
|
if (childNode->recType != Nif::RC_RootCollisionNode)
|
||||||
continue;
|
continue;
|
||||||
const Nif::NiNode* niChildnode
|
const Nif::NiNode* niChildnode
|
||||||
= static_cast<const Nif::NiNode*>(childNode); // RootCollisionNode is always a NiNode
|
= static_cast<const Nif::NiNode*>(childNode); // RootCollisionNode is always a NiNode
|
||||||
if (childNode->hasBounds || niChildnode->children.length() > 0)
|
if (childNode->hasBounds || niChildnode->children.size() > 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,13 +405,13 @@ namespace NifBullet
|
||||||
{
|
{
|
||||||
const Nif::NodeList& list = ninode->children;
|
const Nif::NodeList& list = ninode->children;
|
||||||
const Nif::Parent currentParent{ *ninode, parent };
|
const Nif::Parent currentParent{ *ninode, parent };
|
||||||
for (size_t i = 0; i < list.length(); i++)
|
for (const auto& child : list)
|
||||||
{
|
{
|
||||||
if (list[i].empty())
|
if (child.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(std::find(list[i]->parents.begin(), list[i]->parents.end(), ninode) != list[i]->parents.end());
|
assert(std::find(child->parents.begin(), child->parents.end(), ninode) != child->parents.end());
|
||||||
handleNode(fileName, list[i].get(), ¤tParent, flags, isCollisionNode, isAnimated, autogenerated,
|
handleNode(fileName, child.get(), ¤tParent, flags, isCollisionNode, isAnimated, autogenerated,
|
||||||
avoid, visualCollisionType);
|
avoid, visualCollisionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace NifBullet
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<Resource::BulletShape> load(const Nif::File& file);
|
osg::ref_ptr<Resource::BulletShape> load(Nif::FileView file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool findBoundingBox(const Nif::Node& node, const std::string& filename);
|
bool findBoundingBox(const Nif::Node& node, const std::string& filename);
|
||||||
|
|
|
@ -199,7 +199,7 @@ namespace NifOsg
|
||||||
|
|
||||||
GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl)
|
GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl)
|
||||||
{
|
{
|
||||||
if (ctrl->mInterpolators.length() == 0)
|
if (ctrl->mInterpolators.size() == 0)
|
||||||
{
|
{
|
||||||
if (!ctrl->mData.empty())
|
if (!ctrl->mData.empty())
|
||||||
{
|
{
|
||||||
|
@ -209,10 +209,10 @@ namespace NifOsg
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyFrames.resize(ctrl->mInterpolators.length());
|
mKeyFrames.resize(ctrl->mInterpolators.size());
|
||||||
mWeights = ctrl->mWeights;
|
mWeights = ctrl->mWeights;
|
||||||
|
|
||||||
for (size_t i = 0; i < ctrl->mInterpolators.length(); ++i)
|
for (std::size_t i = 0, n = ctrl->mInterpolators.size(); i < n; ++i)
|
||||||
{
|
{
|
||||||
if (!ctrl->mInterpolators[i].empty() && ctrl->mInterpolators[i]->recType == Nif::RC_NiFloatInterpolator)
|
if (!ctrl->mInterpolators[i].empty() && ctrl->mInterpolators[i]->recType == Nif::RC_NiFloatInterpolator)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include <components/nif/controlled.hpp>
|
#include <components/nif/controlled.hpp>
|
||||||
#include <components/nif/effect.hpp>
|
#include <components/nif/effect.hpp>
|
||||||
|
#include <components/nif/exception.hpp>
|
||||||
#include <components/nif/extra.hpp>
|
#include <components/nif/extra.hpp>
|
||||||
#include <components/nif/node.hpp>
|
#include <components/nif/node.hpp>
|
||||||
#include <components/nif/property.hpp>
|
#include <components/nif/property.hpp>
|
||||||
|
@ -75,9 +76,9 @@ namespace
|
||||||
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(node))
|
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(node))
|
||||||
{
|
{
|
||||||
outIndices.push_back(ninode->recIndex);
|
outIndices.push_back(ninode->recIndex);
|
||||||
for (unsigned int i = 0; i < ninode->children.length(); ++i)
|
for (const auto& child : ninode->children)
|
||||||
if (!ninode->children[i].empty())
|
if (!child.empty())
|
||||||
getAllNiNodes(ninode->children[i].getPtr(), outIndices);
|
getAllNiNodes(child.getPtr(), outIndices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,18 +102,17 @@ namespace
|
||||||
{
|
{
|
||||||
if (parent != nullptr)
|
if (parent != nullptr)
|
||||||
collectDrawableProperties(&parent->mNiNode, parent->mParent, out);
|
collectDrawableProperties(&parent->mNiNode, parent->mParent, out);
|
||||||
const Nif::PropertyList& props = nifNode->props;
|
for (const auto& property : nifNode->props)
|
||||||
for (size_t i = 0; i < props.length(); ++i)
|
|
||||||
{
|
{
|
||||||
if (!props[i].empty())
|
if (!property.empty())
|
||||||
{
|
{
|
||||||
switch (props[i]->recType)
|
switch (property->recType)
|
||||||
{
|
{
|
||||||
case Nif::RC_NiMaterialProperty:
|
case Nif::RC_NiMaterialProperty:
|
||||||
case Nif::RC_NiVertexColorProperty:
|
case Nif::RC_NiVertexColorProperty:
|
||||||
case Nif::RC_NiSpecularProperty:
|
case Nif::RC_NiSpecularProperty:
|
||||||
case Nif::RC_NiAlphaProperty:
|
case Nif::RC_NiAlphaProperty:
|
||||||
out.push_back(props[i].getPtr());
|
out.push_back(property.getPtr());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -249,13 +249,13 @@ namespace NifOsg
|
||||||
// This is used to queue emitters that weren't attached to their node yet.
|
// This is used to queue emitters that weren't attached to their node yet.
|
||||||
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
|
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
|
||||||
|
|
||||||
void loadKf(Nif::NIFFilePtr nif, SceneUtil::KeyframeHolder& target) const
|
void loadKf(Nif::FileView nif, SceneUtil::KeyframeHolder& target) const
|
||||||
{
|
{
|
||||||
const Nif::NiSequenceStreamHelper* seq = nullptr;
|
const Nif::NiSequenceStreamHelper* seq = nullptr;
|
||||||
const size_t numRoots = nif->numRoots();
|
const size_t numRoots = nif.numRoots();
|
||||||
for (size_t i = 0; i < numRoots; ++i)
|
for (size_t i = 0; i < numRoots; ++i)
|
||||||
{
|
{
|
||||||
const Nif::Record* r = nif->getRoot(i);
|
const Nif::Record* r = nif.getRoot(i);
|
||||||
if (r && r->recType == Nif::RC_NiSequenceStreamHelper)
|
if (r && r->recType == Nif::RC_NiSequenceStreamHelper)
|
||||||
{
|
{
|
||||||
seq = static_cast<const Nif::NiSequenceStreamHelper*>(r);
|
seq = static_cast<const Nif::NiSequenceStreamHelper*>(r);
|
||||||
|
@ -265,15 +265,17 @@ namespace NifOsg
|
||||||
|
|
||||||
if (!seq)
|
if (!seq)
|
||||||
{
|
{
|
||||||
nif->warn("Found no NiSequenceStreamHelper root record");
|
Log(Debug::Warning) << "NIFFile Warning: Found no NiSequenceStreamHelper root record. File: "
|
||||||
|
<< nif.getFilename();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nif::ExtraPtr extra = seq->extra;
|
Nif::ExtraPtr extra = seq->extra;
|
||||||
if (extra.empty() || extra->recType != Nif::RC_NiTextKeyExtraData)
|
if (extra.empty() || extra->recType != Nif::RC_NiTextKeyExtraData)
|
||||||
{
|
{
|
||||||
nif->warn("First extra data was not a NiTextKeyExtraData, but a "
|
Log(Debug::Warning) << "NIFFile Warning: First extra data was not a NiTextKeyExtraData, but a "
|
||||||
+ (extra.empty() ? std::string("nil") : extra->recName) + ".");
|
<< (extra.empty() ? std::string_view("nil") : std::string_view(extra->recName))
|
||||||
|
<< ". File: " << nif.getFilename();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +287,8 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
|
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
|
||||||
{
|
{
|
||||||
nif->warn("Unexpected extra data " + extra->recName + " with controller " + ctrl->recName);
|
Log(Debug::Warning) << "NIFFile Warning: Unexpected extra data " << extra->recName
|
||||||
|
<< " with controller " << ctrl->recName << ". File: " << nif.getFilename();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,17 +313,17 @@ namespace NifOsg
|
||||||
|
|
||||||
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
|
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
|
||||||
Log(Debug::Verbose) << "Controller " << strdata->string << " present more than once in "
|
Log(Debug::Verbose) << "Controller " << strdata->string << " present more than once in "
|
||||||
<< nif->getFilename() << ", ignoring later version";
|
<< nif.getFilename() << ", ignoring later version";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr nif, Resource::ImageManager* imageManager)
|
osg::ref_ptr<osg::Node> load(Nif::FileView nif, Resource::ImageManager* imageManager)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
const Nif::Record* r = nif->getRoot(i);
|
const Nif::Record* r = nif.getRoot(i);
|
||||||
if (!r)
|
if (!r)
|
||||||
continue;
|
continue;
|
||||||
const Nif::Node* nifNode = dynamic_cast<const Nif::Node*>(r);
|
const Nif::Node* nifNode = dynamic_cast<const Nif::Node*>(r);
|
||||||
|
@ -328,7 +331,7 @@ namespace NifOsg
|
||||||
roots.emplace_back(nifNode);
|
roots.emplace_back(nifNode);
|
||||||
}
|
}
|
||||||
if (roots.empty())
|
if (roots.empty())
|
||||||
nif->fail("Found no root nodes");
|
throw Nif::Exception("Found no root nodes", nif.getFilename());
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::TextKeyMapHolder> textkeys(new SceneUtil::TextKeyMapHolder);
|
osg::ref_ptr<SceneUtil::TextKeyMapHolder> textkeys(new SceneUtil::TextKeyMapHolder);
|
||||||
|
|
||||||
|
@ -348,7 +351,7 @@ namespace NifOsg
|
||||||
// Attach particle emitters to their nodes which should all be loaded by now.
|
// Attach particle emitters to their nodes which should all be loaded by now.
|
||||||
handleQueuedParticleEmitters(created, nif);
|
handleQueuedParticleEmitters(created, nif);
|
||||||
|
|
||||||
if (nif->getUseSkinning())
|
if (nif.getUseSkinning())
|
||||||
{
|
{
|
||||||
osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton;
|
osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton;
|
||||||
skel->setStateSet(created->getStateSet());
|
skel->setStateSet(created->getStateSet());
|
||||||
|
@ -362,7 +365,7 @@ namespace NifOsg
|
||||||
if (!textkeys->mTextKeys.empty())
|
if (!textkeys->mTextKeys.empty())
|
||||||
created->getOrCreateUserDataContainer()->addUserObject(textkeys);
|
created->getOrCreateUserDataContainer()->addUserObject(textkeys);
|
||||||
|
|
||||||
created->setUserValue(Misc::OsgUserValues::sFileHash, nif->getHash());
|
created->setUserValue(Misc::OsgUserValues::sFileHash, nif.getHash());
|
||||||
|
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
@ -371,19 +374,17 @@ namespace NifOsg
|
||||||
SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager,
|
SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager,
|
||||||
std::vector<unsigned int>& boundTextures, int animflags)
|
std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::PropertyList& props = nifNode->props;
|
|
||||||
|
|
||||||
bool hasStencilProperty = false;
|
bool hasStencilProperty = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < props.length(); ++i)
|
for (const auto& property : nifNode->props)
|
||||||
{
|
{
|
||||||
if (props[i].empty())
|
if (property.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (props[i].getPtr()->recType == Nif::RC_NiStencilProperty)
|
if (property.getPtr()->recType == Nif::RC_NiStencilProperty)
|
||||||
{
|
{
|
||||||
const Nif::NiStencilProperty* stencilprop
|
const Nif::NiStencilProperty* stencilprop
|
||||||
= static_cast<const Nif::NiStencilProperty*>(props[i].getPtr());
|
= static_cast<const Nif::NiStencilProperty*>(property.getPtr());
|
||||||
if (stencilprop->data.enabled != 0)
|
if (stencilprop->data.enabled != 0)
|
||||||
{
|
{
|
||||||
hasStencilProperty = true;
|
hasStencilProperty = true;
|
||||||
|
@ -392,24 +393,24 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < props.length(); ++i)
|
for (const auto& property : nifNode->props)
|
||||||
{
|
{
|
||||||
if (!props[i].empty())
|
if (!property.empty())
|
||||||
{
|
{
|
||||||
// Get the lowest numbered recIndex of the NiTexturingProperty root node.
|
// Get the lowest numbered recIndex of the NiTexturingProperty root node.
|
||||||
// This is what is overridden when a spell effect "particle texture" is used.
|
// This is what is overridden when a spell effect "particle texture" is used.
|
||||||
if (nifNode->parents.empty() && !mFoundFirstRootTexturingProperty
|
if (nifNode->parents.empty() && !mFoundFirstRootTexturingProperty
|
||||||
&& props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
&& property.getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
{
|
{
|
||||||
mFirstRootTextureIndex = props[i].getPtr()->recIndex;
|
mFirstRootTextureIndex = property.getPtr()->recIndex;
|
||||||
mFoundFirstRootTexturingProperty = true;
|
mFoundFirstRootTexturingProperty = true;
|
||||||
}
|
}
|
||||||
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
else if (property.getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
{
|
{
|
||||||
if (props[i].getPtr()->recIndex == mFirstRootTextureIndex)
|
if (property.getPtr()->recIndex == mFirstRootTextureIndex)
|
||||||
applyTo->setUserValue("overrideFx", 1);
|
applyTo->setUserValue("overrideFx", 1);
|
||||||
}
|
}
|
||||||
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags,
|
handleProperty(property.getPtr(), applyTo, composite, imageManager, boundTextures, animflags,
|
||||||
hasStencilProperty);
|
hasStencilProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,13 +460,13 @@ namespace NifOsg
|
||||||
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
|
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
|
||||||
osg::ref_ptr<osg::Sequence> sequenceNode(new osg::Sequence);
|
osg::ref_ptr<osg::Sequence> sequenceNode(new osg::Sequence);
|
||||||
sequenceNode->setName(niFltAnimationNode->name);
|
sequenceNode->setName(niFltAnimationNode->name);
|
||||||
if (niFltAnimationNode->children.length() != 0)
|
if (!niFltAnimationNode->children.empty())
|
||||||
{
|
{
|
||||||
if (niFltAnimationNode->swing())
|
if (niFltAnimationNode->swing())
|
||||||
sequenceNode->setDefaultTime(
|
sequenceNode->setDefaultTime(
|
||||||
niFltAnimationNode->mDuration / (niFltAnimationNode->children.length() * 2));
|
niFltAnimationNode->mDuration / (niFltAnimationNode->children.size() * 2));
|
||||||
else
|
else
|
||||||
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->children.length());
|
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->children.size());
|
||||||
}
|
}
|
||||||
return sequenceNode;
|
return sequenceNode;
|
||||||
}
|
}
|
||||||
|
@ -626,12 +627,9 @@ namespace NifOsg
|
||||||
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next)
|
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next)
|
||||||
extraCollection.emplace_back(e);
|
extraCollection.emplace_back(e);
|
||||||
|
|
||||||
for (size_t i = 0; i < nifNode->extralist.length(); ++i)
|
for (const auto& extraNode : nifNode->extralist)
|
||||||
{
|
if (!extraNode.empty())
|
||||||
Nif::ExtraPtr e = nifNode->extralist[i];
|
extraCollection.emplace_back(extraNode);
|
||||||
if (!e.empty())
|
|
||||||
extraCollection.emplace_back(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& e : extraCollection)
|
for (const auto& e : extraCollection)
|
||||||
{
|
{
|
||||||
|
@ -801,20 +799,16 @@ namespace NifOsg
|
||||||
if (ninode)
|
if (ninode)
|
||||||
{
|
{
|
||||||
const Nif::NodeList& effects = ninode->effects;
|
const Nif::NodeList& effects = ninode->effects;
|
||||||
for (size_t i = 0; i < effects.length(); ++i)
|
for (const auto& effect : effects)
|
||||||
{
|
if (!effect.empty())
|
||||||
if (!effects[i].empty())
|
handleEffect(effect.getPtr(), currentNode, imageManager);
|
||||||
handleEffect(effects[i].getPtr(), currentNode, imageManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Nif::NodeList& children = ninode->children;
|
const Nif::NodeList& children = ninode->children;
|
||||||
const Nif::Parent currentParent{ *ninode, parent };
|
const Nif::Parent currentParent{ *ninode, parent };
|
||||||
for (size_t i = 0; i < children.length(); ++i)
|
for (const auto& child : children)
|
||||||
{
|
if (!child.empty())
|
||||||
if (!children[i].empty())
|
handleNode(child.getPtr(), ¤tParent, currentNode, imageManager, boundTextures, animflags,
|
||||||
handleNode(children[i].getPtr(), ¤tParent, currentNode, imageManager, boundTextures,
|
skipMeshes, hasMarkers, hasAnimatedParents, textKeys, rootNode);
|
||||||
animflags, skipMeshes, hasMarkers, hasAnimatedParents, textKeys, rootNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nifNode->recType == Nif::RC_NiFltAnimationNode)
|
if (nifNode->recType == Nif::RC_NiFltAnimationNode)
|
||||||
|
@ -959,7 +953,7 @@ namespace NifOsg
|
||||||
if (matctrl->mData.empty() && matctrl->mInterpolator.empty())
|
if (matctrl->mData.empty() && matctrl->mInterpolator.empty())
|
||||||
continue;
|
continue;
|
||||||
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->mTargetColor);
|
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->mTargetColor);
|
||||||
if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW
|
if (mVersion <= Nif::NIFFile::VER_MW
|
||||||
&& targetColor == MaterialColorController::TargetColor::Specular)
|
&& targetColor == MaterialColorController::TargetColor::Specular)
|
||||||
continue;
|
continue;
|
||||||
if (!matctrl->mInterpolator.empty()
|
if (!matctrl->mInterpolator.empty()
|
||||||
|
@ -1008,13 +1002,12 @@ namespace NifOsg
|
||||||
wrapT = inherit->getWrap(osg::Texture2D::WRAP_T);
|
wrapT = inherit->getWrap(osg::Texture2D::WRAP_T);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < flipctrl->mSources.length(); ++i)
|
for (const auto& source : flipctrl->mSources)
|
||||||
{
|
{
|
||||||
Nif::NiSourceTexturePtr st = flipctrl->mSources[i];
|
if (source.empty())
|
||||||
if (st.empty())
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Image> image(handleSourceTexture(st.getPtr(), imageManager));
|
osg::ref_ptr<osg::Image> image(handleSourceTexture(source.getPtr(), imageManager));
|
||||||
osg::ref_ptr<osg::Texture2D> texture(new osg::Texture2D(image));
|
osg::ref_ptr<osg::Texture2D> texture(new osg::Texture2D(image));
|
||||||
if (image)
|
if (image)
|
||||||
texture->setTextureSize(image->s(), image->t());
|
texture->setTextureSize(image->s(), image->t());
|
||||||
|
@ -1188,7 +1181,7 @@ namespace NifOsg
|
||||||
return emitter;
|
return emitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleQueuedParticleEmitters(osg::Group* rootNode, Nif::NIFFilePtr nif)
|
void handleQueuedParticleEmitters(osg::Group* rootNode, Nif::FileView nif)
|
||||||
{
|
{
|
||||||
for (const auto& emitterPair : mEmitterQueue)
|
for (const auto& emitterPair : mEmitterQueue)
|
||||||
{
|
{
|
||||||
|
@ -1198,8 +1191,9 @@ namespace NifOsg
|
||||||
osg::Group* emitterNode = findEmitterNode.mFound;
|
osg::Group* emitterNode = findEmitterNode.mFound;
|
||||||
if (!emitterNode)
|
if (!emitterNode)
|
||||||
{
|
{
|
||||||
nif->warn("Failed to find particle emitter emitter node (node record index "
|
Log(Debug::Warning)
|
||||||
+ std::to_string(recIndex) + ")");
|
<< "NIFFile Warning: Failed to find particle emitter emitter node (node record index "
|
||||||
|
<< recIndex << "). File: " << nif.getFilename();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1475,7 +1469,7 @@ namespace NifOsg
|
||||||
const Nif::NiSkinInstance* skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin.getPtr();
|
const Nif::NiSkinInstance* skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin.getPtr();
|
||||||
const Nif::NiSkinData* data = skin->data.getPtr();
|
const Nif::NiSkinData* data = skin->data.getPtr();
|
||||||
const Nif::NodeList& bones = skin->bones;
|
const Nif::NodeList& bones = skin->bones;
|
||||||
for (size_t i = 0; i < bones.length(); i++)
|
for (std::size_t i = 0, n = bones.size(); i < n; ++i)
|
||||||
{
|
{
|
||||||
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
|
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
|
||||||
|
|
||||||
|
@ -2393,7 +2387,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled.
|
// While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled.
|
||||||
if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW || !specEnabled)
|
if (mVersion <= Nif::NIFFile::VER_MW || !specEnabled)
|
||||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
|
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
|
||||||
|
|
||||||
if (lightmode == 0)
|
if (lightmode == 0)
|
||||||
|
@ -2495,15 +2489,15 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> Loader::load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager)
|
osg::ref_ptr<osg::Node> Loader::load(Nif::FileView file, Resource::ImageManager* imageManager)
|
||||||
{
|
{
|
||||||
LoaderImpl impl(file->getFilename(), file->getVersion(), file->getUserVersion(), file->getBethVersion());
|
LoaderImpl impl(file.getFilename(), file.getVersion(), file.getUserVersion(), file.getBethVersion());
|
||||||
return impl.load(file, imageManager);
|
return impl.load(file, imageManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target)
|
void Loader::loadKf(Nif::FileView kf, SceneUtil::KeyframeHolder& target)
|
||||||
{
|
{
|
||||||
LoaderImpl impl(kf->getFilename(), kf->getVersion(), kf->getUserVersion(), kf->getBethVersion());
|
LoaderImpl impl(kf.getFilename(), kf.getVersion(), kf.getUserVersion(), kf.getBethVersion());
|
||||||
impl.loadKf(kf, target);
|
impl.loadKf(kf, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ namespace NifOsg
|
||||||
public:
|
public:
|
||||||
/// Create a scene graph for the given NIF. Auto-detects when skinning is used and wraps the graph in a Skeleton
|
/// Create a scene graph for the given NIF. Auto-detects when skinning is used and wraps the graph in a Skeleton
|
||||||
/// if so.
|
/// if so.
|
||||||
static osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager);
|
static osg::ref_ptr<osg::Node> load(Nif::FileView file, Resource::ImageManager* imageManager);
|
||||||
|
|
||||||
/// Load keyframe controllers from the given kf file.
|
/// Load keyframe controllers from the given kf file.
|
||||||
static void loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target);
|
static void loadKf(Nif::FileView kf, SceneUtil::KeyframeHolder& target);
|
||||||
|
|
||||||
/// Set whether or not nodes marked as "MRK" should be shown.
|
/// Set whether or not nodes marked as "MRK" should be shown.
|
||||||
/// These should be hidden ingame, but visible in the editor.
|
/// These should be hidden ingame, but visible in the editor.
|
||||||
|
|
|
@ -156,8 +156,10 @@ namespace Resource
|
||||||
osg::ref_ptr<SceneUtil::KeyframeHolder> loaded(new SceneUtil::KeyframeHolder);
|
osg::ref_ptr<SceneUtil::KeyframeHolder> loaded(new SceneUtil::KeyframeHolder);
|
||||||
if (Misc::getFileExtension(normalized) == "kf")
|
if (Misc::getFileExtension(normalized) == "kf")
|
||||||
{
|
{
|
||||||
NifOsg::Loader::loadKf(
|
auto file = std::make_shared<Nif::NIFFile>(normalized);
|
||||||
Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get());
|
Nif::Reader reader(*file);
|
||||||
|
reader.parse(mVFS->getNormalized(normalized));
|
||||||
|
NifOsg::Loader::loadKf(*file, *loaded.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,7 +45,9 @@ namespace Resource
|
||||||
return static_cast<NifFileHolder*>(obj.get())->mNifFile;
|
return static_cast<NifFileHolder*>(obj.get())->mNifFile;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Nif::NIFFilePtr file(new Nif::NIFFile(mVFS->get(name), name));
|
auto file = std::make_shared<Nif::NIFFile>(name);
|
||||||
|
Nif::Reader reader(*file);
|
||||||
|
reader.parse(mVFS->get(name));
|
||||||
obj = new NifFileHolder(file);
|
obj = new NifFileHolder(file);
|
||||||
mCache->addEntryToObjectCache(name, obj);
|
mCache->addEntryToObjectCache(name, obj);
|
||||||
return file;
|
return file;
|
||||||
|
|
|
@ -714,7 +714,7 @@ namespace Resource
|
||||||
{
|
{
|
||||||
auto ext = Misc::getFileExtension(normalizedFilename);
|
auto ext = Misc::getFileExtension(normalizedFilename);
|
||||||
if (ext == "nif")
|
if (ext == "nif")
|
||||||
return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), imageManager);
|
return NifOsg::Loader::load(*nifFileManager->get(normalizedFilename), imageManager);
|
||||||
else
|
else
|
||||||
return loadNonNif(normalizedFilename, *vfs->get(normalizedFilename), imageManager);
|
return loadNonNif(normalizedFilename, *vfs->get(normalizedFilename), imageManager);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue