From Cedric Pinson, Pulled in osgAnimation from OpenSceneGraph-osgWidget-dev into svn/trunk.

This commit is contained in:
Robert Osfield
2008-11-22 12:14:19 +00:00
parent fdaa75400b
commit 56a2cc65d0
55 changed files with 6623 additions and 3 deletions

View File

@@ -6,14 +6,15 @@ FOREACH( mylibfolder
osgUtil
osgGA
osgText
osgManipulator
osgSim
osgViewer
osgAnimation
osgFX
osgManipulator
osgParticle
osgShadow
osgSim
osgTerrain
osgVolume
osgViewer
)
ADD_SUBDIRECTORY(${mylibfolder})

View File

@@ -0,0 +1,147 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Animation>
using namespace osgAnimation;
Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& c)
{
_duration = anim._duration;
_originalDuration = anim._originalDuration;
_weight = anim._weight;
_startTime = anim._startTime;
_playmode = anim._playmode;
}
void Animation::addChannel(Channel* pChannel)
{
_channels.push_back(pChannel);
if (!_duration)
computeDuration();
else
_originalDuration = computeDurationFromChannels();
}
double Animation::computeDurationFromChannels() const
{
double tmin = 1e5;
double tmax = -1e5;
ChannelList::const_iterator chan;
for( chan=_channels.begin(); chan!=_channels.end(); chan++ )
{
float min = (*chan)->getStartTime();
if (min < tmin)
tmin = min;
float max = (*chan)->getEndTime();
if (max > tmax)
tmax = max;
}
return tmax-tmin;
}
void Animation::computeDuration()
{
_duration = computeDurationFromChannels();
_originalDuration = _duration;
}
osgAnimation::ChannelList& Animation::getChannels()
{
return _channels;
}
const osgAnimation::ChannelList& Animation::getChannels() const
{
return _channels;
}
void Animation::setDuration(double duration)
{
_originalDuration = computeDurationFromChannels();
_duration = duration;
}
float Animation::getDuration() const
{
return _duration;
}
float Animation::getWeight () const
{
return _weight;
}
void Animation::setWeight (float weight)
{
_weight = weight;
}
bool Animation::update (float time)
{
if (!_duration) // if not initialized then do it
computeDuration();
double ratio = _originalDuration / _duration;
float t = (time - _startTime) * ratio;
switch (_playmode)
{
case ONCE:
if (t > _duration)
return false;
break;
case STAY:
if (t > _duration)
t = _duration;
break;
case LOOP:
if (!_duration)
t = _startTime;
else if (t > _duration)
t = fmodf(t, _duration);
// std::cout << "t " << t << " duration " << _duration << std::endl;
break;
case PPONG:
if (!_duration)
t = _startTime;
else
{
int tt = (int) (t / _duration);
t = fmodf(t, _duration);
if (tt%2)
t = _duration - t;
}
break;
}
// std::cout << "t " << t << " / " << _duration << std::endl;
ChannelList::const_iterator chan;
for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
{
(*chan)->setWeight(_weight);
(*chan)->update(t);
}
return true;
}
void Animation::resetTargets()
{
ChannelList::const_iterator chan;
for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
(*chan)->reset();
}

View File

@@ -0,0 +1,141 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/AnimationManager>
#include <osgAnimation/LinkVisitor>
#include <osgAnimation/Assert>
using namespace osgAnimation;
AnimationManager::~AnimationManager() {}
void AnimationManager::stopAll()
{
// loop over all playing animation
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
{
AnimationList& list = iterAnim->second;
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
(*it)->resetTargets();
}
_animationsPlaying.clear();
}
AnimationManager::AnimationManager()
{
_lastUpdate = 0;
}
void AnimationManager::playAnimation(Animation* pAnimation, int priority, float weight)
{
bool r = findAnimation(pAnimation);
OSGANIMATION_ASSERT(r && "This animation is not registered");
if ( isPlaying(pAnimation) )
stopAnimation(pAnimation);
_animationsPlaying[priority].push_back(pAnimation);
pAnimation->setStartTime(_lastUpdate);
pAnimation->setWeight(weight);
}
bool AnimationManager::stopAnimation(Animation* pAnimation)
{
// search though the layer and remove animation
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
{
AnimationList& list = iterAnim->second;
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
if( (*it) == pAnimation )
{
(*it)->resetTargets();
list.erase(it);
return true;
}
}
return false;
}
void AnimationManager::update (double time)
{
if (!_lastUpdate)
_lastUpdate = time;
// could filtered with an active flag
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
(*it).get()->reset();
// update from high priority to low priority
for( AnimationLayers::reverse_iterator iterAnim = _animationsPlaying.rbegin(); iterAnim != _animationsPlaying.rend(); ++iterAnim )
{
// update all animation
std::vector<int> toremove;
AnimationList& list = iterAnim->second;
for (unsigned int i = 0; i < list.size(); i++)
{
if (! list[i]->update(time))
toremove.push_back(i);
}
// remove finished animation
while (!toremove.empty())
{
list.erase(list.begin() + toremove.back());
toremove.pop_back();
}
}
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
(*it).get()->normalize();
}
bool AnimationManager::findAnimation(Animation* pAnimation)
{
for( AnimationList::const_iterator iterAnim = _animations.begin(); iterAnim != _animations.end(); ++iterAnim )
{
if ( (*iterAnim) == pAnimation )
return true;
}
return false;
}
bool AnimationManager::isPlaying(Animation* pAnimation)
{
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
{
AnimationList& list = iterAnim->second;
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
if ( (*it) == pAnimation )
return true;
}
return false;
}
bool AnimationManager::isPlaying(const std::string& name)
{
// loop over all playing animation
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
{
AnimationList& list = iterAnim->second;
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
if ( (*it)->getName() == name )
return true;
}
return false;
}

View File

@@ -0,0 +1,71 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/LinkVisitor>
#include <osgAnimation/Assert>
using namespace osgAnimation;
AnimationManagerBase::~AnimationManagerBase() {}
AnimationManagerBase::AnimationManagerBase()
{
setUpdateCallback(new UpdateCallback);
_needToLink = false;
}
void AnimationManagerBase::buildTargetReference()
{
_targets.clear();
for( AnimationList::iterator iterAnim = _animations.begin(); iterAnim != _animations.end(); ++iterAnim )
{
Animation* anim = (*iterAnim).get();
for (ChannelList::iterator it = anim->getChannels().begin();
it != anim->getChannels().end();
it++)
_targets.insert((*it)->getTarget());
}
}
void AnimationManagerBase::registerAnimation (Animation* animation)
{
_needToLink = true;
_animations.push_back(animation);
buildTargetReference();
}
bool AnimationManagerBase::needToLink() const { return _needToLink; }
void AnimationManagerBase::link()
{
LinkVisitor linker(_animations);
accept(linker);
_needToLink = false;
buildTargetReference();
}
osgAnimation::AnimationMap AnimationManagerBase::getAnimationMap() const
{
osgAnimation::AnimationMap map;
for (AnimationList::const_iterator it = _animations.begin(); it != _animations.end(); it++)
map[(*it)->getName()] = *it;
return map;
}

104
src/osgAnimation/Bone.cpp Normal file
View File

@@ -0,0 +1,104 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Skinning>
#include <osgAnimation/Bone>
#include <osgAnimation/Skeleton>
osgAnimation::Bone::UpdateBone::UpdateBone(const osgAnimation::Bone::UpdateBone& apc,const osg::CopyOp& copyop):
osgAnimation::AnimationUpdateCallback(apc, copyop),
_position(apc._position),
_quaternion(apc._quaternion),
_scale(apc._scale)
{
}
void osgAnimation::Bone::computeBindMatrix()
{
_invBindInSkeletonSpace = osg::Matrix::inverse(_bindInBoneSpace);
const Bone* parent = getBoneParent();
_needToRecomputeBindMatrix = false;
if (!parent)
{
#if 0
// no more parent means, we get the skeleton
if (getParents().empty()) {
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;
return;
} else if (getParents().size() > 1) {
osg::notify(osg::WARN) << "Warning " << className() <<"::computeBindMatrix you have more than one parent in a skeleton structure (" << getName() <<") unknown behaviour" << std::endl;
return;
}
osgAnimation::Skeleton* skel = dynamic_cast<osgAnimation::Skeleton*>(getParents()[0]);
if (!skel) {
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;
return;
}
_invBindInSkeletonSpace = osg::Matrix::inverse(skel->getMatrix()) * _invBindInSkeletonSpace;
#else
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;
#endif
return;
}
_invBindInSkeletonSpace = parent->getInvBindMatrixInSkeletonSpace() * _invBindInSkeletonSpace;
}
osgAnimation::Bone* osgAnimation::Bone::getBoneParent()
{
if (getParents().empty())
return 0;
osg::Node::ParentList parents = getParents();
for (osg::Node::ParentList::iterator it = parents.begin(); it != parents.end(); it++)
{
Bone* pb = dynamic_cast<Bone*>(*it);
if (pb)
return pb;
}
return 0;
}
const osgAnimation::Bone* osgAnimation::Bone::getBoneParent() const
{
if (getParents().empty())
return 0;
const osg::Node::ParentList& parents = getParents();
for (osg::Node::ParentList::const_iterator it = parents.begin(); it != parents.end(); it++)
{
const Bone* pb = dynamic_cast<const Bone*>(*it);
if (pb)
return pb;
}
return 0;
}
/** Add Node to Group.
* If node is not NULL and is not contained in Group then increment its
* reference count, add it to the child list and dirty the bounding
* sphere to force it to recompute on next getBound() and return true for success.
* Otherwise return false. Scene nodes can't be added as child nodes.
*/
bool osgAnimation::Bone::addChild( Node *child )
{
Bone* bone = dynamic_cast<Bone*>(child);
if (bone)
bone->setNeedToComputeBindMatrix(true);
return osg::Group::addChild(child);
}
osgAnimation::Bone::BoneMap osgAnimation::Bone::getBoneMap()
{
BoneMapVisitor mapVisitor;
this->accept(mapVisitor);
return mapVisitor._map;
}

View File

@@ -0,0 +1,56 @@
IF (DYNAMIC_OPENSCENEGRAPH)
ADD_DEFINITIONS(-DOSGANIMATION_LIBRARY)
ELSE (DYNAMIC_OPENSCENEGRAPH)
ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC)
ENDIF(DYNAMIC_OPENSCENEGRAPH)
SET(LIB_NAME osgAnimation)
SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME})
SET(LIB_PUBLIC_HEADERS
${HEADER_PATH}/Export
${HEADER_PATH}/Bone
${HEADER_PATH}/Skeleton
${HEADER_PATH}/Channel
${HEADER_PATH}/Sampler
${HEADER_PATH}/Interpolator
${HEADER_PATH}/Target
${HEADER_PATH}/Animation
${HEADER_PATH}/Keyframe
${HEADER_PATH}/Skinning
${HEADER_PATH}/CubicBezier
${HEADER_PATH}/Vec3Packed
${HEADER_PATH}/AnimationManager
${HEADER_PATH}/AnimationManagerBase
${HEADER_PATH}/UpdateCallback
${HEADER_PATH}/LinkVisitor
${HEADER_PATH}/VertexInfluence
${HEADER_PATH}/EaseMotion
${HEADER_PATH}/Assert
${HEADER_PATH}/Timeline
)
ADD_LIBRARY(${LIB_NAME}
${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC}
${LIB_PUBLIC_HEADERS}
Channel.cpp
Target.cpp
Animation.cpp
Bone.cpp
RigGeometry.cpp
AnimationManager.cpp
AnimationManagerBase.cpp
Skeleton.cpp
VertexInfluence.cpp
UpdateCallback.cpp
Timeline.cpp
)
LINK_INTERNAL(${LIB_NAME}
osg
)
LINK_CORELIB_DEFAULT(${LIB_NAME})
INCLUDE(ModuleInstall OPTIONAL)

View File

@@ -0,0 +1,29 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Channel>
using namespace osgAnimation;
Channel::Channel() { _weight=1; }
Channel::~Channel() {}
const std::string& Channel::getName() const { return _name; }
void Channel::setName (const std::string& name) { _name = name; }
const std::string& Channel::getTargetName() const { return _targetName;}
void Channel::setTargetName (const std::string& name) { _targetName = name; }
float Channel::getWeight() const { return _weight;}
void Channel::setWeight(float w) { _weight = w;}

View File

@@ -0,0 +1,93 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors:
*
* Cedric Pinson <mornifle@plopbyte.net>
*
*/
#include <osgAnimation/RigGeometry>
void osgAnimation::RigGeometry::buildTransformer(Skeleton* root)
{
Bone::BoneMap bm = root->getBoneMap();
_transformVertexes.init(bm, _vertexInfluenceSet.getUniqVertexSetToBoneSetList());
_root = root;
}
void osgAnimation::RigGeometry::buildVertexSet()
{
if (!_vertexInfluenceMap.valid())
{
osg::notify(osg::WARN) << "buildVertexSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl;
return;
}
_vertexInfluenceSet.clear();
for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin();
it != _vertexInfluenceMap->end();
it++)
_vertexInfluenceSet.addVertexInfluence(it->second);
_vertexInfluenceSet.buildVertex2BoneList();
_vertexInfluenceSet.buildUniqVertexSetToBoneSetList();
std::cout << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl;
}
void osgAnimation::RigGeometry::computeMatrixFromRootSkeleton()
{
if (!_root.valid())
{
osg::notify(osg::WARN) << "Warning " << className() <<"::computeMatrixFromRootSkeleton if you have this message it means you miss to call buildTransformer(Skeleton* root), or your RigGeometry (" << getName() <<") is not attached to a Skeleton subgraph" << std::endl;
return;
}
osg::MatrixList mtxList = getParent(0)->getWorldMatrices(_root.get());
_matrixFromSkeletonToGeometry = mtxList[0];
_invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(_matrixFromSkeletonToGeometry);
_needToComputeMatrix = false;
}
void osgAnimation::RigGeometry::transformSoftwareMethod()
{
// std::cout << getName() << " _matrixFromSkeletonToGeometry" << _matrixFromSkeletonToGeometry << std::endl;
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(getVertexArray());
if (pos && _positionSource.size() != pos->size())
{
_positionSource = std::vector<osg::Vec3>(pos->begin(),pos->end());
getVertexArray()->setDataVariance(osg::Object::DYNAMIC);
}
osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(getNormalArray());
if (normal && _normalSource.size() != normal->size())
{
_normalSource = std::vector<osg::Vec3>(normal->begin(),normal->end());
getNormalArray()->setDataVariance(osg::Object::DYNAMIC);
}
if (!_positionSource.empty())
{
_transformVertexes.compute<osg::Vec3>(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_positionSource.front(), &pos->front());
pos->dirty();
}
if (!_normalSource.empty())
{
_transformVertexes.compute<osg::Vec3>(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_normalSource.front(), &normal->front());
normal->dirty();
}
dirtyBound();
}
const osgAnimation::Skeleton* osgAnimation::RigGeometry::getSkeleton() const { return _root.get(); }
osgAnimation::Skeleton* osgAnimation::RigGeometry::getSkeleton() { return _root.get(); }

View File

@@ -0,0 +1,94 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Skeleton>
#include <osgAnimation/Bone>
using namespace osgAnimation;
struct computeBindMatrixVisitor : public osg::NodeVisitor
{
osg::Matrix _skeleton;
computeBindMatrixVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
void apply(osg::Node& node) { return ;}
void apply(osg::Transform& node)
{
Bone* bone = dynamic_cast<Bone*>(&node);
if (!bone)
return;
bone->computeBindMatrix();
traverse(node);
}
};
struct updateMatrixVisitor : public osg::NodeVisitor
{
osg::Matrix _skeleton;
updateMatrixVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
void apply(osg::Node& node) { return ;}
void apply(osg::Transform& node)
{
// the idea is to traverse the skeleton or bone but to stop if other node is found
Bone* bone = dynamic_cast<Bone*>(&node);
if (!bone)
return;
Bone* parent = bone->getBoneParent();
if (bone->needToComputeBindMatrix())
{
computeBindMatrixVisitor visitor;
bone->accept(visitor);
}
if (parent)
bone->_boneInSkeletonSpace = bone->getMatrixInBoneSpace() * bone->getBoneParent()->getMatrixInSkeletonSpace();
else
bone->_boneInSkeletonSpace = bone->getMatrixInBoneSpace();// * _skeleton;
traverse(node);
}
};
void Skeleton::UpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
{
Skeleton* b = dynamic_cast<Skeleton*>(node);
if (b)
{
// apply the updater only on the root bone, The udpateMatrixVisitor will
// traverse only bone and will update only bone. Then we continu on the classic
// process. It's important to update Bone before other things because the update
// of RigGeometry need it
updateMatrixVisitor visitor;
#if 0
visitor._skeleton = b->getMatrix();
int numChildren = b->getNumChildren();
for (int i = 0; i < numChildren; i++)
{
b->getChild(i)->accept(visitor);
}
#else
b->accept(visitor);
#endif
}
}
traverse(node,nv);
}
Skeleton::Skeleton()
{
setUpdateCallback(new UpdateCallback());
}

View File

@@ -0,0 +1,22 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Target>
#include <osgAnimation/Channel>
using namespace osgAnimation;
Target::Target() { reset();}
Target::~Target() {}

View File

@@ -0,0 +1,49 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/Timeline>
using namespace osgAnimation;
// temporary
// the problem comes that the AnimationManagerBase should only a group
// and it's data should be in an update callback
struct TimelineAdaptator : public Timeline
{
osg::ref_ptr<AnimationManagerTimeline> _manager;
TimelineAdaptator(AnimationManagerTimeline* manager) : _manager(manager) {}
void evaluate(unsigned int frame)
{
_manager->clearTargets();
Timeline::evaluate(frame);
_manager->normalizeTargets();
}
};
AnimationManagerTimeline::AnimationManagerTimeline()
{
_timeline = new TimelineAdaptator(this);
}
AnimationManagerTimeline::AnimationManagerTimeline(const AnimationManagerBase& manager) : AnimationManagerBase(manager)
{
_timeline = new TimelineAdaptator(this);
}
void AnimationManagerTimeline::update(double time)
{
_timeline->update(time);
}

View File

@@ -0,0 +1,170 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/UpdateCallback>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
using namespace osgAnimation;
osgAnimation::AnimationManagerBase* AnimationUpdateCallback::getAnimationManager() { return _manager.get(); }
AnimationUpdateCallback::AnimationUpdateCallback(const AnimationUpdateCallback& apc,const osg::CopyOp& copyop):
osg::NodeCallback(apc, copyop),
_manager(apc._manager) {}
int AnimationUpdateCallback::link(osgAnimation::Animation* animation)
{
int nbLinks = 0;
for (osgAnimation::ChannelList::iterator it = animation->getChannels().begin();
it != animation->getChannels().end();
it++)
{
std::string targetName = (*it)->getTargetName();
if (targetName == getName())
{
link((*it).get());
nbLinks++;
}
}
return nbLinks;
}
void AnimationUpdateCallback::updateLink()
{
if (_manager.valid())
{
if (needLink())
{
/** this item is not linked yet then we do it for all animation
registered in the manager.
Maybe this function should be on the manager side like
_manager->linkItem(Bone);
*/
AnimationMap map = _manager->getAnimationMap();
for (AnimationMap::iterator it = map.begin(); it != map.end(); it++)
link(it->second.get());
_manager->buildTargetReference();
}
}
}
UpdateTransform::UpdateTransform(const UpdateTransform& apc,const osg::CopyOp& copyop)
: AnimationUpdateCallback(apc, copyop),
_euler(apc._euler),
_position(apc._position),
_scale(apc._scale)
{
}
UpdateTransform::UpdateTransform(const std::string& name) : AnimationUpdateCallback(name)
{
_euler = new osgAnimation::Vec3Target;
_position = new osgAnimation::Vec3Target;
_scale = new osgAnimation::Vec3Target(osg::Vec3(1,1,1));
}
/** Callback method called by the NodeVisitor when visiting a node.*/
void UpdateTransform::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
{
osg::MatrixTransform* matrix = dynamic_cast<osg::MatrixTransform*>(node);
if (matrix)
{
update(*matrix);
}
else
{
osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
if (pat)
update(*pat);
}
}
traverse(node,nv);
}
void UpdateTransform::update(osg::MatrixTransform& mat)
{
float z = _euler->getValue()[2];
float x = _euler->getValue()[0];
float y = _euler->getValue()[1];
osg::Matrix m =
osg::Matrix::rotate(x,1.0,0.0,0.0) *
osg::Matrix::rotate(y,0.0,1.0,0.0) *
osg::Matrix::rotate(z,0.0,0.0,1.0);
mat.setMatrix(osg::Matrix::scale(_scale->getValue()) *
m *
osg::Matrix::translate(_position->getValue()));
mat.dirtyBound();
}
void UpdateTransform::update(osg::PositionAttitudeTransform& pat)
{
float heading = _euler->getValue()[0];
float pitch = _euler->getValue()[1];
float roll = _euler->getValue()[2];
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);
osg::Quat q = m.getRotate();
pat.setPosition(_position->getValue());
pat.setScale(_scale->getValue());
pat.setAttitude(q);
pat.dirtyBound();
}
bool UpdateTransform::needLink() const
{
// the idea is to return true if nothing is linked
return !((_position->getCount() + _euler->getCount() + _scale->getCount()) > 3);
}
bool UpdateTransform::link(osgAnimation::Channel* channel)
{
if (channel->getName().find("euler") != std::string::npos)
{
osgAnimation::Vec3LinearChannel* qc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
if (qc)
{
qc->setTarget(_euler.get());
return true;
}
}
else if (channel->getName().find("position") != std::string::npos)
{
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
if (vc)
{
vc->setTarget(_position.get());
return true;
}
}
else if (channel->getName().find("scale") != std::string::npos)
{
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
if (vc)
{
vc->setTarget(_scale.get());
return true;
}
}
else
{
std::cerr << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;
}
return false;
}

View File

@@ -0,0 +1,130 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgAnimation/VertexInfluence>
#include <iostream>
#include <algorithm>
using namespace osgAnimation;
// this class manage VertexInfluence database by mesh
// reference bones per vertex ...
void osgAnimation::VertexInfluenceSet::buildVertex2BoneList()
{
_vertex2Bones.clear();
for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); it++)
{
const VertexInfluence& vi = (*it);
int size = vi.size();
for (int i = 0; i < size; i++)
{
VertexIndexWeight viw = vi[i];
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;
_vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight));
}
}
// normalize weight per vertex
for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++)
{
BoneWeightList& bones = it->second;
int size = bones.size();
float sum = 0;
for (int i = 0; i < size; i++)
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;
}
else
{
float mult = 1.0/sum;
for (int i = 0; i < size; i++)
bones[i].setWeight(bones[i].getWeight() * mult);
}
}
}
// sort by name and weight
struct SortByNameAndWeight : public std::less<osgAnimation::VertexInfluenceSet::BoneWeight>
{
bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeight& b0,
const osgAnimation::VertexInfluenceSet::BoneWeight& b1) const
{
if (b0.getBoneName() < b1.getBoneName())
return true;
else if (b0.getBoneName() > b1.getBoneName())
return false;
if (b0.getWeight() < b1.getWeight())
return true;
return false;
}
};
struct SortByBoneWeightList : public std::less<osgAnimation::VertexInfluenceSet::BoneWeightList>
{
bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeightList& b0,
const osgAnimation::VertexInfluenceSet::BoneWeightList& b1) const
{
if (b0.size() < b1.size())
return true;
else if (b0.size() > b1.size())
return false;
int size = b0.size();
for (int i = 0; i < size; i++)
{
bool result = SortByNameAndWeight()(b0[i], b1[i]);
if (result)
return true;
else if (SortByNameAndWeight()(b1[i], b0[i]))
return false;
}
return false;
}
};
void osgAnimation::VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
{
_uniqVertexSetToBoneSet.clear();
typedef std::map<BoneWeightList,UniqVertexSetToBoneSet, SortByBoneWeightList> UnifyBoneGroup;
UnifyBoneGroup unifyBuffer;
for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++)
{
BoneWeightList bones = it->second;
int vertexIndex = it->first;
// sort the vector to have a consistent key
std::sort(bones.begin(), bones.end(), SortByNameAndWeight());
// we use the vector<BoneWeight> as key to differentiate group
UnifyBoneGroup::iterator result = unifyBuffer.find(bones);
if (result == unifyBuffer.end())
unifyBuffer[bones].setBones(bones);
unifyBuffer[bones].getVertexes().push_back(vertexIndex);
}
_uniqVertexSetToBoneSet.reserve(unifyBuffer.size());
for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); it++)
{
_uniqVertexSetToBoneSet.push_back(it->second);
}
}

View File

@@ -33,6 +33,7 @@ SET(TARGET_COMMON_LIBRARIES
#
# NodeKit/Psudo loader plugins
#
ADD_SUBDIRECTORY(osgAnimation)
ADD_SUBDIRECTORY(osgFX)
ADD_SUBDIRECTORY(osgParticle)
ADD_SUBDIRECTORY(osgSim)

View File

@@ -0,0 +1,9 @@
SET(TARGET_SRC
ReaderWriter.cpp
)
SET(TARGET_ADDED_LIBRARIES osgAnimation )
#### end var setup ###
SETUP_PLUGIN(osganimation)

View File

@@ -0,0 +1,491 @@
/* -*-c++-*-
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
*
* 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
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgDB/Registry>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/ReaderWriter>
#include <osgAnimation/AnimationManager>
#include <osgAnimation/VertexInfluence>
#include <osgAnimation/Animation>
#include <osgAnimation/Bone>
#include <osgAnimation/Skeleton>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/UpdateCallback>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
using namespace osgDB;
using namespace osg;
bool Bone_readLocalData(Object& obj, Input& fr)
{
osgAnimation::Bone& bone = dynamic_cast<osgAnimation::Bone&>(obj);
osg::Quat att;
bool iteratorAdvanced = false;
if (fr.matchSequence("bindQuaternion %f %f %f %f"))
{
fr[1].getFloat(att[0]);
fr[2].getFloat(att[1]);
fr[3].getFloat(att[2]);
fr[4].getFloat(att[3]);
fr += 5;
iteratorAdvanced = true;
}
osg::Vec3d pos(0,0,0);
if (fr.matchSequence("bindPosition %f %f %f"))
{
fr[1].getFloat(pos[0]);
fr[2].getFloat(pos[1]);
fr[3].getFloat(pos[2]);
fr += 4;
iteratorAdvanced = true;
}
osg::Vec3d scale(1,1,1);
if (fr.matchSequence("bindScale %f %f %f"))
{
fr[1].getFloat(scale[0]);
fr[2].getFloat(scale[1]);
fr[3].getFloat(scale[2]);
fr += 4;
iteratorAdvanced = true;
}
bone.setBindMatrixInBoneSpace( osg::Matrix(att) * osg::Matrix::translate(pos));
if (bone.getUpdateCallback() && bone.getUpdateCallback()->getName().empty() && bone.getUpdateCallback()->getNestedCallback())
bone.setUpdateCallback(bone.getUpdateCallback()->getNestedCallback()); // skip the default callback build in constructor of Bone
return iteratorAdvanced;
}
bool Bone_writeLocalData(const Object& obj, Output& fw)
{
const osgAnimation::Bone& bone = dynamic_cast<const osgAnimation::Bone&>(obj);
osg::Vec3 t;
osg::Quat r;
osg::Vec3 s;
osg::Quat rs;
bone.getBindMatrixInBoneSpace().decompose(t,r,s,rs);
fw.indent() << "bindQuaternion " << r << std::endl;
fw.indent() << "bindPosition " << t << std::endl;
fw.indent() << "bindScale " << s << std::endl;
return true;
}
RegisterDotOsgWrapperProxy g_atkBoneProxy
(
new osgAnimation::Bone,
"osgAnimation::Bone",
"Object Node Transform osgAnimation::Bone Group",
&Bone_readLocalData,
&Bone_writeLocalData
);
bool Skeleton_readLocalData(Object& obj, Input& fr)
{
return false;
}
bool Skeleton_writeLocalData(const Object& obj, Output& fr)
{
return true;
}
RegisterDotOsgWrapperProxy g_atkRootSkeletonProxy
(
new osgAnimation::Skeleton,
"osgAnimation::Skeleton",
"Object Node Transform osgAnimation::Bone osgAnimation::Skeleton Group",
&Skeleton_readLocalData,
&Skeleton_writeLocalData,
DotOsgWrapper::READ_AND_WRITE
);
bool Animation_readLocalData(Object& obj, Input& fr)
{
osgAnimation::Animation& anim = dynamic_cast<osgAnimation::Animation&>(obj);
bool iteratorAdvanced = false;
int nbChannels = 0;
if (fr.matchSequence("num_channels %i"))
{
fr[1].getInt(nbChannels);
fr += 2;
iteratorAdvanced = true;
}
for (int i = 0; i < nbChannels; i++)
{
if (fr.matchSequence("Channel {"))
{
fr += 2;
std::string name = "unknown";
if (fr.matchSequence("name %s"))
{
name = fr[1].getStr();
fr += 2;
iteratorAdvanced = true;
}
std::string target = "unknown";
if (fr.matchSequence("target %s"))
{
target = fr[1].getStr();
fr += 2;
iteratorAdvanced = true;
}
std::string type;
int nbKeys;
if (fr.matchSequence("Keyframes %s %i {"))
{
type = fr[1].getStr();
fr[2].getInt(nbKeys);
fr += 4;
iteratorAdvanced = true;
osgAnimation::Channel* channel = 0;
if (type == "Quat")
{
osgAnimation::QuatSphericalLinearChannel* c = new osgAnimation::QuatSphericalLinearChannel;
c->getOrCreateSampler()->getOrCreateKeyframeContainer();
channel = c;
}
else if (type == "Vec3")
{
channel = new osgAnimation::Vec3LinearChannel;
osgAnimation::Vec3LinearChannel* c = new osgAnimation::Vec3LinearChannel;
c->getOrCreateSampler()->getOrCreateKeyframeContainer();
channel = c;
}
if (channel)
{
for (int k = 0; k < nbKeys; k++)
{
if (type == "Quat")
{
osg::Quat q;
float time;
fr.matchSequence("key %f %f %f %f %f");
fr[1].getFloat(time);
fr[2].getFloat(q[0]);
fr[3].getFloat(q[1]);
fr[4].getFloat(q[2]);
fr[5].getFloat(q[3]);
fr += 6;
osgAnimation::QuatSphericalLinearChannel* c = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(channel);
c->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::QuatKeyframe(time, q));
iteratorAdvanced = true;
}
else if (type == "Vec3")
{
osg::Vec3 v;
float time;
fr.matchSequence("key %f %f %f %f");
fr[1].getFloat(time);
fr[2].getFloat(v[0]);
fr[3].getFloat(v[1]);
fr[4].getFloat(v[2]);
fr += 5;
osgAnimation::Vec3LinearChannel* c = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
c->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(time, v));
iteratorAdvanced = true;
}
}
channel->setName(name);
channel->setTargetName(target);
anim.addChannel(channel);
}
if (fr.matchSequence("}")) // keyframes
fr += 1;
if (fr.matchSequence("}")) // channel
fr += 1;
}
}
}
return iteratorAdvanced;
}
bool Animation_writeLocalData(const Object& obj, Output& fw)
{
const osgAnimation::Animation& anim = dynamic_cast<const osgAnimation::Animation&>(obj);
fw.indent() << "num_channels " << anim.getChannels().size() << std::endl;
for (unsigned int i = 0; i < anim.getChannels().size(); i++)
{
fw.indent() << "Channel {" << std::endl;
fw.moveIn();
fw.indent() << "name \"" << anim.getChannels()[i]->getName() << "\"" << std::endl;
fw.indent() << "target \"" << anim.getChannels()[i]->getTargetName() << "\"" << std::endl;
std::string type = "unknown";
if (anim.getChannels()[i]->getName() == std::string("quaternion"))
{
type = "Quat";
}
else if (anim.getChannels()[i]->getName() == std::string("rotation"))
{
type = "Quat";
}
else if (anim.getChannels()[i]->getName() == std::string("euler"))
{
type = "Vec3";
}
else if (anim.getChannels()[i]->getName() == std::string("scale"))
{
type = "Vec3";
}
else if (anim.getChannels()[i]->getName() == std::string("position"))
{
type = "Vec3";
}
osgAnimation::KeyframeContainer* kf = anim.getChannels()[i]->getSampler()->getKeyframeContainer();
fw.indent() << "Keyframes \"" << type << "\" " << kf->size() << " {" << std::endl;
fw.moveIn();
for (unsigned int k = 0; k < kf->size(); k++)
{
if (type == "Vec3")
{
osgAnimation::Vec3KeyframeContainer* kk = dynamic_cast<osgAnimation::Vec3KeyframeContainer*>(kf);
fw.indent() << "key " << (*kk)[k].getTime() << " " << (*kk)[k].getValue() << std::endl;
}
else if ( type == "Quat")
{
osgAnimation::QuatKeyframeContainer* kk = dynamic_cast<osgAnimation::QuatKeyframeContainer*>(kf);
fw.indent() << "key " << (*kk)[k].getTime() << " " << (*kk)[k].getValue() << std::endl;
}
}
fw.moveOut();
fw.indent() << "}" << std::endl;
fw.moveOut();
fw.indent() << "}" << std::endl;
}
return true;
}
RegisterDotOsgWrapperProxy g_atkAnimationProxy
(
new osgAnimation::Animation,
"osgAnimation::Animation",
"Object osgAnimation::Animation",
&Animation_readLocalData,
&Animation_writeLocalData
);
bool AnimationManager_readLocalData(Object& obj, Input& fr)
{
osgAnimation::AnimationManager& manager = dynamic_cast<osgAnimation::AnimationManager&>(obj);
int nbAnims = 0;
bool iteratorAdvanced = false;
if (fr.matchSequence("num_animations %i"))
{
fr[1].getInt(nbAnims);
fr += 2;
iteratorAdvanced = true;
}
for (int i = 0; i < nbAnims; i++)
{
Object* o = fr.readObject();
osgAnimation::Animation* a = dynamic_cast<osgAnimation::Animation*>(o);
if (a)
{
manager.registerAnimation(a);
iteratorAdvanced = true;
}
else
osg::notify(osg::WARN)<<"Warning: can't read an animation object"<< std::endl;
}
return iteratorAdvanced;
}
bool AnimationManager_writeLocalData(const Object& obj, Output& fw)
{
const osgAnimation::AnimationManager& manager = dynamic_cast<const osgAnimation::AnimationManager&>(obj);
osgAnimation::AnimationMap map = manager.getAnimationMap();
int nbanims = map.size();
fw.indent() << "num_animations " << nbanims << std::endl;
for (osgAnimation::AnimationMap::iterator it = map.begin(); it != map.end(); it++)
{
if (!fw.writeObject(*it->second))
osg::notify(osg::WARN)<<"Warning: can't write an animation object"<< std::endl;
}
return true;
}
RegisterDotOsgWrapperProxy g_atkAnimationManagerProxy
(
new osgAnimation::AnimationManager,
"osgAnimation::AnimationManager",
"Object Node Group osgAnimation::AnimationManager",
&AnimationManager_readLocalData,
&AnimationManager_writeLocalData,
DotOsgWrapper::READ_AND_WRITE
);
bool RigGeometry_readLocalData(Object& obj, Input& fr)
{
osgAnimation::RigGeometry& geom = dynamic_cast<osgAnimation::RigGeometry&>(obj);
osg::ref_ptr<osgAnimation::VertexInfluenceMap> vmap = new osgAnimation::VertexInfluenceMap;
int nbGroups = 0;
bool iteratorAdvanced = false;
if (fr.matchSequence("num_influences %i"))
{
fr[1].getInt(nbGroups);
fr += 2;
iteratorAdvanced = true;
}
for (int i = 0; i < nbGroups; i++)
{
int nbVertexes = 0;
std::string name;
if (fr.matchSequence("osgAnimation::VertexInfluence %s %i {"))
{
name = fr[1].getStr();
fr[2].getInt(nbVertexes);
fr += 4;
iteratorAdvanced = true;
}
osgAnimation::VertexInfluence vi;
vi.setName(name);
vi.reserve(nbVertexes);
for (int j = 0; j < nbVertexes; j++)
{
int index = -1;
float weight = 1;
if (fr.matchSequence("%i %f"))
{
fr[0].getInt(index);
fr[1].getFloat(weight);
fr += 2;
iteratorAdvanced = true;
}
vi.push_back(osgAnimation::VertexIndexWeight(index, weight));
}
if (fr.matchSequence("}"))
{
fr+=1;
}
(*vmap)[name] = vi;
}
if (!vmap->empty())
geom.setInfluenceMap(vmap.get());
return iteratorAdvanced;
}
bool RigGeometry_writeLocalData(const Object& obj, Output& fw)
{
const osgAnimation::RigGeometry& geom = dynamic_cast<const osgAnimation::RigGeometry&>(obj);
const osgAnimation::VertexInfluenceMap* vm = geom.getInfluenceMap();
if (!vm)
return true;
fw.indent() << "num_influences " << vm->size() << std::endl;
fw.moveIn();
for (osgAnimation::VertexInfluenceMap::const_iterator it = vm->begin(); it != vm->end(); it++)
{
std::string name = it->first;
if (name.empty())
name = "Empty";
fw.indent() << "osgAnimation::VertexInfluence \"" << name << "\" " << it->second.size() << " {" << std::endl;
fw.moveIn();
const osgAnimation::VertexInfluence& vi = it->second;
for (osgAnimation::VertexInfluence::const_iterator itv = vi.begin(); itv != vi.end(); itv++)
{
fw.indent() << itv->first << " " << itv->second << std::endl;
}
fw.moveOut();
fw.indent() << "}" << std::endl;
}
fw.moveOut();
return true;
}
RegisterDotOsgWrapperProxy g_atkRigGeometryProxy
(
new osgAnimation::RigGeometry,
"osgAnimation::RigGeometry",
"Object Drawable osgAnimation::RigGeometry Geometry",
&RigGeometry_readLocalData,
&RigGeometry_writeLocalData,
DotOsgWrapper::READ_AND_WRITE
);
bool UpdateBone_readLocalData(Object& obj, Input& fr)
{
bool iteratorAdvanced = false;
return iteratorAdvanced;
}
bool UpdateBone_writeLocalData(const Object& obj, Output& fw)
{
return true;
}
RegisterDotOsgWrapperProxy g_atkUpdateBoneProxy
(
new osgAnimation::Bone::UpdateBone,
"osgAnimation::UpdateBone",
"Object osgAnimation::UpdateBone",
&UpdateBone_readLocalData,
&UpdateBone_writeLocalData,
DotOsgWrapper::READ_AND_WRITE
);
bool UpdateTransform_readLocalData(Object& obj, Input& fr)
{
bool iteratorAdvanced = false;
return iteratorAdvanced;
}
bool UpdateTransform_writeLocalData(const Object& obj, Output& fw)
{
return true;
}
RegisterDotOsgWrapperProxy g_atkUpdateTransformProxy
(
new osgAnimation::UpdateTransform,
"osgAnimation::UpdateTransform",
"Object osgAnimation::UpdateTransform",
&UpdateTransform_readLocalData,
&UpdateTransform_writeLocalData,
DotOsgWrapper::READ_AND_WRITE
);