diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 285719eef..bdd104b3d 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -356,7 +356,7 @@ namespace NifOsg osg::ref_ptr textkeys (new TextKeyMapHolder); - osg::ref_ptr created = handleNode(nifNode, NULL, imageManager, std::vector(), 0, false, &textkeys->mTextKeys); + osg::ref_ptr created = handleNode(nifNode, NULL, imageManager, std::vector(), 0, false, false, &textkeys->mTextKeys); if (nif->getUseSkinning()) { @@ -511,15 +511,12 @@ namespace NifOsg stateset->addUniform(new osg::Uniform("envMapColor", osg::Vec4f(1,1,1,1))); } - osg::ref_ptr handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager, - std::vector boundTextures, int animflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL) + // Get a default dataVariance for this node to be used as a hint by optimization (post)routines + osg::Object::DataVariance getDataVariance(const Nif::Node* nifNode) { - if (rootNode != NULL && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box")) - return NULL; - - osg::ref_ptr node = new osg::MatrixTransform(nifNode->trafo.toMatrix()); + if (nifNode->boneTrafo || nifNode->boneIndex != -1) + return osg::Object::DYNAMIC; - // Set a default DataVariance (used as hint by optimization routines). switch (nifNode->recType) { case Nif::RC_NiTriShape: @@ -527,15 +524,29 @@ namespace NifOsg case Nif::RC_NiRotatingParticles: // Leaf nodes in the NIF hierarchy, so won't be able to dynamically attach children. // No support for keyframe controllers (just crashes in the original engine). - if (nifNode->trafo.isIdentity()) - node = new osg::Group; - node->setDataVariance(osg::Object::STATIC); - break; + return osg::Object::STATIC; default: - // could have new children attached at any time, or added external keyframe controllers from .kf files - node->setDataVariance(osg::Object::DYNAMIC); - break; + return osg::Object::DYNAMIC; } + } + + osg::ref_ptr handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager, + std::vector boundTextures, int animflags, bool skipMeshes, bool isAnimated, TextKeyMap* textKeys, osg::Node* rootNode=NULL) + { + if (rootNode != NULL && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box")) + return NULL; + + osg::Object::DataVariance dataVariance = getDataVariance(nifNode); + + osg::ref_ptr node; + if (dataVariance == osg::Object::STATIC && nifNode->trafo.isIdentity()) + node = new osg::Group; + else + node = new osg::MatrixTransform(nifNode->trafo.toMatrix()); + node->setDataVariance(dataVariance); + + if (nifNode->controller.empty()) + node->setDataVariance(osg::Object::STATIC); if (nifNode->recType == Nif::RC_NiBillboardNode) { @@ -550,6 +561,9 @@ namespace NifOsg node->setDataVariance(osg::Object::STATIC); } + if (!nifNode->controller.empty() && nifNode->controller->recType == Nif::RC_NiKeyframeController) + isAnimated = true; + node->setName(nifNode->name); if (parentNode) @@ -599,6 +613,11 @@ namespace NifOsg node->setNodeMask(0x1); } + if (skipMeshes && isAnimated) // make sure the empty node is not optimized away so the physicssystem can find it. + { + node->setDataVariance(osg::Object::DYNAMIC); + } + // We can skip creating meshes for hidden nodes if they don't have a VisController that // might make them visible later if (nifNode->flags & Nif::NiNode::Flag_Hidden) @@ -665,7 +684,7 @@ namespace NifOsg for(size_t i = 0;i < children.length();++i) { if(!children[i].empty()) - handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, textKeys, rootNode); + handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, isAnimated, textKeys, rootNode); } }