From bd88758962628219f1912a12bd96b52f423e1028 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 21 Apr 2015 18:52:13 +0200 Subject: [PATCH] Use the new skinning system in OpenMW --- components/nifosg/skeleton.cpp | 3 +- components/sceneutil/attach.cpp | 136 ++++--------------------------- components/sceneutil/visitor.hpp | 9 +- 3 files changed, 24 insertions(+), 124 deletions(-) diff --git a/components/nifosg/skeleton.cpp b/components/nifosg/skeleton.cpp index 26c6e80b3..2e00eb76e 100644 --- a/components/nifosg/skeleton.cpp +++ b/components/nifosg/skeleton.cpp @@ -39,7 +39,8 @@ Skeleton::Skeleton() } Skeleton::Skeleton(const Skeleton ©, const osg::CopyOp ©op) - : mBoneCacheInit(false) + : osg::Group(copy, copyop) + , mBoneCacheInit(false) , mNeedToUpdateBoneMatrices(true) { diff --git a/components/sceneutil/attach.cpp b/components/sceneutil/attach.cpp index 26185eb3e..b88bddc8d 100644 --- a/components/sceneutil/attach.cpp +++ b/components/sceneutil/attach.cpp @@ -8,155 +8,55 @@ #include #include #include - -#include -#include +#include #include +#include + #include "visitor.hpp" namespace SceneUtil { - class NodeMapVisitor : public osg::NodeVisitor - { - public: - NodeMapVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} - - void apply(osg::MatrixTransform& trans) - { - mMap[trans.getName()] = &trans; - traverse(trans); - } - - typedef std::map > NodeMap; - - const NodeMap& getNodeMap() const - { - return mMap; - } - - private: - NodeMap mMap; - }; - - /// Copy the matrix of a "source" node to a "dest" node (the node that the callback is attached to). - /// Must be set on a MatrixTransform. - class CopyController : public osg::NodeCallback - { - public: - CopyController(osg::MatrixTransform* copyFrom) - : mCopyFrom(copyFrom) - { - } - CopyController(const CopyController& copy, const osg::CopyOp& copyop) - : osg::NodeCallback(copy, copyop) - , mCopyFrom(copy.mCopyFrom) - { - } - CopyController() - : mCopyFrom(NULL) - { - } - - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) - { - osgAnimation::Bone* bone = static_cast(node); - - if (mCopyFrom) - { - bone->setMatrix(mCopyFrom->getMatrix()); - } - - traverse(node, nv); - } - - private: - const osg::MatrixTransform* mCopyFrom; - }; - - class AddCopyControllerVisitor : public osg::NodeVisitor + class CopyRigVisitor : public osg::NodeVisitor { public: - AddCopyControllerVisitor(const NodeMapVisitor::NodeMap& boneMap) - : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) - , mNodeMap(boneMap) - { - } - - virtual void apply(osg::MatrixTransform &node) - { - if (osgAnimation::Bone* bone = dynamic_cast(&node)) - { - NodeMapVisitor::NodeMap::const_iterator found = mNodeMap.find(bone->getName()); - if (found != mNodeMap.end()) - { - // add the CopyController at position 0 so it's executed before UpdateBone - osg::ref_ptr old = bone->getUpdateCallback(); - bone->setUpdateCallback(new CopyController(found->second.get())); - bone->addUpdateCallback(old); - } - } - traverse(node); - } - - private: - const NodeMapVisitor::NodeMap& mNodeMap; - }; - - // FIXME: would be more efficient to copy only the wanted nodes instead of deleting unwanted ones later - // copying is kinda cheap though, so don't bother for now - class FilterVisitor : public osg::NodeVisitor - { - public: - FilterVisitor(const std::string& filter) + CopyRigVisitor(osg::ref_ptr parent, const std::string& filter) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + , mParent(parent) , mFilter(Misc::StringUtils::lowerCase(filter)) { } - virtual void apply(osg::Geode &node) + virtual void apply(osg::Node& node) { std::string lowerName = Misc::StringUtils::lowerCase(node.getName()); - if (lowerName.find(mFilter) == std::string::npos) + if (lowerName.find(mFilter) != std::string::npos) { - mToRemove.push_back(&node); - } - } - - void removeFilteredParts() - { - for (std::vector::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it) - { - osg::Geode* geode = *it; - geode->getParent(0)->removeChild(geode); + mParent->addChild(&node); } + else + traverse(node); } private: - std::vector mToRemove; + osg::ref_ptr mParent; std::string mFilter; }; osg::ref_ptr attach(osg::ref_ptr toAttach, osg::Node *master, const std::string &filter, const std::string &attachNode) { - if (osgAnimation::Skeleton* skel = dynamic_cast(toAttach.get())) + if (dynamic_cast(toAttach.get())) { - NodeMapVisitor nodeMapVisitor; - master->accept(nodeMapVisitor); + osg::ref_ptr handle = new osg::Group; - // would be more efficient if we could attach the RigGeometry directly to the master skeleton, but currently not possible - // due to a difference in binding pose of the two skeletons - AddCopyControllerVisitor visitor(nodeMapVisitor.getNodeMap()); - toAttach->accept(visitor); + CopyRigVisitor copyVisitor(handle, filter); + toAttach->accept(copyVisitor); - FilterVisitor filterVisitor(filter); - toAttach->accept(filterVisitor); - filterVisitor.removeFilteredParts(); + master->asGroup()->addChild(handle); - master->asGroup()->addChild(skel); - return skel; + return handle; } else { diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index d26f95116..6bb8b2e35 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -17,15 +17,14 @@ namespace SceneUtil { } - virtual void apply(osg::Node &node) + virtual void apply(osg::Group& group) { - osg::Group* group = node.asGroup(); - if (group && node.getName() == mNameToFind) + if (group.getName() == mNameToFind) { - mFoundNode = group; + mFoundNode = &group; return; } - traverse(node); + traverse(group); } std::string mNameToFind;