From ef896faa900f99576b86190d06b7e1a5e50a1350 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 9 Sep 2023 21:32:42 +0300 Subject: [PATCH 1/6] Rename Named->NiObjectNET and update everything directly related to it BulletNifLoader: properly check if the node has animation controllers Flatten extra data linked list --- apps/openmw_test_suite/nif/node.hpp | 12 +-- .../nifloader/testbulletnifloader.cpp | 20 ++-- .../nifosg/testnifloader.cpp | 4 +- components/nif/base.cpp | 26 ++++-- components/nif/base.hpp | 22 +++-- components/nif/node.cpp | 6 +- components/nif/node.hpp | 6 +- components/nif/property.hpp | 2 +- components/nif/recordptr.hpp | 4 +- components/nif/texture.hpp | 2 +- components/nifbullet/bulletnifloader.cpp | 30 +++--- components/nifosg/nifloader.cpp | 92 +++++++++---------- 12 files changed, 123 insertions(+), 103 deletions(-) diff --git a/apps/openmw_test_suite/nif/node.hpp b/apps/openmw_test_suite/nif/node.hpp index 19276059c8..ce42faef08 100644 --- a/apps/openmw_test_suite/nif/node.hpp +++ b/apps/openmw_test_suite/nif/node.hpp @@ -16,16 +16,16 @@ namespace Nif::Testing value.mNext = ExtraPtr(nullptr); } - inline void init(Named& value) + inline void init(NiObjectNET& value) { - value.extra = ExtraPtr(nullptr); - value.extralist = ExtraList(); - value.controller = ControllerPtr(nullptr); + value.mExtra = ExtraPtr(nullptr); + value.mExtraList = ExtraList(); + value.mController = ControllerPtr(nullptr); } inline void init(Node& value) { - init(static_cast(value)); + init(static_cast(value)); value.flags = 0; init(value.trafo); value.hasBounds = false; @@ -65,7 +65,7 @@ namespace Nif::Testing value.phase = 0; value.timeStart = 0; value.timeStop = 0; - value.target = NamedPtr(nullptr); + value.target = NiObjectNETPtr(nullptr); } } diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 99f91aacb9..7c675fd22d 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -837,7 +837,7 @@ namespace copy(mTransform, mNiTriShape.trafo); mNiTriShape.trafo.scale = 3; mNiTriShape.parents.push_back(&mNiNode); - mNiTriShape.controller = Nif::ControllerPtr(&mController); + mNiTriShape.mController = Nif::ControllerPtr(&mController); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); mNiNode.trafo.scale = 4; @@ -870,7 +870,7 @@ namespace copy(mTransform, mNiTriShape2.trafo); mNiTriShape2.trafo.scale = 3; mNiTriShape2.parents.push_back(&mNiNode); - mNiTriShape2.controller = Nif::ControllerPtr(&mController); + mNiTriShape2.mController = Nif::ControllerPtr(&mController); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2), @@ -998,7 +998,7 @@ namespace { mNiStringExtraData.mData = "NCC__"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); @@ -1027,7 +1027,7 @@ namespace mNiStringExtraData.mNext = Nif::ExtraPtr(&mNiStringExtraData2); mNiStringExtraData2.mData = "NCC__"; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); @@ -1054,7 +1054,7 @@ namespace { mNiStringExtraData.mData = "NC___"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); @@ -1082,7 +1082,7 @@ namespace mNiStringExtraData.mNext = Nif::ExtraPtr(&mNiStringExtraData2); mNiStringExtraData2.mData = "NC___"; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); @@ -1143,7 +1143,7 @@ namespace { mNiStringExtraData.mData = "MRK"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); @@ -1162,9 +1162,9 @@ namespace { mNiIntegerExtraData.mData = 32; // BSX flag "editor marker" mNiIntegerExtraData.recType = Nif::RC_BSXFlags; - mNiTriShape.extralist.push_back(Nif::ExtraPtr(&mNiIntegerExtraData)); + mNiTriShape.mExtraList.push_back(Nif::ExtraPtr(&mNiIntegerExtraData)); mNiTriShape.parents.push_back(&mNiNode); - mNiTriShape.name = "EditorMarker"; + mNiTriShape.mName = "EditorMarker"; mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); Nif::NIFFile file("test.nif"); @@ -1183,7 +1183,7 @@ namespace { mNiStringExtraData.mData = "MRK"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; - mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); + mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.parents.push_back(&mNiNode2); mNiNode2.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.recType = Nif::RC_RootCollisionNode; diff --git a/apps/openmw_test_suite/nifosg/testnifloader.cpp b/apps/openmw_test_suite/nifosg/testnifloader.cpp index 5c9caf4799..6bcef223d9 100644 --- a/apps/openmw_test_suite/nifosg/testnifloader.cpp +++ b/apps/openmw_test_suite/nifosg/testnifloader.cpp @@ -188,7 +188,7 @@ osg::Group { Nif::BSShaderPPLightingProperty property; property.recType = Nif::RC_BSShaderPPLightingProperty; property.textureSet = nullptr; - property.controller = nullptr; + property.mController = nullptr; property.type = GetParam().mShaderType; node.props.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); @@ -216,7 +216,7 @@ osg::Group { Nif::BSLightingShaderProperty property; property.recType = Nif::RC_BSLightingShaderProperty; property.mTextureSet = nullptr; - property.controller = nullptr; + property.mController = nullptr; property.type = GetParam().mShaderType; node.props.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); diff --git a/components/nif/base.cpp b/components/nif/base.cpp index af98cfa16d..ee5851bda6 100644 --- a/components/nif/base.cpp +++ b/components/nif/base.cpp @@ -13,20 +13,28 @@ namespace Nif } } - void Named::read(NIFStream* nif) + void NiObjectNET::read(NIFStream* nif) { - name = nif->getString(); + nif->read(mName); if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0)) - extra.read(nif); + mExtra.read(nif); else - readRecordList(nif, extralist); - controller.read(nif); + readRecordList(nif, mExtraList); + mController.read(nif); } - void Named::post(Reader& nif) + void NiObjectNET::post(Reader& nif) { - extra.post(nif); - postRecordList(nif, extralist); - controller.post(nif); + mExtra.post(nif); + postRecordList(nif, mExtraList); + mController.post(nif); + } + + ExtraList NiObjectNET::getExtraList() const + { + ExtraList list = mExtraList; + for (ExtraPtr extra = mExtra; !extra.empty(); extra = extra->mNext) + list.emplace_back(extra); + return list; } } diff --git a/components/nif/base.hpp b/components/nif/base.hpp index 69094ffc51..6b4d5710b4 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -40,7 +40,7 @@ namespace Nif int flags; float frequency, phase; float timeStart, timeStop; - NamedPtr target; + NiObjectNETPtr target; void read(NIFStream* nif) override; void post(Reader& nif) override; @@ -49,18 +49,20 @@ namespace Nif ExtrapolationMode extrapolationMode() const { return static_cast(flags & Mask); } }; - /// Has name, extra-data and controller - struct Named : public Record + /// Abstract object that has a name, extra data and controllers + struct NiObjectNET : public Record { - std::string name; - ExtraPtr extra; - ExtraList extralist; - ControllerPtr controller; + std::string mName; + ExtraPtr mExtra; + ExtraList mExtraList; + ControllerPtr mController; void read(NIFStream* nif) override; void post(Reader& nif) override; - }; - using NiSequenceStreamHelper = Named; -} // Namespace + // Collect extra records attached to the object + ExtraList getExtraList() const; + }; + +} #endif diff --git a/components/nif/node.cpp b/components/nif/node.cpp index 6028ac253f..733d5319e9 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -77,7 +77,7 @@ namespace Nif void Node::read(NIFStream* nif) { - Named::read(nif); + NiObjectNET::read(nif); flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt(); trafo = nif->getTrafo(); @@ -101,7 +101,7 @@ namespace Nif void Node::post(Reader& nif) { - Named::post(nif); + NiObjectNET::post(nif); postRecordList(nif, props); collision.post(nif); } @@ -128,7 +128,7 @@ namespace Nif // FIXME: if node 0 is *not* the only root node, this must not happen. // FIXME: doing this here is awful. // We want to do this on world scene graph level rather than local scene graph level. - if (0 == recIndex && !Misc::StringUtils::ciEqual(name, "bip01")) + if (0 == recIndex && !Misc::StringUtils::ciEqual(mName, "bip01")) { trafo = Nif::Transformation::getIdentity(); } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 2d8021eb49..129e74a617 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -62,11 +62,15 @@ namespace Nif void read(NIFStream* nif); }; + struct NiSequenceStreamHelper : NiObjectNET + { + }; + /** A Node is an object that's part of the main NIF tree. It has parent node (unless it's the root), and transformation (location and rotation) relative to it's parent. */ - struct Node : public Named + struct Node : public NiObjectNET { enum Flags { diff --git a/components/nif/property.hpp b/components/nif/property.hpp index a0800d2700..90f1e9ffb5 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -29,7 +29,7 @@ namespace Nif { - struct Property : public Named + struct Property : public NiObjectNET { }; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index e2836d458d..5b890eec54 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -115,7 +115,7 @@ namespace Nif struct NiPosData; struct NiVisData; struct Controller; - struct Named; + struct NiObjectNET; struct NiSkinData; struct NiFloatData; struct NiMorphData; @@ -156,7 +156,7 @@ namespace Nif using NiPosDataPtr = RecordPtrT; using NiVisDataPtr = RecordPtrT; using ControllerPtr = RecordPtrT; - using NamedPtr = RecordPtrT; + using NiObjectNETPtr = RecordPtrT; using NiSkinDataPtr = RecordPtrT; using NiMorphDataPtr = RecordPtrT; using NiPixelDataPtr = RecordPtrT; diff --git a/components/nif/texture.hpp b/components/nif/texture.hpp index a326b47f14..8d7e44990f 100644 --- a/components/nif/texture.hpp +++ b/components/nif/texture.hpp @@ -6,7 +6,7 @@ namespace Nif { - struct NiTexture : public Named + struct NiTexture : public NiObjectNET { }; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index be27b04603..31be54b030 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -277,9 +277,23 @@ namespace NifBullet if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive()) return; - if (!node.controller.empty() && node.controller->recType == Nif::RC_NiKeyframeController - && node.controller->isActive()) - args.mAnimated = true; + for (Nif::ControllerPtr ctrl = node.mController; !ctrl.empty(); ctrl = ctrl->next) + { + if (args.mAnimated) + break; + if (!ctrl->isActive()) + continue; + switch (ctrl->recType) + { + case Nif::RC_NiKeyframeController: + case Nif::RC_NiPathController: + case Nif::RC_NiRollController: + args.mAnimated = true; + break; + default: + continue; + } + } if (node.recType == Nif::RC_RootCollisionNode) { @@ -304,13 +318,7 @@ namespace NifBullet args.mAvoid = true; // Check for extra data - std::vector extraCollection; - for (Nif::ExtraPtr e = node.extra; !e.empty(); e = e->mNext) - extraCollection.emplace_back(e); - for (const auto& extraNode : node.extralist) - if (!extraNode.empty()) - extraCollection.emplace_back(extraNode); - for (const auto& e : extraCollection) + for (const auto& e : node.getExtraList()) { if (e->recType == Nif::RC_NiStringExtraData) { @@ -378,7 +386,7 @@ namespace NifBullet { // mHasMarkers is specifically BSXFlags editor marker flag. // If this changes, the check must be corrected. - if (args.mHasMarkers && Misc::StringUtils::ciStartsWith(niGeometry.name, "EditorMarker")) + if (args.mHasMarkers && Misc::StringUtils::ciStartsWith(niGeometry.mName, "EditorMarker")) return; if (niGeometry.data.empty() || niGeometry.data->mVertices.empty()) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index d1563df63c..1a595a3ab5 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -275,21 +275,28 @@ namespace NifOsg return; } - Nif::ExtraPtr extra = seq->extra; - if (extra.empty() || extra->recType != Nif::RC_NiTextKeyExtraData) + Nif::ExtraList extraList = seq->getExtraList(); + if (extraList.empty()) { - Log(Debug::Warning) << "NIFFile Warning: First extra data was not a NiTextKeyExtraData, but a " - << (extra.empty() ? std::string_view("nil") : std::string_view(extra->recName)) - << ". File: " << nif.getFilename(); + Log(Debug::Warning) << "NIFFile Warning: NiSequenceStreamHelper has no text keys. File: " + << nif.getFilename(); return; } - extractTextKeys(static_cast(extra.getPtr()), target.mTextKeys); - - extra = extra->mNext; - Nif::ControllerPtr ctrl = seq->controller; - for (; !extra.empty() && !ctrl.empty(); (extra = extra->mNext), (ctrl = ctrl->next)) + if (extraList[0]->recType != Nif::RC_NiTextKeyExtraData) { + Log(Debug::Warning) << "NIFFile Warning: First extra data was not a NiTextKeyExtraData, but a " + << std::string_view(extraList[0]->recName) << ". File: " << nif.getFilename(); + return; + } + + auto textKeyExtraData = static_cast(extraList[0].getPtr()); + extractTextKeys(textKeyExtraData, target.mTextKeys); + + Nif::ControllerPtr ctrl = seq->mController; + for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->next)) + { + Nif::ExtraPtr extra = extraList[i]; if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController) { Log(Debug::Warning) << "NIFFile Warning: Unexpected extra data " << extra->recName @@ -454,7 +461,7 @@ namespace NifOsg static osg::ref_ptr handleLodNode(const Nif::NiLODNode* niLodNode) { osg::ref_ptr lod(new osg::LOD); - lod->setName(niLodNode->name); + lod->setName(niLodNode->mName); lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER); lod->setCenter(niLodNode->lodCenter); for (unsigned int i = 0; i < niLodNode->lodLevels.size(); ++i) @@ -469,7 +476,7 @@ namespace NifOsg static osg::ref_ptr handleSwitchNode(const Nif::NiSwitchNode* niSwitchNode) { osg::ref_ptr switchNode(new osg::Switch); - switchNode->setName(niSwitchNode->name); + switchNode->setName(niSwitchNode->mName); switchNode->setNewChildDefaultValue(false); switchNode->setSingleChildOn(niSwitchNode->initialIndex); return switchNode; @@ -479,7 +486,7 @@ namespace NifOsg { const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast(nifNode); osg::ref_ptr sequenceNode(new osg::Sequence); - sequenceNode->setName(niFltAnimationNode->name); + sequenceNode->setName(niFltAnimationNode->mName); if (!niFltAnimationNode->children.empty()) { if (niFltAnimationNode->swing()) @@ -604,7 +611,7 @@ namespace NifOsg // This takes advantage of the fact root nodes can't have additional controllers // loaded from an external .kf file (original engine just throws "can't find node" errors if you // try). - if (nifNode->parents.empty() && nifNode->controller.empty() && nifNode->trafo.isIdentity()) + if (nifNode->parents.empty() && nifNode->mController.empty() && nifNode->trafo.isIdentity()) node = new osg::Group; dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC; @@ -622,7 +629,7 @@ namespace NifOsg osg::ref_ptr handleNode( const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args) { - if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box")) + if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->mName, "Bounding Box")) return nullptr; osg::ref_ptr node = createNode(nifNode); @@ -632,7 +639,7 @@ namespace NifOsg node->addCullCallback(new BillboardCallback); } - node->setName(nifNode->name); + node->setName(nifNode->mName); if (parentNode) parentNode->addChild(node); @@ -646,16 +653,7 @@ namespace NifOsg // - finding a random child NiNode in NiBspArrayController node->setUserValue("recIndex", nifNode->recIndex); - std::vector extraCollection; - - for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->mNext) - extraCollection.emplace_back(e); - - for (const auto& extraNode : nifNode->extralist) - if (!extraNode.empty()) - extraCollection.emplace_back(extraNode); - - for (const auto& e : extraCollection) + for (const auto& e : nifNode->getExtraList()) { if (e->recType == Nif::RC_NiTextKeyExtraData && args.mTextKeys) { @@ -727,7 +725,7 @@ namespace NifOsg if (nifNode->isHidden()) { bool hasVisController = false; - for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { hasVisController |= (ctrl->recType == Nif::RC_NiVisController); if (hasVisController) @@ -755,12 +753,12 @@ namespace NifOsg bool skip; if (args.mNifVersion <= Nif::NIFFile::NIFVersion::VER_MW) { - skip = (args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->name, "tri editormarker")) - || Misc::StringUtils::ciStartsWith(nifNode->name, "shadow") - || Misc::StringUtils::ciStartsWith(nifNode->name, "tri shadow"); + skip = (args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->mName, "tri editormarker")) + || Misc::StringUtils::ciStartsWith(nifNode->mName, "shadow") + || Misc::StringUtils::ciStartsWith(nifNode->mName, "tri shadow"); } else - skip = args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->name, "EditorMarker"); + skip = args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->mName, "EditorMarker"); if (!skip) { Nif::NiSkinInstancePtr skin = static_cast(nifNode)->skin; @@ -770,7 +768,7 @@ namespace NifOsg else handleSkinnedGeometry(nifNode, parent, node, composite, args.mBoundTextures, args.mAnimFlags); - if (!nifNode->controller.empty()) + if (!nifNode->mController.empty()) handleMeshControllers(nifNode, node, composite, args.mBoundTextures, args.mAnimFlags); } } @@ -807,9 +805,9 @@ namespace NifOsg const Nif::NiSwitchNode* niSwitchNode = static_cast(nifNode); osg::ref_ptr switchNode = handleSwitchNode(niSwitchNode); node->addChild(switchNode); - if (niSwitchNode->name == Constants::NightDayLabel) + if (niSwitchNode->mName == Constants::NightDayLabel) mHasNightDayLabel = true; - else if (niSwitchNode->name == Constants::HerbalismLabel) + else if (niSwitchNode->mName == Constants::HerbalismLabel) mHasHerbalismLabel = true; currentNode = switchNode; @@ -860,7 +858,7 @@ namespace NifOsg SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -887,7 +885,7 @@ namespace NifOsg void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated) { - for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -965,7 +963,7 @@ namespace NifOsg void handleMaterialControllers(const Nif::Property* materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial) { - for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -1016,7 +1014,7 @@ namespace NifOsg void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags) { - for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -1256,7 +1254,7 @@ namespace NifOsg partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT); const Nif::NiParticleSystemController* partctrl = nullptr; - for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -1465,7 +1463,7 @@ namespace NifOsg new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, line.size(), line.data())); } } - handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->name); + handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->mName); // osg::Material properties are handled here for two reasons: // - if there are no vertex colors, we need to disable colorMode. @@ -1487,7 +1485,7 @@ namespace NifOsg if (geom->empty()) return; osg::ref_ptr drawable; - for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { if (!ctrl->isActive()) continue; @@ -1507,7 +1505,7 @@ namespace NifOsg } if (!drawable.get()) drawable = geom; - drawable->setName(nifNode->name); + drawable->setName(nifNode->mName); parentNode->addChild(drawable); } @@ -1543,7 +1541,7 @@ namespace NifOsg return; osg::ref_ptr rig(new SceneUtil::RigGeometry); rig->setSourceGeometry(geometry); - rig->setName(nifNode->name); + rig->setName(nifNode->mName); // Assign bone weights osg::ref_ptr map(new SceneUtil::RigGeometry::InfluenceMap); @@ -1553,7 +1551,7 @@ namespace NifOsg const Nif::NodeList& bones = skin->mBones; for (std::size_t i = 0; i < bones.size(); ++i) { - std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name); + std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName); SceneUtil::RigGeometry::BoneInfluence influence; influence.mWeights = data->mBones[i].mWeights; @@ -1839,7 +1837,7 @@ namespace NifOsg for (size_t i = 0; i < texprop->textures.size(); ++i) { if (texprop->textures[i].inUse - || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->controller.empty())) + || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->mController.empty())) { switch (i) { @@ -1866,7 +1864,7 @@ namespace NifOsg if (texprop->textures[i].inUse) { const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; - if (tex.texture.empty() && texprop->controller.empty()) + if (tex.texture.empty() && texprop->mController.empty()) { if (i == 0) Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName @@ -2424,7 +2422,7 @@ namespace NifOsg mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.specular, 1.f)); mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness); - if (!matprop->controller.empty()) + if (!matprop->mController.empty()) { hasMatCtrl = true; handleMaterialControllers(matprop, composite, animflags, mat); From 535290a83d11c03edf36ab7b95ffee58ccff831c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 10 Sep 2023 00:04:17 +0300 Subject: [PATCH 2/6] Update NIF Reader class and related code Update BSStreamHeader definitions Fix 10.0.1.8 loading Explicitly avoid loading 20.3.1.2 --- components/nif/niffile.cpp | 199 ++++++++++++++++++++----------------- components/nif/niffile.hpp | 45 +++++---- 2 files changed, 133 insertions(+), 111 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index e147ee3528..ae871002c3 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -25,13 +25,13 @@ namespace Nif { Reader::Reader(NIFFile& file) - : ver(file.mVersion) - , userVer(file.mUserVersion) - , bethVer(file.mBethVersion) - , filename(file.mPath) - , hash(file.mHash) - , records(file.mRecords) - , roots(file.mRoots) + : mVersion(file.mVersion) + , mUserVersion(file.mUserVersion) + , mBethVersion(file.mBethVersion) + , mFilename(file.mPath) + , mHash(file.mHash) + , mRecords(file.mRecords) + , mRoots(file.mRoots) , mUseSkinning(file.mUseSkinning) { } @@ -315,7 +315,7 @@ namespace Nif /// Make the factory map used for parsing the file static const std::map factories = makeFactory(); - std::string Reader::printVersion(unsigned int version) + std::string Reader::versionToString(std::uint32_t version) { int major = (version >> 24) & 0xFF; int minor = (version >> 16) & 0xFF; @@ -329,8 +329,8 @@ namespace Nif void Reader::parse(Files::IStreamPtr&& stream) { - const std::array fileHash = Files::getHash(filename, *stream); - hash.append(reinterpret_cast(fileHash.data()), fileHash.size() * sizeof(std::uint64_t)); + const std::array fileHash = Files::getHash(mFilename, *stream); + mHash.append(reinterpret_cast(fileHash.data()), fileHash.size() * sizeof(std::uint64_t)); NIFStream nif(*this, std::move(stream)); @@ -343,151 +343,172 @@ namespace Nif const bool supportedHeader = std::any_of(verStrings.begin(), verStrings.end(), [&](const std::string& verString) { return head.starts_with(verString); }); if (!supportedHeader) - throw Nif::Exception("Invalid NIF header: " + head, filename); + throw Nif::Exception("Invalid NIF header: " + head, mFilename); // Get BCD version - ver = nif.getUInt(); + nif.read(mVersion); // 4.0.0.0 is an older, practically identical version of the format. // It's not used by Morrowind assets but Morrowind supports it. static const std::array supportedVers = { NIFStream::generateVersion(4, 0, 0, 0), NIFFile::VER_MW, }; - const bool supportedVersion = std::find(supportedVers.begin(), supportedVers.end(), ver) != supportedVers.end(); + const bool supportedVersion + = std::find(supportedVers.begin(), supportedVers.end(), mVersion) != supportedVers.end(); const bool writeDebugLog = sWriteNifDebugLog; if (!supportedVersion) { if (!sLoadUnsupportedFiles) - throw Nif::Exception("Unsupported NIF version: " + printVersion(ver), filename); + throw Nif::Exception("Unsupported NIF version: " + versionToString(mVersion), mFilename); if (writeDebugLog) - Log(Debug::Warning) << " NIFFile Warning: Unsupported NIF version: " << printVersion(ver) - << ". Proceed with caution! File: " << filename; + Log(Debug::Warning) << " NIFFile Warning: Unsupported NIF version: " << versionToString(mVersion) + << ". Proceed with caution! File: " << mFilename; } - // NIF data endianness - if (ver >= NIFStream::generateVersion(20, 0, 0, 4)) + const bool hasEndianness = mVersion >= NIFStream::generateVersion(20, 0, 0, 4); + const bool hasUserVersion = mVersion >= NIFStream::generateVersion(10, 0, 1, 8); + const bool hasRecTypeListings = mVersion >= NIFStream::generateVersion(5, 0, 0, 1); + const bool hasRecTypeHashes = mVersion == NIFStream::generateVersion(20, 3, 1, 2); + const bool hasRecordSizes = mVersion >= NIFStream::generateVersion(20, 2, 0, 5); + const bool hasGroups = mVersion >= NIFStream::generateVersion(5, 0, 0, 6); + const bool hasStringTable = mVersion >= NIFStream::generateVersion(20, 1, 0, 1); + const bool hasRecordSeparators + = mVersion >= NIFStream::generateVersion(10, 0, 0, 0) && mVersion < NIFStream::generateVersion(10, 2, 0, 0); + + // Record type list + std::vector recTypes; + // Record type mapping for each record + std::vector recTypeIndices; + { - unsigned char endianness = nif.getChar(); + std::uint8_t endianness = 1; + if (hasEndianness) + nif.read(endianness); + + // TODO: find some big-endian files and investigate the difference if (endianness == 0) - throw Nif::Exception("Big endian NIF files are unsupported", filename); + throw Nif::Exception("Big endian NIF files are unsupported", mFilename); } - // User version - if (ver > NIFStream::generateVersion(10, 0, 1, 8)) - userVer = nif.getUInt(); + if (hasUserVersion) + nif.read(mUserVersion); - // Number of records - const std::size_t recNum = nif.getUInt(); - records.resize(recNum); + mRecords.resize(nif.get()); // Bethesda stream header - // It contains Bethesda format version and (useless) export information - if (ver == NIFFile::VER_OB_OLD - || (userVer >= 3 - && ((ver == NIFFile::VER_OB || ver == NIFFile::VER_BGS) - || (ver >= NIFStream::generateVersion(10, 1, 0, 0) && ver <= NIFStream::generateVersion(20, 0, 0, 4) - && userVer <= 11)))) { - bethVer = nif.getUInt(); - nif.getExportString(); // Author - if (bethVer > NIFFile::BETHVER_FO4) - nif.getUInt(); // Unknown - nif.getExportString(); // Process script - nif.getExportString(); // Export script - if (bethVer == NIFFile::BETHVER_FO4) - nif.getExportString(); // Max file path - } - - std::vector recTypes; - std::vector recTypeIndices; - - const bool hasRecTypeListings = ver >= NIFStream::generateVersion(5, 0, 0, 1); - if (hasRecTypeListings) - { - unsigned short recTypeNum = nif.getUShort(); - // Record type list - nif.getSizedStrings(recTypes, recTypeNum); - // Record type mapping for each record - nif.readVector(recTypeIndices, recNum); - if (ver >= NIFStream::generateVersion(5, 0, 0, 6)) // Groups + bool hasBSStreamHeader = false; + if (mVersion == NIFFile::VER_OB_OLD) + hasBSStreamHeader = true; + else if (mUserVersion >= 3 && mVersion >= NIFStream::generateVersion(10, 1, 0, 0)) { - if (ver >= NIFStream::generateVersion(20, 1, 0, 1)) // String table - { - if (ver >= NIFStream::generateVersion(20, 2, 0, 5)) // Record sizes - { - std::vector recSizes; // Currently unused - nif.readVector(recSizes, recNum); - } - const std::size_t stringNum = nif.getUInt(); - nif.getUInt(); // Max string length - nif.getSizedStrings(strings, stringNum); - } - std::vector groups; // Currently unused - unsigned int groupNum = nif.getUInt(); - nif.readVector(groups, groupNum); + if (mVersion <= NIFFile::VER_OB || mVersion == NIFFile::VER_BGS) + hasBSStreamHeader = mUserVersion <= 11 || mVersion >= NIFFile::VER_OB; + } + + if (hasBSStreamHeader) + { + nif.read(mBethVersion); + nif.getExportString(); // Author + if (mBethVersion >= 131) + nif.get(); // Unknown + else + nif.getExportString(); // Process script + nif.getExportString(); // Export script + if (mBethVersion >= 103) + nif.getExportString(); // Max file path } } - const bool hasRecordSeparators - = ver >= NIFStream::generateVersion(10, 0, 0, 0) && ver < NIFStream::generateVersion(10, 2, 0, 0); - for (std::size_t i = 0; i < recNum; i++) + if (hasRecTypeListings) + { + // TODO: 20.3.1.2 uses DJB hashes instead of strings + if (hasRecTypeHashes) + throw Nif::Exception("Hashed record types are unsupported", mFilename); + else + { + nif.getSizedStrings(recTypes, nif.get()); + nif.readVector(recTypeIndices, mRecords.size()); + } + } + + if (hasRecordSizes) // Record sizes + { + std::vector recSizes; // Currently unused + nif.readVector(recSizes, mRecords.size()); + } + + if (hasStringTable) + { + std::uint32_t stringNum, maxStringLength; + nif.read(stringNum); + nif.read(maxStringLength); + nif.getSizedStrings(mStrings, stringNum); + } + + if (hasGroups) + { + std::vector groups; // Currently unused + nif.readVector(groups, nif.get()); + } + + for (std::size_t i = 0; i < mRecords.size(); i++) { std::unique_ptr r; - std::string rec = hasRecTypeListings ? recTypes[recTypeIndices[i]] : nif.getString(); + std::string rec = hasRecTypeListings ? recTypes[recTypeIndices[i]] : nif.get(); if (rec.empty()) { std::stringstream error; error << "Record type is blank (index " << i << ")"; - throw Nif::Exception(error.str(), filename); + throw Nif::Exception(error.str(), mFilename); } // Record separator. Some Havok records in Oblivion do not have it. if (hasRecordSeparators && !rec.starts_with("bhk")) - if (nif.getInt()) + if (nif.get()) Log(Debug::Warning) << "NIFFile Warning: Record of type " << rec << ", index " << i - << " is preceded by a non-zero separator. File: " << filename; + << " is preceded by a non-zero separator. File: " << mFilename; const auto entry = factories.find(rec); if (entry == factories.end()) - throw Nif::Exception("Unknown record type " + rec, filename); + throw Nif::Exception("Unknown record type " + rec, mFilename); r = entry->second(); if (!supportedVersion && writeDebugLog) Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" - << filename << ")"; + << mFilename << ")"; assert(r != nullptr); assert(r->recType != RC_MISSING); r->recName = rec; r->recIndex = i; r->read(&nif); - records[i] = std::move(r); + mRecords[i] = std::move(r); } - const std::size_t rootNum = nif.getUInt(); - roots.resize(rootNum); - // Determine which records are roots - for (std::size_t i = 0; i < rootNum; i++) + mRoots.resize(nif.get()); + for (std::size_t i = 0; i < mRoots.size(); i++) { - int idx = nif.getInt(); - if (idx >= 0 && static_cast(idx) < records.size()) + std::int32_t idx; + nif.read(idx); + if (idx >= 0 && static_cast(idx) < mRecords.size()) { - roots[i] = records[idx].get(); + mRoots[i] = mRecords[idx].get(); } else { - roots[i] = nullptr; + mRoots[i] = nullptr; Log(Debug::Warning) << "NIFFile Warning: Root " << i + 1 << " does not point to a record: index " << idx - << ". File: " << filename; + << ". File: " << mFilename; } } // Once parsing is done, do post-processing. - for (const auto& record : records) + for (const auto& record : mRecords) record->post(*this); } @@ -513,7 +534,7 @@ namespace Nif { if (index == std::numeric_limits::max()) return std::string(); - return strings.at(index); + return mStrings.at(index); } } diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 154ab6b140..6f0030af47 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -30,13 +30,14 @@ namespace Nif BETHVER_SKY = 83, // Skyrim BETHVER_SSE = 100, // Skyrim SE BETHVER_FO4 = 130, // Fallout 4 - BETHVER_F76 = 155 // Fallout 76 + BETHVER_F76 = 155, // Fallout 76 + BETHVER_STF = 172, // Starfield }; /// File version, user version, Bethesda version - unsigned int mVersion = 0; - unsigned int mUserVersion = 0; - unsigned int mBethVersion = 0; + std::uint32_t mVersion = 0; + std::uint32_t mUserVersion = 0; + std::uint32_t mBethVersion = 0; /// File name, used for error messages and opening the file std::filesystem::path mPath; @@ -76,13 +77,13 @@ namespace Nif const std::string& getHash() const { return mFile->mHash; } /// Get the version of the NIF format used - unsigned int getVersion() const { return mFile->mVersion; } + std::uint32_t getVersion() const { return mFile->mVersion; } /// Get the user version of the NIF format used - unsigned int getUserVersion() const { return mFile->mUserVersion; } + std::uint32_t getUserVersion() const { return mFile->mUserVersion; } /// Get the Bethesda version of the NIF format used - unsigned int getBethVersion() const { return mFile->mBethVersion; } + std::uint32_t getBethVersion() const { return mFile->mBethVersion; } bool getUseSkinning() const { return mFile->mUseSkinning; } @@ -93,22 +94,22 @@ namespace Nif class Reader { /// File version, user version, Bethesda version - unsigned int& ver; - unsigned int& userVer; - unsigned int& bethVer; + std::uint32_t& mVersion; + std::uint32_t& mUserVersion; + std::uint32_t& mBethVersion; /// File name, used for error messages and opening the file - std::filesystem::path& filename; - std::string& hash; + std::filesystem::path& mFilename; + std::string& mHash; /// Record list - std::vector>& records; + std::vector>& mRecords; /// Root list. This is a select portion of the pointers from records - std::vector& roots; + std::vector& mRoots; /// String table - std::vector strings; + std::vector mStrings; bool& mUseSkinning; @@ -117,7 +118,7 @@ namespace Nif /// 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); + std::string versionToString(std::uint32_t version); public: /// Open a NIF stream. The name is used for error messages. @@ -127,26 +128,26 @@ namespace Nif void parse(Files::IStreamPtr&& stream); /// Get a given record - Record* getRecord(size_t index) const { return records.at(index).get(); } + Record* getRecord(size_t index) const { return mRecords.at(index).get(); } /// Get a given string from the file's string table - std::string getString(uint32_t index) const; + std::string getString(std::uint32_t index) const; /// 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. void setUseSkinning(bool skinning); /// Get the name of the file - std::filesystem::path getFilename() const { return filename; } + std::filesystem::path getFilename() const { return mFilename; } /// Get the version of the NIF format used - unsigned int getVersion() const { return ver; } + std::uint32_t getVersion() const { return mVersion; } /// Get the user version of the NIF format used - unsigned int getUserVersion() const { return userVer; } + std::uint32_t getUserVersion() const { return mUserVersion; } /// Get the Bethesda version of the NIF format used - unsigned int getBethVersion() const { return bethVer; } + std::uint32_t getBethVersion() const { return mBethVersion; } static void setLoadUnsupportedFiles(bool load); From 6872c7144e4feb4f4f66798cf6d6aed4aa969422 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 10 Sep 2023 01:38:17 +0300 Subject: [PATCH 3/6] Rename Transformation->NiTransform and update everything directly related --- apps/openmw_test_suite/nif/node.hpp | 4 +-- .../nifloader/testbulletnifloader.cpp | 32 +++++++++--------- components/nif/data.cpp | 8 ++--- components/nif/data.hpp | 33 +++---------------- components/nif/nifstream.cpp | 10 +++--- components/nif/nifstream.hpp | 5 ++- components/nif/niftypes.hpp | 18 +++++----- components/nif/node.cpp | 7 ++-- components/nif/node.hpp | 2 +- components/nifosg/matrixtransform.cpp | 8 ++--- components/nifosg/matrixtransform.hpp | 2 +- 11 files changed, 52 insertions(+), 77 deletions(-) diff --git a/apps/openmw_test_suite/nif/node.hpp b/apps/openmw_test_suite/nif/node.hpp index ce42faef08..70a1fe16be 100644 --- a/apps/openmw_test_suite/nif/node.hpp +++ b/apps/openmw_test_suite/nif/node.hpp @@ -6,9 +6,9 @@ namespace Nif::Testing { - inline void init(Transformation& value) + inline void init(NiTransform& value) { - value = Transformation::getIdentity(); + value = NiTransform::getIdentity(); } inline void init(Extra& value) diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 7c675fd22d..2381d2d5a4 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -274,12 +274,12 @@ namespace using namespace Nif::Testing; using NifBullet::BulletNifLoader; - void copy(const btTransform& src, Nif::Transformation& dst) + void copy(const btTransform& src, Nif::NiTransform& dst) { - dst.pos = osg::Vec3f(src.getOrigin().x(), src.getOrigin().y(), src.getOrigin().z()); + dst.mTranslation = osg::Vec3f(src.getOrigin().x(), src.getOrigin().y(), src.getOrigin().z()); for (int row = 0; row < 3; ++row) for (int column = 0; column < 3; ++column) - dst.rotation.mValues[row][column] = src.getBasis().getRow(row)[column]; + dst.mRotation.mValues[row][column] = src.getBasis().getRow(row)[column]; } struct TestBulletNifLoader : Test @@ -740,7 +740,7 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_root_node_and_filename_starting_with_x_should_return_animated_shape) { copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 3; + mNiTriShape.trafo.mScale = 3; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiTriShape); @@ -764,10 +764,10 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_should_return_animated_shape) { copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 3; + mNiTriShape.trafo.mScale = 3; mNiTriShape.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.scale = 4; + mNiNode.trafo.mScale = 4; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -792,11 +792,11 @@ namespace TestBulletNifLoader, for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_animated_shape) { copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 3; + mNiTriShape.trafo.mScale = 3; mNiTriShape.parents.push_back(&mNiNode); copy(mTransform, mNiTriShape2.trafo); - mNiTriShape2.trafo.scale = 3; + mNiTriShape2.trafo.mScale = 3; mNiTriShape2.parents.push_back(&mNiNode); mNiNode.children = Nif::NodeList(std::vector({ @@ -835,11 +835,11 @@ namespace mController.recType = Nif::RC_NiKeyframeController; mController.flags |= Nif::Controller::Flag_Active; copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 3; + mNiTriShape.trafo.mScale = 3; mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mController = Nif::ControllerPtr(&mController); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.scale = 4; + mNiNode.trafo.mScale = 4; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -865,17 +865,17 @@ namespace mController.recType = Nif::RC_NiKeyframeController; mController.flags |= Nif::Controller::Flag_Active; copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 3; + mNiTriShape.trafo.mScale = 3; mNiTriShape.parents.push_back(&mNiNode); copy(mTransform, mNiTriShape2.trafo); - mNiTriShape2.trafo.scale = 3; + mNiTriShape2.trafo.mScale = 3; mNiTriShape2.parents.push_back(&mNiNode); mNiTriShape2.mController = Nif::ControllerPtr(&mController); mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2), })); - mNiNode.trafo.scale = 4; + mNiNode.trafo.mScale = 4; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1352,12 +1352,12 @@ namespace TEST_F(TestBulletNifLoader, should_handle_node_with_multiple_parents) { copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.scale = 4; + mNiTriShape.trafo.mScale = 4; mNiTriShape.parents = { &mNiNode, &mNiNode2 }; mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.scale = 2; + mNiNode.trafo.mScale = 2; mNiNode2.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode2.trafo.scale = 3; + mNiNode2.trafo.mScale = 3; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 799d0cbe43..6570ce6e5c 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -347,9 +347,7 @@ namespace Nif void NiSkinData::read(NIFStream* nif) { - nif->read(mTransform.rotation); - nif->read(mTransform.pos); - nif->read(mTransform.scale); + nif->read(mTransform); uint32_t numBones; nif->read(numBones); @@ -366,9 +364,7 @@ namespace Nif mBones.resize(numBones); for (BoneInfo& bi : mBones) { - nif->read(bi.mTransform.rotation); - nif->read(bi.mTransform.pos); - nif->read(bi.mTransform.scale); + nif->read(bi.mTransform); nif->read(bi.mBoundSphere); uint16_t numVertices; diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 42f52ba5f1..d81f6de22f 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -1,33 +1,10 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: https://openmw.org/ - - This file (data.h) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - https://www.gnu.org/licenses/ . - - */ - #ifndef OPENMW_COMPONENTS_NIF_DATA_HPP #define OPENMW_COMPONENTS_NIF_DATA_HPP #include "nifkey.hpp" -#include "niftypes.hpp" // Transformation +#include "niftypes.hpp" // NiTransform +#include "node.hpp" #include "recordptr.hpp" -#include namespace Nif { @@ -278,12 +255,12 @@ namespace Nif struct BoneInfo { - Transformation mTransform; + NiTransform mTransform; osg::BoundingSpheref mBoundSphere; std::vector mWeights; }; - Transformation mTransform; + NiTransform mTransform; std::vector mBones; NiSkinPartitionPtr mPartitions; @@ -413,5 +390,5 @@ namespace Nif void read(NIFStream* nif) override; }; -} // Namespace +} #endif diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index c666a5edab..e33dc4f7b1 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -130,11 +130,11 @@ namespace Nif } template <> - void NIFStream::read(Transformation& t) + void NIFStream::read(NiTransform& transform) { - read(t.pos); - read(t.rotation); - read(t.scale); + read(transform.mRotation); + read(transform.mTranslation); + read(transform.mScale); } template <> @@ -192,7 +192,7 @@ namespace Nif } template <> - void NIFStream::read(Transformation* dest, size_t size) + void NIFStream::read(NiTransform* dest, size_t size) { readRange(*this, dest, size); } diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 217d924059..f4c35e6625 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -159,7 +159,6 @@ namespace Nif osg::Vec4f getVector4() { return get(); } Matrix3 getMatrix3() { return get(); } osg::Quat getQuaternion() { return get(); } - Transformation getTrafo() { return get(); } bool getBoolean() { return get(); } std::string getString() { return get(); } }; @@ -177,7 +176,7 @@ namespace Nif template <> void NIFStream::read(osg::BoundingSpheref& sphere); template <> - void NIFStream::read(Transformation& t); + void NIFStream::read(NiTransform& transform); template <> void NIFStream::read(bool& data); template <> @@ -196,7 +195,7 @@ namespace Nif template <> void NIFStream::read(osg::BoundingSpheref* dest, size_t size); template <> - void NIFStream::read(Transformation* dest, size_t size); + void NIFStream::read(NiTransform* dest, size_t size); template <> void NIFStream::read(bool* dest, size_t size); template <> diff --git a/components/nif/niftypes.hpp b/components/nif/niftypes.hpp index b6a97b6ecb..3b2a4c1578 100644 --- a/components/nif/niftypes.hpp +++ b/components/nif/niftypes.hpp @@ -53,29 +53,29 @@ namespace Nif } }; - struct Transformation + struct NiTransform { - osg::Vec3f pos; - Matrix3 rotation; // this can contain scale components too, including negative and nonuniform scales - float scale; + Matrix3 mRotation; // this can contain scale components too, including negative and nonuniform scales + osg::Vec3f mTranslation; + float mScale; osg::Matrixf toMatrix() const { osg::Matrixf transform; - transform.setTrans(pos); + transform.setTrans(mTranslation); for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) - transform(j, i) = rotation.mValues[i][j] * scale; // NB column/row major difference + transform(j, i) = mRotation.mValues[i][j] * mScale; // NB column/row major difference return transform; } - bool isIdentity() const { return pos == osg::Vec3f(0, 0, 0) && rotation.isIdentity() && scale == 1.f; } + bool isIdentity() const { return mRotation.isIdentity() && mTranslation == osg::Vec3f() && mScale == 1.f; } - static const Transformation& getIdentity() + static const NiTransform& getIdentity() { - static const Transformation identity = { osg::Vec3f(), Matrix3(), 1.0f }; + static const NiTransform identity = { Matrix3(), osg::Vec3f(), 1.0f }; return identity; } }; diff --git a/components/nif/node.cpp b/components/nif/node.cpp index 733d5319e9..fba0e1a69a 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -80,7 +80,10 @@ namespace Nif NiObjectNET::read(nif); flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt(); - trafo = nif->getTrafo(); + nif->read(trafo.mTranslation); + nif->read(trafo.mRotation); + nif->read(trafo.mScale); + if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0)) velocity = nif->getVector3(); if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) @@ -130,7 +133,7 @@ namespace Nif // We want to do this on world scene graph level rather than local scene graph level. if (0 == recIndex && !Misc::StringUtils::ciEqual(mName, "bip01")) { - trafo = Nif::Transformation::getIdentity(); + trafo = Nif::NiTransform::getIdentity(); } } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 129e74a617..2a1fcd9af6 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -83,7 +83,7 @@ namespace Nif // Node flags. Interpretation depends somewhat on the type of node. unsigned int flags; - Transformation trafo; + NiTransform trafo; osg::Vec3f velocity; // Unused? Might be a run-time game state PropertyList props; diff --git a/components/nifosg/matrixtransform.cpp b/components/nifosg/matrixtransform.cpp index 44eac28def..a59f10360a 100644 --- a/components/nifosg/matrixtransform.cpp +++ b/components/nifosg/matrixtransform.cpp @@ -2,10 +2,10 @@ namespace NifOsg { - MatrixTransform::MatrixTransform(const Nif::Transformation& trafo) - : osg::MatrixTransform(trafo.toMatrix()) - , mScale(trafo.scale) - , mRotationScale(trafo.rotation) + MatrixTransform::MatrixTransform(const Nif::NiTransform& transform) + : osg::MatrixTransform(transform.toMatrix()) + , mScale(transform.mScale) + , mRotationScale(transform.mRotation) { } diff --git a/components/nifosg/matrixtransform.hpp b/components/nifosg/matrixtransform.hpp index e1e7ff1828..4e42d00787 100644 --- a/components/nifosg/matrixtransform.hpp +++ b/components/nifosg/matrixtransform.hpp @@ -12,7 +12,7 @@ namespace NifOsg { public: MatrixTransform() = default; - MatrixTransform(const Nif::Transformation& trafo); + MatrixTransform(const Nif::NiTransform& transform); MatrixTransform(const MatrixTransform& copy, const osg::CopyOp& copyop); META_Node(NifOsg, MatrixTransform) From 878d4ddaa7703561232eb17f09e8e6d52f694d29 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 10 Sep 2023 02:45:51 +0300 Subject: [PATCH 4/6] Update record pointer loading --- components/nif/recordptr.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 5b890eec54..eb704dbc21 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -1,9 +1,10 @@ #ifndef OPENMW_COMPONENTS_NIF_RECORDPTR_HPP #define OPENMW_COMPONENTS_NIF_RECORDPTR_HPP +#include + #include "niffile.hpp" #include "nifstream.hpp" -#include namespace Nif { @@ -39,7 +40,7 @@ namespace Nif assert(index == -2); // Store the index for later - index = nif->getInt(); + index = nif->get(); assert(index >= -1); } @@ -90,12 +91,13 @@ namespace Nif template void readRecordList(NIFStream* nif, RecordListT& list) { - const int length = nif->getInt(); + const std::uint32_t length = nif->get(); - if (length < 0) - throw std::runtime_error("Negative NIF record list length: " + std::to_string(length)); + // No reasonable list can hit this generous limit + if (length >= (1 << 24)) + throw std::runtime_error("Record list too long: " + std::to_string(length)); - list.resize(static_cast(length)); + list.resize(length); for (auto& value : list) value.read(nif); From a7cc4e6ba64e7a4ff30348fd370f97c5f853a8c8 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 10 Sep 2023 05:23:25 +0300 Subject: [PATCH 5/6] Rename Node->NiAVObject and update everything directly related Update NiNode Simplify RootCollisionNode handling in BulletNifLoader --- apps/openmw_test_suite/nif/node.hpp | 12 +- .../nifloader/testbulletnifloader.cpp | 286 +++++++++--------- .../nifosg/testnifloader.cpp | 10 +- components/nif/controller.cpp | 2 +- components/nif/controller.hpp | 6 +- components/nif/data.hpp | 4 +- components/nif/effect.cpp | 2 +- components/nif/effect.hpp | 2 +- components/nif/node.cpp | 77 +++-- components/nif/node.hpp | 74 ++--- components/nif/physics.hpp | 4 +- components/nif/recordptr.hpp | 6 +- components/nifbullet/bulletnifloader.cpp | 113 +++---- components/nifbullet/bulletnifloader.hpp | 13 +- components/nifosg/nifloader.cpp | 66 ++-- 15 files changed, 310 insertions(+), 367 deletions(-) diff --git a/apps/openmw_test_suite/nif/node.hpp b/apps/openmw_test_suite/nif/node.hpp index 70a1fe16be..b39729c876 100644 --- a/apps/openmw_test_suite/nif/node.hpp +++ b/apps/openmw_test_suite/nif/node.hpp @@ -23,18 +23,16 @@ namespace Nif::Testing value.mController = ControllerPtr(nullptr); } - inline void init(Node& value) + inline void init(NiAVObject& value) { init(static_cast(value)); - value.flags = 0; - init(value.trafo); - value.hasBounds = false; - value.isBone = false; + value.mFlags = 0; + init(value.mTransform); } inline void init(NiGeometry& value) { - init(static_cast(value)); + init(static_cast(value)); value.data = NiGeometryDataPtr(nullptr); value.skin = NiSkinInstancePtr(nullptr); } @@ -54,7 +52,7 @@ namespace Nif::Testing inline void init(NiSkinInstance& value) { value.mData = NiSkinDataPtr(nullptr); - value.mRoot = NodePtr(nullptr); + value.mRoot = NiAVObjectPtr(nullptr); } inline void init(Controller& value) diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 2381d2d5a4..fc6a21f62c 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -285,8 +285,8 @@ namespace struct TestBulletNifLoader : Test { BulletNifLoader mLoader; - Nif::Node mNode; - Nif::Node mNode2; + Nif::NiAVObject mNode; + Nif::NiAVObject mNode2; Nif::NiNode mNiNode; Nif::NiNode mNiNode2; Nif::NiNode mNiNode3; @@ -414,11 +414,10 @@ namespace TEST_F( TestBulletNifLoader, for_root_nif_node_with_bounding_box_should_return_shape_with_compound_shape_and_box_inside) { - mNode.hasBounds = true; - mNode.flags |= Nif::Node::Flag_BBoxCollision; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision; + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNode); @@ -439,13 +438,12 @@ namespace TEST_F(TestBulletNifLoader, for_child_nif_node_with_bounding_box) { - mNode.hasBounds = true; - mNode.flags |= Nif::Node::Flag_BBoxCollision; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); - mNode.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNode) })); + mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision; + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -467,18 +465,16 @@ namespace TEST_F(TestBulletNifLoader, for_root_and_child_nif_node_with_bounding_box_but_root_without_flag_should_use_child_bounds) { - mNode.hasBounds = true; - mNode.flags |= Nif::Node::Flag_BBoxCollision; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); - mNode.parents.push_back(&mNiNode); + mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision; + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mParents.push_back(&mNiNode); - mNiNode.hasBounds = true; - mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNiNode.bounds.box.extents = osg::Vec3f(4, 5, 6); - mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNode) })); + mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.mBounds.box.extents = osg::Vec3f(4, 5, 6); + mNiNode.mBounds.box.center = osg::Vec3f(-4, -5, -6); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -500,24 +496,21 @@ namespace TEST_F(TestBulletNifLoader, for_root_and_two_children_where_both_with_bounds_but_only_first_with_flag_should_use_first_bounds) { - mNode.hasBounds = true; - mNode.flags |= Nif::Node::Flag_BBoxCollision; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); - mNode.parents.push_back(&mNiNode); + mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision; + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mParents.push_back(&mNiNode); - mNode2.hasBounds = true; - mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); - mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6); - mNode2.parents.push_back(&mNiNode); + mNode2.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode2.mBounds.box.extents = osg::Vec3f(4, 5, 6); + mNode2.mBounds.box.center = osg::Vec3f(-4, -5, -6); + mNode2.mParents.push_back(&mNiNode); - mNiNode.hasBounds = true; - mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9); - mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) })); + mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.mBounds.box.extents = osg::Vec3f(7, 8, 9); + mNiNode.mBounds.box.center = osg::Vec3f(-7, -8, -9); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode), Nif::NiAVObjectPtr(&mNode2) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -539,24 +532,21 @@ namespace TEST_F(TestBulletNifLoader, for_root_and_two_children_where_both_with_bounds_but_only_second_with_flag_should_use_second_bounds) { - mNode.hasBounds = true; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); - mNode.parents.push_back(&mNiNode); + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mParents.push_back(&mNiNode); - mNode2.hasBounds = true; - mNode2.flags |= Nif::Node::Flag_BBoxCollision; - mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); - mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6); - mNode2.parents.push_back(&mNiNode); + mNode2.mFlags |= Nif::NiAVObject::Flag_BBoxCollision; + mNode2.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode2.mBounds.box.extents = osg::Vec3f(4, 5, 6); + mNode2.mBounds.box.center = osg::Vec3f(-4, -5, -6); + mNode2.mParents.push_back(&mNiNode); - mNiNode.hasBounds = true; - mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9); - mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) })); + mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.mBounds.box.extents = osg::Vec3f(7, 8, 9); + mNiNode.mBounds.box.center = osg::Vec3f(-7, -8, -9); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode), Nif::NiAVObjectPtr(&mNode2) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -578,10 +568,9 @@ namespace TEST_F(TestBulletNifLoader, for_root_nif_node_with_bounds_but_without_flag_should_return_shape_with_bounds_but_with_null_collision_shape) { - mNode.hasBounds = true; - mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); + mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNode); @@ -619,10 +608,9 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_root_node_with_bounds_should_return_static_shape_with_bounds_but_with_null_collision_shape) { - mNiTriShape.hasBounds = true; - mNiTriShape.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; - mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3); - mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3); + mNiTriShape.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiTriShape.mBounds.box.extents = osg::Vec3f(1, 2, 3); + mNiTriShape.mBounds.box.center = osg::Vec3f(-1, -2, -3); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiTriShape); @@ -639,8 +627,8 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_static_shape) { - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -662,10 +650,10 @@ namespace TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_static_shape) { - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiNode2) })); - mNiNode2.parents.push_back(&mNiNode); - mNiNode2.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiTriShape.parents.push_back(&mNiNode2); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiNode2) }; + mNiNode2.mParents.push_back(&mNiNode); + mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; + mNiTriShape.mParents.push_back(&mNiNode2); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -687,10 +675,9 @@ namespace TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_static_shape_with_all_meshes) { - mNiTriShape.parents.push_back(&mNiNode); - mNiTriShape2.parents.push_back(&mNiNode); - mNiNode.children - = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiTriShape2.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape2) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -717,8 +704,8 @@ namespace for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_static_shape) { mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -739,8 +726,8 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_root_node_and_filename_starting_with_x_should_return_animated_shape) { - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 3; + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 3; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiTriShape); @@ -763,11 +750,11 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_should_return_animated_shape) { - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 3; - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.mScale = 4; + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 3; + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; + mNiNode.mTransform.mScale = 4; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -791,18 +778,15 @@ namespace TEST_F( TestBulletNifLoader, for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_animated_shape) { - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 3; - mNiTriShape.parents.push_back(&mNiNode); + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 3; + mNiTriShape.mParents.push_back(&mNiNode); - copy(mTransform, mNiTriShape2.trafo); - mNiTriShape2.trafo.mScale = 3; - mNiTriShape2.parents.push_back(&mNiNode); + copy(mTransform, mNiTriShape2.mTransform); + mNiTriShape2.mTransform.mScale = 3; + mNiTriShape2.mParents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ - Nif::NodePtr(&mNiTriShape), - Nif::NodePtr(&mNiTriShape2), - })); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape2) }; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -834,12 +818,12 @@ namespace { mController.recType = Nif::RC_NiKeyframeController; mController.flags |= Nif::Controller::Flag_Active; - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 3; - mNiTriShape.parents.push_back(&mNiNode); + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 3; + mNiTriShape.mParents.push_back(&mNiNode); mNiTriShape.mController = Nif::ControllerPtr(&mController); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.mScale = 4; + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; + mNiNode.mTransform.mScale = 4; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -864,18 +848,18 @@ namespace { mController.recType = Nif::RC_NiKeyframeController; mController.flags |= Nif::Controller::Flag_Active; - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 3; - mNiTriShape.parents.push_back(&mNiNode); - copy(mTransform, mNiTriShape2.trafo); - mNiTriShape2.trafo.mScale = 3; - mNiTriShape2.parents.push_back(&mNiNode); + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 3; + mNiTriShape.mParents.push_back(&mNiNode); + copy(mTransform, mNiTriShape2.mTransform); + mNiTriShape2.mTransform.mScale = 3; + mNiTriShape2.mParents.push_back(&mNiNode); mNiTriShape2.mController = Nif::ControllerPtr(&mController); - mNiNode.children = Nif::NodeList(std::vector({ - Nif::NodePtr(&mNiTriShape), - Nif::NodePtr(&mNiTriShape2), - })); - mNiNode.trafo.mScale = 4; + mNiNode.mChildren = Nif::NiAVObjectList{ + Nif::NiAVObjectPtr(&mNiTriShape), + Nif::NiAVObjectPtr(&mNiTriShape2), + }; + mNiNode.mTransform.mScale = 4; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -905,8 +889,8 @@ namespace TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh) { - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -936,8 +920,8 @@ namespace TEST_F( TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape) { - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; mNiNode.recType = Nif::RC_AvoidNode; Nif::NIFFile file("test.nif"); @@ -960,8 +944,8 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_empty_data_should_return_shape_with_null_collision_shape) { mNiTriShape.data = Nif::NiGeometryDataPtr(nullptr); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -979,8 +963,8 @@ namespace { auto data = static_cast(mNiTriShape.data.getPtr()); data->mTriangles.clear(); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -999,8 +983,8 @@ namespace mNiStringExtraData.mData = "NCC__"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1028,8 +1012,8 @@ namespace mNiStringExtraData2.mData = "NCC__"; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1055,8 +1039,8 @@ namespace mNiStringExtraData.mData = "NC___"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1083,8 +1067,8 @@ namespace mNiStringExtraData2.mData = "NC___"; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1112,13 +1096,13 @@ namespace init(emptyCollisionNode); niTriShape.data = Nif::NiGeometryDataPtr(&mNiTriShapeData); - niTriShape.parents.push_back(&mNiNode); + niTriShape.mParents.push_back(&mNiNode); emptyCollisionNode.recType = Nif::RC_RootCollisionNode; - emptyCollisionNode.parents.push_back(&mNiNode); + emptyCollisionNode.mParents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList( - std::vector({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) })); + mNiNode.mChildren + = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&niTriShape), Nif::NiAVObjectPtr(&emptyCollisionNode) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1144,8 +1128,8 @@ namespace mNiStringExtraData.mData = "MRK"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1163,9 +1147,9 @@ namespace mNiIntegerExtraData.mData = 32; // BSX flag "editor marker" mNiIntegerExtraData.recType = Nif::RC_BSXFlags; mNiTriShape.mExtraList.push_back(Nif::ExtraPtr(&mNiIntegerExtraData)); - mNiTriShape.parents.push_back(&mNiNode); + mNiTriShape.mParents.push_back(&mNiNode); mNiTriShape.mName = "EditorMarker"; - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("test.nif"); file.mRoots.push_back(&mNiNode); @@ -1184,11 +1168,11 @@ namespace mNiStringExtraData.mData = "MRK"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); - mNiTriShape.parents.push_back(&mNiNode2); - mNiNode2.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode2); + mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; mNiNode2.recType = Nif::RC_RootCollisionNode; - mNiNode2.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiNode2) })); + mNiNode2.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiNode2) }; mNiNode.recType = Nif::RC_NiNode; Nif::NIFFile file("test.nif"); @@ -1290,8 +1274,8 @@ namespace TEST_F(TestBulletNifLoader, for_avoid_collision_mesh_should_ignore_tri_strips_data_with_less_than_3_strips) { - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; mNiNode.recType = Nif::RC_AvoidNode; mNiTriStripsData.mStrips.front() = { 0, 1 }; @@ -1309,8 +1293,8 @@ namespace TEST_F(TestBulletNifLoader, for_animated_mesh_should_ignore_tri_strips_data_with_less_than_3_strips) { mNiTriStripsData.mStrips.front() = { 0, 1 }; - mNiTriStrips.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriStrips) })); + mNiTriStrips.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriStrips) }; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -1326,8 +1310,8 @@ namespace TEST_F(TestBulletNifLoader, should_not_add_static_mesh_with_no_triangles_to_compound_shape) { mNiTriStripsData.mStrips.front() = { 0, 1 }; - mNiTriShape.parents.push_back(&mNiNode); - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); + mNiTriShape.mParents.push_back(&mNiNode); + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); @@ -1351,13 +1335,13 @@ namespace TEST_F(TestBulletNifLoader, should_handle_node_with_multiple_parents) { - copy(mTransform, mNiTriShape.trafo); - mNiTriShape.trafo.mScale = 4; - mNiTriShape.parents = { &mNiNode, &mNiNode2 }; - mNiNode.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode.trafo.mScale = 2; - mNiNode2.children = Nif::NodeList(std::vector({ Nif::NodePtr(&mNiTriShape) })); - mNiNode2.trafo.mScale = 3; + copy(mTransform, mNiTriShape.mTransform); + mNiTriShape.mTransform.mScale = 4; + mNiTriShape.mParents = { &mNiNode, &mNiNode2 }; + mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; + mNiNode.mTransform.mScale = 2; + mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; + mNiNode2.mTransform.mScale = 3; Nif::NIFFile file("xtest.nif"); file.mRoots.push_back(&mNiNode); diff --git a/apps/openmw_test_suite/nifosg/testnifloader.cpp b/apps/openmw_test_suite/nifosg/testnifloader.cpp index 6bcef223d9..a8b9e2fd09 100644 --- a/apps/openmw_test_suite/nifosg/testnifloader.cpp +++ b/apps/openmw_test_suite/nifosg/testnifloader.cpp @@ -66,7 +66,7 @@ namespace TEST_F(NifOsgLoaderTest, shouldLoadFileWithDefaultNode) { - Nif::Node node; + Nif::NiAVObject node; init(node); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); @@ -183,14 +183,14 @@ osg::Group { TEST_P(NifOsgLoaderBSShaderPrefixTest, shouldAddShaderPrefix) { - Nif::Node node; + Nif::NiAVObject node; init(node); Nif::BSShaderPPLightingProperty property; property.recType = Nif::RC_BSShaderPPLightingProperty; property.textureSet = nullptr; property.mController = nullptr; property.type = GetParam().mShaderType; - node.props.push_back(Nif::RecordPtrT(&property)); + node.mProperties.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); auto result = Loader::load(file, &mImageManager); @@ -211,14 +211,14 @@ osg::Group { TEST_P(NifOsgLoaderBSLightingShaderPrefixTest, shouldAddShaderPrefix) { - Nif::Node node; + Nif::NiAVObject node; init(node); Nif::BSLightingShaderProperty property; property.recType = Nif::RC_BSLightingShaderProperty; property.mTextureSet = nullptr; property.mController = nullptr; property.type = GetParam().mShaderType; - node.props.push_back(Nif::RecordPtrT(&property)); + node.mProperties.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); auto result = Loader::load(file, &mImageManager); diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 1355ce21d3..a3d7f33e45 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -308,7 +308,7 @@ namespace Nif { NiInterpController::read(nif); size_t numTargets = nif->getUShort(); - std::vector targets; + std::vector targets; targets.resize(numTargets); for (size_t i = 0; i < targets.size(); i++) targets[i].read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index d194ea3060..68e795e7fc 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -160,7 +160,7 @@ namespace Nif osg::Vec3f offsetRandom; - NodePtr emitter; + NiAVObjectPtr emitter; int numParticles; int activeCount; @@ -211,7 +211,7 @@ namespace Nif struct NiLookAtController : public Controller { - NodePtr target; + NiAVObjectPtr target; unsigned short lookAtFlags{ 0 }; void read(NIFStream* nif) override; @@ -237,7 +237,7 @@ namespace Nif struct NiMultiTargetTransformController : public NiInterpController { - NodeList mExtraTargets; + NiAVObjectList mExtraTargets; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/data.hpp b/components/nif/data.hpp index d81f6de22f..849cbde7bd 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -229,8 +229,8 @@ namespace Nif { NiSkinDataPtr mData; NiSkinPartitionPtr mPartitions; - NodePtr mRoot; - NodeList mBones; + NiAVObjectPtr mRoot; + NiAVObjectList mBones; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/effect.cpp b/components/nif/effect.cpp index 36407f8dc2..8db6de06d4 100644 --- a/components/nif/effect.cpp +++ b/components/nif/effect.cpp @@ -8,7 +8,7 @@ namespace Nif void NiDynamicEffect::read(NIFStream* nif) { - Node::read(nif); + NiAVObject::read(nif); if (nif->getVersion() > NIFFile::VER_MW && nif->getVersion() < nif->generateVersion(10, 1, 0, 0)) return; diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index 06f85cd5d5..906a7fdedf 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -30,7 +30,7 @@ namespace Nif { // Abstract - struct NiDynamicEffect : public Node + struct NiDynamicEffect : public NiAVObject { bool mSwitchState{ true }; void read(NIFStream* nif) override; diff --git a/components/nif/node.cpp b/components/nif/node.cpp index fba0e1a69a..010a363436 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -75,51 +75,47 @@ namespace Nif } } - void Node::read(NIFStream* nif) + void NiAVObject::read(NIFStream* nif) { NiObjectNET::read(nif); - flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt(); - nif->read(trafo.mTranslation); - nif->read(trafo.mRotation); - nif->read(trafo.mScale); - + if (nif->getBethVersion() <= 26) + mFlags = nif->get(); + else + nif->read(mFlags); + nif->read(mTransform.mTranslation); + nif->read(mTransform.mRotation); + nif->read(mTransform.mScale); if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0)) - velocity = nif->getVector3(); + nif->read(mVelocity); if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) - readRecordList(nif, props); - - if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0)) - hasBounds = nif->getBoolean(); - if (hasBounds) - bounds.read(nif); - // Reference to the collision object in Gamebryo files. + readRecordList(nif, mProperties); + if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0) && nif->get()) + mBounds.read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) - collision.read(nif); - - parents.clear(); - - isBone = false; + mCollision.read(nif); } - void Node::post(Reader& nif) + void NiAVObject::post(Reader& nif) { NiObjectNET::post(nif); - postRecordList(nif, props); - collision.post(nif); + + postRecordList(nif, mProperties); + mCollision.post(nif); } - void Node::setBone() + void NiAVObject::setBone() { - isBone = true; + mIsBone = true; } void NiNode::read(NIFStream* nif) { - Node::read(nif); - readRecordList(nif, children); + NiAVObject::read(nif); + + readRecordList(nif, mChildren); if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) - readRecordList(nif, effects); + readRecordList(nif, mEffects); // FIXME: stopgap solution until we figure out what Oblivion does if it does anything if (nif->getVersion() > NIFFile::NIFVersion::VER_MW && nif->getVersion() < NIFFile::NIFVersion::VER_BGS) @@ -131,23 +127,24 @@ namespace Nif // FIXME: if node 0 is *not* the only root node, this must not happen. // FIXME: doing this here is awful. // We want to do this on world scene graph level rather than local scene graph level. - if (0 == recIndex && !Misc::StringUtils::ciEqual(mName, "bip01")) + if (recIndex == 0 && !Misc::StringUtils::ciEqual(mName, "bip01")) { - trafo = Nif::NiTransform::getIdentity(); + mTransform = Nif::NiTransform::getIdentity(); } } void NiNode::post(Reader& nif) { - Node::post(nif); - postRecordList(nif, children); - postRecordList(nif, effects); + NiAVObject::post(nif); - for (auto& child : children) + postRecordList(nif, mChildren); + postRecordList(nif, mEffects); + + for (auto& child : mChildren) { // Why would a unique list of children contain empty refs? if (!child.empty()) - child->parents.push_back(this); + child->mParents.push_back(this); } } @@ -171,7 +168,7 @@ namespace Nif void NiGeometry::read(NIFStream* nif) { - Node::read(nif); + NiAVObject::read(nif); data.read(nif); skin.read(nif); material.read(nif); @@ -185,7 +182,7 @@ namespace Nif void NiGeometry::post(Reader& nif) { - Node::post(nif); + NiAVObject::post(nif); data.post(nif); skin.post(nif); shaderprop.post(nif); @@ -224,7 +221,7 @@ namespace Nif void NiCamera::read(NIFStream* nif) { - Node::read(nif); + NiAVObject::read(nif); cam.read(nif); @@ -290,7 +287,7 @@ namespace Nif if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) mMode = nif->getUShort() & 0x7; else - mMode = (flags >> 5) & 0x3; + mMode = (mFlags >> 5) & 0x3; } void NiDefaultAVObjectPalette::read(NIFStream* nif) @@ -338,7 +335,7 @@ namespace Nif void BSTriShape::read(NIFStream* nif) { - Node::read(nif); + NiAVObject::read(nif); nif->read(mBoundingSphere); if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76) @@ -392,7 +389,7 @@ namespace Nif void BSTriShape::post(Reader& nif) { - Node::post(nif); + NiAVObject::post(nif); mSkin.post(nif); mShaderProperty.post(nif); mAlphaProperty.post(nif); diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 2a1fcd9af6..76651b05db 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -51,7 +51,7 @@ namespace Nif osg::Vec3f origin; }; - unsigned int type; + unsigned int type{ BASE_BV }; osg::BoundingSpheref sphere; NiBoxBV box; NiCapsuleBV capsule; @@ -66,11 +66,9 @@ namespace Nif { }; - /** A Node is an object that's part of the main NIF tree. It has - parent node (unless it's the root), and transformation (location - and rotation) relative to it's parent. - */ - struct Node : public NiObjectNET + // NiAVObject is an object that is a part of the main NIF tree. It has + // a parent node (unless it's the root) and transformation relative to its parent. + struct NiAVObject : public NiObjectNET { enum Flags { @@ -80,57 +78,48 @@ namespace Nif Flag_ActiveCollision = 0x0020 }; - // Node flags. Interpretation depends somewhat on the type of node. - unsigned int flags; - - NiTransform trafo; - osg::Vec3f velocity; // Unused? Might be a run-time game state - PropertyList props; - - // Bounding box info - bool hasBounds{ false }; - NiBoundingVolume bounds; - - // Collision object info - NiCollisionObjectPtr collision; + // Node flags. Interpretation depends on the record type. + uint32_t mFlags; + NiTransform mTransform; + osg::Vec3f mVelocity; + PropertyList mProperties; + NiBoundingVolume mBounds; + NiCollisionObjectPtr mCollision; + // Parent nodes for the node. Only types derived from NiNode can be parents. + std::vector mParents; + bool mIsBone{ false }; void read(NIFStream* nif) override; void post(Reader& nif) override; - // Parent node, or nullptr for the root node. As far as I'm aware, only - // NiNodes (or types derived from NiNodes) can be parents. - std::vector parents; - - bool isBone{ false }; - void setBone(); - - bool isHidden() const { return flags & Flag_Hidden; } - bool hasMeshCollision() const { return flags & Flag_MeshCollision; } - bool hasBBoxCollision() const { return flags & Flag_BBoxCollision; } - bool collisionActive() const { return flags & Flag_ActiveCollision; } + bool isHidden() const { return mFlags & Flag_Hidden; } + bool hasMeshCollision() const { return mFlags & Flag_MeshCollision; } + bool hasBBoxCollision() const { return mFlags & Flag_BBoxCollision; } + bool collisionActive() const { return mFlags & Flag_ActiveCollision; } }; - struct NiNode : Node + struct NiNode : NiAVObject { - NodeList children; - NodeList effects; - enum BSAnimFlags { AnimFlag_AutoPlay = 0x0020 }; + enum BSParticleFlags { ParticleFlag_AutoPlay = 0x0020, ParticleFlag_LocalSpace = 0x0080 }; + NiAVObjectList mChildren; + NiAVObjectList mEffects; + void read(NIFStream* nif) override; void post(Reader& nif) override; }; - struct NiGeometry : Node + struct NiGeometry : NiAVObject { /* Possible flags: 0x40 - mesh has no vertex normals ? @@ -176,7 +165,7 @@ namespace Nif { }; - struct NiCamera : Node + struct NiCamera : NiAVObject { struct Camera { @@ -234,7 +223,7 @@ namespace Nif void read(NIFStream* nif) override; - bool swing() const { return flags & Flag_Swing; } + bool swing() const { return mFlags & Flag_Swing; } }; // Abstract @@ -276,8 +265,8 @@ namespace Nif struct NiDefaultAVObjectPalette : Record { - NodePtr mScene; - std::unordered_map mObjects; + NiAVObjectPtr mScene; + std::unordered_map mObjects; void read(NIFStream* nif) override; void post(Reader& nif) override; @@ -285,7 +274,7 @@ namespace Nif struct BSTreeNode : NiNode { - NodeList mBones1, mBones2; + NiAVObjectList mBones1, mBones2; void read(NIFStream* nif) override; void post(Reader& nif) override; }; @@ -350,7 +339,7 @@ namespace Nif void read(NIFStream* nif, uint16_t flags); }; - struct BSTriShape : Node + struct BSTriShape : NiAVObject { osg::BoundingSpheref mBoundingSphere; std::array mBoundMinMax; @@ -397,5 +386,6 @@ namespace Nif void read(NIFStream* nif) override; }; -} // Namespace + +} #endif diff --git a/components/nif/physics.hpp b/components/nif/physics.hpp index a7bfa1425d..7c7c3df21e 100644 --- a/components/nif/physics.hpp +++ b/components/nif/physics.hpp @@ -374,7 +374,7 @@ namespace Nif struct NiCollisionObject : public Record { // The node that references this object - NodePtr mTarget; + NiAVObjectPtr mTarget; void read(NIFStream* nif) override { mTarget.read(nif); } void post(Reader& nif) override { mTarget.post(nif); } @@ -541,7 +541,7 @@ namespace Nif struct bhkCompressedMeshShape : public bhkShape { - NodePtr mTarget; + NiAVObjectPtr mTarget; uint32_t mUserData; float mRadius; osg::Vec4f mScale; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index eb704dbc21..9f75b31d74 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -110,7 +110,7 @@ namespace Nif value.post(nif); } - struct Node; + struct NiAVObject; struct Extra; struct Property; struct NiUVData; @@ -152,7 +152,7 @@ namespace Nif struct BSMultiBound; struct BSMultiBoundData; - using NodePtr = RecordPtrT; + using NiAVObjectPtr = RecordPtrT; using ExtraPtr = RecordPtrT; using NiUVDataPtr = RecordPtrT; using NiPosDataPtr = RecordPtrT; @@ -190,7 +190,7 @@ namespace Nif using BSMultiBoundPtr = RecordPtrT; using BSMultiBoundDataPtr = RecordPtrT; - using NodeList = RecordListT; + using NiAVObjectList = RecordListT; using PropertyList = RecordListT; using ExtraList = RecordListT; using NiSourceTextureList = RecordListT; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 31be54b030..bc207e52bf 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -132,13 +132,13 @@ namespace NifBullet mShape->mFileHash = nif.getHash(); const size_t numRoots = nif.numRoots(); - std::vector roots; + std::vector roots; for (size_t i = 0; i < numRoots; ++i) { const Nif::Record* r = nif.getRoot(i); if (!r) continue; - const Nif::Node* node = dynamic_cast(r); + const Nif::NiAVObject* node = dynamic_cast(r); if (node) roots.emplace_back(node); } @@ -151,7 +151,7 @@ namespace NifBullet } // Try to find a valid bounding box first. If one's found for any root node, use that. - for (const Nif::Node* node : roots) + for (const Nif::NiAVObject* node : roots) { if (findBoundingBox(*node, filename)) { @@ -175,15 +175,19 @@ namespace NifBullet // If there's no bounding box, we'll have to generate a Bullet collision shape // from the collision data present in every root node. - for (const Nif::Node* node : roots) + for (const Nif::NiAVObject* node : roots) { - bool hasCollisionNode = hasRootCollisionNode(*node); - bool hasCollisionShape = hasCollisionNode && !collisionShapeIsEmpty(*node); - if (hasCollisionNode && !hasCollisionShape) - mShape->mVisualCollisionType = Resource::VisualCollisionType::Camera; - bool generateCollisionShape = !hasCollisionShape; + const Nif::NiNode* colNode = findRootCollisionNode(*node); + bool hasCollisionShape = false; + if (colNode != nullptr) + { + if (colNode->mBounds.type == Nif::NiBoundingVolume::Type::BASE_BV && !colNode->mChildren.empty()) + hasCollisionShape = true; + else + mShape->mVisualCollisionType = Resource::VisualCollisionType::Camera; + } HandleNodeArgs args; - args.mAutogenerated = args.mIsCollisionNode = generateCollisionShape; + args.mAutogenerated = args.mIsCollisionNode = !hasCollisionShape; args.mAnimated = isAnimated; handleNode(filename, *node, nullptr, args, mShape->mVisualCollisionType); } @@ -199,79 +203,53 @@ namespace NifBullet // Find a boundingBox in the node hierarchy. // Return: use bounding box for collision? - bool BulletNifLoader::findBoundingBox(const Nif::Node& node, const std::string& filename) + bool BulletNifLoader::findBoundingBox(const Nif::NiAVObject& node, const std::string& filename) { - if (node.hasBounds) + unsigned int type = node.mBounds.type; + switch (type) { - unsigned int type = node.bounds.type; - switch (type) + case Nif::NiBoundingVolume::Type::BASE_BV: + break; + case Nif::NiBoundingVolume::Type::BOX_BV: + mShape->mCollisionBox.mExtents = node.mBounds.box.extents; + mShape->mCollisionBox.mCenter = node.mBounds.box.center; + break; + default: { - case Nif::NiBoundingVolume::Type::BOX_BV: - mShape->mCollisionBox.mExtents = node.bounds.box.extents; - mShape->mCollisionBox.mCenter = node.bounds.box.center; - break; - default: - { - std::stringstream warning; - warning << "Unsupported NiBoundingVolume type " << type << " in node " << node.recIndex; - warning << " in file " << filename; - warn(warning.str()); - } - } - - if (node.hasBBoxCollision()) - { - return true; + std::stringstream warning; + warning << "Unsupported NiBoundingVolume type " << type << " in node " << node.recIndex; + warning << " in file " << filename; + warn(warning.str()); } } + if (type != Nif::NiBoundingVolume::Type::BASE_BV && node.hasBBoxCollision()) + return true; + if (const Nif::NiNode* ninode = dynamic_cast(&node)) { - const Nif::NodeList& list = ninode->children; - for (const auto& child : list) + for (const auto& child : ninode->mChildren) if (!child.empty() && findBoundingBox(child.get(), filename)) return true; } return false; } - bool BulletNifLoader::hasRootCollisionNode(const Nif::Node& rootNode) const + const Nif::NiNode* BulletNifLoader::findRootCollisionNode(const Nif::NiAVObject& rootNode) const { if (const Nif::NiNode* ninode = dynamic_cast(&rootNode)) { - for (const auto& child : ninode->children) + for (const auto& child : ninode->mChildren) { - if (child.empty()) - continue; - if (child.getPtr()->recType == Nif::RC_RootCollisionNode) - return true; + if (!child.empty() && child.getPtr()->recType == Nif::RC_RootCollisionNode) + return static_cast(child.getPtr()); } } - return false; + return nullptr; } - bool BulletNifLoader::collisionShapeIsEmpty(const Nif::Node& rootNode) const - { - if (const Nif::NiNode* ninode = dynamic_cast(&rootNode)) - { - for (const auto& child : ninode->children) - { - if (child.empty()) - continue; - const Nif::Node* childNode = child.getPtr(); - if (childNode->recType != Nif::RC_RootCollisionNode) - continue; - const Nif::NiNode* niChildnode - = static_cast(childNode); // RootCollisionNode is always a NiNode - if (childNode->hasBounds || niChildnode->children.size() > 0) - return false; - } - } - return true; - } - - void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent, - HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType) + void BulletNifLoader::handleNode(const std::string& fileName, const Nif::NiAVObject& node, + const Nif::Parent* parent, HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType) { // TODO: allow on-the fly collision switching via toggling this flag if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive()) @@ -354,10 +332,10 @@ namespace NifBullet if (args.mIsCollisionNode) { - // NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape! + // NOTE: a trishape with bounds, but no BBoxCollision flag should NOT go through handleNiTriShape! // It must be ignored completely. // (occurs in tr_ex_imp_wall_arch_04.nif) - if (!node.hasBounds + if (node.mBounds.type == Nif::NiBoundingVolume::Type::BASE_BV && (node.recType == Nif::RC_NiTriShape || node.recType == Nif::RC_NiTriStrips || node.recType == Nif::RC_BSLODTriShape)) { @@ -368,14 +346,13 @@ namespace NifBullet // For NiNodes, loop through children if (const Nif::NiNode* ninode = dynamic_cast(&node)) { - const Nif::NodeList& list = ninode->children; const Nif::Parent currentParent{ *ninode, parent }; - for (const auto& child : list) + for (const auto& child : ninode->mChildren) { if (child.empty()) continue; - assert(std::find(child->parents.begin(), child->parents.end(), ninode) != child->parents.end()); + assert(std::find(child->mParents.begin(), child->mParents.end(), ninode) != child->mParents.end()); handleNode(fileName, child.get(), ¤tParent, args, visualCollisionType); } } @@ -403,9 +380,9 @@ namespace NifBullet auto childShape = std::make_unique(childMesh.get(), true); std::ignore = childMesh.release(); - osg::Matrixf transform = niGeometry.trafo.toMatrix(); + osg::Matrixf transform = niGeometry.mTransform.toMatrix(); for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent) - transform *= parent->mNiNode.trafo.toMatrix(); + transform *= parent->mNiNode.mTransform.toMatrix(); childShape->setLocalScaling(Misc::Convert::toBullet(transform.getScale())); transform.orthoNormalize(transform); diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index c70eb997fa..819ba34b34 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -22,10 +22,8 @@ class btCollisionShape; namespace Nif { - struct Node; - struct Transformation; - struct NiTriShape; - struct NiTriStrips; + struct NiAVObject; + struct NiNode; struct NiGeometry; struct Parent; } @@ -50,7 +48,7 @@ namespace NifBullet osg::ref_ptr load(Nif::FileView file); private: - bool findBoundingBox(const Nif::Node& node, const std::string& filename); + bool findBoundingBox(const Nif::NiAVObject& node, const std::string& filename); struct HandleNodeArgs { @@ -61,11 +59,10 @@ namespace NifBullet bool mAvoid{ false }; }; - void handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent, + void handleNode(const std::string& fileName, const Nif::NiAVObject& node, const Nif::Parent* parent, HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType); - bool hasRootCollisionNode(const Nif::Node& rootNode) const; - bool collisionShapeIsEmpty(const Nif::Node& rootNode) const; + const Nif::NiNode* findRootCollisionNode(const Nif::NiAVObject& rootNode) const; void handleNiTriShape(const Nif::NiGeometry& nifNode, const Nif::Parent* parent, HandleNodeArgs args); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 1a595a3ab5..9683de9a23 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -76,12 +76,12 @@ namespace void apply(osg::Drawable& node) override { traverse(node); } }; - void getAllNiNodes(const Nif::Node* node, std::vector& outIndices) + void getAllNiNodes(const Nif::NiAVObject* node, std::vector& outIndices) { if (const Nif::NiNode* ninode = dynamic_cast(node)) { outIndices.push_back(ninode->recIndex); - for (const auto& child : ninode->children) + for (const auto& child : ninode->mChildren) if (!child.empty()) getAllNiNodes(child.getPtr(), outIndices); } @@ -103,11 +103,11 @@ namespace // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the // node hierarchy above it. void collectDrawableProperties( - const Nif::Node* nifNode, const Nif::Parent* parent, std::vector& out) + const Nif::NiAVObject* nifNode, const Nif::Parent* parent, std::vector& out) { if (parent != nullptr) collectDrawableProperties(&parent->mNiNode, parent->mParent, out); - for (const auto& property : nifNode->props) + for (const auto& property : nifNode->mProperties) { if (!property.empty()) { @@ -345,13 +345,13 @@ namespace NifOsg osg::ref_ptr load(Nif::FileView nif, Resource::ImageManager* imageManager) { const size_t numRoots = nif.numRoots(); - std::vector roots; + std::vector roots; for (size_t i = 0; i < numRoots; ++i) { const Nif::Record* r = nif.getRoot(i); if (!r) continue; - const Nif::Node* nifNode = dynamic_cast(r); + const Nif::NiAVObject* nifNode = dynamic_cast(r); if (nifNode) roots.emplace_back(nifNode); } @@ -362,7 +362,7 @@ namespace NifOsg osg::ref_ptr created(new osg::Group); created->setDataVariance(osg::Object::STATIC); - for (const Nif::Node* root : roots) + for (const Nif::NiAVObject* root : roots) { auto node = handleNode(root, nullptr, nullptr, { .mNifVersion = nif.getVersion(), @@ -397,13 +397,13 @@ namespace NifOsg return created; } - void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, + void applyNodeProperties(const Nif::NiAVObject* nifNode, osg::Node* applyTo, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, std::vector& boundTextures, int animflags) { bool hasStencilProperty = false; - for (const auto& property : nifNode->props) + for (const auto& property : nifNode->mProperties) { if (property.empty()) continue; @@ -420,13 +420,13 @@ namespace NifOsg } } - for (const auto& property : nifNode->props) + for (const auto& property : nifNode->mProperties) { if (!property.empty()) { // Get the lowest numbered recIndex of the NiTexturingProperty root node. // This is what is overridden when a spell effect "particle texture" is used. - if (nifNode->parents.empty() && !mFoundFirstRootTexturingProperty + if (nifNode->mParents.empty() && !mFoundFirstRootTexturingProperty && property.getPtr()->recType == Nif::RC_NiTexturingProperty) { mFirstRootTextureIndex = property.getPtr()->recIndex; @@ -482,23 +482,23 @@ namespace NifOsg return switchNode; } - static osg::ref_ptr prepareSequenceNode(const Nif::Node* nifNode) + static osg::ref_ptr prepareSequenceNode(const Nif::NiAVObject* nifNode) { const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast(nifNode); osg::ref_ptr sequenceNode(new osg::Sequence); sequenceNode->setName(niFltAnimationNode->mName); - if (!niFltAnimationNode->children.empty()) + if (!niFltAnimationNode->mChildren.empty()) { if (niFltAnimationNode->swing()) sequenceNode->setDefaultTime( - niFltAnimationNode->mDuration / (niFltAnimationNode->children.size() * 2)); + niFltAnimationNode->mDuration / (niFltAnimationNode->mChildren.size() * 2)); else - sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->children.size()); + sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->mChildren.size()); } return sequenceNode; } - static void activateSequenceNode(osg::Group* osgNode, const Nif::Node* nifNode) + static void activateSequenceNode(osg::Group* osgNode, const Nif::NiAVObject* nifNode) { const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast(nifNode); osg::Sequence* sequenceNode = static_cast(osgNode); @@ -535,7 +535,7 @@ namespace NifOsg texture->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); } - bool handleEffect(const Nif::Node* nifNode, osg::StateSet* stateset, Resource::ImageManager* imageManager) + bool handleEffect(const Nif::NiAVObject* nifNode, osg::StateSet* stateset, Resource::ImageManager* imageManager) { if (nifNode->recType != Nif::RC_NiTextureEffect) { @@ -596,7 +596,7 @@ namespace NifOsg } // Get a default dataVariance for this node to be used as a hint by optimization (post)routines - osg::ref_ptr createNode(const Nif::Node* nifNode) + osg::ref_ptr createNode(const Nif::NiAVObject* nifNode) { osg::ref_ptr node; osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED; @@ -611,15 +611,15 @@ namespace NifOsg // This takes advantage of the fact root nodes can't have additional controllers // loaded from an external .kf file (original engine just throws "can't find node" errors if you // try). - if (nifNode->parents.empty() && nifNode->mController.empty() && nifNode->trafo.isIdentity()) + if (nifNode->mParents.empty() && nifNode->mController.empty() && nifNode->mTransform.isIdentity()) node = new osg::Group; - dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC; + dataVariance = nifNode->mIsBone ? osg::Object::DYNAMIC : osg::Object::STATIC; break; } if (!node) - node = new NifOsg::MatrixTransform(nifNode->trafo); + node = new NifOsg::MatrixTransform(nifNode->mTransform); node->setDataVariance(dataVariance); @@ -627,7 +627,7 @@ namespace NifOsg } osg::ref_ptr handleNode( - const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args) + const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args) { if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->mName, "Bounding Box")) return nullptr; @@ -692,7 +692,7 @@ namespace NifOsg } if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode) - args.mAnimFlags = nifNode->flags; + args.mAnimFlags = nifNode->mFlags; if (nifNode->recType == Nif::RC_NiSortAdjustNode) { @@ -829,7 +829,7 @@ namespace NifOsg const Nif::NiNode* ninode = dynamic_cast(nifNode); if (ninode) { - const Nif::NodeList& children = ninode->children; + const Nif::NiAVObjectList& children = ninode->mChildren; const Nif::Parent currentParent{ *ninode, parent }; for (const auto& child : children) if (!child.empty()) @@ -838,7 +838,7 @@ namespace NifOsg // Propagate effects to the the direct subgraph instead of the node itself // This simulates their "affected node list" which Morrowind appears to replace with the subgraph (?) // Note that the serialized affected node list is actually unused - for (const auto& effect : ninode->effects) + for (const auto& effect : ninode->mEffects) if (!effect.empty()) { osg::ref_ptr effectStateSet = new osg::StateSet; @@ -854,7 +854,7 @@ namespace NifOsg return node; } - void handleMeshControllers(const Nif::Node* nifNode, osg::Node* node, + void handleMeshControllers(const Nif::NiAVObject* nifNode, osg::Node* node, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { @@ -883,7 +883,7 @@ namespace NifOsg } } - void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated) + void handleNodeControllers(const Nif::NiAVObject* nifNode, osg::Node* node, int animflags, bool& isAnimated) { for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) { @@ -1121,7 +1121,7 @@ namespace NifOsg // Load the initial state of the particle system, i.e. the initial particles and their positions, velocity and // colors. void handleParticleInitialState( - const Nif::Node* nifNode, ParticleSystem* partsys, const Nif::NiParticleSystemController* partctrl) + const Nif::NiAVObject* nifNode, ParticleSystem* partsys, const Nif::NiParticleSystemController* partctrl) { auto particleNode = static_cast(nifNode); if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData) @@ -1247,7 +1247,7 @@ namespace NifOsg mEmitterQueue.clear(); } - void handleParticleSystem(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, + void handleParticleSystem(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags) { osg::ref_ptr partsys(new ParticleSystem); @@ -1375,7 +1375,7 @@ namespace NifOsg } } - void handleNiGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Geometry* geometry, + void handleNiGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Geometry* geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { @@ -1474,7 +1474,7 @@ namespace NifOsg applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->mColors.empty(), animflags); } - void handleGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, + void handleGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { @@ -1530,7 +1530,7 @@ namespace NifOsg return morphGeom; } - void handleSkinnedGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, + void handleSkinnedGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { @@ -1548,7 +1548,7 @@ namespace NifOsg const Nif::NiSkinInstance* skin = static_cast(nifNode)->skin.getPtr(); const Nif::NiSkinData* data = skin->mData.getPtr(); - const Nif::NodeList& bones = skin->mBones; + const Nif::NiAVObjectList& bones = skin->mBones; for (std::size_t i = 0; i < bones.size(); ++i) { std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName); From 4dd2f34e3088307ac45dd45f29a44f351a0e3e7d Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 10 Sep 2023 09:20:06 +0300 Subject: [PATCH 6/6] Fix Windows build --- components/nif/node.cpp | 2 +- components/nif/node.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/nif/node.cpp b/components/nif/node.cpp index 010a363436..d7b6c3945b 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -12,7 +12,7 @@ namespace Nif { void NiBoundingVolume::read(NIFStream* nif) { - type = nif->getUInt(); + nif->read(type); switch (type) { case BASE_BV: diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 76651b05db..51781a5290 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -15,7 +15,7 @@ namespace Nif struct NiBoundingVolume { - enum Type + enum Type : uint32_t { BASE_BV = 0xFFFFFFFF, SPHERE_BV = 0, @@ -51,7 +51,7 @@ namespace Nif osg::Vec3f origin; }; - unsigned int type{ BASE_BV }; + uint32_t type{ BASE_BV }; osg::BoundingSpheref sphere; NiBoxBV box; NiCapsuleBV capsule;