root/OpenSceneGraph/trunk/src/osgAnimation/UpdateCallback.cpp @ 10386

Revision 10386, 5.7 kB (checked in by cedricpinson, 6 years ago)

From Cedric Pinson, fix constructors for cloning osgAnimation objects

Line 
1/*  -*-c++-*-
2 *  Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
3 *
4 * This library is open source and may be redistributed and/or modified under 
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version.  The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * OpenSceneGraph Public License for more details.
13*/
14
15#include <osgAnimation/UpdateCallback>
16#include <osg/MatrixTransform>
17#include <osg/PositionAttitudeTransform>
18
19using namespace osgAnimation;
20
21osgAnimation::AnimationManagerBase* AnimationUpdateCallback::getAnimationManager() { return _manager.get(); }
22
23AnimationUpdateCallback::AnimationUpdateCallback(const AnimationUpdateCallback& apc,const osg::CopyOp& copyop):
24    osg::NodeCallback(apc, copyop),
25    _manager(apc._manager) {}
26
27int AnimationUpdateCallback::link(osgAnimation::Animation* animation)
28{
29    if (getName().empty())
30        osg::notify(osg::WARN) << "An update callback has no name, it means it can link only with \"\" named Target, often an error" << std::endl;
31    int nbLinks = 0;
32    for (osgAnimation::ChannelList::iterator it = animation->getChannels().begin();
33         it != animation->getChannels().end();
34         it++)
35    {
36        std::string targetName = (*it)->getTargetName();
37        if (targetName == getName())
38        {
39            link((*it).get());
40            nbLinks++;
41        }
42    }
43    return nbLinks;
44}
45   
46void AnimationUpdateCallback::updateLink()
47{
48    if (_manager.valid())
49    {
50        if (needLink())
51        {
52            /** this item is not linked yet then we do it for all animation
53                registered in the manager.
54                Maybe this function should be on the manager side like
55                _manager->linkItem(Bone);
56            */
57            const AnimationList& animationList = _manager->getAnimationList();
58            for (AnimationList::const_iterator it = animationList.begin(); it != animationList.end(); it++)
59                link(it->get());
60            _manager->buildTargetReference();
61        }
62    }
63}
64
65
66
67
68UpdateTransform::UpdateTransform(const UpdateTransform& apc,const osg::CopyOp& copyop)
69    : osg::Object(apc, copyop),
70      AnimationUpdateCallback(apc, copyop)
71{
72    _euler = new osgAnimation::Vec3Target(apc._euler->getValue());
73    _position = new osgAnimation::Vec3Target(apc._euler->getValue());
74    _scale = new osgAnimation::Vec3Target(apc._euler->getValue());
75}
76
77UpdateTransform::UpdateTransform(const std::string& name) : AnimationUpdateCallback(name)
78{
79    _euler = new osgAnimation::Vec3Target;
80    _position = new osgAnimation::Vec3Target;
81    _scale = new osgAnimation::Vec3Target(osg::Vec3(1,1,1));
82}
83
84/** Callback method called by the NodeVisitor when visiting a node.*/
85void UpdateTransform::operator()(osg::Node* node, osg::NodeVisitor* nv)
86{
87    if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
88    {
89        osg::MatrixTransform* matrix = dynamic_cast<osg::MatrixTransform*>(node);
90        if (matrix)
91        {
92            update(*matrix);
93        }
94        else 
95        {
96            osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
97            if (pat)
98                update(*pat);
99        }
100    }
101    traverse(node,nv);
102}
103
104void UpdateTransform::update(osg::MatrixTransform& mat)
105{
106    float z = _euler->getValue()[2];
107    float x = _euler->getValue()[0];
108    float y = _euler->getValue()[1];
109    osg::Matrix m =
110        osg::Matrix::rotate(x,1.0,0.0,0.0) *
111        osg::Matrix::rotate(y,0.0,1.0,0.0) *
112        osg::Matrix::rotate(z,0.0,0.0,1.0);
113    mat.setMatrix(osg::Matrix::scale(_scale->getValue()) *
114                  m *
115                  osg::Matrix::translate(_position->getValue()));
116    mat.dirtyBound();
117}
118
119void UpdateTransform::update(osg::PositionAttitudeTransform& pat)
120{
121    float heading = _euler->getValue()[0];
122    float pitch = _euler->getValue()[1];
123    float roll = _euler->getValue()[2];
124    osg::Matrix m = osg::Matrix::rotate(roll,0.0,1.0,0.0) * osg::Matrix::rotate(pitch,1.0,0.0,0.0) * osg::Matrix::rotate(-heading,0.0,0.0,1.0);
125    osg::Quat q = m.getRotate();
126
127    pat.setPosition(_position->getValue());
128    pat.setScale(_scale->getValue());
129    pat.setAttitude(q);
130    pat.dirtyBound();
131}
132
133bool UpdateTransform::needLink() const
134{
135    // the idea is to return true if nothing is linked
136    return !((_position->getCount() + _euler->getCount() + _scale->getCount()) > 3);
137}
138
139bool UpdateTransform::link(osgAnimation::Channel* channel)
140{
141    if (channel->getName().find("euler") != std::string::npos)
142    {
143        osgAnimation::Vec3LinearChannel* qc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
144        if (qc)
145        {
146            qc->setTarget(_euler.get());
147            return true;
148        }
149    }
150    else if (channel->getName().find("position") != std::string::npos)
151    {
152        osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
153        if (vc)
154        {
155            vc->setTarget(_position.get());
156            return true;
157        }
158    }
159    else if (channel->getName().find("scale") != std::string::npos)
160    {
161        osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
162        if (vc)
163        {
164            vc->setTarget(_scale.get());
165            return true;
166        }
167    }
168    else 
169    {
170        std::cerr << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;
171    }
172    return false;
173}
Note: See TracBrowser for help on using the browser.