diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index bba1d8c288..72654da6de 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -170,6 +170,17 @@ namespace NifOsg class CollisionSwitch : public osg::MatrixTransform { public: + CollisionSwitch() : osg::MatrixTransform() + { + } + + CollisionSwitch(const CollisionSwitch& copy, const osg::CopyOp& copyop) + : osg::MatrixTransform(copy, copyop) + { + } + + META_Node(NifOsg, CollisionSwitch) + CollisionSwitch(const osg::Matrixf& transformations, bool enabled) : osg::MatrixTransform(transformations) { setEnabled(enabled); @@ -478,17 +489,8 @@ namespace NifOsg osg::ref_ptr node; osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED; - // TODO: it is unclear how to handle transformations of LOD nodes and controllers for them. switch (nifNode->recType) { - case Nif::RC_NiLODNode: - { - const Nif::NiLODNode* niLodNode = static_cast(nifNode); - node = handleLodNode(niLodNode); - dataVariance = osg::Object::DYNAMIC; - break; - } - case Nif::RC_NiSwitchNode: case Nif::RC_NiAutoNormalParticles: case Nif::RC_NiRotatingParticles: // Leaf nodes in the NIF hierarchy, so won't be able to dynamically attach children. @@ -669,6 +671,11 @@ namespace NifOsg && !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC) handleNodeControllers(nifNode, static_cast(node.get()), animflags); + // LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly + // and we need to attach their children to the osg::LOD/osg::Switch nodes + // but we must return that transform to the caller of handleNode instead of the actual LOD/Switch nodes. + osg::ref_ptr currentNode = node; + if (nifNode->recType == Nif::RC_NiSwitchNode) { const Nif::NiSwitchNode* niSwitchNode = static_cast(nifNode); @@ -679,7 +686,14 @@ namespace NifOsg else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel)) rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel); - node = switchNode; + currentNode = switchNode; + } + else if (nifNode->recType == Nif::RC_NiLODNode) + { + const Nif::NiLODNode* niLodNode = static_cast(nifNode); + osg::ref_ptr lodNode = handleLodNode(niLodNode); + node->addChild(lodNode); + currentNode = lodNode; } const Nif::NiNode *ninode = dynamic_cast(nifNode); @@ -689,14 +703,14 @@ namespace NifOsg for (size_t i = 0; i < effects.length(); ++i) { if (!effects[i].empty()) - handleEffect(effects[i].getPtr(), node, imageManager); + handleEffect(effects[i].getPtr(), currentNode, imageManager); } const Nif::NodeList &children = ninode->children; for(size_t i = 0;i < children.length();++i) { if(!children[i].empty()) - handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, isAnimated, textKeys, rootNode); + handleNode(children[i].getPtr(), currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, isAnimated, textKeys, rootNode); } } diff --git a/components/sceneutil/optimizer.cpp b/components/sceneutil/optimizer.cpp index e8ebed8686..487126627c 100644 --- a/components/sceneutil/optimizer.cpp +++ b/components/sceneutil/optimizer.cpp @@ -735,20 +735,6 @@ bool Optimizer::CombineStaticTransformsVisitor::removeTransforms(osg::Node* node // RemoveEmptyNodes. //////////////////////////////////////////////////////////////////////////// -void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Switch& switchNode) -{ - // We should keep all switch child nodes since they reflect different switch states. - for (unsigned int i=0; i0) @@ -787,8 +773,11 @@ void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes() ++pitr) { osg::Group* parent = *pitr; - parent->removeChild(nodeToRemove.get()); - if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent); + if (!parent->asSwitch() && !dynamic_cast(parent)) + { + parent->removeChild(nodeToRemove.get()); + if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent); + } } } diff --git a/components/sceneutil/optimizer.hpp b/components/sceneutil/optimizer.hpp index 9974e70974..6dd4394d18 100644 --- a/components/sceneutil/optimizer.hpp +++ b/components/sceneutil/optimizer.hpp @@ -321,8 +321,6 @@ class Optimizer BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} virtual void apply(osg::Group& group); - virtual void apply(osg::LOD& lod); - virtual void apply(osg::Switch& switchNode); void removeEmptyNodes(); diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index f84a19876c..60f096a724 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -131,6 +131,7 @@ void registerSerializers() "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController", "NifOsg::UpdateMorphGeometry", + "NifOsg::CollisionSwitch", "osgMyGUI::Drawable", "osg::DrawCallback", "osgOQ::ClearQueriesCallback",