root/OpenSceneGraph/trunk/src/osgAnimation/Bone.cpp @ 10693

Revision 10693, 5.4 kB (checked in by cedricpinson, 5 years ago)

From Cedric Pinson, The following commit include:
* Refactore of RigGeometry? to support hardware skinning
* Refactore of Timeline to split Action in differents files
* Add example how to use hardware skinning

RevLine 
[9093]1/*  -*-c++-*-
[10561]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9093]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/Bone>
16#include <osgAnimation/Skeleton>
[10561]17#include <osgAnimation/FindParentAnimationManagerVisitor>
18#include <osgAnimation/BoneMapVisitor>
19#include <osgAnimation/ComputeBindMatrixVisitor>
[9093]20
[10558]21
[9877]22osgAnimation::Bone::UpdateBone::UpdateBone(const osgAnimation::Bone::UpdateBone& apc,const osg::CopyOp& copyop) :
[10386]23    osg::Object(apc, copyop),
[10518]24    osgAnimation::AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
[9093]25{
[10343]26    _quaternion = new osgAnimation::QuatTarget(apc._quaternion->getValue());
27    _position = new osgAnimation::Vec3Target(apc._position->getValue());
28    _scale = new osgAnimation::Vec3Target(apc._scale->getValue());
[9093]29}
30
[10558]31bool osgAnimation::Bone::UpdateBone::link(osgAnimation::Channel* channel)
32{
33    if (channel->getName().find("quaternion") != std::string::npos)
34    {
35        return channel->setTarget(_quaternion.get());
36    }
37    else if (channel->getName().find("position") != std::string::npos)
38    {
39        return channel->setTarget(_position.get());
40    }
41    else if (channel->getName().find("scale") != std::string::npos)
42    {
43        return channel->setTarget(_scale.get());
44    }
45    else 
46    {
47        osg::notify(osg::WARN) << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << className() << std::endl;
48    }
49    return false;
50}
[9370]51
[10558]52
53/** Callback method called by the NodeVisitor when visiting a node.*/
54void osgAnimation::Bone::UpdateBone::operator()(osg::Node* node, osg::NodeVisitor* nv)
55{
56    if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
57    {
58        Bone* b = dynamic_cast<Bone*>(node);
59        if (!b)
60        {
61            osg::notify(osg::WARN) << "Warning: UpdateBone set on non-Bone object." << std::endl;
62            return;
63        }
64
65        if (b->needToComputeBindMatrix())
66        {
67            ComputeBindMatrixVisitor visitor;
68            b->accept(visitor);
69        }
70
71        update(*b);
72
73        Bone* parent = b->getBoneParent();
74        if (parent)
75            b->setMatrixInSkeletonSpace(b->getMatrixInBoneSpace() * parent->getMatrixInSkeletonSpace());
76        else
77            b->setMatrixInSkeletonSpace(b->getMatrixInBoneSpace());
78
79    }
80    traverse(node,nv);
81}
82
83
[9877]84osgAnimation::Bone::Bone(const Bone& b, const osg::CopyOp& copyop) :
85    osg::Transform(b,copyop),
86    _position(b._position),
[9370]87    _rotation(b._rotation),
[9877]88    _scale(b._scale),
[10346]89    _needToRecomputeBindMatrix(true),
[10343]90    _bindInBoneSpace(b._bindInBoneSpace),
91    _invBindInSkeletonSpace(b._invBindInSkeletonSpace),
[10346]92    _boneInSkeletonSpace(b._boneInSkeletonSpace)
[9370]93{
94}
95
96osgAnimation::Bone::Bone(const std::string& name)
97{
98    if (!name.empty())
99        setName(name);
100    _needToRecomputeBindMatrix = false;
101}
102
103
104void osgAnimation::Bone::setDefaultUpdateCallback(const std::string& name)
105{
106    std::string cbName = name;
107    if (cbName.empty())
108        cbName = getName();
109    setUpdateCallback(new UpdateBone(cbName));
110}
111
[9093]112void osgAnimation::Bone::computeBindMatrix()
113{
114    _invBindInSkeletonSpace = osg::Matrix::inverse(_bindInBoneSpace);
115    const Bone* parent = getBoneParent();
116    _needToRecomputeBindMatrix = false;
117    if (!parent)
118    {
119        osg::notify(osg::WARN) << "Warning " << className() <<"::computeBindMatrix you should not have this message, it means you miss to attach this bone(" << getName() <<") to a Skeleton node" << std::endl;
120        return;
121    }
122    _invBindInSkeletonSpace = parent->getInvBindMatrixInSkeletonSpace() * _invBindInSkeletonSpace;
123}
124
[10561]125osgAnimation::Bone* osgAnimation::Bone::getBoneParent()
[9093]126{
127    if (getParents().empty())
128        return 0;
129    osg::Node::ParentList parents = getParents();
130    for (osg::Node::ParentList::iterator it = parents.begin(); it != parents.end(); it++)
131    {
132        Bone* pb = dynamic_cast<Bone*>(*it);
133        if (pb)
134            return pb;
135    }
136    return 0;
137}
138const osgAnimation::Bone* osgAnimation::Bone::getBoneParent() const
139{
140    if (getParents().empty())
141        return 0;
142    const osg::Node::ParentList& parents = getParents();
143    for (osg::Node::ParentList::const_iterator it = parents.begin(); it != parents.end(); it++)
144    {
145        const Bone* pb = dynamic_cast<const Bone*>(*it);
146        if (pb)
147            return pb;
148    }
149    return 0;
150}
151
152
153/** Add Node to Group.
154 * If node is not NULL and is not contained in Group then increment its
155 * reference count, add it to the child list and dirty the bounding
156 * sphere to force it to recompute on next getBound() and return true for success.
157 * Otherwise return false. Scene nodes can't be added as child nodes.
158 */
159bool osgAnimation::Bone::addChild( Node *child )
160{
161    Bone* bone = dynamic_cast<Bone*>(child);
162    if (bone)
163        bone->setNeedToComputeBindMatrix(true);
164    return osg::Group::addChild(child);
165}
166
167osgAnimation::Bone::BoneMap osgAnimation::Bone::getBoneMap()
168{
169    BoneMapVisitor mapVisitor;
170    this->accept(mapVisitor);
[10561]171    return mapVisitor.getBoneMap();
[9093]172}
Note: See TracBrowser for help on using the browser.