diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index a2311be49..2361718b1 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -929,10 +929,8 @@ namespace mNiStringExtraData.string = "MRK"; mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); - mNiNode3.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNiTriShape)})); - mNiNode3.recType = Nif::RC_RootCollisionNode; - mNiNode2.children = Nif::NodeList(std::vector({Nif::NodePtr(nullptr), Nif::NodePtr(&mNiNode3)})); - mNiNode2.recType = Nif::RC_NiNode; + mNiNode2.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNiTriShape)})); + mNiNode2.recType = Nif::RC_RootCollisionNode; mNiNode.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNiNode2)})); mNiNode.recType = Nif::RC_NiNode; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 7b206e40c..20307f252 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -96,17 +96,14 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) } else { + bool autogenerated = hasAutoGeneratedCollision(node); + // files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see Animation::addAnimSource). // assume all nodes in the file will be animated const auto filename = nif.getFilename(); const bool isAnimated = pathFileNameStartsWithX(filename); - // If the mesh has RootCollisionNode, attached to actual root node, use it as collision mesh - const Nif::Node* rootCollisionNode = getCollisionNode(node); - if (rootCollisionNode) - handleNode(filename, rootCollisionNode, 0, false, isAnimated, false); - else - handleNode(filename, node, 0, true, isAnimated, true); + handleNode(filename, node, 0, autogenerated, isAnimated, autogenerated); if (mCompoundShape) { @@ -163,31 +160,22 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node, int flags) return false; } -const Nif::Node* BulletNifLoader::getCollisionNode(const Nif::Node* rootNode) +bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node* rootNode) { const Nif::NiNode *ninode = dynamic_cast(rootNode); if(ninode) { - // If root NiNode has only other NiNode as child, consider it as a wrapper, not as actual root node const Nif::NodeList &list = ninode->children; - if (list.length() == 1 && - rootNode->recType == Nif::RC_NiNode && - list[0].getPtr()->recType == Nif::RC_NiNode) + for(size_t i = 0;i < list.length();i++) { - return getCollisionNode(list[0].getPtr()); - } - - for(size_t i = 0; i < list.length(); i++) - { - if(list[i].empty()) - continue; - - const Nif::Node* childNode = list[i].getPtr(); - if(childNode->recType == Nif::RC_RootCollisionNode) - return childNode; + if(!list[i].empty()) + { + if(list[i].getPtr()->recType == Nif::RC_RootCollisionNode) + return false; + } } } - return nullptr; + return true; } void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *node, int flags, @@ -203,13 +191,14 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode); - if (node->recType == Nif::RC_RootCollisionNode && autogenerated) - Log(Debug::Info) << "Found RootCollisionNode attached to non-root node in " << fileName << ". Treat it as a common NiTriShape."; - // Don't collide with AvoidNode shapes if(node->recType == Nif::RC_AvoidNode) flags |= 0x800; + // We encountered a RootCollisionNode inside autogenerated mesh. It is not right. + if (node->recType == Nif::RC_RootCollisionNode && autogenerated) + Log(Debug::Info) << "Found RootCollisionNode attached to non-root node in " << fileName << ". Treat it as a common NiTriShape."; + // Check for extra data Nif::Extra const *e = node; while (!e->extra.empty()) @@ -234,6 +223,7 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n // Marker can still have collision if the model explicitely specifies it via a RootCollisionNode. return; } + } } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index f970b7f3e..f67ab402e 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -57,7 +57,7 @@ private: void handleNode(const std::string& fileName, Nif::Node const *node, int flags, bool isCollisionNode, bool isAnimated=false, bool autogenerated=false); - const Nif::Node* getCollisionNode(const Nif::Node* rootNode); + bool hasAutoGeneratedCollision(const Nif::Node *rootNode); void handleNiTriShape(const Nif::NiTriShape *shape, int flags, const osg::Matrixf& transform, bool isAnimated);