From 4372ec3cba0ed87ac5d14ab55901cbc6d3896603 Mon Sep 17 00:00:00 2001 From: Cedric Pinson Date: Wed, 21 Oct 2009 15:45:13 +0000 Subject: [PATCH] From Cedric Pinson, this commit contains the following change: * Change ref_ptr to observer_ptr to avoid cross reference and leak in Skinning * Set invalidate to true to re run the check visitor in Skeleton * Shallow copy Sampler in channel copy constructor * Add accessor in VertexInfluence * Remove dead code in Timeline.cpp * Dont force linking in Bone::UpdateBone, the decision is done by the user or the manager * Add offset in timeline stats to display each manager on the screen * Add a flag in animation manager base to enable or not automatic link when modifying the manager --- include/osgAnimation/AnimationManagerBase | 11 ++++++- include/osgAnimation/Channel | 11 ++++--- include/osgAnimation/Skeleton | 2 +- include/osgAnimation/Skinning | 6 ++-- include/osgAnimation/VertexInfluence | 4 ++- src/osgAnimation/Animation.cpp | 2 -- src/osgAnimation/AnimationManagerBase.cpp | 14 +++++++-- src/osgAnimation/Bone.cpp | 35 ----------------------- src/osgAnimation/StatsHandler.cpp | 3 +- src/osgAnimation/Timeline.cpp | 23 --------------- src/osgAnimation/VertexInfluence.cpp | 8 ++++-- 11 files changed, 43 insertions(+), 76 deletions(-) diff --git a/include/osgAnimation/AnimationManagerBase b/include/osgAnimation/AnimationManagerBase index c19bfb272..69156e1a3 100644 --- a/include/osgAnimation/AnimationManagerBase +++ b/include/osgAnimation/AnimationManagerBase @@ -44,18 +44,27 @@ namespace osgAnimation /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); - /// Operation that must be done each frame + /** Reset the value of targets + this Operation must be done each frame */ void clearTargets(); + LinkVisitor* getOrCreateLinkVisitor(); void setLinkVisitor(LinkVisitor*); + /// set a flag to define the behaviour + void setAutomaticLink(bool); + bool isAutomaticLink() const; + + void dirty(); + protected: osg::ref_ptr _linker; AnimationList _animations; TargetSet _targets; bool _needToLink; + bool _automaticLink; }; } #endif diff --git a/include/osgAnimation/Channel b/include/osgAnimation/Channel index f7acc4d44..0c98267b7 100644 --- a/include/osgAnimation/Channel +++ b/include/osgAnimation/Channel @@ -77,10 +77,13 @@ namespace osgAnimation Channel* clone() const { return new TemplateChannel(*this); } TemplateChannel (const TemplateChannel& channel) : - Channel(channel), - _target(new TargetType(*channel.getTargetTyped())), - _sampler(channel._sampler.get()) + Channel(channel) { + if (channel.getTargetTyped()) + _target = new TargetType(*channel.getTargetTyped()); + + if (channel.getSamplerTyped()) + _sampler = new SamplerType(*channel.getSamplerTyped()); } TemplateChannel (SamplerType* s = 0,TargetType* target = 0) @@ -102,7 +105,7 @@ namespace osgAnimation // create a key from current target value typename KeyframeContainerType::KeyType key(0, _target->getValue()); // recreate the keyframe container - _sampler = 0; + getOrCreateSampler()->setKeyframeContainer(0); getOrCreateSampler()->getOrCreateKeyframeContainer(); // add the key _sampler->getKeyframeContainerTyped()->push_back(key); diff --git a/include/osgAnimation/Skeleton b/include/osgAnimation/Skeleton index 69689b8eb..88fb1df4c 100644 --- a/include/osgAnimation/Skeleton +++ b/include/osgAnimation/Skeleton @@ -32,7 +32,7 @@ namespace osgAnimation public: META_Object(osgAnimation, UpdateSkeleton); UpdateSkeleton() : _needValidate(true) {} - UpdateSkeleton(const UpdateSkeleton& us, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : osg::Object(us, copyop), osg::NodeCallback(us, copyop) {} + UpdateSkeleton(const UpdateSkeleton& us, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : osg::Object(us, copyop), osg::NodeCallback(us, copyop) { _needValidate = true;} virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); protected: diff --git a/include/osgAnimation/Skinning b/include/osgAnimation/Skinning index 926995b6a..20517b057 100644 --- a/include/osgAnimation/Skinning +++ b/include/osgAnimation/Skinning @@ -46,11 +46,11 @@ namespace osgAnimation { public: BoneWeight(BoneType* bone, float weight) : _bone(bone), _weight(weight) {} - const BoneType* getBone() const { return &(*_bone); } + const BoneType* getBone() const { return _bone.get(); } float getWeight() const { return _weight; } void setWeight(float w) { _weight = w; } protected: - osg::ref_ptr _bone; + osg::observer_ptr _bone; float _weight; }; @@ -191,7 +191,7 @@ namespace osgAnimation const VertexList& vertexes = uniq.getVertexes(); int vertexSize = vertexes.size(); - for (int j = 0; j < vertexSize; j++) + for (int j = 0; j < vertexSize; j++) { int idx = vertexes[j]; dst[idx] = src[idx] * matrix; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 172bf79cd..fa93d070b 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -96,6 +96,8 @@ namespace osgAnimation _bone2Vertexes.clear(); _uniqVertexSetToBoneSet.clear(); } + + const VertexIndexToBoneWeightMap& getVertexToBoneList() const; protected: BoneToVertexList _bone2Vertexes; VertexIndexToBoneWeightMap _vertex2Bones; diff --git a/src/osgAnimation/Animation.cpp b/src/osgAnimation/Animation.cpp index 3f353aa4a..e8232ddb0 100644 --- a/src/osgAnimation/Animation.cpp +++ b/src/osgAnimation/Animation.cpp @@ -133,8 +133,6 @@ bool Animation::update (float time, int priority) break; } - // std::cout << "t " << t << " / " << _duration << std::endl; - ChannelList::const_iterator chan; for( chan=_channels.begin(); chan!=_channels.end(); ++chan) { diff --git a/src/osgAnimation/AnimationManagerBase.cpp b/src/osgAnimation/AnimationManagerBase.cpp index 2e3d2f67a..83ca83e14 100644 --- a/src/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgAnimation/AnimationManagerBase.cpp @@ -23,6 +23,7 @@ AnimationManagerBase::~AnimationManagerBase() {} AnimationManagerBase::AnimationManagerBase() { _needToLink = false; + _automaticLink = true; } void AnimationManagerBase::clearTargets() @@ -31,6 +32,14 @@ void AnimationManagerBase::clearTargets() (*it).get()->reset(); } +void AnimationManagerBase::dirty() +{ + _needToLink = true; +} + +void AnimationManagerBase::setAutomaticLink(bool state) { _automaticLink = state; } +bool AnimationManagerBase::isAutomaticLink() const { return _automaticLink; } + void AnimationManagerBase::operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) @@ -64,13 +73,14 @@ AnimationManagerBase::AnimationManagerBase(const AnimationManagerBase& b, const _animations.push_back(animation); } _needToLink = true; + _automaticLink = b._automaticLink; buildTargetReference(); } void AnimationManagerBase::buildTargetReference() { _targets.clear(); - for( AnimationList::iterator iterAnim = _animations.begin(); iterAnim != _animations.end(); ++iterAnim ) + for( AnimationList::iterator iterAnim = _animations.begin(); iterAnim != _animations.end(); ++iterAnim ) { Animation* anim = (*iterAnim).get(); for (ChannelList::iterator it = anim->getChannels().begin(); @@ -98,7 +108,7 @@ void AnimationManagerBase::unregisterAnimation (Animation* animation) buildTargetReference(); } -bool AnimationManagerBase::needToLink() const { return _needToLink; } +bool AnimationManagerBase::needToLink() const { return _needToLink && isAutomaticLink(); } void AnimationManagerBase::setLinkVisitor(LinkVisitor* visitor) diff --git a/src/osgAnimation/Bone.cpp b/src/osgAnimation/Bone.cpp index ae01dd49b..cbd664dbd 100644 --- a/src/osgAnimation/Bone.cpp +++ b/src/osgAnimation/Bone.cpp @@ -69,31 +69,6 @@ void osgAnimation::Bone::UpdateBone::operator()(osg::Node* node, osg::NodeVisito b->accept(visitor); } - if (!_manager.valid()) - { - FindParentAnimationManagerVisitor finder; - - if (b->getParents().size() > 1) - { - osg::notify(osg::WARN) << "A Bone should not have multi parent ( " << b->getName() << " ) has parents "; - osg::notify(osg::WARN) << "( " << b->getParents()[0]->getName(); - for (int i = 1; i < (int)b->getParents().size(); i++) - osg::notify(osg::WARN) << ", " << b->getParents()[i]->getName(); - osg::notify(osg::WARN) << ")" << std::endl; - return; - } - b->getParents()[0]->accept(finder); - - if (!finder.getAnimationManager()) - { - osg::notify(osg::WARN) << "Warning can't update Bone, path to parent AnimationManagerBase not found" << std::endl; - return; - } - - _manager = finder.getAnimationManager(); - } - - updateLink(); update(*b); Bone* parent = b->getBoneParent(); @@ -117,16 +92,6 @@ osgAnimation::Bone::Bone(const Bone& b, const osg::CopyOp& copyop) : _invBindInSkeletonSpace(b._invBindInSkeletonSpace), _boneInSkeletonSpace(b._boneInSkeletonSpace) { -#if 0 - osg::ref_ptr updatecallback = getUpdateCallback(); - setUpdateCallback(0); - while (updatecallback.valid()) { - osg::NodeCallback* ucb = dynamic_cast(updatecallback->clone(copyop)); - ucb->setNestedCallback(0); - addUpdateCallback(ucb); - updatecallback = updatecallback->getNestedCallback(); - } -#endif } osgAnimation::Bone::Bone(const std::string& name) diff --git a/src/osgAnimation/StatsHandler.cpp b/src/osgAnimation/StatsHandler.cpp index 426fb5474..745bc9b6b 100644 --- a/src/osgAnimation/StatsHandler.cpp +++ b/src/osgAnimation/StatsHandler.cpp @@ -563,7 +563,7 @@ bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdap StatsList statsList; for (int i = 0; i < (int)finder._timelines.size(); i++) - statsList.push_back(finder._timelines[0]->getStats()); + statsList.push_back(finder._timelines[i]->getStats()); for(int i = statsList[0]->getEarliestFrameNumber(); i<= statsList[0]->getLatestFrameNumber()-1; ++i) { @@ -653,6 +653,7 @@ void StatsHandler::setUpScene(osgViewer::Viewer* viewer) StatsTimeline* s = new StatsTimeline; osg::MatrixTransform* m = s->createStatsForTimeline(finder._timelines[i].get()); m->setUpdateCallback(s); + m->setMatrix(osg::Matrix::translate(0, -i * 100, 0)); _group->addChild(m); } } diff --git a/src/osgAnimation/Timeline.cpp b/src/osgAnimation/Timeline.cpp index 8713a9b73..50f661019 100644 --- a/src/osgAnimation/Timeline.cpp +++ b/src/osgAnimation/Timeline.cpp @@ -201,31 +201,8 @@ void osgAnimation::Timeline::internalRemoveAction(Action* action) void osgAnimation::Timeline::internalAddAction(int priority, const FrameAction& ftl) { _actions[priority].insert(_actions[priority].begin(), ftl); -// _actions[priority].push_back(ftl); } -#if 0 -void osgAnimation::Timeline::evaluateCallback(unsigned int frame) -{ - // update from high priority to low priority - for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim ) - { - // update all animation - ActionList& list = iterAnim->second; - for (unsigned int i = 0; i < list.size(); i++) - { - unsigned int firstFrame = list[i].first; - Action* action = list[i].second.get(); - // check if current frame of timeline hit an action interval - if (frame >= firstFrame && - frame < (firstFrame + action->getNumFrames()) ) - action->evaluateCallback(frame - firstFrame); - } - } - processPendingOperation(); -} -#endif - bool osgAnimation::Timeline::isActive(Action* activeAction) { // update from high priority to low priority diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 3ef29f0db..c3d1d84fc 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -13,11 +13,13 @@ */ #include +#include #include #include using namespace osgAnimation; +const osgAnimation::VertexInfluenceSet::VertexIndexToBoneWeightMap& osgAnimation::VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} // this class manage VertexInfluence database by mesh // reference bones per vertex ... void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() @@ -33,13 +35,13 @@ void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() int index = viw.first; float weight = viw.second; if (vi.getName().empty()) - std::cout << "osgAnimation::VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; + osg::notify(osg::WARN) << "osgAnimation::VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight)); } } // normalize weight per vertex - for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++) + for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++) { BoneWeightList& bones = it->second; int size = bones.size(); @@ -48,7 +50,7 @@ void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() sum += bones[i].getWeight(); if (sum < 1e-4) { - std::cerr << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; + osg::notify(osg::WARN) << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; } else {