diff --git a/examples/osganimationmorph/osganimationmorph.cpp b/examples/osganimationmorph/osganimationmorph.cpp index 8506bb49f..01143b880 100644 --- a/examples/osganimationmorph/osganimationmorph.cpp +++ b/examples/osganimationmorph/osganimationmorph.cpp @@ -107,7 +107,9 @@ int main (int argc, char* argv[]) osg::Geode* geode = new osg::Geode; geode->addDrawable(morph); - geode->addUpdateCallback(new osgAnimation::UpdateMorph("MorphNodeCallback")); + osgAnimation::UpdateMorph* morphupdate=new osgAnimation::UpdateMorph("MorphNodeCallback"); + morphupdate->addTarget("MorphNodeCallback"); + geode->addUpdateCallback(morphupdate); scene->addChild(geode); viewer.addEventHandler(new osgViewer::StatsHandler()); diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 15ad85087..565e070f1 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -18,6 +18,7 @@ #include #include #include +#include namespace osgAnimation { @@ -81,6 +82,25 @@ namespace osgAnimation */ virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) { _morphTargets.push_back(MorphTarget(morphTarget, weight)); _dirty = true; } + virtual void removeMorphTarget( osg::Geometry *morphTarget ) { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { + if(iterator->getGeometry() == morphTarget) { + _morphTargets.erase(iterator); + break; + } + } + } + + virtual void removeMorphTarget( const std::string& name ) { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { + if(iterator->getGeometry() && iterator->getGeometry()->getName() == name) { + _morphTargets.erase(iterator); + break; + } + } + + } + void setWeight(unsigned int index, float morphWeight) { if (index < _morphTargets.size()) @@ -121,20 +141,41 @@ namespace osgAnimation class OSGANIMATION_EXPORT UpdateMorph : public AnimationUpdateCallback { - protected: - std::map > _weightTargets; - public: + typedef std::vector TargetNames; + typedef std::map< int, osg::ref_ptr > WeightTargets; META_Object(osgAnimation, UpdateMorph); UpdateMorph(const std::string& name = ""); UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop); + void addTarget(const std::string& name) { _targetNames.push_back(name); } + unsigned int getNumTarget() const { return _targetNames.size(); } + const std::string& getTargetName(unsigned int index) { return _targetNames[index]; } + void removeTarget(const std::string& name) { + TargetNames::iterator found = std::find(_targetNames.begin(), _targetNames.end(), name); + if(found != _targetNames.end()) + _targetNames.erase(found); + } + + // for serialization + const std::vector& getTargetNames() const { return _targetNames; } + std::vector& getTargetNames() { return _targetNames; } + + void setTargetNames(const TargetNames& targetNames) { + _targetNames.assign(targetNames.begin(), targetNames.end()); + } + /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); bool needLink() const; bool link(osgAnimation::Channel* channel); + int link(Animation* animation); + + protected: + WeightTargets _weightTargets; + TargetNames _targetNames; }; struct UpdateMorphGeometry : public osg::DrawableUpdateCallback diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 88c40b56f..7d8213654 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -56,6 +56,7 @@ MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) setUseVertexBufferObjects(true); } + void MorphGeometry::transformSoftwareMethod() { if (_dirty) @@ -279,3 +280,29 @@ bool UpdateMorph::link(osgAnimation::Channel* channel) } return false; } + +int UpdateMorph::link(Animation* animation) +{ + if (getNumTarget() == 0) + { + osg::notify(osg::WARN) << "An update callback has no name, it means it could link only with \"\" named Target, often an error, discard" << std::endl; + return 0; + } + + unsigned int nbLinks = 0; + for (ChannelList::iterator channel = animation->getChannels().begin(); + channel != animation->getChannels().end(); + ++channel) + { + std::string targetName = (*channel)->getTargetName(); + for(int i = 0, num = getNumTarget(); i < num; ++i) { + if (targetName == getTargetName(i)) + { + AnimationUpdateCallbackBase* a = this; + a->link((*channel).get()); + nbLinks++; + } + } + } + return nbLinks; +}