2.8 branch: backport of osgAnimation from svn head 11026.
This commit is contained in:
147
include/osgAnimation/Action
Normal file
147
include/osgAnimation/Action
Normal file
@@ -0,0 +1,147 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_H
|
||||
#define OSGANIMATION_ACTION_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/ActionVisitor>
|
||||
#include <osgAnimation/FrameAction>
|
||||
#include <iostream>
|
||||
|
||||
#define META_Action(library,name) \
|
||||
virtual osg::Object* cloneType() const { return new name (); } \
|
||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
|
||||
virtual const char* className() const { return #name; } \
|
||||
virtual const char* libraryName() const { return #library; } \
|
||||
virtual void accept(osgAnimation::ActionVisitor& nv) { nv.apply(*this); } \
|
||||
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Action : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
class Callback : public osg::Object
|
||||
{
|
||||
public:
|
||||
Callback(){}
|
||||
Callback(const Callback& nc,const osg::CopyOp&) :
|
||||
_nestedCallback(nc._nestedCallback) {}
|
||||
|
||||
META_Object(osgAnimation,Callback);
|
||||
|
||||
virtual void operator()(Action* action, osgAnimation::ActionVisitor* nv) {}
|
||||
|
||||
Callback* getNestedCallback() { return _nestedCallback.get(); }
|
||||
void addNestedCallback(Callback* callback)
|
||||
{
|
||||
if (callback) {
|
||||
if (_nestedCallback.valid())
|
||||
_nestedCallback->addNestedCallback(callback);
|
||||
else
|
||||
_nestedCallback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
void removeCallback(Callback* cb)
|
||||
{
|
||||
if (!cb)
|
||||
return;
|
||||
|
||||
if (_nestedCallback.get() == cb)
|
||||
_nestedCallback = _nestedCallback->getNestedCallback();
|
||||
else if (_nestedCallback.valid())
|
||||
_nestedCallback->removeCallback(cb);
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Callback> _nestedCallback;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
|
||||
|
||||
META_Action(osgAnimation, Action);
|
||||
|
||||
Action();
|
||||
Action(const Action&,const osg::CopyOp&);
|
||||
|
||||
void setCallback(double when, Callback* callback)
|
||||
{
|
||||
setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
|
||||
}
|
||||
|
||||
void setCallback(unsigned int frame, Callback* callback)
|
||||
{
|
||||
if (_framesCallback[frame].valid())
|
||||
_framesCallback[frame]->addNestedCallback(callback);
|
||||
else
|
||||
_framesCallback[frame] = callback;
|
||||
}
|
||||
Callback* getCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) == _framesCallback.end())
|
||||
return 0;
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
|
||||
void removeCallback(Callback*);
|
||||
|
||||
Callback* getFrameCallback(unsigned int frame);
|
||||
Callback* getFrameCallback(double time);
|
||||
unsigned int getFramesPerSecond() const { return _fps; }
|
||||
|
||||
void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
|
||||
void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
|
||||
unsigned int getNumFrames() const { return _numberFrame;}
|
||||
double getDuration() const { return _numberFrame * 1.0 / _fps; }
|
||||
|
||||
// 0 means infini else it's the number of loop
|
||||
virtual void setLoop(int nb) { _loop = nb; }
|
||||
virtual unsigned int getLoop() const { return _loop;}
|
||||
|
||||
// get the number of loop, the frame relative to loop.
|
||||
// return true if in range, and false if out of range.
|
||||
bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop );
|
||||
virtual void traverse(ActionVisitor& visitor) {}
|
||||
//virtual void evaluate(unsigned int frame);
|
||||
|
||||
protected:
|
||||
FrameCallback _framesCallback;
|
||||
|
||||
double _speed;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _loop;
|
||||
|
||||
enum Status
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
};
|
||||
|
||||
Status _state;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
41
include/osgAnimation/ActionAnimation
Normal file
41
include/osgAnimation/ActionAnimation
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_ANIMATION_H
|
||||
#define OSGANIMATION_ACTION_ANIMATION_H
|
||||
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
|
||||
namespace osgAnimation {
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT ActionAnimation : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, ActionAnimation);
|
||||
ActionAnimation();
|
||||
ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c);
|
||||
ActionAnimation(Animation* animation);
|
||||
void updateAnimation(unsigned int frame, int priority);
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
44
include/osgAnimation/ActionBlendIn
Normal file
44
include/osgAnimation/ActionBlendIn
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_BLENDIN_H
|
||||
#define OSGANIMATION_ACTION_BLENDIN_H
|
||||
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
|
||||
namespace osgAnimation {
|
||||
|
||||
|
||||
/// blend in from 0 to weight in duration
|
||||
class OSGANIMATION_EXPORT ActionBlendIn : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, ActionBlendIn);
|
||||
ActionBlendIn();
|
||||
ActionBlendIn(const ActionBlendIn& a, const osg::CopyOp& c);
|
||||
ActionBlendIn(Animation* animation, double duration, double weight);
|
||||
double getWeight() const { return _weight;}
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
void computeWeight(unsigned int frame);
|
||||
|
||||
protected:
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
45
include/osgAnimation/ActionBlendOut
Normal file
45
include/osgAnimation/ActionBlendOut
Normal file
@@ -0,0 +1,45 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_BLENDOUT_H
|
||||
#define OSGANIMATION_ACTION_BLENDOUT_H
|
||||
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/Export>
|
||||
|
||||
|
||||
namespace osgAnimation {
|
||||
|
||||
|
||||
/// blend out from weight to 0 in duration
|
||||
class OSGANIMATION_EXPORT ActionBlendOut : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, ActionBlendOut);
|
||||
ActionBlendOut();
|
||||
ActionBlendOut(const ActionBlendOut& a, const osg::CopyOp& c);
|
||||
ActionBlendOut(Animation* animation, double duration);
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
double getWeight() const { return _weight;}
|
||||
void computeWeight(unsigned int frame);
|
||||
|
||||
protected:
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
41
include/osgAnimation/ActionCallback
Normal file
41
include/osgAnimation/ActionCallback
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_CALLBACK_H
|
||||
#define OSGANIMATION_ACTION_CALLBACK_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Action>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
/** Callback used to run new action on the timeline.*/
|
||||
class OSGANIMATION_EXPORT RunAction : public Action::Callback
|
||||
{
|
||||
public:
|
||||
RunAction(Action* a, int priority = 0) : _action(a), _priority(priority) {}
|
||||
virtual void operator()(Action* action, ActionVisitor* visitor);
|
||||
|
||||
Action* getAction() const { return _action.get(); }
|
||||
int getPriority() const { return _priority; }
|
||||
protected:
|
||||
osg::ref_ptr<Action> _action;
|
||||
int _priority;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
57
include/osgAnimation/ActionStripAnimation
Normal file
57
include/osgAnimation/ActionStripAnimation
Normal file
@@ -0,0 +1,57 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_STRIPANIMATION_H
|
||||
#define OSGANIMATION_ACTION_STRIPANIMATION_H
|
||||
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/FrameAction>
|
||||
#include <osgAnimation/ActionBlendIn>
|
||||
#include <osgAnimation/ActionBlendOut>
|
||||
#include <osgAnimation/ActionAnimation>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
// encapsulate animation with blend in blend out for classic usage
|
||||
class OSGANIMATION_EXPORT ActionStripAnimation : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, ActionStripAnimation);
|
||||
ActionStripAnimation() {}
|
||||
ActionStripAnimation(const ActionStripAnimation& a, const osg::CopyOp& c);
|
||||
ActionStripAnimation(Animation* animation, double blendInDuration = 0.0, double blendOutDuration = 0.0, double blendInWeightTarget = 1.0 );
|
||||
ActionAnimation* getAnimation();
|
||||
ActionBlendIn* getBlendIn();
|
||||
ActionBlendOut* getBlendOut();
|
||||
const ActionAnimation* getAnimation() const;
|
||||
const ActionBlendIn* getBlendIn() const;
|
||||
const ActionBlendOut* getBlendOut() const;
|
||||
unsigned int getBlendOutStartFrame() const;
|
||||
|
||||
unsigned int getLoop() const;
|
||||
void setLoop(unsigned int loop);
|
||||
void traverse(ActionVisitor& visitor);
|
||||
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<ActionBlendOut> > FrameBlendOut;
|
||||
osg::ref_ptr<ActionBlendIn> _blendIn;
|
||||
FrameBlendOut _blendOut;
|
||||
osg::ref_ptr<ActionAnimation> _animation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
117
include/osgAnimation/ActionVisitor
Normal file
117
include/osgAnimation/ActionVisitor
Normal file
@@ -0,0 +1,117 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTIONVISITOR_H
|
||||
#define OSGANIMATION_ACTIONVISITOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/Referenced>
|
||||
#include <osgAnimation/FrameAction>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Timeline;
|
||||
class Action;
|
||||
class ActionBlendIn;
|
||||
class ActionBlendOut;
|
||||
class ActionAnimation;
|
||||
class ActionStripAnimation;
|
||||
|
||||
#define META_ActionVisitor(library,name) \
|
||||
virtual const char* libraryName() const { return #library; }\
|
||||
virtual const char* className() const { return #name; }
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT ActionVisitor : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
META_ActionVisitor(osgAnimation, ActionVisitor);
|
||||
ActionVisitor();
|
||||
void traverse(Action& visitor);
|
||||
|
||||
void pushFrameActionOnStack(const FrameAction& fa);
|
||||
void popFrameAction();
|
||||
|
||||
void pushTimelineOnStack(Timeline* tm);
|
||||
void popTimeline();
|
||||
|
||||
Timeline* getCurrentTimeline();
|
||||
void setCurrentLayer(int layer) { _currentLayer = layer;}
|
||||
int getCurrentLayer() const { return _currentLayer; }
|
||||
|
||||
const std::vector<FrameAction>& getStackedFrameAction() const { return _stackFrameAction; }
|
||||
|
||||
virtual void apply(Action& action);
|
||||
virtual void apply(Timeline& tm);
|
||||
virtual void apply(ActionBlendIn& action);
|
||||
virtual void apply(ActionBlendOut& action);
|
||||
virtual void apply(ActionAnimation& action);
|
||||
virtual void apply(ActionStripAnimation& action);
|
||||
|
||||
protected:
|
||||
std::vector<FrameAction> _stackFrameAction;
|
||||
std::vector<Timeline*> _stackTimeline;
|
||||
int _currentLayer;
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateActionVisitor : public osgAnimation::ActionVisitor
|
||||
{
|
||||
protected:
|
||||
unsigned int _frame;
|
||||
unsigned int _currentAnimationPriority;
|
||||
public:
|
||||
META_ActionVisitor(osgAnimation, UpdateActionVisitor);
|
||||
UpdateActionVisitor();
|
||||
void setFrame(unsigned int frame) { _frame = frame;}
|
||||
|
||||
bool isActive(Action& action) const;
|
||||
unsigned int getLocalFrame() const;
|
||||
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
void apply(ActionBlendIn& action);
|
||||
void apply(ActionBlendOut& action);
|
||||
void apply(ActionAnimation& action);
|
||||
void apply(ActionStripAnimation& action);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT ClearActionVisitor : public osgAnimation::ActionVisitor
|
||||
{
|
||||
public:
|
||||
enum ClearType {
|
||||
BEFORE_FRAME,
|
||||
AFTER_FRAME
|
||||
};
|
||||
|
||||
META_ActionVisitor(osgAnimation, ClearActionVisitor);
|
||||
ClearActionVisitor(ClearType type = BEFORE_FRAME);
|
||||
void setFrame(unsigned int frame) { _frame = frame;}
|
||||
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
|
||||
protected:
|
||||
unsigned int _frame;
|
||||
std::vector<osg::ref_ptr<Action> > _remove;
|
||||
ClearType _clearType;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -31,7 +31,7 @@ namespace osgAnimation
|
||||
META_Object(osgAnimation, Animation)
|
||||
|
||||
Animation() : _duration(0), _weight(0), _startTime(0), _playmode(LOOP) {}
|
||||
Animation(const osgAnimation::Animation& anim, const osg::CopyOp&);
|
||||
Animation(const osgAnimation::Animation&, const osg::CopyOp&);
|
||||
|
||||
enum PlayMode
|
||||
{
|
||||
@@ -71,10 +71,12 @@ namespace osgAnimation
|
||||
void setWeight (float weight);
|
||||
float getWeight() const;
|
||||
|
||||
bool update (float time);
|
||||
bool update (float time, int priority = 0);
|
||||
void resetTargets();
|
||||
|
||||
void setPlaymode (PlayMode mode) { _playmode = mode; }
|
||||
PlayMode getPlayMode() const { return _playmode; }
|
||||
|
||||
void setStartTime(float time) { _startTime = time;}
|
||||
float getStartTime() const { return _startTime;}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,9 +12,10 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ANIMATION_MANAGER_BASE_H
|
||||
#define OSGANIMATION_ANIMATION_MANAGER_BASE_H
|
||||
#ifndef OSGANIMATION_ANIMATION_MANAGER_BASE
|
||||
#define OSGANIMATION_ANIMATION_MANAGER_BASE 1
|
||||
|
||||
#include <osgAnimation/LinkVisitor>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/FrameStamp>
|
||||
@@ -33,7 +34,8 @@ namespace osgAnimation
|
||||
AnimationManagerBase(const AnimationManagerBase& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY);
|
||||
virtual ~AnimationManagerBase();
|
||||
virtual void buildTargetReference();
|
||||
virtual void registerAnimation (Animation* animation);
|
||||
virtual void registerAnimation (Animation*);
|
||||
virtual void unregisterAnimation (Animation*);
|
||||
virtual void link(osg::Node* subgraph);
|
||||
virtual void update(double t) = 0;
|
||||
virtual bool needToLink() const;
|
||||
@@ -42,16 +44,26 @@ 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();
|
||||
void normalizeTargets();
|
||||
|
||||
|
||||
LinkVisitor* getOrCreateLinkVisitor();
|
||||
void setLinkVisitor(LinkVisitor*);
|
||||
|
||||
/// set a flag to define the behaviour
|
||||
void setAutomaticLink(bool);
|
||||
bool isAutomaticLink() const;
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
|
||||
osg::ref_ptr<LinkVisitor> _linker;
|
||||
AnimationList _animations;
|
||||
TargetSet _targets;
|
||||
bool _needToLink;
|
||||
bool _automaticLink;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
72
include/osgAnimation/AnimationUpdateCallback
Normal file
72
include/osgAnimation/AnimationUpdateCallback
Normal file
@@ -0,0 +1,72 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ANIMATION_UPDATE_CALLBACK
|
||||
#define OSGANIMATION_ANIMATION_UPDATE_CALLBACK 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <string>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class AnimationUpdateCallbackBase : public virtual osg::Object
|
||||
{
|
||||
public:
|
||||
virtual bool link(Channel* channel) = 0;
|
||||
virtual int link(Animation* animation) = 0;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class AnimationUpdateCallback : public AnimationUpdateCallbackBase, public T
|
||||
{
|
||||
public:
|
||||
AnimationUpdateCallback() {}
|
||||
AnimationUpdateCallback(const std::string& name) { T::setName(name);}
|
||||
AnimationUpdateCallback(const AnimationUpdateCallback& apc,const osg::CopyOp& copyop): T(apc, copyop) {}
|
||||
|
||||
META_Object(osgAnimation, AnimationUpdateCallback<T>);
|
||||
|
||||
const std::string& getName() const { return T::getName(); }
|
||||
bool link(Channel* channel) { return 0; }
|
||||
int link(Animation* animation)
|
||||
{
|
||||
if (T::getName().empty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
int nbLinks = 0;
|
||||
for (ChannelList::iterator it = animation->getChannels().begin();
|
||||
it != animation->getChannels().end();
|
||||
++it)
|
||||
{
|
||||
std::string targetName = (*it)->getTargetName();
|
||||
if (targetName == T::getName())
|
||||
{
|
||||
AnimationUpdateCallbackBase* a = this;
|
||||
a->link((*it).get());
|
||||
nbLinks++;
|
||||
}
|
||||
}
|
||||
return nbLinks;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,39 +10,26 @@
|
||||
* 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.
|
||||
*/
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
* Michael Platings <mplatings@pixelpower.com>
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_BONE_H
|
||||
#define OSGANIMATION_BONE_H
|
||||
#ifndef OSGANIMATION_BONE
|
||||
#define OSGANIMATION_BONE 1
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Node>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Target>
|
||||
#include <osgAnimation/Sampler>
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osgAnimation/Keyframe>
|
||||
#include <osgAnimation/UpdateCallback>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
// A bone can't have more than one parent Bone, so sharing a part of Bone's hierarchy
|
||||
// has not sense. You can share the entire hierarchie but not only a part of
|
||||
class OSGANIMATION_EXPORT Bone : public osg::Transform
|
||||
// makes no sense. You can share the entire hierarchy but not only a part of it.
|
||||
class OSGANIMATION_EXPORT Bone : public osg::MatrixTransform
|
||||
{
|
||||
public:
|
||||
typedef osg::ref_ptr<Bone> PointerType;
|
||||
typedef std::map<std::string, PointerType > BoneMap;
|
||||
typedef osg::Matrix MatrixType;
|
||||
|
||||
META_Node(osgAnimation, Bone);
|
||||
@@ -51,230 +38,24 @@ namespace osgAnimation
|
||||
|
||||
void setDefaultUpdateCallback(const std::string& name = "");
|
||||
|
||||
struct BoneMapVisitor : public osg::NodeVisitor
|
||||
{
|
||||
BoneMap _map;
|
||||
BoneMapVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
|
||||
META_NodeVisitor("osgAnimation","BoneMapVisitor")
|
||||
|
||||
void apply(osg::Node&) { return; }
|
||||
void apply(osg::Transform& node)
|
||||
{
|
||||
Bone* bone = dynamic_cast<Bone*>(&node);
|
||||
if (bone)
|
||||
{
|
||||
_map[bone->getName()] = bone;
|
||||
traverse(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FindNearestParentAnimationManager : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<osgAnimation::AnimationManagerBase> _manager;
|
||||
FindNearestParentAnimationManager() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
|
||||
void apply(osg::Node& node)
|
||||
{
|
||||
if (_manager.valid())
|
||||
return;
|
||||
osg::NodeCallback* callback = node.getUpdateCallback();
|
||||
while (callback)
|
||||
{
|
||||
_manager = dynamic_cast<osgAnimation::AnimationManagerBase*>(callback);
|
||||
if (_manager.valid())
|
||||
return;
|
||||
callback = callback->getNestedCallback();
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateBone : public AnimationUpdateCallback
|
||||
{
|
||||
public:
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _position;
|
||||
osg::ref_ptr<osgAnimation::QuatTarget> _quaternion;
|
||||
osg::ref_ptr<osgAnimation::Vec3Target> _scale;
|
||||
|
||||
public:
|
||||
META_Object(osgAnimation, UpdateBone);
|
||||
UpdateBone(const UpdateBone& apc,const osg::CopyOp& copyop);
|
||||
|
||||
UpdateBone(const std::string& name = "")
|
||||
{
|
||||
setName(name);
|
||||
_quaternion = new osgAnimation::QuatTarget;
|
||||
_position = new osgAnimation::Vec3Target;
|
||||
_scale = new osgAnimation::Vec3Target;
|
||||
}
|
||||
|
||||
void update(osgAnimation::Bone& bone)
|
||||
{
|
||||
bone.setTranslation(_position->getValue());
|
||||
bone.setRotation(_quaternion->getValue());
|
||||
bone.setScale(_scale->getValue());
|
||||
bone.dirtyBound();
|
||||
}
|
||||
|
||||
bool needLink() const
|
||||
{
|
||||
// the idea is to return true if nothing is linked
|
||||
return !((_position->getCount() + _quaternion->getCount() + _scale->getCount()) > 3);
|
||||
}
|
||||
|
||||
bool link(osgAnimation::Channel* channel)
|
||||
{
|
||||
if (channel->getName().find("quaternion") != std::string::npos)
|
||||
{
|
||||
osgAnimation::QuatSphericalLinearChannel* qc = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(channel);
|
||||
if (qc)
|
||||
{
|
||||
qc->setTarget(_quaternion.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;
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
Bone* b = dynamic_cast<Bone*>(node);
|
||||
if (b && !_manager.valid())
|
||||
{
|
||||
FindNearestParentAnimationManager 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._manager.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "Warning can't update Bone, path to parent AnimationManagerBase not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_manager = finder._manager.get();
|
||||
}
|
||||
|
||||
updateLink();
|
||||
update(*b);
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
};
|
||||
|
||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
|
||||
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
|
||||
|
||||
Bone* getBoneParent();
|
||||
const Bone* getBoneParent() const;
|
||||
|
||||
void setTranslation(const osg::Vec3& trans) { _position = trans;}
|
||||
void setRotation(const osg::Quat& quat) { _rotation = quat;}
|
||||
void setScale(const osg::Vec3& scale) { _scale = scale;}
|
||||
|
||||
const osg::Vec3& getTranslation() const { return _position;}
|
||||
const osg::Quat& getRotation() const { return _rotation;}
|
||||
osg::Matrix getMatrixInBoneSpace() const { return (osg::Matrix(getRotation())) * osg::Matrix::translate(getTranslation()) * _bindInBoneSpace;}
|
||||
const osg::Matrix& getBindMatrixInBoneSpace() const { return _bindInBoneSpace; }
|
||||
const osg::Matrix& getMatrixInBoneSpace() const { return getMatrix();}
|
||||
const osg::Matrix& getMatrixInSkeletonSpace() const { return _boneInSkeletonSpace; }
|
||||
const osg::Matrix& getInvBindMatrixInSkeletonSpace() const { return _invBindInSkeletonSpace;}
|
||||
void setMatrixInSkeletonSpace(const osg::Matrix& matrix) { _boneInSkeletonSpace = matrix; }
|
||||
void setBindMatrixInBoneSpace(const osg::Matrix& matrix)
|
||||
{
|
||||
_bindInBoneSpace = matrix;
|
||||
_needToRecomputeBindMatrix = true;
|
||||
}
|
||||
|
||||
inline bool needToComputeBindMatrix() { return _needToRecomputeBindMatrix;}
|
||||
virtual void computeBindMatrix();
|
||||
|
||||
bool needLink() const;
|
||||
|
||||
void setNeedToComputeBindMatrix(bool state) { _needToRecomputeBindMatrix = state; }
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
virtual bool addChild( Node *child );
|
||||
BoneMap getBoneMap();
|
||||
|
||||
void setInvBindMatrixInSkeletonSpace(const osg::Matrix& matrix) { _invBindInSkeletonSpace = matrix; }
|
||||
|
||||
protected:
|
||||
|
||||
osg::Vec3 _position;
|
||||
osg::Quat _rotation;
|
||||
osg::Vec3 _scale;
|
||||
|
||||
|
||||
// flag to recompute bind pose
|
||||
bool _needToRecomputeBindMatrix;
|
||||
|
||||
// bind data
|
||||
osg::Matrix _bindInBoneSpace;
|
||||
osg::Matrix _invBindInSkeletonSpace;
|
||||
|
||||
// bone updated
|
||||
osg::Matrix _boneInSkeletonSpace;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline bool Bone::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
|
||||
{
|
||||
if (_referenceFrame==RELATIVE_RF)
|
||||
matrix.preMult(getMatrixInBoneSpace());
|
||||
else
|
||||
matrix = getMatrixInBoneSpace();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool Bone::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
|
||||
{
|
||||
if (_referenceFrame==RELATIVE_RF)
|
||||
matrix.postMult(osg::Matrix::inverse(getMatrixInBoneSpace()));
|
||||
else
|
||||
matrix = osg::Matrix::inverse(getMatrixInBoneSpace());
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef std::map<std::string, osg::ref_ptr<Bone> > BoneMap;
|
||||
}
|
||||
#endif
|
||||
|
||||
42
include/osgAnimation/BoneMapVisitor
Normal file
42
include/osgAnimation/BoneMapVisitor
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_BONEMAP_VISITOR
|
||||
#define OSGANIMATION_BONEMAP_VISITOR 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class OSGANIMATION_EXPORT BoneMapVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
META_NodeVisitor("osgAnimation","BoneMapVisitor")
|
||||
BoneMapVisitor();
|
||||
|
||||
void apply(osg::Node&);
|
||||
void apply(osg::Transform& node);
|
||||
const BoneMap& getBoneMap() const;
|
||||
|
||||
protected:
|
||||
BoneMap _map;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,7 +10,11 @@
|
||||
* 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.
|
||||
*/
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
* Michael Platings <mplatings@pixelpower.com>
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_CHANNEL_H
|
||||
#define OSGANIMATION_CHANNEL_H
|
||||
@@ -29,11 +33,14 @@ namespace osgAnimation
|
||||
public:
|
||||
|
||||
Channel();
|
||||
Channel(const Channel& channel);
|
||||
virtual ~Channel();
|
||||
virtual Channel* clone() const = 0;
|
||||
|
||||
virtual void update(float time) = 0;
|
||||
virtual void update(float time, float weight, int priority) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual Target* getTarget() = 0;
|
||||
virtual bool setTarget(Target*) = 0;
|
||||
|
||||
const std::string& getName() const;
|
||||
void setName(const std::string& name);
|
||||
@@ -44,17 +51,18 @@ namespace osgAnimation
|
||||
const std::string& getTargetName() const;
|
||||
void setTargetName(const std::string& name);
|
||||
|
||||
float getWeight() const;
|
||||
void setWeight(float w);
|
||||
|
||||
virtual Sampler* getSampler() = 0;
|
||||
virtual const Sampler* getSampler() const = 0;
|
||||
|
||||
// create a keyframe container from current target value
|
||||
// with one key only, can be used for debug or to create
|
||||
// easily a default channel from an existing one
|
||||
virtual bool createKeyframeContainerFromTargetValue() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
std::string _targetName;
|
||||
std::string _name;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,8 +74,19 @@ namespace osgAnimation
|
||||
typedef typename SamplerType::UsingType UsingType;
|
||||
typedef TemplateTarget<UsingType> TargetType;
|
||||
typedef TemplateKeyframeContainer<typename SamplerType::KeyframeType> KeyframeContainerType;
|
||||
Channel* clone() const { return new TemplateChannel<SamplerType>(*this); }
|
||||
|
||||
TemplateChannel (SamplerType* s = 0,TargetType* target = 0)
|
||||
TemplateChannel (const TemplateChannel& channel) :
|
||||
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)
|
||||
{
|
||||
if (target)
|
||||
_target = target;
|
||||
@@ -76,20 +95,42 @@ namespace osgAnimation
|
||||
_sampler = s;
|
||||
}
|
||||
|
||||
virtual bool createKeyframeContainerFromTargetValue()
|
||||
{
|
||||
if (!_target.valid()) // no target it does not make sense to do it
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a key from current target value
|
||||
typename KeyframeContainerType::KeyType key(0, _target->getValue());
|
||||
// recreate the keyframe container
|
||||
getOrCreateSampler()->setKeyframeContainer(0);
|
||||
getOrCreateSampler()->getOrCreateKeyframeContainer();
|
||||
// add the key
|
||||
_sampler->getKeyframeContainerTyped()->push_back(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~TemplateChannel() {}
|
||||
virtual void update(float time)
|
||||
virtual void update(float time, float weight, int priority)
|
||||
{
|
||||
// skip if weight == 0
|
||||
if (_weight < 1e-4)
|
||||
if (weight < 1e-4)
|
||||
return;
|
||||
typename SamplerType::UsingType value;
|
||||
_sampler->getValueAt(time, value);
|
||||
_target->update(_weight, value);
|
||||
_target->update(weight, value, priority);
|
||||
}
|
||||
virtual void reset() { _target->reset(); }
|
||||
virtual Target* getTarget() { return _target.get();}
|
||||
virtual bool setTarget(Target* target)
|
||||
{
|
||||
_target = dynamic_cast<TargetType*>(target);
|
||||
return _target.get() == target;
|
||||
}
|
||||
|
||||
SamplerType* getOrCreateSampler()
|
||||
SamplerType* getOrCreateSampler()
|
||||
{
|
||||
if (!_sampler.valid())
|
||||
_sampler = new SamplerType;
|
||||
@@ -104,6 +145,7 @@ namespace osgAnimation
|
||||
void setSampler(SamplerType* sampler) { _sampler = sampler; }
|
||||
|
||||
TargetType* getTargetTyped() { return _target.get(); }
|
||||
const TargetType* getTargetTyped() const { return _target.get(); }
|
||||
void setTarget(TargetType* target) { _target = target; }
|
||||
|
||||
virtual float getStartTime() const { return _sampler->getStartTime(); }
|
||||
@@ -116,13 +158,21 @@ namespace osgAnimation
|
||||
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osgAnimation::Channel> > ChannelList;
|
||||
|
||||
typedef TemplateChannel<DoubleStepSampler> DoubleStepChannel;
|
||||
typedef TemplateChannel<FloatStepSampler> FloatStepChannel;
|
||||
typedef TemplateChannel<Vec2StepSampler> Vec2StepChannel;
|
||||
typedef TemplateChannel<Vec3StepSampler> Vec3StepChannel;
|
||||
typedef TemplateChannel<Vec4StepSampler> Vec4StepChannel;
|
||||
typedef TemplateChannel<QuatStepSampler> QuatStepChannel;
|
||||
|
||||
typedef TemplateChannel<DoubleLinearSampler> DoubleLinearChannel;
|
||||
typedef TemplateChannel<FloatLinearSampler> FloatLinearChannel;
|
||||
|
||||
typedef TemplateChannel<Vec2LinearSampler> Vec2LinearChannel;
|
||||
typedef TemplateChannel<Vec3LinearSampler> Vec3LinearChannel;
|
||||
typedef TemplateChannel<Vec4LinearSampler> Vec4LinearChannel;
|
||||
typedef TemplateChannel<QuatSphericalLinearSampler> QuatSphericalLinearChannel;
|
||||
typedef TemplateChannel<MatrixLinearSampler> MatrixLinearChannel;
|
||||
|
||||
typedef TemplateChannel<FloatCubicBezierSampler> FloatCubicBezierChannel;
|
||||
typedef TemplateChannel<DoubleCubicBezierSampler> DoubleCubicBezierChannel;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,38 +12,61 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_CUBIC_BEZIER_H
|
||||
#define OSGANIMATION_CUBIC_BEZIER_H
|
||||
#ifndef OSGANIMATION_CUBIC_BEZIER
|
||||
#define OSGANIMATION_CUBIC_BEZIER 1
|
||||
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct TemplateCubicBezier
|
||||
class TemplateCubicBezier
|
||||
{
|
||||
T mPoint[3];
|
||||
const T& getP0() const { return mPoint[0];}
|
||||
const T& getP1() const { return mPoint[1];}
|
||||
const T& getP2() const { return mPoint[2];}
|
||||
TemplateCubicBezier(const T& v0, const T& v1, const T& v2)
|
||||
{
|
||||
mPoint[0] = v0;
|
||||
mPoint[1] = v1;
|
||||
mPoint[2] = v2;
|
||||
}
|
||||
|
||||
public:
|
||||
TemplateCubicBezier() {}
|
||||
|
||||
const T& getPosition() const { return mPoint[0];}
|
||||
const T& getTangentPoint1() const { return mPoint[1];}
|
||||
const T& getTangentPoint2() const { return mPoint[2];}
|
||||
};
|
||||
TemplateCubicBezier(const T& p, const T& i, const T& o) : _position(p), _controlPointIn(i), _controlPointOut(o)
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor with value only
|
||||
TemplateCubicBezier(const T& p) : _position(p), _controlPointIn(p), _controlPointOut(p)
|
||||
{
|
||||
}
|
||||
|
||||
const T& getPosition() const { return _position;}
|
||||
const T& getControlPointIn() const { return _controlPointIn;}
|
||||
const T& getControlPointOut() const { return _controlPointOut;}
|
||||
|
||||
T& getPosition() { return _position;}
|
||||
T& getControlPointIn() { return _controlPointIn;}
|
||||
T& getControlPointOut() { return _controlPointOut;}
|
||||
|
||||
void setPosition(const T& v) {_position = v;}
|
||||
void setControlPointIn(const T& v) {_controlPointIn = v;}
|
||||
void setControlPointOut(const T& v) {_controlPointOut = v;}
|
||||
|
||||
// steaming operators.
|
||||
friend std::ostream& operator << (std::ostream& output, const TemplateCubicBezier<T>& tcb)
|
||||
{
|
||||
output << tcb._position << " "
|
||||
<< tcb._controlPointIn << " "
|
||||
<< tcb._controlPointOut;
|
||||
return output; // to enable cascading
|
||||
}
|
||||
|
||||
friend std::istream& operator >> (std::istream& input, TemplateCubicBezier<T>& tcb)
|
||||
{
|
||||
input >> tcb._position >> tcb._controlPointIn >> tcb._controlPointOut;
|
||||
return input;
|
||||
}
|
||||
|
||||
protected:
|
||||
T _position, _controlPointIn, _controlPointOut;
|
||||
};
|
||||
|
||||
typedef TemplateCubicBezier<float> FloatCubicBezier;
|
||||
typedef TemplateCubicBezier<double> DoubleCubicBezier;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,10 +10,10 @@
|
||||
* 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.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_EASE_MOTION_H
|
||||
#define OSGANIMATION_EASE_MOTION_H
|
||||
#ifndef OSGANIMATION_EASE_MOTION
|
||||
#define OSGANIMATION_EASE_MOTION 1
|
||||
|
||||
#include <osg/Referenced>
|
||||
#include <osg/ref_ptr>
|
||||
@@ -21,9 +21,8 @@
|
||||
#include <osg/Math>
|
||||
#include <vector>
|
||||
|
||||
namespace osgAnimation {
|
||||
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
struct OutBounceFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
@@ -76,14 +75,12 @@ namespace osgAnimation {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Linear function
|
||||
struct LinearFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t;}
|
||||
};
|
||||
|
||||
|
||||
/// Quad function
|
||||
struct OutQuadFunction
|
||||
{
|
||||
@@ -94,46 +91,47 @@ namespace osgAnimation {
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t*t;}
|
||||
};
|
||||
|
||||
struct InOutQuadFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t = t * 2.0;
|
||||
if (t < 1.0)
|
||||
{
|
||||
t *= 2.0;
|
||||
if (t < 1.0)
|
||||
result = 0.5 * t * t;
|
||||
else
|
||||
{
|
||||
t = t - 1.0;
|
||||
result = - 0.5 * t * ( t - 2) - 1;
|
||||
t -= 1.0;
|
||||
result = - 0.5 * (t * ( t - 2) - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Cubic function
|
||||
struct OutCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;}
|
||||
};
|
||||
|
||||
struct InCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result) { result = t*t*t;}
|
||||
};
|
||||
|
||||
struct InOutCubicFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t = t * 2;
|
||||
if (t < 1.0)
|
||||
result = 0.5 * t * t * t;
|
||||
t *= 2.0f;
|
||||
if (t < 1.0f)
|
||||
result = 0.5f * t * t * t;
|
||||
else {
|
||||
t = t - 2;
|
||||
result = 0.5 * t * t * t + 2;
|
||||
t -= 2.0f;
|
||||
result = 0.5 * (t * t * t + 2.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Quart function
|
||||
struct InQuartFunction
|
||||
{
|
||||
@@ -160,7 +158,191 @@ namespace osgAnimation {
|
||||
}
|
||||
};
|
||||
|
||||
/// Elastic function
|
||||
struct OutElasticFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = pow(2.0f, -10.0f * t) * sinf((t - 0.3f / 4.0f) * (2.0f * osg::PI) / 0.3f) + 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct InElasticFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
OutElasticFunction::getValueAt(1.0f - t, result);
|
||||
result = 1.0f - result;
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutElasticFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t *= 2.0f;
|
||||
if (t < 1.0f)
|
||||
{
|
||||
t -= 1.0f;
|
||||
result = -0.5 * (1.0f * pow(2.0f, 10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f));
|
||||
}
|
||||
else
|
||||
{
|
||||
t -= 1.0f;
|
||||
result = pow(2.0f, -10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f) * 0.5f + 1.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Sine function
|
||||
struct OutSineFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = sinf(t * (osg::PI / 2.0f));
|
||||
}
|
||||
};
|
||||
|
||||
struct InSineFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = -cosf(t * (osg::PI / 2.0f)) + 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutSineFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = -0.5f * (cosf((osg::PI * t)) - 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
// Back function
|
||||
struct OutBackFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t -= 1.0f;
|
||||
result = t * t * ((1.70158 + 1.0f) * t + 1.70158) + 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
struct InBackFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = t * t * ((1.70158 + 1.0f) * t - 1.70158);
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutBackFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
float s = 1.70158 * 1.525f;
|
||||
t *= 2.0f;
|
||||
if (t < 1.0f)
|
||||
{
|
||||
result = 0.5f * (t * t * ((s + 1.0f) * t - s));
|
||||
}
|
||||
else
|
||||
{
|
||||
float p = t -= 2.0f;
|
||||
result = 0.5f * ((p) * t * ((s + 1.0f) * t + s) + 2.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Circ function
|
||||
struct OutCircFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t -= 1.0f;
|
||||
result = sqrt(1.0f - t * t);
|
||||
}
|
||||
};
|
||||
|
||||
struct InCircFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
result = -(sqrt(1.0f - (t * t)) - 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutCircFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
t *= 2.0f;
|
||||
if (t < 1.0f)
|
||||
{
|
||||
result = -0.5f * (sqrt(1.0f - t * t) - 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
t -= 2.0f;
|
||||
result = 0.5f * (sqrt(1 - t * t) + 1.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Expo function
|
||||
struct OutExpoFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
if(t == 1.0f)
|
||||
{
|
||||
result = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -powf(2.0f, -10.0f * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct InExpoFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
if(t == 0.0f)
|
||||
{
|
||||
result = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = powf(2.0f, 10.0f * (t - 1.0f));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutExpoFunction
|
||||
{
|
||||
inline static void getValueAt(float t, float& result)
|
||||
{
|
||||
if(t == 0.0f || t == 1.0f)
|
||||
{
|
||||
result = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
t *= 2.0f;
|
||||
if(t < 1.0f)
|
||||
{
|
||||
result = 0.5f * powf(2.0f, 10.0f * (t - 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Motion : public osg::Referenced
|
||||
{
|
||||
@@ -278,7 +460,7 @@ namespace osgAnimation {
|
||||
osg::notify(osg::WARN) << "CompositeMotion::getValueInNormalizedRange no Motion in the CompositeMotion, add motion to have result" << std::endl;
|
||||
return;
|
||||
}
|
||||
for (MotionList::const_iterator it = _motions.begin(); it != _motions.end(); it++)
|
||||
for (MotionList::const_iterator it = _motions.begin(); it != _motions.end(); ++it)
|
||||
{
|
||||
const Motion* motion = static_cast<const Motion*>(it->get());
|
||||
float durationInRange = motion->getDuration() / getDuration();
|
||||
@@ -314,13 +496,35 @@ namespace osgAnimation {
|
||||
typedef MathMotionTemplate<InQuartFunction> InQuartMotion;
|
||||
typedef MathMotionTemplate<InOutQuartFunction> InOutQuartMotion;
|
||||
|
||||
|
||||
// bounce
|
||||
typedef MathMotionTemplate<OutBounceFunction > OutBounceMotion;
|
||||
typedef MathMotionTemplate<InBounceFunction> InBounceMotion;
|
||||
typedef MathMotionTemplate<InOutBounceFunction> InOutBounceMotion;
|
||||
|
||||
// elastic
|
||||
typedef MathMotionTemplate<OutElasticFunction > OutElasticMotion;
|
||||
typedef MathMotionTemplate<InElasticFunction > InElasticMotion;
|
||||
typedef MathMotionTemplate<InOutElasticFunction > InOutElasticMotion;
|
||||
|
||||
// sine
|
||||
typedef MathMotionTemplate<OutSineFunction > OutSineMotion;
|
||||
typedef MathMotionTemplate<InSineFunction > InSineMotion;
|
||||
typedef MathMotionTemplate<InOutSineFunction > InOutSineMotion;
|
||||
|
||||
// back
|
||||
typedef MathMotionTemplate<OutBackFunction > OutBackMotion;
|
||||
typedef MathMotionTemplate<InBackFunction > InBackMotion;
|
||||
typedef MathMotionTemplate<InOutBackFunction > InOutBackMotion;
|
||||
|
||||
// circ
|
||||
typedef MathMotionTemplate<OutCircFunction > OutCircMotion;
|
||||
typedef MathMotionTemplate<InCircFunction > InCircMotion;
|
||||
typedef MathMotionTemplate<InOutCircFunction > InOutCircMotion;
|
||||
|
||||
// expo
|
||||
typedef MathMotionTemplate<OutExpoFunction > OutExpoMotion;
|
||||
typedef MathMotionTemplate<InExpoFunction > InExpoMotion;
|
||||
typedef MathMotionTemplate<InOutExpoFunction > InOutExpoMotion;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
26
include/osgAnimation/FrameAction
Normal file
26
include/osgAnimation/FrameAction
Normal file
@@ -0,0 +1,26 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_FRAMEACTION_H
|
||||
#define OSGANIMATION_FRAMEACTION_H
|
||||
|
||||
#include <map>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class Action;
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,13 +10,16 @@
|
||||
* 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.
|
||||
*/
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
* Michael Platings <mplatings@pixelpower.com>
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_INTERPOLATOR_H
|
||||
#define OSGANIMATION_INTERPOLATOR_H
|
||||
#ifndef OSGANIMATION_INTERPOLATOR
|
||||
#define OSGANIMATION_INTERPOLATOR 1
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osgAnimation/Interpolator>
|
||||
#include <osgAnimation/Keyframe>
|
||||
|
||||
namespace osgAnimation
|
||||
@@ -61,6 +64,32 @@ namespace osgAnimation
|
||||
};
|
||||
|
||||
|
||||
template <class TYPE, class KEY=TYPE>
|
||||
class TemplateStepInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateStepInterpolator() {}
|
||||
void getValue(const TemplateKeyframeContainer<KEY>& keyframes, float time, TYPE& result) const
|
||||
{
|
||||
|
||||
if (time >= keyframes.back().getTime())
|
||||
{
|
||||
result = keyframes.back().getValue();
|
||||
return;
|
||||
}
|
||||
else if (time <= keyframes.front().getTime())
|
||||
{
|
||||
result = keyframes.front().getValue();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = getKeyIndexFromTime(keyframes,time);
|
||||
result = keyframes[i].getValue();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class TYPE, class KEY=TYPE>
|
||||
class TemplateLinearInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
|
||||
{
|
||||
@@ -176,14 +205,22 @@ namespace osgAnimation
|
||||
float t2 = t * t;
|
||||
|
||||
TYPE v0 = keyframes[i].getValue().getPosition() * one_minus_t3;
|
||||
TYPE v1 = keyframes[i].getValue().getTangentPoint1() * (3.0 * t * one_minus_t2);
|
||||
TYPE v2 = keyframes[i].getValue().getTangentPoint2() * (3.0 * t2 * one_minus_t);
|
||||
TYPE v1 = keyframes[i].getValue().getControlPointIn() * (3.0 * t * one_minus_t2);
|
||||
TYPE v2 = keyframes[i].getValue().getControlPointOut() * (3.0 * t2 * one_minus_t);
|
||||
TYPE v3 = keyframes[i+1].getValue().getPosition() * (t2 * t);
|
||||
|
||||
result = v0 + v1 + v2 + v3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef TemplateStepInterpolator<double, double> DoubleStepInterpolator;
|
||||
typedef TemplateStepInterpolator<float, float> FloatStepInterpolator;
|
||||
typedef TemplateStepInterpolator<osg::Vec2, osg::Vec2> Vec2StepInterpolator;
|
||||
typedef TemplateStepInterpolator<osg::Vec3, osg::Vec3> Vec3StepInterpolator;
|
||||
typedef TemplateStepInterpolator<osg::Vec3, Vec3Packed> Vec3PackedStepInterpolator;
|
||||
typedef TemplateStepInterpolator<osg::Vec4, osg::Vec4> Vec4StepInterpolator;
|
||||
typedef TemplateStepInterpolator<osg::Quat, osg::Quat> QuatStepInterpolator;
|
||||
|
||||
typedef TemplateLinearInterpolator<double, double> DoubleLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<float, float> FloatLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec2, osg::Vec2> Vec2LinearInterpolator;
|
||||
@@ -191,6 +228,7 @@ namespace osgAnimation
|
||||
typedef TemplateLinearInterpolator<osg::Vec3, Vec3Packed> Vec3PackedLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Vec4, osg::Vec4> Vec4LinearInterpolator;
|
||||
typedef TemplateSphericalLinearInterpolator<osg::Quat, osg::Quat> QuatSphericalLinearInterpolator;
|
||||
typedef TemplateLinearInterpolator<osg::Matrixf, osg::Matrixf> MatrixLinearInterpolator;
|
||||
|
||||
typedef TemplateCubicBezierInterpolator<float, FloatCubicBezier > FloatCubicBezierInterpolator;
|
||||
typedef TemplateCubicBezierInterpolator<double, DoubleCubicBezier> DoubleCubicBezierInterpolator;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Matrixf>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
@@ -98,6 +99,9 @@ namespace osgAnimation
|
||||
|
||||
typedef TemplateKeyframe<float> FloatKeyframe;
|
||||
typedef TemplateKeyframeContainer<float> FloatKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<double> DoubleKeyframe;
|
||||
typedef TemplateKeyframeContainer<double> DoubleKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Vec2> Vec2Keyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Vec2> Vec2KeyframeContainer;
|
||||
@@ -111,17 +115,24 @@ namespace osgAnimation
|
||||
typedef TemplateKeyframe<osg::Quat> QuatKeyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Quat> QuatKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<osg::Matrixf> MatrixKeyframe;
|
||||
typedef TemplateKeyframeContainer<osg::Matrixf> MatrixKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<Vec3Packed> Vec3PackedKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec3Packed> Vec3PackedKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<FloatCubicBezier> FloatCubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<FloatCubicBezier> FloatCubicBezierKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<DoubleCubicBezier> DoubleCubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<DoubleCubicBezier> DoubleCubicBezierKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<Vec2CubicBezier> Vec2CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec2CubicBezier> Vec2CubicBezierKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<Vec3CubicBezier> Vec3CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec3CubicBezier> Vec3CubicBezierKeyframeContainer;
|
||||
|
||||
typedef TemplateKeyframe<Vec4CubicBezier> Vec4CubicBezierKeyframe;
|
||||
typedef TemplateKeyframeContainer<Vec4CubicBezier> Vec4CubicBezierKeyframeContainer;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -16,37 +16,39 @@
|
||||
#define OSGANIMATION_NODE_VISITOR_H
|
||||
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/StateSet>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/UpdateCallback>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class AnimationUpdateCallbackBase;
|
||||
|
||||
struct LinkVisitor : public osg::NodeVisitor
|
||||
/** This class is instancied by the AnimationManagerBase, it will link animation target to updatecallback that have the same name
|
||||
*/
|
||||
class OSGANIMATION_EXPORT LinkVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
LinkVisitor();
|
||||
|
||||
META_NodeVisitor("osgAnimation","LinkVisitor");
|
||||
|
||||
void apply(osg::Node& node);
|
||||
void apply(osg::Geode& node);
|
||||
|
||||
AnimationList& getAnimationList();
|
||||
void reset();
|
||||
unsigned int getNbLinkedTarget() const { return _nbLinkedTarget; }
|
||||
|
||||
protected:
|
||||
|
||||
void handle_stateset(osg::StateSet* stateset);
|
||||
void link(osgAnimation::AnimationUpdateCallbackBase* cb);
|
||||
|
||||
// animation list to link
|
||||
AnimationList _animations;
|
||||
|
||||
// number of success link done
|
||||
unsigned int _nbLinkedTarget;
|
||||
|
||||
LinkVisitor(Animation* animation) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _animations.push_back(animation); _nbLinkedTarget = 0;}
|
||||
LinkVisitor(const AnimationList& animations) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _animations = animations; _nbLinkedTarget = 0;}
|
||||
|
||||
META_NodeVisitor("osgAnimation","LinkVisitor")
|
||||
|
||||
void apply(osg::Node& node)
|
||||
{
|
||||
osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(node.getUpdateCallback());
|
||||
if (cb)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < (int)_animations.size(); i++)
|
||||
{
|
||||
result += cb->link(_animations[i].get());
|
||||
_nbLinkedTarget += result;
|
||||
}
|
||||
std::cout << "LinkVisitor links " << result << " for \"" << cb->getName() << '"' << std::endl;
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
154
include/osgAnimation/MorphGeometry
Normal file
154
include/osgAnimation/MorphGeometry
Normal file
@@ -0,0 +1,154 @@
|
||||
/* -*-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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_MORPHGEOMETRY_H
|
||||
#define OSGANIMATION_MORPHGEOMETRY_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/AnimationUpdateCallback>
|
||||
#include <osg/Geometry>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT MorphGeometry : public osg::Geometry
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum Method {
|
||||
NORMALIZED,
|
||||
RELATIVE
|
||||
};
|
||||
|
||||
class MorphTarget
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<osg::Geometry> _geom;
|
||||
float _weight;
|
||||
public:
|
||||
MorphTarget(osg::Geometry* geom, float w = 1.0) : _geom(geom), _weight(w) {}
|
||||
void setWeight(float weight) { _weight = weight; }
|
||||
const float getWeight() const { return _weight; }
|
||||
osg::Geometry* getGeometry() { return _geom.get(); }
|
||||
const osg::Geometry* getGeometry() const { return _geom.get(); }
|
||||
void setGeometry(osg::Geometry* geom) { _geom = geom; }
|
||||
};
|
||||
|
||||
typedef std::vector<MorphTarget> MorphTargetList;
|
||||
|
||||
struct UpdateVertex : public osg::Drawable::UpdateCallback
|
||||
{
|
||||
virtual void update(osg::NodeVisitor*, osg::Drawable* drw)
|
||||
{
|
||||
MorphGeometry* geom = dynamic_cast<MorphGeometry*>(drw);
|
||||
if (!geom)
|
||||
return;
|
||||
|
||||
geom->transformSoftwareMethod();
|
||||
}
|
||||
};
|
||||
|
||||
MorphGeometry();
|
||||
MorphGeometry(const osg::Geometry& b);
|
||||
MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
virtual osg::Object* cloneType() const { return new MorphGeometry(); }
|
||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MorphGeometry(*this,copyop); }
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MorphGeometry*>(obj)!=NULL; }
|
||||
virtual const char* libraryName() const { return "osgAnimation"; }
|
||||
virtual const char* className() const { return "MorphGeometry"; }
|
||||
|
||||
virtual void transformSoftwareMethod();
|
||||
|
||||
/** Set the morphing method. */
|
||||
void setMethod(Method method) { _method = method; }
|
||||
/** Get the morphing method. */
|
||||
inline Method getMethod() const { return _method; }
|
||||
|
||||
/** Set flag for morphing normals. */
|
||||
void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; }
|
||||
/** Get the flag for morphing normals. */
|
||||
inline bool getMorphNormals() const { return _morphNormals; }
|
||||
|
||||
/** Add a \c MorphTarget to the \c MorphGeometry.
|
||||
* If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry
|
||||
* then increment its reference count, add it to the MorphTargets list and
|
||||
* dirty the bounding sphere to force it to be recomputed on the next
|
||||
* call to \c getBound().
|
||||
* @param morphTarget The \c MorphTarget to be added to the \c MorphGeometry.
|
||||
* @param weight The weight to be added to the \c MorphGeometry.
|
||||
* @return \c true for success; \c false otherwise.
|
||||
*/
|
||||
virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) { _morphTargets.push_back(MorphTarget(morphTarget, weight)); _dirty = true; }
|
||||
|
||||
void setWeight(unsigned int index, float morphWeight)
|
||||
{
|
||||
if (index < _morphTargets.size())
|
||||
{
|
||||
_morphTargets[index].setWeight(morphWeight);
|
||||
dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the MorphGeometry dirty.*/
|
||||
void dirty() { _dirty = true; }
|
||||
|
||||
/** Get the list of MorphTargets.*/
|
||||
const MorphTargetList& getMorphTargetList() const { return _morphTargets; }
|
||||
|
||||
/** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */
|
||||
MorphTargetList& getMorphTargetList() { return _morphTargets; }
|
||||
|
||||
/** Return the \c MorphTarget at position \c i.*/
|
||||
inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; }
|
||||
|
||||
/** Return the \c MorphTarget at position \c i.*/
|
||||
inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; }
|
||||
|
||||
protected:
|
||||
/// Do we need to recalculate the morphed geometry?
|
||||
bool _dirty;
|
||||
|
||||
Method _method;
|
||||
MorphTargetList _morphTargets;
|
||||
|
||||
std::vector<osg::Vec3> _positionSource;
|
||||
std::vector<osg::Vec3> _normalSource;
|
||||
|
||||
/// Do we also morph between normals?
|
||||
bool _morphNormals;
|
||||
};
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateMorph : public AnimationUpdateCallback<osg::NodeCallback>
|
||||
{
|
||||
protected:
|
||||
std::map<int, osg::ref_ptr<osgAnimation::FloatTarget> > _weightTargets;
|
||||
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, UpdateMorph);
|
||||
|
||||
UpdateMorph(const std::string& name = "");
|
||||
UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop);
|
||||
|
||||
/** 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -16,8 +16,9 @@
|
||||
#define OSGANIMATION_RIGGEOMETRY_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Skinning>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/RigTransform>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osg/Geometry>
|
||||
|
||||
namespace osgAnimation
|
||||
@@ -28,49 +29,63 @@ namespace osgAnimation
|
||||
public:
|
||||
|
||||
RigGeometry();
|
||||
RigGeometry(const osg::Geometry& b);
|
||||
// RigGeometry(const osg::Geometry& b);
|
||||
RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osgAnimation, RigGeometry);
|
||||
|
||||
void setInfluenceMap(osgAnimation::VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
|
||||
const osgAnimation::VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();}
|
||||
osgAnimation::VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();}
|
||||
void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
|
||||
const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();}
|
||||
VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();}
|
||||
|
||||
const Skeleton* getSkeleton() const;
|
||||
Skeleton* getSkeleton();
|
||||
// will be used by the update callback to init correctly the rig mesh
|
||||
void setSkeleton(Skeleton*);
|
||||
|
||||
void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;}
|
||||
bool getNeedToComputeMatrix() const { return _needToComputeMatrix;}
|
||||
|
||||
void buildVertexSet();
|
||||
void buildTransformer(Skeleton* root);
|
||||
|
||||
// this build the internal database about vertex influence and bones
|
||||
void buildVertexInfluenceSet();
|
||||
const VertexInfluenceSet& getVertexInfluenceSet() const;
|
||||
|
||||
void computeMatrixFromRootSkeleton();
|
||||
|
||||
virtual void transformSoftwareMethod();
|
||||
const osgAnimation::VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;}
|
||||
|
||||
const std::vector<osg::Vec3>& getPositionSource() const { return _positionSource;}
|
||||
const std::vector<osg::Vec3>& getNormalSource() const { return _normalSource;}
|
||||
// set implementation of rig method
|
||||
void setRigTransformImplementation(RigTransform*);
|
||||
RigTransform* getRigTransformImplementation();
|
||||
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
|
||||
void update();
|
||||
|
||||
const osg::Matrix& getMatrixFromSkeletonToGeometry() const;
|
||||
const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const;
|
||||
|
||||
osg::Geometry* getSourceGeometry();
|
||||
const osg::Geometry* getSourceGeometry() const;
|
||||
void setSourceGeometry(osg::Geometry* geometry);
|
||||
|
||||
void copyFrom(osg::Geometry& from);
|
||||
|
||||
protected:
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _geometry;
|
||||
osg::ref_ptr<RigTransform> _rigTransformImplementation;
|
||||
|
||||
std::vector<osg::Vec3> _positionSource;
|
||||
std::vector<osg::Vec3> _normalSource;
|
||||
|
||||
osgAnimation::VertexInfluenceSet _vertexInfluenceSet;
|
||||
osg::ref_ptr<osgAnimation::VertexInfluenceMap> _vertexInfluenceMap;
|
||||
osgAnimation::TransformVertexFunctor _transformVertexes;
|
||||
VertexInfluenceSet _vertexInfluenceSet;
|
||||
osg::ref_ptr<VertexInfluenceMap> _vertexInfluenceMap;
|
||||
|
||||
osg::Matrix _matrixFromSkeletonToGeometry;
|
||||
osg::Matrix _invMatrixFromSkeletonToGeometry;
|
||||
osg::observer_ptr<Skeleton> _root;
|
||||
bool _needToComputeMatrix;
|
||||
|
||||
|
||||
struct FindNearestParentSkeleton : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<osgAnimation::Skeleton> _root;
|
||||
osg::ref_ptr<Skeleton> _root;
|
||||
FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
|
||||
void apply(osg::Transform& node)
|
||||
{
|
||||
@@ -89,7 +104,7 @@ namespace osgAnimation
|
||||
RigGeometry* geom = dynamic_cast<RigGeometry*>(drw);
|
||||
if (!geom)
|
||||
return;
|
||||
if (!geom->getSkeleton() && !geom->getParents().empty())
|
||||
if (!geom->getSkeleton() && !geom->getParents().empty())
|
||||
{
|
||||
FindNearestParentSkeleton finder;
|
||||
if (geom->getParents().size() > 1)
|
||||
@@ -97,9 +112,12 @@ namespace osgAnimation
|
||||
geom->getParents()[0]->accept(finder);
|
||||
|
||||
if (!finder._root.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeomtry ( " << geom->getName() << " )" << std::endl;
|
||||
return;
|
||||
geom->buildVertexSet();
|
||||
geom->buildTransformer(finder._root.get());
|
||||
}
|
||||
geom->buildVertexInfluenceSet();
|
||||
geom->setSkeleton(finder._root.get());
|
||||
}
|
||||
|
||||
if (!geom->getSkeleton())
|
||||
@@ -107,34 +125,10 @@ namespace osgAnimation
|
||||
|
||||
if (geom->getNeedToComputeMatrix())
|
||||
geom->computeMatrixFromRootSkeleton();
|
||||
geom->transformSoftwareMethod();
|
||||
|
||||
geom->update();
|
||||
}
|
||||
};
|
||||
|
||||
/** BuildVertexTransformerVisitor is used to setup RigGeometry drawable
|
||||
* throw a subgraph.
|
||||
*/
|
||||
struct BuildVertexTransformerVisitor : public osg::NodeVisitor
|
||||
{
|
||||
osg::ref_ptr<Skeleton> _root;
|
||||
BuildVertexTransformerVisitor(Skeleton* root): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _root = root;}
|
||||
|
||||
META_NodeVisitor("osgAnimation","BuildVertexTransformerVisitor")
|
||||
|
||||
void apply(osg::Geode& node)
|
||||
{
|
||||
int num = node.getNumDrawables();
|
||||
for (int i = 0; i < num; i++) {
|
||||
RigGeometry* geom = dynamic_cast<RigGeometry*>(node.getDrawable(i));
|
||||
if (geom)
|
||||
{
|
||||
geom->buildVertexSet();
|
||||
geom->buildTransformer(_root.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
36
include/osgAnimation/RigTransform
Normal file
36
include/osgAnimation/RigTransform
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_RIGTRANSFORM
|
||||
#define OSGANIMATION_RIGTRANSFORM 1
|
||||
|
||||
#include <osg/Referenced>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class RigGeometry;
|
||||
|
||||
class RigTransform : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
RigTransform() {}
|
||||
virtual ~RigTransform() {}
|
||||
virtual void operator()(RigGeometry& geometry) {}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
85
include/osgAnimation/RigTransformHardware
Normal file
85
include/osgAnimation/RigTransformHardware
Normal file
@@ -0,0 +1,85 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_RIG_TRANSFORM_HARDWARE
|
||||
#define OSGANIMATION_RIG_TRANSFORM_HARDWARE 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/RigTransform>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Array>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class RigGeometry;
|
||||
|
||||
/// This class manage format for hardware skinning
|
||||
class OSGANIMATION_EXPORT RigTransformHardware : public RigTransform
|
||||
{
|
||||
public:
|
||||
typedef osg::Matrix MatrixType;
|
||||
typedef osgAnimation::Bone BoneType;
|
||||
typedef std::vector<osg::ref_ptr<osg::Vec4Array> > BoneWeightAttribList;
|
||||
typedef std::vector<osg::ref_ptr<BoneType> > BonePalette;
|
||||
|
||||
typedef std::vector<osg::Matrix> MatrixPalette;
|
||||
struct IndexWeightEntry
|
||||
{
|
||||
int _boneIndex;
|
||||
float _boneWeight;
|
||||
IndexWeightEntry() { _boneIndex = 0; _boneWeight = 0;}
|
||||
IndexWeightEntry(int index, float weight) { _boneIndex = index; _boneWeight = weight;}
|
||||
int getIndex() const { return _boneIndex; }
|
||||
float getWeight() const { return _boneWeight; }
|
||||
};
|
||||
typedef std::vector<std::vector<IndexWeightEntry> > VertexIndexWeightList;
|
||||
|
||||
RigTransformHardware();
|
||||
|
||||
osg::Vec4Array* getVertexAttrib(int index);
|
||||
int getNumVertexAttrib();
|
||||
|
||||
osg::Uniform* getMatrixPaletteUniform();
|
||||
void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry);
|
||||
|
||||
int getNumBonesPerVertex() const;
|
||||
int getNumVertexes() const;
|
||||
|
||||
bool createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap);
|
||||
|
||||
virtual void operator()(RigGeometry&);
|
||||
void setShader(osg::Shader*);
|
||||
|
||||
protected:
|
||||
|
||||
bool init(RigGeometry&);
|
||||
|
||||
BoneWeightAttribList createVertexAttribList();
|
||||
osg::Uniform* createVertexUniform();
|
||||
|
||||
int _bonesPerVertex;
|
||||
int _nbVertexes;
|
||||
VertexIndexWeightList _vertexIndexMatrixWeightList;
|
||||
BonePalette _bonePalette;
|
||||
BoneWeightAttribList _boneWeightAttribArrays;
|
||||
osg::ref_ptr<osg::Uniform> _uniformMatrixPalette;
|
||||
osg::ref_ptr<osg::Shader> _shader;
|
||||
|
||||
bool _needInit;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
172
include/osgAnimation/RigTransformSoftware
Normal file
172
include/osgAnimation/RigTransformSoftware
Normal file
@@ -0,0 +1,172 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_RIGTRANSFORM_SOFTWARE
|
||||
#define OSGANIMATION_RIGTRANSFORM_SOFTWARE 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/RigTransform>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osg/observer_ptr>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class RigGeometry;
|
||||
|
||||
/// This class manage format for hardware skinning
|
||||
class OSGANIMATION_EXPORT RigTransformSoftware : public RigTransform
|
||||
{
|
||||
public:
|
||||
|
||||
RigTransformSoftware();
|
||||
virtual void operator()(RigGeometry&);
|
||||
|
||||
|
||||
class BoneWeight
|
||||
{
|
||||
public:
|
||||
BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {}
|
||||
const Bone* getBone() const { return _bone.get(); }
|
||||
float getWeight() const { return _weight; }
|
||||
void setWeight(float w) { _weight = w; }
|
||||
protected:
|
||||
osg::observer_ptr<Bone> _bone;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
typedef std::vector<BoneWeight> BoneWeightList;
|
||||
typedef std::vector<int> VertexList;
|
||||
|
||||
class UniqBoneSetVertexSet
|
||||
{
|
||||
public:
|
||||
BoneWeightList& getBones() { return _bones; }
|
||||
VertexList& getVertexes() { return _vertexes; }
|
||||
|
||||
void resetMatrix()
|
||||
{
|
||||
_result.set(0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight)
|
||||
{
|
||||
osg::Matrix m = invBindMatrix * matrix;
|
||||
osg::Matrix::value_type* ptr = m.ptr();
|
||||
osg::Matrix::value_type* ptrresult = _result.ptr();
|
||||
ptrresult[0] += ptr[0] * weight;
|
||||
ptrresult[1] += ptr[1] * weight;
|
||||
ptrresult[2] += ptr[2] * weight;
|
||||
|
||||
ptrresult[4] += ptr[4] * weight;
|
||||
ptrresult[5] += ptr[5] * weight;
|
||||
ptrresult[6] += ptr[6] * weight;
|
||||
|
||||
ptrresult[8] += ptr[8] * weight;
|
||||
ptrresult[9] += ptr[9] * weight;
|
||||
ptrresult[10] += ptr[10] * weight;
|
||||
|
||||
ptrresult[12] += ptr[12] * weight;
|
||||
ptrresult[13] += ptr[13] * weight;
|
||||
ptrresult[14] += ptr[14] * weight;
|
||||
}
|
||||
void computeMatrixForVertexSet()
|
||||
{
|
||||
if (_bones.empty())
|
||||
{
|
||||
osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl;
|
||||
_result = osg::Matrix::identity();
|
||||
return;
|
||||
}
|
||||
resetMatrix();
|
||||
|
||||
int size = _bones.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const Bone* bone = _bones[i].getBone();
|
||||
if (!bone)
|
||||
{
|
||||
osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl;
|
||||
continue;
|
||||
}
|
||||
const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||
const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace();
|
||||
osg::Matrix::value_type w = _bones[i].getWeight();
|
||||
accummulateMatrix(invBindMatrix, matrix, w);
|
||||
}
|
||||
}
|
||||
const osg::Matrix& getMatrix() const { return _result;}
|
||||
protected:
|
||||
BoneWeightList _bones;
|
||||
VertexList _vertexes;
|
||||
osg::Matrix _result;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class V> void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
||||
{
|
||||
// the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = src[idx] * matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class V> void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
||||
{
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = osg::Matrix::transform3x3(src[idx],matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool init(RigGeometry&);
|
||||
void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence);
|
||||
std::vector<UniqBoneSetVertexSet> _boneSetVertexSet;
|
||||
|
||||
bool _needInit;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,7 +10,11 @@
|
||||
* 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.
|
||||
*/
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
* Michael Platings <mplatings@pixelpower.com>
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SAMPLER_H
|
||||
#define OSGANIMATION_SAMPLER_H
|
||||
@@ -108,12 +112,21 @@ namespace osgAnimation
|
||||
};
|
||||
|
||||
|
||||
typedef TemplateSampler<DoubleStepInterpolator> DoubleStepSampler;
|
||||
typedef TemplateSampler<FloatStepInterpolator> FloatStepSampler;
|
||||
typedef TemplateSampler<Vec2StepInterpolator> Vec2StepSampler;
|
||||
typedef TemplateSampler<Vec3StepInterpolator> Vec3StepSampler;
|
||||
typedef TemplateSampler<Vec4StepInterpolator> Vec4StepSampler;
|
||||
typedef TemplateSampler<QuatStepInterpolator> QuatStepSampler;
|
||||
|
||||
typedef TemplateSampler<DoubleLinearInterpolator> DoubleLinearSampler;
|
||||
typedef TemplateSampler<FloatLinearInterpolator> FloatLinearSampler;
|
||||
typedef TemplateSampler<Vec2LinearInterpolator> Vec2LinearSampler;
|
||||
typedef TemplateSampler<Vec3LinearInterpolator> Vec3LinearSampler;
|
||||
typedef TemplateSampler<Vec4LinearInterpolator> Vec4LinearSampler;
|
||||
typedef TemplateSampler<QuatSphericalLinearInterpolator> QuatSphericalLinearSampler;
|
||||
typedef TemplateSampler<MatrixLinearInterpolator> MatrixLinearSampler;
|
||||
|
||||
typedef TemplateSampler<FloatCubicBezierInterpolator> FloatCubicBezierSampler;
|
||||
typedef TemplateSampler<DoubleCubicBezierInterpolator> DoubleCubicBezierSampler;
|
||||
typedef TemplateSampler<Vec2CubicBezierInterpolator> Vec2CubicBezierSampler;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,33 +12,36 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SKELETON_H
|
||||
#define OSGANIMATION_SKELETON_H
|
||||
#ifndef OSGANIMATION_SKELETON
|
||||
#define OSGANIMATION_SKELETON 1
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Skeleton : public Bone
|
||||
class OSGANIMATION_EXPORT Skeleton : public osg::MatrixTransform
|
||||
{
|
||||
public:
|
||||
META_Node(osgAnimation, Skeleton);
|
||||
|
||||
struct OSGANIMATION_EXPORT UpdateSkeleton : public osg::NodeCallback
|
||||
class OSGANIMATION_EXPORT UpdateSkeleton : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, UpdateSkeleton);
|
||||
UpdateSkeleton() {}
|
||||
UpdateSkeleton(const UpdateSkeleton& us, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : osg::NodeCallback(us, copyop) {}
|
||||
UpdateSkeleton();
|
||||
UpdateSkeleton(const UpdateSkeleton&, const osg::CopyOp&);
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
bool needToValidate() const;
|
||||
protected:
|
||||
bool _needValidate;
|
||||
};
|
||||
|
||||
Skeleton(const Skeleton& b, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : Bone(b,copyop) {}
|
||||
Skeleton();
|
||||
void setDefaultUpdateCallback(void);
|
||||
void computeBindMatrix() { _invBindInSkeletonSpace = osg::Matrix::inverse(_bindInBoneSpace); }
|
||||
Skeleton(const Skeleton&, const osg::CopyOp&);
|
||||
void setDefaultUpdateCallback();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
54
include/osgAnimation/StackedMatrixElement
Normal file
54
include/osgAnimation/StackedMatrixElement
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_MATRIX_ELEMENT
|
||||
#define OSGANIMATION_STACKED_MATRIX_ELEMENT 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/Target>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedMatrixElement : public StackedTransformElement
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, StackedMatrixElement);
|
||||
|
||||
StackedMatrixElement();
|
||||
StackedMatrixElement(const StackedMatrixElement&, const osg::CopyOp&);
|
||||
StackedMatrixElement(const std::string& name, const osg::Matrix& matrix);
|
||||
StackedMatrixElement(const osg::Matrix& matrix);
|
||||
|
||||
void applyToMatrix(osg::Matrix& matrix) const { matrix = _matrix * matrix; }
|
||||
osg::Matrix getAsMatrix() const { return _matrix; }
|
||||
const osg::Matrix& getMatrix() const { return _matrix;}
|
||||
void setMatrix(const osg::Matrix& matrix) { _matrix = matrix;}
|
||||
bool isIdentity() const { return _matrix.isIdentity(); }
|
||||
void update();
|
||||
virtual Target* getOrCreateTarget();
|
||||
virtual Target* getTarget() {return _target.get();}
|
||||
virtual const Target* getTarget() const {return _target.get();}
|
||||
|
||||
protected:
|
||||
osg::Matrix _matrix;
|
||||
osg::ref_ptr<MatrixTarget> _target;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
54
include/osgAnimation/StackedQuaternionElement
Normal file
54
include/osgAnimation/StackedQuaternionElement
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_QUATERNION_ELEMENT
|
||||
#define OSGANIMATION_STACKED_QUATERNION_ELEMENT 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/Target>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedQuaternionElement : public StackedTransformElement
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, StackedQuaternionElement);
|
||||
|
||||
StackedQuaternionElement();
|
||||
StackedQuaternionElement(const StackedQuaternionElement&, const osg::CopyOp&);
|
||||
StackedQuaternionElement(const std::string&, const osg::Quat& q = osg::Quat(0,0,0,1));
|
||||
StackedQuaternionElement(const osg::Quat&);
|
||||
|
||||
void applyToMatrix(osg::Matrix& matrix) const;
|
||||
osg::Matrix getAsMatrix() const;
|
||||
bool isIdentity() const;
|
||||
void update();
|
||||
|
||||
const osg::Quat& getQuaternion() const;
|
||||
void setQuaternion(const osg::Quat&);
|
||||
virtual Target* getOrCreateTarget();
|
||||
virtual Target* getTarget();
|
||||
virtual const Target* getTarget() const;
|
||||
|
||||
protected:
|
||||
osg::Quat _quaternion;
|
||||
osg::ref_ptr<QuatTarget> _target;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
59
include/osgAnimation/StackedRotateAxisElement
Normal file
59
include/osgAnimation/StackedRotateAxisElement
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_ROTATE_AXIS_ELEMENT
|
||||
#define OSGANIMATION_STACKED_ROTATE_AXIS_ELEMENT 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/Target>
|
||||
#include <osg/Vec3>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedRotateAxisElement : public StackedTransformElement
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, StackedRotateAxisElement);
|
||||
|
||||
StackedRotateAxisElement();
|
||||
StackedRotateAxisElement(const StackedRotateAxisElement&, const osg::CopyOp&);
|
||||
StackedRotateAxisElement(const std::string& name, const osg::Vec3& axis, double angle);
|
||||
StackedRotateAxisElement(const osg::Vec3& axis, double angle);
|
||||
|
||||
void applyToMatrix(osg::Matrix& matrix) const;
|
||||
osg::Matrix getAsMatrix() const;
|
||||
bool isIdentity() const { return (_angle == 0); }
|
||||
void update();
|
||||
|
||||
const osg::Vec3& getAxis() const;
|
||||
const double getAngle() const;
|
||||
void setAxis(const osg::Vec3&);
|
||||
void setAngle(const double&);
|
||||
|
||||
virtual Target* getOrCreateTarget();
|
||||
virtual Target* getTarget() {return _target.get();}
|
||||
virtual const Target* getTarget() const {return _target.get();}
|
||||
|
||||
protected:
|
||||
osg::Vec3 _axis;
|
||||
double _angle;
|
||||
osg::ref_ptr<FloatTarget> _target;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
56
include/osgAnimation/StackedScaleElement
Normal file
56
include/osgAnimation/StackedScaleElement
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_SCALE_ELEMENT
|
||||
#define OSGANIMATION_STACKED_SCALE_ELEMENT 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/Target>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedScaleElement : public StackedTransformElement
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, StackedScaleElement)
|
||||
|
||||
StackedScaleElement();
|
||||
StackedScaleElement(const StackedScaleElement&, const osg::CopyOp&);
|
||||
StackedScaleElement(const std::string& name, const osg::Vec3& scale = osg::Vec3(1,1,1));
|
||||
StackedScaleElement(const osg::Vec3& scale);
|
||||
|
||||
void applyToMatrix(osg::Matrix& matrix) const;
|
||||
osg::Matrix getAsMatrix() const;
|
||||
bool isIdentity() const;
|
||||
void update();
|
||||
const osg::Vec3& getScale() const;
|
||||
void setScale(const osg::Vec3& scale);
|
||||
|
||||
virtual Target* getOrCreateTarget();
|
||||
virtual Target* getTarget();
|
||||
virtual const Target* getTarget() const;
|
||||
|
||||
protected:
|
||||
osg::Vec3 _scale;
|
||||
osg::ref_ptr<Vec3Target> _target;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
42
include/osgAnimation/StackedTransform
Normal file
42
include/osgAnimation/StackedTransform
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_TRANSFORM
|
||||
#define OSGANIMATION_STACKED_TRANSFORM 1
|
||||
|
||||
#include <osg/MixinVector>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedTransform : public osg::MixinVector<osg::ref_ptr<StackedTransformElement> >
|
||||
{
|
||||
public:
|
||||
StackedTransform();
|
||||
StackedTransform(const StackedTransform&, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
void update();
|
||||
const osg::Matrix& getMatrix() const;
|
||||
|
||||
protected:
|
||||
osg::Matrix _matrix;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
42
include/osgAnimation/StackedTransformElement
Normal file
42
include/osgAnimation/StackedTransformElement
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_TRANSFORM_ELEMENT
|
||||
#define OSGANIMATION_STACKED_TRANSFORM_ELEMENT 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/Object>
|
||||
#include <osg/Matrix>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class Target;
|
||||
class OSGANIMATION_EXPORT StackedTransformElement : public osg::Object
|
||||
{
|
||||
public:
|
||||
StackedTransformElement() {}
|
||||
StackedTransformElement(const StackedTransformElement& rhs, const osg::CopyOp& c) : osg::Object(rhs, c) {}
|
||||
virtual void applyToMatrix(osg::Matrix& matrix) const = 0;
|
||||
virtual osg::Matrix getAsMatrix() const = 0;
|
||||
virtual bool isIdentity() const = 0;
|
||||
virtual void update() = 0;
|
||||
virtual Target* getOrCreateTarget() {return 0;}
|
||||
virtual Target* getTarget() {return 0;}
|
||||
virtual const Target* getTarget() const {return 0;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
54
include/osgAnimation/StackedTranslateElement
Normal file
54
include/osgAnimation/StackedTranslateElement
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_STACKED_TRANSLATE_ELEMENT
|
||||
#define OSGANIMATION_STACKED_TRANSLATE_ELEMENT 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/Target>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StackedTranslateElement : public StackedTransformElement
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, StackedTranslateElement);
|
||||
|
||||
StackedTranslateElement();
|
||||
StackedTranslateElement(const StackedTranslateElement&, const osg::CopyOp&);
|
||||
StackedTranslateElement(const std::string&, const osg::Vec3& translate = osg::Vec3(0,0,0));
|
||||
StackedTranslateElement(const osg::Vec3& translate);
|
||||
|
||||
void applyToMatrix(osg::Matrix& matrix) const;
|
||||
osg::Matrix getAsMatrix() const;
|
||||
bool isIdentity() const;
|
||||
void update();
|
||||
|
||||
const osg::Vec3& getTranslate() const;
|
||||
void setTranslate(const osg::Vec3& );
|
||||
virtual Target* getOrCreateTarget();
|
||||
virtual Target* getTarget();
|
||||
virtual const Target* getTarget() const;
|
||||
|
||||
protected:
|
||||
osg::Vec3 _translate;
|
||||
osg::ref_ptr<Vec3Target> _target;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
113
include/osgAnimation/StatsHandler
Normal file
113
include/osgAnimation/StatsHandler
Normal file
@@ -0,0 +1,113 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STATSHANDLER_H
|
||||
#define OSGANIMATION_STATSHANDLER_H
|
||||
|
||||
#include <osgAnimation/Timeline>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
#include <osgViewer/ViewerBase>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgText/Text>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
#if 0
|
||||
struct StatAction
|
||||
{
|
||||
|
||||
std::string _name;
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
osg::ref_ptr<osg::Geode> _label;
|
||||
osg::ref_ptr<osg::MatrixTransform> _graph;
|
||||
osg::ref_ptr<osgText::Text> _textLabel;
|
||||
|
||||
void init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float heigh, const osg::Vec4& color);
|
||||
void setPosition(const osg::Vec3& pos);
|
||||
void setAlpha(float v);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** Event handler for adding on screen stats reporting to Viewers.*/
|
||||
class OSGANIMATION_EXPORT StatsHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
StatsHandler();
|
||||
|
||||
enum StatsType
|
||||
{
|
||||
NO_STATS = 0,
|
||||
FRAME_RATE = 1,
|
||||
LAST = 2
|
||||
};
|
||||
|
||||
void setKeyEventTogglesOnScreenStats(int key) { _keyEventTogglesOnScreenStats = key; }
|
||||
int getKeyEventTogglesOnScreenStats() const { return _keyEventTogglesOnScreenStats; }
|
||||
|
||||
void setKeyEventPrintsOutStats(int key) { _keyEventPrintsOutStats = key; }
|
||||
int getKeyEventPrintsOutStats() const { return _keyEventPrintsOutStats; }
|
||||
|
||||
double getBlockMultiplier() const { return _blockMultiplier; }
|
||||
|
||||
void reset();
|
||||
|
||||
osg::Camera* getCamera() { return _camera.get(); }
|
||||
const osg::Camera* getCamera() const { return _camera.get(); }
|
||||
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
|
||||
|
||||
/** Get the keyboard and mouse usage of this manipulator.*/
|
||||
virtual void getUsage(osg::ApplicationUsage& usage) const;
|
||||
|
||||
protected:
|
||||
|
||||
void setUpHUDCamera(osgViewer::ViewerBase* viewer);
|
||||
|
||||
osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color);
|
||||
|
||||
osg::Geometry* createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
|
||||
|
||||
osg::Geometry* createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
|
||||
|
||||
osg::Geometry* createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks);
|
||||
|
||||
osg::Node* createCameraTimeStats(const std::string& font, osg::Vec3& pos, float startBlocks, bool acquireGPUStats, float characterSize, osg::Stats* viewerStats, osg::Camera* camera);
|
||||
|
||||
void setUpScene(osgViewer::Viewer* viewer);
|
||||
|
||||
int _keyEventTogglesOnScreenStats;
|
||||
int _keyEventPrintsOutStats;
|
||||
|
||||
int _statsType;
|
||||
|
||||
bool _initialized;
|
||||
osg::ref_ptr<osg::Camera> _camera;
|
||||
|
||||
osg::ref_ptr<osg::Switch> _switch;
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
|
||||
unsigned int _frameRateChildNum;
|
||||
unsigned int _numBlocks;
|
||||
double _blockMultiplier;
|
||||
|
||||
float _statsWidth;
|
||||
float _statsHeight;
|
||||
|
||||
// std::map<std::string, StatAction > _actions;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
53
include/osgAnimation/StatsVisitor
Normal file
53
include/osgAnimation/StatsVisitor
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STATSVISITOR_H
|
||||
#define OSGANIMATION_STATSVISITOR_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/ActionVisitor>
|
||||
#include <osg/Stats>
|
||||
#include <vector>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StatsActionVisitor : public osgAnimation::UpdateActionVisitor
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
std::vector<std::string> _channels;
|
||||
|
||||
public:
|
||||
META_ActionVisitor(osgAnimation, StatsActionVisitor);
|
||||
|
||||
StatsActionVisitor();
|
||||
StatsActionVisitor(osg::Stats* stats, unsigned int frame);
|
||||
void reset();
|
||||
const std::vector<std::string>& getChannels() const { return _channels; }
|
||||
osg::Stats* getStats() { return _stats.get(); }
|
||||
void setStats(osg::Stats* stats) { _stats = stats; }
|
||||
void setFrame(unsigned int frame) { _frame = frame; }
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
void apply(ActionBlendIn& action);
|
||||
void apply(ActionBlendOut& action);
|
||||
void apply(ActionAnimation& action);
|
||||
void apply(ActionStripAnimation& action);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -34,15 +34,14 @@ namespace osgAnimation
|
||||
public:
|
||||
|
||||
Target();
|
||||
virtual ~Target();
|
||||
virtual void normalize() = 0;
|
||||
float getWeight() const { return _weight; }
|
||||
void reset() { _weight = 0;}
|
||||
virtual ~Target() {}
|
||||
void reset() { _weight = 0; _priorityWeight = 0; }
|
||||
int getCount() const { return referenceCount(); }
|
||||
float getWeight() const { return _weight; }
|
||||
protected:
|
||||
|
||||
void addWeight(float w) { _weight += w; }
|
||||
float _weight;
|
||||
float _priorityWeight;
|
||||
int _lastPriority;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,75 +50,78 @@ namespace osgAnimation
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateTarget() {}
|
||||
TemplateTarget() : _target() {}
|
||||
TemplateTarget(const T& v) { setValue(v); }
|
||||
TemplateTarget(const TemplateTarget& v) { setValue(v.getValue()); }
|
||||
|
||||
void update(float weight, const T& val)
|
||||
inline void lerp(float t, const T& a, const T& b);
|
||||
|
||||
/**
|
||||
* The priority is used to detect a change of priority
|
||||
* It's important to update animation target in priority
|
||||
* order. eg:
|
||||
* all animation with priority 1
|
||||
* all animation with priority 0
|
||||
* all animation with priority -1
|
||||
* ...
|
||||
*/
|
||||
void update(float weight, const T& val, int priority)
|
||||
{
|
||||
if (!_weight)
|
||||
_target = val * weight;
|
||||
if (_weight || _priorityWeight)
|
||||
{
|
||||
if (_lastPriority != priority)
|
||||
{
|
||||
// change in priority
|
||||
// add to weight with the same previous priority cumulated weight
|
||||
_weight += _priorityWeight * (1.0 - _weight);
|
||||
_priorityWeight = 0;
|
||||
_lastPriority = priority;
|
||||
}
|
||||
|
||||
_priorityWeight += weight;
|
||||
float t = (1.0 - _weight) * weight / _priorityWeight;
|
||||
lerp(t, _target, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = (1.0 - _weight) * weight;
|
||||
_target += val * weight;
|
||||
_priorityWeight = weight;
|
||||
_lastPriority = priority;
|
||||
_target = val;
|
||||
}
|
||||
addWeight(weight);
|
||||
}
|
||||
const T& getValue() const { return _target;}
|
||||
const T& getValue() const { return _target; }
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float weightSummed = getWeight();
|
||||
if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1) < 1e-4)
|
||||
return;
|
||||
(_target) /= weightSummed;
|
||||
}
|
||||
|
||||
void setValue(const T& value) { _target = value;}
|
||||
void setValue(const T& value) { _target = value; }
|
||||
|
||||
protected:
|
||||
|
||||
T _target;
|
||||
};
|
||||
|
||||
|
||||
// Target Specialisation for Quaternions
|
||||
template <>
|
||||
class TemplateTarget< osg::Quat > : public Target
|
||||
template <class T>
|
||||
inline void TemplateTarget<T>::lerp(float t, const T& a, const T& b)
|
||||
{
|
||||
public:
|
||||
|
||||
TemplateTarget () {}
|
||||
_target = a * (1.0f - t) + b * t;
|
||||
}
|
||||
|
||||
const osg::Quat& getValue() const { return _target;}
|
||||
void update(float weight, const osg::Quat& val)
|
||||
{
|
||||
if (!_weight)
|
||||
_target = val * weight;
|
||||
else
|
||||
{
|
||||
weight = (1.0 - _weight) * weight;
|
||||
_target += val * weight;
|
||||
}
|
||||
addWeight(weight);
|
||||
}
|
||||
|
||||
// maybe normalize could be non virtual and put on ITarget
|
||||
void normalize()
|
||||
template <>
|
||||
inline void TemplateTarget<osg::Quat>::lerp(float t, const osg::Quat& a, const osg::Quat& b)
|
||||
{
|
||||
if (a.asVec4() * b.asVec4() < 0.0)
|
||||
{
|
||||
float weightSummed = getWeight();
|
||||
if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1.0) < 1e-4)
|
||||
return;
|
||||
(_target) /= weightSummed;
|
||||
_target = a * (1.0f - t) + b * -t;
|
||||
}
|
||||
else
|
||||
{
|
||||
_target = a * (1.0f - t) + b * t;
|
||||
}
|
||||
|
||||
void setValue(const osg::Quat& value) { _target = value;}
|
||||
|
||||
protected:
|
||||
osg::Quat::value_type len2 = _target.length2();
|
||||
if ( len2 != 1.0 && len2 != 0.0)
|
||||
_target *= 1.0/sqrt(len2);
|
||||
}
|
||||
|
||||
osg::Quat _target;
|
||||
};
|
||||
|
||||
typedef TemplateTarget<osg::Matrixf> MatrixTarget;
|
||||
typedef TemplateTarget<osg::Quat> QuatTarget;
|
||||
typedef TemplateTarget<osg::Vec3> Vec3Target;
|
||||
typedef TemplateTarget<osg::Vec4> Vec4Target;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,180 +12,88 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_TIMELINE_H
|
||||
#define OSGANIMATION_TIMELINE_H
|
||||
#ifndef OSGANIMATION_TIMELINE
|
||||
#define OSGANIMATION_TIMELINE 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/Object>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <osg/observer_ptr>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Group>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osg/Stats>
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/FrameAction>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/StatsVisitor>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Action : public osg::Object
|
||||
class OSGANIMATION_EXPORT Timeline : public Action
|
||||
{
|
||||
public:
|
||||
|
||||
class Callback : public osg::Object
|
||||
{
|
||||
public:
|
||||
Callback(){}
|
||||
Callback(const Callback&,const osg::CopyOp&) {}
|
||||
Timeline();
|
||||
Timeline(const Timeline& nc,const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osgAnimation,Callback);
|
||||
|
||||
virtual void operator()(Action* /*action*/) {}
|
||||
|
||||
void addNestedCallback(Callback* callback)
|
||||
{
|
||||
if (_nested.valid())
|
||||
_nested->addNestedCallback(callback);
|
||||
else
|
||||
_nested = callback;
|
||||
}
|
||||
META_Action(osgAnimation, Timeline);
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Callback> _nested;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
|
||||
|
||||
META_Object(osgAnimation, Action);
|
||||
|
||||
Action()
|
||||
{
|
||||
_numberFrame = 25;
|
||||
_fps = 25;
|
||||
_speed = 1.0;
|
||||
_loop = 1;
|
||||
}
|
||||
|
||||
Action(const Action&,const osg::CopyOp&) {}
|
||||
|
||||
void setCallback(double when, Callback* callback)
|
||||
{
|
||||
setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
|
||||
}
|
||||
|
||||
void setCallback(unsigned int frame, Callback* callback)
|
||||
{
|
||||
if (_framesCallback[frame].valid())
|
||||
_framesCallback[frame]->addNestedCallback(callback);
|
||||
else
|
||||
_framesCallback[frame] = callback;
|
||||
}
|
||||
Callback* getCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) == _framesCallback.end())
|
||||
return 0;
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
|
||||
void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
|
||||
void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
|
||||
|
||||
unsigned int getNumFrames() const { return _numberFrame;}
|
||||
double getDuration() const { return _numberFrame * 1.0 / _fps; }
|
||||
|
||||
// 0 means infini else it's the number of loop
|
||||
virtual void setLoop(int nb) { _loop = nb; }
|
||||
virtual unsigned int getLoop() const { return _loop;}
|
||||
|
||||
// get the number of loop, the frame relative to loop.
|
||||
// return true if in range, and false if out of range.
|
||||
bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop )
|
||||
{
|
||||
nbloop = frame / getNumFrames();
|
||||
resultframe = frame;
|
||||
|
||||
if (frame > getNumFrames()-1)
|
||||
{
|
||||
if (!getLoop())
|
||||
resultframe = frame % getNumFrames();
|
||||
else
|
||||
{
|
||||
if (nbloop >= getLoop())
|
||||
return false;
|
||||
else
|
||||
resultframe = frame % getNumFrames();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frameInAction << " finished" << std::endl;
|
||||
else
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frame << " relative to loop " << frameInAction << " no loop " << loopDone<< std::endl;
|
||||
}
|
||||
|
||||
virtual void evaluateCallback(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
return;
|
||||
|
||||
frame = frameInAction;
|
||||
if (_framesCallback.find(frame) != _framesCallback.end())
|
||||
{
|
||||
std::cout << getName() << " evaluate callback " << _framesCallback[frame]->getName() << " at " << frame << std::endl;
|
||||
(*_framesCallback[frame])(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FrameCallback _framesCallback;
|
||||
|
||||
double _speed;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _loop;
|
||||
|
||||
enum State
|
||||
enum TimelineStatus
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
};
|
||||
|
||||
State _state;
|
||||
};
|
||||
|
||||
TimelineStatus getStatus() const { return _state; }
|
||||
|
||||
class Timeline : public osg::Object
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
typedef std::vector<FrameAction> ActionList;
|
||||
typedef std::map<int, ActionList> ActionLayers;
|
||||
enum State
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
};
|
||||
|
||||
|
||||
const ActionList& getActionLayer(int i) { return _actions[i];}
|
||||
unsigned int getCurrentFrame() const { return _currentFrame;}
|
||||
double getCurrentTime() const { return _currentFrame * 1.0 / _fps;}
|
||||
|
||||
void play() { _state = Play; }
|
||||
void gotoFrame(unsigned int frame) { _currentFrame = frame; }
|
||||
void stop() { _state = Stop; }
|
||||
bool getEvaluating() const { return _evaluating;}
|
||||
|
||||
bool isActive(Action* activeAction);
|
||||
|
||||
void removeAction(Action* action);
|
||||
virtual void addActionAt(unsigned int frame, Action* action, int priority = 0);
|
||||
virtual void addActionAt(double t, Action* action, int priority = 0);
|
||||
void addActionNow(Action* action, int priority = 0);
|
||||
|
||||
void clearActions();
|
||||
|
||||
virtual void update(double simulationTime);
|
||||
void setLastFrameEvaluated(unsigned int frame) { _previousFrameEvaluated = frame; }
|
||||
|
||||
void setEvaluating(bool state) { _evaluating = state;}
|
||||
void traverse(ActionVisitor& visitor);
|
||||
|
||||
void setStats(osg::Stats* stats);
|
||||
osg::Stats* getStats();
|
||||
void collectStats(bool state);
|
||||
osgAnimation::StatsActionVisitor* getStatsVisitor();
|
||||
|
||||
const ActionLayers& getActionLayers() const { return _actions; }
|
||||
|
||||
void processPendingOperation();
|
||||
void setAnimationManager(AnimationManagerBase*);
|
||||
protected:
|
||||
osg::observer_ptr<AnimationManagerBase> _animationManager;
|
||||
ActionLayers _actions;
|
||||
double _lastUpdate;
|
||||
double _speed;
|
||||
unsigned int _currentFrame;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _previousFrameEvaluated;
|
||||
bool _loop;
|
||||
bool _initFirstFrame;
|
||||
|
||||
State _state;
|
||||
TimelineStatus _state;
|
||||
|
||||
bool _collectStats;
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
osg::ref_ptr<osgAnimation::StatsActionVisitor> _statsVisitor;
|
||||
|
||||
// to manage pending operation
|
||||
bool _evaluating;
|
||||
@@ -202,331 +110,9 @@ namespace osgAnimation
|
||||
CommandList _addActionOperations;
|
||||
ActionList _removeActionOperations;
|
||||
|
||||
void setEvaluating(bool state) { _evaluating = state;}
|
||||
void processPendingOperation()
|
||||
{
|
||||
// process all pending add action operation
|
||||
while( !_addActionOperations.empty())
|
||||
{
|
||||
internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
|
||||
_addActionOperations.pop_back();
|
||||
}
|
||||
|
||||
// process all pending remove action operation
|
||||
while( !_removeActionOperations.empty())
|
||||
{
|
||||
internalRemoveAction(_removeActionOperations.back().second.get());
|
||||
_removeActionOperations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void internalRemoveAction(Action* action)
|
||||
{
|
||||
for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); it++)
|
||||
{
|
||||
ActionList& fa = it->second;
|
||||
for (unsigned int i = 0; i < fa.size(); i++)
|
||||
if (fa[i].second.get() == action)
|
||||
{
|
||||
fa.erase(fa.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void internalAddAction(int priority, const FrameAction& ftl)
|
||||
{
|
||||
_actions[priority].push_back(ftl);
|
||||
}
|
||||
void internalRemoveAction(Action* action);
|
||||
void internalAddAction(int priority, const FrameAction& ftl);
|
||||
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, Timeline);
|
||||
|
||||
Timeline();
|
||||
Timeline(const Timeline& nc,const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY);
|
||||
State getStatus() const { return _state; }
|
||||
const ActionList& getActionLayer(int i)
|
||||
{
|
||||
return _actions[i];
|
||||
}
|
||||
unsigned int getCurrentFrame() const { return _currentFrame;}
|
||||
double getCurrentTime() const { return _currentFrame * 1.0 / _fps;}
|
||||
|
||||
void play() { _state = Play; }
|
||||
void gotoFrame(unsigned int frame) { _currentFrame = frame; }
|
||||
void stop() { _state = Stop; }
|
||||
bool getEvaluating() const { return _evaluating;}
|
||||
|
||||
bool isActive(Action* activeAction)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
Action* action = list[i].second.get();
|
||||
if (action == activeAction)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (_currentFrame >= firstFrame &&
|
||||
_currentFrame < (firstFrame + action->getNumFrames()) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeAction(Action* action)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_removeActionOperations.push_back(FrameAction(0, action));
|
||||
else
|
||||
internalRemoveAction(action);
|
||||
}
|
||||
|
||||
virtual void addActionAt(unsigned int frame, Action* action, int priority = 0)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
|
||||
else
|
||||
internalAddAction(priority, FrameAction(frame, action));
|
||||
}
|
||||
virtual void addActionAt(double t, Action* action, int priority = 0)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
|
||||
addActionAt(frame, action, priority);
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
setEvaluating(true);
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " evaluate frame " << _currentFrame << std::endl;
|
||||
|
||||
// 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->evaluate(frame - firstFrame);
|
||||
}
|
||||
}
|
||||
setEvaluating(false);
|
||||
|
||||
// evaluate callback after updating all animation
|
||||
evaluateCallback(frame);
|
||||
_previousFrameEvaluated = frame;
|
||||
}
|
||||
|
||||
virtual void 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();
|
||||
}
|
||||
|
||||
virtual void update(double simulationTime)
|
||||
{
|
||||
// first time we call update we generate one frame
|
||||
if (!_initFirstFrame)
|
||||
{
|
||||
_lastUpdate = simulationTime;
|
||||
_initFirstFrame = true;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
|
||||
// find the number of frame pass since the last update
|
||||
double delta = (simulationTime - _lastUpdate);
|
||||
double nbframes = delta * _fps * _speed;
|
||||
unsigned int nb = static_cast<unsigned int>(floor(nbframes));
|
||||
|
||||
for (unsigned int i = 0; i < nb; i++)
|
||||
{
|
||||
if (_state == Play)
|
||||
_currentFrame++;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
if (nb)
|
||||
{
|
||||
_lastUpdate += ((double)nb) / _fps;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendIn : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
|
||||
public:
|
||||
BlendIn(Animation* animation, double duration, double weight)
|
||||
{
|
||||
_animation = animation;
|
||||
_weight = weight;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d)) + 1);
|
||||
setName("BlendIn");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = _weight;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * ratio;
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendOut : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
public:
|
||||
BlendOut(Animation* animation, double duration)
|
||||
{
|
||||
_animation = animation;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d) + 1));
|
||||
_weight = 1.0;
|
||||
setName("BlendOut");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = 0.0;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * (1.0-ratio);
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ActionAnimation : public Action
|
||||
{
|
||||
public:
|
||||
ActionAnimation(Animation* animation) : _animation(animation)
|
||||
{
|
||||
setDuration(animation->getDuration());
|
||||
setName(animation->getName());
|
||||
}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
_animation->update(frame * 1.0/_fps);
|
||||
}
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
protected:
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
|
||||
// encapsulate animation with blend in blend out for classic usage
|
||||
class StripAnimation : public Action
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
|
||||
public:
|
||||
StripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget = 1.0 )
|
||||
{
|
||||
_blendIn = new BlendIn(animation, blendInDuration, blendInWeightTarget);
|
||||
_animation = new ActionAnimation(animation);
|
||||
unsigned int start = static_cast<unsigned int>(floor((_animation->getDuration() - blendOutDuration) * _fps));
|
||||
_blendOut = FrameAction(start, new BlendOut(animation, blendOutDuration));
|
||||
setName(animation->getName() + "_Strip");
|
||||
_blendIn->setName(_animation->getName() + "_" + _blendIn->getName());
|
||||
_blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName());
|
||||
setDuration(animation->getDuration());
|
||||
}
|
||||
|
||||
ActionAnimation* getActionAnimation() { return _animation.get(); }
|
||||
BlendIn* getBlendIn() { return _blendIn.get(); }
|
||||
BlendOut* getBlendOut() { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
const ActionAnimation* getActionAnimation() const { return _animation.get(); }
|
||||
const BlendIn* getBlendIn() const { return _blendIn.get(); }
|
||||
const BlendOut* getBlendOut() const { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
|
||||
unsigned int getLoop() const { return _animation->getLoop(); }
|
||||
void setLoop(unsigned int loop)
|
||||
{
|
||||
_animation->setLoop(loop);
|
||||
if (!loop)
|
||||
setDuration(-1);
|
||||
else
|
||||
setDuration(loop * _animation->getDuration());
|
||||
|
||||
// duration changed re evaluate the blendout duration
|
||||
unsigned int start = static_cast<unsigned int>(floor((getDuration() - _blendOut.second->getDuration()) * _fps));
|
||||
_blendOut = FrameAction(start, _blendOut.second);
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
if (frame > getNumFrames() - 1)
|
||||
return;
|
||||
|
||||
Action::evaluate(frame);
|
||||
if (frame < _blendIn->getNumFrames())
|
||||
_blendIn->evaluate(frame);
|
||||
if (frame >= _blendOut.first)
|
||||
_blendOut.second->evaluate(frame - _blendOut.first);
|
||||
_animation->evaluate(frame);
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<BlendIn> _blendIn;
|
||||
FrameAction _blendOut;
|
||||
osg::ref_ptr<ActionAnimation> _animation;
|
||||
};
|
||||
|
||||
|
||||
class RunAction : public Action::Callback
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _tm;
|
||||
osg::ref_ptr<Action> _action;
|
||||
|
||||
public:
|
||||
RunAction(Timeline* tm, Action* a) : _tm(tm), _action(a) {}
|
||||
virtual void operator()(Action* /*action*/)
|
||||
{
|
||||
_tm->addActionAt(_tm->getCurrentFrame(), _action.get()); // warning we are trsversing the vector
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,10 +10,10 @@
|
||||
* 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.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_TIMELINE_ANIMATION_MANAGER_H
|
||||
#define OSGANIMATION_TIMELINE_ANIMATION_MANAGER_H
|
||||
#ifndef OSGANIMATION_TIMELINE_ANIMATION_MANAGER
|
||||
#define OSGANIMATION_TIMELINE_ANIMATION_MANAGER 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
@@ -23,21 +23,21 @@
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT TimelineAnimationManager : public AnimationManagerBase
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _timeline;
|
||||
class OSGANIMATION_EXPORT TimelineAnimationManager : public AnimationManagerBase
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _timeline;
|
||||
|
||||
public:
|
||||
META_Object(osgAnimation, TimelineAnimationManager);
|
||||
TimelineAnimationManager();
|
||||
TimelineAnimationManager(const AnimationManagerBase& manager);
|
||||
TimelineAnimationManager(const TimelineAnimationManager& nc,const osg::CopyOp&);
|
||||
public:
|
||||
META_Object(osgAnimation, TimelineAnimationManager);
|
||||
TimelineAnimationManager();
|
||||
TimelineAnimationManager(const AnimationManagerBase& manager);
|
||||
TimelineAnimationManager(const TimelineAnimationManager& nc,const osg::CopyOp&);
|
||||
|
||||
Timeline* getTimeline() { return _timeline.get(); }
|
||||
const Timeline* getTimeline() const { return _timeline.get(); }
|
||||
void update(double time);
|
||||
};
|
||||
Timeline* getTimeline() { return _timeline.get(); }
|
||||
const Timeline* getTimeline() const { return _timeline.get(); }
|
||||
void update(double time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
36
include/osgAnimation/UpdateBone
Normal file
36
include/osgAnimation/UpdateBone
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_UPDATE_BONE
|
||||
#define OSGANIMATION_UPDATE_BONE 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateBone : public UpdateMatrixTransform
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, UpdateBone);
|
||||
|
||||
UpdateBone(const std::string& name = "");
|
||||
UpdateBone(const UpdateBone&,const osg::CopyOp&);
|
||||
void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
46
include/osgAnimation/UpdateMaterial
Normal file
46
include/osgAnimation/UpdateMaterial
Normal file
@@ -0,0 +1,46 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_UPDATE_MATERIAL
|
||||
#define OSGANIMATION_UPDATE_MATERIAL 1
|
||||
|
||||
#include <osgAnimation/AnimationUpdateCallback>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/StateAttribute>
|
||||
#include <osg/Material>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateMaterial : public AnimationUpdateCallback<osg::StateAttributeCallback>
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Vec4Target> _diffuse;
|
||||
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, UpdateMaterial);
|
||||
|
||||
UpdateMaterial(const std::string& name = "");
|
||||
UpdateMaterial(const UpdateMaterial& apc,const osg::CopyOp& copyop);
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
virtual void operator () (osg::StateAttribute*, osg::NodeVisitor*);
|
||||
void update(osg::Material& material);
|
||||
bool link(Channel* channel);
|
||||
Vec4Target* getDiffuse();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
48
include/osgAnimation/UpdateMatrixTransform
Normal file
48
include/osgAnimation/UpdateMatrixTransform
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OSGANIMATION_UPDATE_MATRIX_TRANSFORM
|
||||
#define OSGANIMATION_UPDATE_MATRIX_TRANSFORM 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/AnimationUpdateCallback>
|
||||
#include <osgAnimation/StackedTransform>
|
||||
#include <osg/NodeCallback>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateMatrixTransform : public AnimationUpdateCallback<osg::NodeCallback>
|
||||
{
|
||||
public:
|
||||
META_Object(osgAnimation, UpdateMatrixTransform);
|
||||
|
||||
UpdateMatrixTransform(const std::string& name = "");
|
||||
UpdateMatrixTransform(const UpdateMatrixTransform& apc,const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
// Callback method called by the NodeVisitor when visiting a node.
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
virtual bool link(osgAnimation::Channel* channel);
|
||||
|
||||
StackedTransform& getStackedTransforms() { return _transforms;}
|
||||
const StackedTransform& getStackedTransforms() const { return _transforms;}
|
||||
|
||||
protected:
|
||||
StackedTransform _transforms;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,8 +12,8 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_VERTEX_INFLUENCES_H
|
||||
#define OSGANIMATION_VERTEX_INFLUENCES_H
|
||||
#ifndef OSGANIMATION_VERTEX_INFLUENCE
|
||||
#define OSGANIMATION_VERTEX_INFLUENCE 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osgAnimation/Export>
|
||||
@@ -38,8 +38,6 @@ namespace osgAnimation
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
// typedef std::map<std::string, VertexInfluence> VertexInfluenceMap;
|
||||
|
||||
class VertexInfluenceMap : public std::map<std::string, VertexInfluence> , public osg::Object
|
||||
{
|
||||
public:
|
||||
@@ -52,7 +50,7 @@ namespace osgAnimation
|
||||
|
||||
// this class manage VertexInfluence database by mesh
|
||||
// reference bones per vertex ...
|
||||
class VertexInfluenceSet
|
||||
class OSGANIMATION_EXPORT VertexInfluenceSet
|
||||
{
|
||||
public:
|
||||
typedef std::vector<VertexInfluence> BoneToVertexList;
|
||||
@@ -73,7 +71,7 @@ namespace osgAnimation
|
||||
typedef std::vector<BoneWeight> BoneWeightList;
|
||||
typedef std::map<int,BoneWeightList> VertexIndexToBoneWeightMap;
|
||||
|
||||
class UniqVertexSetToBoneSet
|
||||
class UniqVertexSetToBoneSet
|
||||
{
|
||||
public:
|
||||
void setBones(BoneWeightList& bones) { _bones = bones;}
|
||||
@@ -88,14 +86,12 @@ namespace osgAnimation
|
||||
typedef std::vector<UniqVertexSetToBoneSet> UniqVertexSetToBoneSetList;
|
||||
|
||||
const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;}
|
||||
void addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
|
||||
void addVertexInfluence(const VertexInfluence& v);
|
||||
void buildVertex2BoneList();
|
||||
void buildUniqVertexSetToBoneSetList();
|
||||
void clear()
|
||||
{
|
||||
_bone2Vertexes.clear();
|
||||
_uniqVertexSetToBoneSet.clear();
|
||||
}
|
||||
void clear();
|
||||
|
||||
const VertexIndexToBoneWeightMap& getVertexToBoneList() const;
|
||||
protected:
|
||||
BoneToVertexList _bone2Vertexes;
|
||||
VertexIndexToBoneWeightMap _vertex2Bones;
|
||||
|
||||
83
src/osgAnimation/Action.cpp
Normal file
83
src/osgAnimation/Action.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/Action>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
Action::Action()
|
||||
{
|
||||
_numberFrame = 25;
|
||||
_fps = 25;
|
||||
_speed = 1.0;
|
||||
_loop = 1;
|
||||
}
|
||||
Action::Action(const Action&,const osg::CopyOp&) {}
|
||||
Action::Callback* Action::getFrameCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) != _framesCallback.end())
|
||||
{
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Action::removeCallback(Callback* cb)
|
||||
{
|
||||
std::vector<unsigned int> keyToRemove;
|
||||
for (FrameCallback::iterator it = _framesCallback.begin(); it != _framesCallback.end(); ++it)
|
||||
{
|
||||
if (it->second.get())
|
||||
{
|
||||
if (it->second.get() == cb)
|
||||
{
|
||||
it->second = it->second->getNestedCallback();
|
||||
if (!it->second.valid())
|
||||
keyToRemove.push_back(it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->removeCallback(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector<unsigned int>::iterator it = keyToRemove.begin(); it != keyToRemove.end(); ++it)
|
||||
_framesCallback.erase(*it);
|
||||
}
|
||||
|
||||
Action::Callback* Action::getFrameCallback(double time)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(time * _fps));
|
||||
return getFrameCallback(frame);
|
||||
}
|
||||
|
||||
bool osgAnimation::Action::evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop )
|
||||
{
|
||||
nbloop = frame / getNumFrames();
|
||||
resultframe = frame;
|
||||
|
||||
if (frame > getNumFrames()-1)
|
||||
{
|
||||
if (!getLoop())
|
||||
resultframe = frame % getNumFrames();
|
||||
else
|
||||
{
|
||||
if (nbloop >= getLoop())
|
||||
return false;
|
||||
else
|
||||
resultframe = frame % getNumFrames();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
32
src/osgAnimation/ActionAnimation.cpp
Normal file
32
src/osgAnimation/ActionAnimation.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/ActionAnimation>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
ActionAnimation::ActionAnimation() {}
|
||||
|
||||
ActionAnimation::ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c) : Action(a,c) { _animation = a._animation;}
|
||||
|
||||
ActionAnimation::ActionAnimation(Animation* animation) : _animation(animation)
|
||||
{
|
||||
Action::setDuration(animation->getDuration());
|
||||
setName(animation->getName());
|
||||
}
|
||||
|
||||
void ActionAnimation::updateAnimation(unsigned int frame, int priority)
|
||||
{
|
||||
_animation->update(frame * 1.0/_fps, priority);
|
||||
}
|
||||
45
src/osgAnimation/ActionBlendIn.cpp
Normal file
45
src/osgAnimation/ActionBlendIn.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/ActionBlendIn>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
ActionBlendIn::ActionBlendIn() : _weight(0) {}
|
||||
ActionBlendIn::ActionBlendIn(const ActionBlendIn& a, const osg::CopyOp& c) : Action(a,c)
|
||||
{
|
||||
_weight = a._weight;
|
||||
_animation = a._animation;
|
||||
}
|
||||
|
||||
ActionBlendIn::ActionBlendIn(Animation* animation, double duration, double weight)
|
||||
{
|
||||
_animation = animation;
|
||||
_weight = weight;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d)) + 1);
|
||||
setName("BlendIn");
|
||||
}
|
||||
|
||||
void ActionBlendIn::computeWeight(unsigned int frame)
|
||||
{
|
||||
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = _weight * ratio;
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " BlendIn frame " << frame << " weight " << w << std::endl;
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
41
src/osgAnimation/ActionBlendOut.cpp
Normal file
41
src/osgAnimation/ActionBlendOut.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/ActionBlendOut>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
ActionBlendOut::ActionBlendOut() : _weight(0) {}
|
||||
ActionBlendOut::ActionBlendOut(const ActionBlendOut& a, const osg::CopyOp& c) : Action(a,c)
|
||||
{
|
||||
_weight = a._weight;
|
||||
_animation = a._animation;
|
||||
}
|
||||
|
||||
ActionBlendOut::ActionBlendOut(Animation* animation, double duration)
|
||||
{
|
||||
_animation = animation;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d) + 1));
|
||||
_weight = 1.0;
|
||||
setName("BlendOut");
|
||||
}
|
||||
|
||||
void ActionBlendOut::computeWeight(unsigned int frame)
|
||||
{
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = _weight * (1.0-ratio);
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " BlendOut frame " << frame << " weight " << w << std::endl;
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
23
src/osgAnimation/ActionCallback.cpp
Normal file
23
src/osgAnimation/ActionCallback.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/ActionCallback>
|
||||
#include <osgAnimation/Timeline>
|
||||
|
||||
void osgAnimation::RunAction::operator()(Action* action, ActionVisitor* visitor)
|
||||
{
|
||||
Timeline* tm = visitor->getCurrentTimeline();
|
||||
tm->addActionNow(_action.get(), _priority);
|
||||
}
|
||||
|
||||
88
src/osgAnimation/ActionStripAnimation.cpp
Normal file
88
src/osgAnimation/ActionStripAnimation.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/ActionStripAnimation>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
ActionAnimation* ActionStripAnimation::getAnimation() { return _animation.get(); }
|
||||
ActionBlendIn* ActionStripAnimation::getBlendIn() { return _blendIn.get(); }
|
||||
ActionBlendOut* ActionStripAnimation::getBlendOut() { return _blendOut.second.get(); }
|
||||
const ActionAnimation* ActionStripAnimation::getAnimation() const { return _animation.get(); }
|
||||
const ActionBlendIn* ActionStripAnimation::getBlendIn() const { return _blendIn.get(); }
|
||||
const ActionBlendOut* ActionStripAnimation::getBlendOut() const { return _blendOut.second.get(); }
|
||||
unsigned int ActionStripAnimation::getBlendOutStartFrame() const { return _blendOut.first; }
|
||||
|
||||
unsigned int ActionStripAnimation::getLoop() const { return _animation->getLoop(); }
|
||||
|
||||
|
||||
ActionStripAnimation::ActionStripAnimation(const ActionStripAnimation& a, const osg::CopyOp& c) : Action(a,c)
|
||||
{
|
||||
_animation = a._animation;
|
||||
_blendIn = a._blendIn;
|
||||
_blendOut = a._blendOut;
|
||||
}
|
||||
|
||||
ActionStripAnimation::ActionStripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget)
|
||||
{
|
||||
_blendIn = new ActionBlendIn(animation, blendInDuration, blendInWeightTarget);
|
||||
_animation = new ActionAnimation(animation);
|
||||
unsigned int start = static_cast<unsigned int>(floor((_animation->getDuration() - blendOutDuration) * _fps));
|
||||
_blendOut = FrameBlendOut(start, new ActionBlendOut(animation, blendOutDuration));
|
||||
setName(animation->getName() + "_Strip");
|
||||
_blendIn->setName(_animation->getName() + "_" + _blendIn->getName());
|
||||
_blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName());
|
||||
setDuration(animation->getDuration());
|
||||
}
|
||||
|
||||
|
||||
void ActionStripAnimation::setLoop(unsigned int loop)
|
||||
{
|
||||
_animation->setLoop(loop);
|
||||
if (!loop)
|
||||
setDuration(-1);
|
||||
else
|
||||
setDuration(loop * _animation->getDuration());
|
||||
|
||||
// duration changed re evaluate the blendout duration
|
||||
unsigned int start = static_cast<unsigned int>(floor((getDuration() - _blendOut.second->getDuration()) * _fps));
|
||||
_blendOut = FrameBlendOut(start, _blendOut.second);
|
||||
}
|
||||
|
||||
void ActionStripAnimation::traverse(ActionVisitor& visitor)
|
||||
{
|
||||
if (_blendIn.valid())
|
||||
{
|
||||
unsigned int f = visitor.getStackedFrameAction().back().first;
|
||||
visitor.pushFrameActionOnStack(FrameAction(f,_blendIn.get()));
|
||||
_blendIn->accept(visitor);
|
||||
visitor.popFrameAction();
|
||||
}
|
||||
if (_blendOut.second.valid())
|
||||
{
|
||||
unsigned int f = visitor.getStackedFrameAction().back().first;
|
||||
visitor.pushFrameActionOnStack(FrameAction(f + _blendOut.first,_blendOut.second.get()));
|
||||
_blendOut.second.get()->accept(visitor);
|
||||
visitor.popFrameAction();
|
||||
}
|
||||
|
||||
if (_animation.valid())
|
||||
{
|
||||
unsigned int f = visitor.getStackedFrameAction().back().first;
|
||||
visitor.pushFrameActionOnStack(FrameAction(f,_animation.get()));
|
||||
_animation->accept(visitor);
|
||||
visitor.popFrameAction();
|
||||
}
|
||||
}
|
||||
184
src/osgAnimation/ActionVisitor.cpp
Normal file
184
src/osgAnimation/ActionVisitor.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/Action>
|
||||
#include <osgAnimation/ActionBlendIn>
|
||||
#include <osgAnimation/ActionBlendOut>
|
||||
#include <osgAnimation/ActionStripAnimation>
|
||||
#include <osgAnimation/ActionAnimation>
|
||||
#include <osgAnimation/ActionVisitor>
|
||||
#include <osgAnimation/Timeline>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
ActionVisitor::ActionVisitor()
|
||||
{
|
||||
_currentLayer = 0;
|
||||
}
|
||||
void ActionVisitor::pushFrameActionOnStack(const FrameAction& fa) { _stackFrameAction.push_back(fa); }
|
||||
void ActionVisitor::popFrameAction() { _stackFrameAction.pop_back(); }
|
||||
void ActionVisitor::pushTimelineOnStack(Timeline* tm) { _stackTimeline.push_back(tm); }
|
||||
void ActionVisitor::popTimeline() { _stackTimeline.pop_back(); }
|
||||
void ActionVisitor::apply(Action& action) { traverse(action); }
|
||||
void ActionVisitor::apply(Timeline& tm) { tm.traverse(*this); }
|
||||
void ActionVisitor::apply(ActionBlendIn& action) { apply(static_cast<Action&>(action));}
|
||||
void ActionVisitor::apply(ActionBlendOut& action) { apply(static_cast<Action&>(action)); }
|
||||
void ActionVisitor::apply(ActionAnimation& action) { apply(static_cast<Action&>(action)); }
|
||||
void ActionVisitor::apply(ActionStripAnimation& action) { apply(static_cast<Action&>(action)); }
|
||||
void ActionVisitor::traverse(Action& action)
|
||||
{
|
||||
action.traverse(*this);
|
||||
}
|
||||
|
||||
Timeline* ActionVisitor::getCurrentTimeline()
|
||||
{
|
||||
if (_stackTimeline.empty())
|
||||
return 0;
|
||||
return _stackTimeline.back();
|
||||
}
|
||||
|
||||
UpdateActionVisitor::UpdateActionVisitor()
|
||||
{
|
||||
_frame = 0;
|
||||
_currentAnimationPriority = 0;
|
||||
}
|
||||
|
||||
|
||||
void UpdateActionVisitor::apply(Timeline& tm)
|
||||
{
|
||||
_currentAnimationPriority = 0;
|
||||
|
||||
tm.setEvaluating(true);
|
||||
|
||||
tm.traverse(*this);
|
||||
|
||||
tm.setEvaluating(false);
|
||||
|
||||
tm.setLastFrameEvaluated(_frame);
|
||||
}
|
||||
|
||||
bool UpdateActionVisitor::isActive(Action& action) const
|
||||
{
|
||||
FrameAction fa = _stackFrameAction.back();
|
||||
if (_frame < fa.first)
|
||||
return false;
|
||||
if (!fa.second.valid())
|
||||
return false;
|
||||
|
||||
unsigned int f = getLocalFrame();
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
return action.evaluateFrame(f, frameInAction, loopDone);
|
||||
}
|
||||
|
||||
unsigned int UpdateActionVisitor::getLocalFrame() const
|
||||
{
|
||||
return _frame - _stackFrameAction.back().first;
|
||||
}
|
||||
|
||||
void UpdateActionVisitor::apply(Action& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
unsigned int frame = getLocalFrame();
|
||||
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
bool result = action.evaluateFrame(frame, frameInAction, loopDone);
|
||||
if (!result)
|
||||
{
|
||||
osg::notify(osg::DEBUG_INFO) << action.getName() << " Action frame " << frameInAction << " finished" << std::endl;
|
||||
return;
|
||||
}
|
||||
osg::notify(osg::DEBUG_INFO) << action.getName() << " Action frame " << frame << " relative to loop " << frameInAction << " no loop " << loopDone<< std::endl;
|
||||
|
||||
frame = frameInAction;
|
||||
Action::Callback* cb = action.getFrameCallback(frame);
|
||||
while (cb)
|
||||
{
|
||||
osg::notify(osg::DEBUG_INFO) << action.getName() << " evaluate callback " << cb->getName() << " at " << frame << std::endl;
|
||||
(*cb)(&action, this);
|
||||
cb = cb->getNestedCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateActionVisitor::apply(ActionBlendIn& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
unsigned int frame = getLocalFrame();
|
||||
apply(static_cast<Action&>(action));
|
||||
action.computeWeight(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateActionVisitor::apply(ActionBlendOut& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
unsigned int frame = getLocalFrame();
|
||||
apply(static_cast<Action&>(action));
|
||||
action.computeWeight(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateActionVisitor::apply(ActionAnimation& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
unsigned int frame = getLocalFrame();
|
||||
apply(static_cast<Action&>(action));
|
||||
int pri = static_cast<int>(_currentAnimationPriority);
|
||||
_currentAnimationPriority++;
|
||||
action.updateAnimation(frame, -pri);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateActionVisitor::apply(ActionStripAnimation& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
apply(static_cast<Action&>(action));
|
||||
action.traverse(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ClearActionVisitor::ClearActionVisitor(ClearType type) : _clearType(type)
|
||||
{
|
||||
}
|
||||
|
||||
void ClearActionVisitor::apply(Timeline& tm)
|
||||
{
|
||||
_remove.clear();
|
||||
tm.traverse(*this);
|
||||
for (int i = 0; i < (int)_remove.size(); i++)
|
||||
tm.removeAction(_remove[i].get());
|
||||
}
|
||||
void ClearActionVisitor::apply(Action& action)
|
||||
{
|
||||
FrameAction fa = _stackFrameAction.back();
|
||||
switch( _clearType) {
|
||||
case BEFORE_FRAME:
|
||||
if (_frame > fa.first)
|
||||
_remove.push_back(&action);
|
||||
break;
|
||||
case AFTER_FRAME:
|
||||
if (_frame - fa.first > action.getNumFrames())
|
||||
_remove.push_back(&action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -16,13 +16,18 @@
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& c)
|
||||
Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& copyop): osg::Object(anim, copyop),
|
||||
_duration(anim._duration),
|
||||
_originalDuration(anim._originalDuration),
|
||||
_weight(anim._weight),
|
||||
_startTime(anim._startTime),
|
||||
_playmode(anim._playmode)
|
||||
{
|
||||
_duration = anim._duration;
|
||||
_originalDuration = anim._originalDuration;
|
||||
_weight = anim._weight;
|
||||
_startTime = anim._startTime;
|
||||
_playmode = anim._playmode;
|
||||
const ChannelList& cl = anim.getChannels();
|
||||
for (ChannelList::const_iterator it = cl.begin(); it != cl.end(); ++it)
|
||||
{
|
||||
addChannel(it->get()->clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +95,7 @@ void Animation::setWeight (float weight)
|
||||
_weight = weight;
|
||||
}
|
||||
|
||||
bool Animation::update (float time)
|
||||
bool Animation::update (float time, int priority)
|
||||
{
|
||||
if (!_duration) // if not initialized then do it
|
||||
computeDuration();
|
||||
@@ -128,13 +133,10 @@ bool Animation::update (float time)
|
||||
break;
|
||||
}
|
||||
|
||||
// std::cout << "t " << t << " / " << _duration << std::endl;
|
||||
|
||||
ChannelList::const_iterator chan;
|
||||
for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
|
||||
for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
|
||||
{
|
||||
(*chan)->setWeight(_weight);
|
||||
(*chan)->update(t);
|
||||
(*chan)->update(t, _weight, priority);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/LinkVisitor>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
@@ -21,23 +22,27 @@ AnimationManagerBase::~AnimationManagerBase() {}
|
||||
|
||||
AnimationManagerBase::AnimationManagerBase()
|
||||
{
|
||||
_needToLink = false;
|
||||
_needToLink = false;
|
||||
_automaticLink = true;
|
||||
}
|
||||
|
||||
void AnimationManagerBase::clearTargets()
|
||||
{
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it)
|
||||
(*it).get()->reset();
|
||||
}
|
||||
void AnimationManagerBase::normalizeTargets()
|
||||
|
||||
void AnimationManagerBase::dirty()
|
||||
{
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
(*it).get()->normalize();
|
||||
_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)
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
if (needToLink())
|
||||
{
|
||||
@@ -57,22 +62,30 @@ void AnimationManagerBase::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
}
|
||||
|
||||
|
||||
AnimationManagerBase::AnimationManagerBase(const AnimationManagerBase& b, const osg::CopyOp& copyop) : osg::NodeCallback(b,copyop)
|
||||
AnimationManagerBase::AnimationManagerBase(const AnimationManagerBase& b, const osg::CopyOp& copyop) : osg::NodeCallback(b,copyop)
|
||||
{
|
||||
_animations = b._animations;
|
||||
_targets = b._targets;
|
||||
_needToLink = b._needToLink;
|
||||
const AnimationList& animationList = b.getAnimationList();
|
||||
for (AnimationList::const_iterator it = animationList.begin();
|
||||
it != animationList.end();
|
||||
++it)
|
||||
{
|
||||
Animation* animation = dynamic_cast<osgAnimation::Animation*>(it->get()->clone(copyop));
|
||||
_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();
|
||||
it != anim->getChannels().end();
|
||||
it++)
|
||||
++it)
|
||||
_targets.insert((*it)->getTarget());
|
||||
}
|
||||
}
|
||||
@@ -85,14 +98,38 @@ void AnimationManagerBase::registerAnimation (Animation* animation)
|
||||
buildTargetReference();
|
||||
}
|
||||
|
||||
bool AnimationManagerBase::needToLink() const { return _needToLink; }
|
||||
void AnimationManagerBase::unregisterAnimation (Animation* animation)
|
||||
{
|
||||
AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation);
|
||||
if (it != _animations.end())
|
||||
{
|
||||
_animations.erase(it);
|
||||
}
|
||||
buildTargetReference();
|
||||
}
|
||||
|
||||
bool AnimationManagerBase::needToLink() const { return _needToLink && isAutomaticLink(); }
|
||||
|
||||
|
||||
void AnimationManagerBase::setLinkVisitor(LinkVisitor* visitor)
|
||||
{
|
||||
_linker = visitor;
|
||||
}
|
||||
|
||||
LinkVisitor* AnimationManagerBase::getOrCreateLinkVisitor()
|
||||
{
|
||||
if (!_linker.valid())
|
||||
_linker = new LinkVisitor;
|
||||
return _linker.get();
|
||||
}
|
||||
|
||||
void AnimationManagerBase::link(osg::Node* subgraph)
|
||||
{
|
||||
LinkVisitor linker(_animations);
|
||||
subgraph->accept(linker);
|
||||
LinkVisitor* linker = getOrCreateLinkVisitor();
|
||||
linker->getAnimationList().clear();
|
||||
linker->getAnimationList() = _animations;
|
||||
|
||||
subgraph->accept(*linker);
|
||||
_needToLink = false;
|
||||
buildTargetReference();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -38,7 +38,7 @@ void BasicAnimationManager::stopAll()
|
||||
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
|
||||
{
|
||||
AnimationList& list = iterAnim->second;
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); ++it)
|
||||
(*it)->resetTargets();
|
||||
}
|
||||
_animationsPlaying.clear();
|
||||
@@ -47,14 +47,14 @@ void BasicAnimationManager::stopAll()
|
||||
void BasicAnimationManager::playAnimation(Animation* pAnimation, int priority, float weight)
|
||||
{
|
||||
if (!findAnimation(pAnimation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isPlaying(pAnimation) )
|
||||
stopAnimation(pAnimation);
|
||||
|
||||
_animationsPlaying[priority].push_back(pAnimation);
|
||||
// for debug
|
||||
//std::cout << "player Animation " << pAnimation->getName() << " at " << _lastUpdate << std::endl;
|
||||
pAnimation->setStartTime(_lastUpdate);
|
||||
pAnimation->setWeight(weight);
|
||||
}
|
||||
@@ -62,10 +62,10 @@ void BasicAnimationManager::playAnimation(Animation* pAnimation, int priority, f
|
||||
bool BasicAnimationManager::stopAnimation(Animation* pAnimation)
|
||||
{
|
||||
// search though the layer and remove animation
|
||||
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
|
||||
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
|
||||
{
|
||||
AnimationList& list = iterAnim->second;
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); ++it)
|
||||
if( (*it) == pAnimation )
|
||||
{
|
||||
(*it)->resetTargets();
|
||||
@@ -79,11 +79,10 @@ bool BasicAnimationManager::stopAnimation(Animation* pAnimation)
|
||||
|
||||
void BasicAnimationManager::update (double time)
|
||||
{
|
||||
if (!_lastUpdate)
|
||||
_lastUpdate = time;
|
||||
_lastUpdate = time; // keep time of last update
|
||||
|
||||
// could filtered with an active flag
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it)
|
||||
(*it).get()->reset();
|
||||
|
||||
// update from high priority to low priority
|
||||
@@ -91,11 +90,20 @@ void BasicAnimationManager::update (double time)
|
||||
{
|
||||
// update all animation
|
||||
std::vector<int> toremove;
|
||||
int priority = iterAnim->first;
|
||||
AnimationList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
if (! list[i]->update(time))
|
||||
if (! list[i]->update(time, priority))
|
||||
{
|
||||
// debug
|
||||
// std::cout << list[i]->getName() << " finished at " << time << std::endl;
|
||||
toremove.push_back(i);
|
||||
} else
|
||||
{
|
||||
// debug
|
||||
//std::cout << list[i]->getName() << " updated" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// remove finished animation
|
||||
@@ -105,9 +113,6 @@ void BasicAnimationManager::update (double time)
|
||||
toremove.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
for (TargetSet::iterator it = _targets.begin(); it != _targets.end(); it++)
|
||||
(*it).get()->normalize();
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +132,7 @@ bool BasicAnimationManager::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++)
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); ++it)
|
||||
if ( (*it) == pAnimation )
|
||||
return true;
|
||||
}
|
||||
@@ -140,7 +145,7 @@ bool BasicAnimationManager::isPlaying(const std::string& name)
|
||||
for( AnimationLayers::iterator iterAnim = _animationsPlaying.begin(); iterAnim != _animationsPlaying.end(); ++iterAnim )
|
||||
{
|
||||
AnimationList& list = iterAnim->second;
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); it++)
|
||||
for (AnimationList::iterator it = list.begin(); it != list.end(); ++it)
|
||||
if ( (*it)->getName() == name )
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -12,36 +12,25 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osgAnimation/Skinning>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
#include <osgAnimation/BoneMapVisitor>
|
||||
|
||||
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)
|
||||
using namespace osgAnimation;
|
||||
|
||||
Bone::Bone(const Bone& b, const osg::CopyOp& copyop) : osg::MatrixTransform(b,copyop), _invBindInSkeletonSpace(b._invBindInSkeletonSpace), _boneInSkeletonSpace(b._boneInSkeletonSpace)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
osgAnimation::Bone::Bone(const Bone& b, const osg::CopyOp& copyop)
|
||||
: osg::Transform(b,copyop),
|
||||
_position(b._position),
|
||||
_rotation(b._rotation),
|
||||
_scale(b._scale)
|
||||
{
|
||||
}
|
||||
|
||||
osgAnimation::Bone::Bone(const std::string& name)
|
||||
Bone::Bone(const std::string& name)
|
||||
{
|
||||
if (!name.empty())
|
||||
setName(name);
|
||||
_needToRecomputeBindMatrix = false;
|
||||
}
|
||||
|
||||
|
||||
void osgAnimation::Bone::setDefaultUpdateCallback(const std::string& name)
|
||||
void Bone::setDefaultUpdateCallback(const std::string& name)
|
||||
{
|
||||
std::string cbName = name;
|
||||
if (cbName.empty())
|
||||
@@ -49,42 +38,12 @@ void osgAnimation::Bone::setDefaultUpdateCallback(const std::string& name)
|
||||
setUpdateCallback(new UpdateBone(cbName));
|
||||
}
|
||||
|
||||
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()
|
||||
Bone* Bone::getBoneParent()
|
||||
{
|
||||
if (getParents().empty())
|
||||
return 0;
|
||||
osg::Node::ParentList parents = getParents();
|
||||
for (osg::Node::ParentList::iterator it = parents.begin(); it != parents.end(); it++)
|
||||
for (osg::Node::ParentList::iterator it = parents.begin(); it != parents.end(); ++it)
|
||||
{
|
||||
Bone* pb = dynamic_cast<Bone*>(*it);
|
||||
if (pb)
|
||||
@@ -92,12 +51,12 @@ osgAnimation::Bone* osgAnimation::Bone::getBoneParent()
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
const osgAnimation::Bone* osgAnimation::Bone::getBoneParent() const
|
||||
const Bone* 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++)
|
||||
for (osg::Node::ParentList::const_iterator it = parents.begin(); it != parents.end(); ++it)
|
||||
{
|
||||
const Bone* pb = dynamic_cast<const Bone*>(*it);
|
||||
if (pb)
|
||||
@@ -105,25 +64,3 @@ const osgAnimation::Bone* osgAnimation::Bone::getBoneParent() const
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
42
src/osgAnimation/BoneMapVisitor.cpp
Normal file
42
src/osgAnimation/BoneMapVisitor.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*/
|
||||
|
||||
#include <osgAnimation/BoneMapVisitor>
|
||||
#include <osgAnimation/Skeleton>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
BoneMapVisitor::BoneMapVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
|
||||
void BoneMapVisitor::apply(osg::Node&) { return; }
|
||||
void BoneMapVisitor::apply(osg::Transform& node)
|
||||
{
|
||||
Bone* bone = dynamic_cast<Bone*>(&node);
|
||||
if (bone)
|
||||
{
|
||||
_map[bone->getName()] = bone;
|
||||
traverse(node);
|
||||
}
|
||||
Skeleton* skeleton = dynamic_cast<Skeleton*>(&node);
|
||||
if (skeleton)
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
const BoneMap& BoneMapVisitor::getBoneMap() const
|
||||
{
|
||||
return _map;
|
||||
}
|
||||
@@ -1,60 +1,108 @@
|
||||
|
||||
IF (DYNAMIC_OPENSCENEGRAPH)
|
||||
IF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ADD_DEFINITIONS(-DOSGANIMATION_LIBRARY)
|
||||
ELSE (DYNAMIC_OPENSCENEGRAPH)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC)
|
||||
ENDIF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ENDIF()
|
||||
|
||||
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}/Action
|
||||
${HEADER_PATH}/ActionAnimation
|
||||
${HEADER_PATH}/ActionBlendIn
|
||||
${HEADER_PATH}/ActionBlendOut
|
||||
${HEADER_PATH}/ActionCallback
|
||||
${HEADER_PATH}/ActionStripAnimation
|
||||
${HEADER_PATH}/ActionVisitor
|
||||
${HEADER_PATH}/Animation
|
||||
${HEADER_PATH}/Keyframe
|
||||
${HEADER_PATH}/Skinning
|
||||
${HEADER_PATH}/CubicBezier
|
||||
${HEADER_PATH}/Vec3Packed
|
||||
${HEADER_PATH}/BasicAnimationManager
|
||||
${HEADER_PATH}/TimelineAnimationManager
|
||||
${HEADER_PATH}/AnimationManagerBase
|
||||
${HEADER_PATH}/UpdateCallback
|
||||
${HEADER_PATH}/LinkVisitor
|
||||
${HEADER_PATH}/VertexInfluence
|
||||
${HEADER_PATH}/AnimationUpdateCallback
|
||||
${HEADER_PATH}/BasicAnimationManager
|
||||
${HEADER_PATH}/Bone
|
||||
${HEADER_PATH}/BoneMapVisitor
|
||||
${HEADER_PATH}/Channel
|
||||
${HEADER_PATH}/CubicBezier
|
||||
${HEADER_PATH}/EaseMotion
|
||||
${HEADER_PATH}/Assert
|
||||
${HEADER_PATH}/Timeline
|
||||
${HEADER_PATH}/Export
|
||||
${HEADER_PATH}/FrameAction
|
||||
${HEADER_PATH}/Interpolator
|
||||
${HEADER_PATH}/Keyframe
|
||||
${HEADER_PATH}/LinkVisitor
|
||||
${HEADER_PATH}/MorphGeometry
|
||||
${HEADER_PATH}/RigGeometry
|
||||
${HEADER_PATH}/RigTransform
|
||||
${HEADER_PATH}/RigTransformHardware
|
||||
${HEADER_PATH}/RigTransformSoftware
|
||||
${HEADER_PATH}/Sampler
|
||||
${HEADER_PATH}/Skeleton
|
||||
${HEADER_PATH}/StackedMatrixElement
|
||||
${HEADER_PATH}/StackedQuaternionElement
|
||||
${HEADER_PATH}/StackedRotateAxisElement
|
||||
${HEADER_PATH}/StackedScaleElement
|
||||
${HEADER_PATH}/StackedTransformElement
|
||||
${HEADER_PATH}/StackedTranslateElement
|
||||
${HEADER_PATH}/StackedTransform
|
||||
${HEADER_PATH}/StatsVisitor
|
||||
${HEADER_PATH}/StatsHandler
|
||||
${HEADER_PATH}/Target
|
||||
${HEADER_PATH}/Timeline
|
||||
${HEADER_PATH}/TimelineAnimationManager
|
||||
${HEADER_PATH}/UpdateBone
|
||||
${HEADER_PATH}/UpdateMaterial
|
||||
${HEADER_PATH}/UpdateMatrixTransform
|
||||
${HEADER_PATH}/Vec3Packed
|
||||
${HEADER_PATH}/VertexInfluence
|
||||
)
|
||||
|
||||
|
||||
ADD_LIBRARY(${LIB_NAME}
|
||||
${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC}
|
||||
${LIB_PUBLIC_HEADERS}
|
||||
Channel.cpp
|
||||
Target.cpp
|
||||
Action.cpp
|
||||
ActionAnimation.cpp
|
||||
ActionBlendIn.cpp
|
||||
ActionBlendOut.cpp
|
||||
ActionCallback.cpp
|
||||
ActionStripAnimation.cpp
|
||||
ActionVisitor.cpp
|
||||
Animation.cpp
|
||||
Bone.cpp
|
||||
RigGeometry.cpp
|
||||
AnimationManager.cpp
|
||||
BasicAnimationManager.cpp
|
||||
TimelineAnimationManager.cpp
|
||||
AnimationManagerBase.cpp
|
||||
BasicAnimationManager.cpp
|
||||
Bone.cpp
|
||||
BoneMapVisitor.cpp
|
||||
Channel.cpp
|
||||
LinkVisitor.cpp
|
||||
MorphGeometry.cpp
|
||||
RigGeometry.cpp
|
||||
RigTransformHardware.cpp
|
||||
RigTransformSoftware.cpp
|
||||
Skeleton.cpp
|
||||
VertexInfluence.cpp
|
||||
UpdateCallback.cpp
|
||||
StackedMatrixElement.cpp
|
||||
StackedQuaternionElement.cpp
|
||||
StackedRotateAxisElement.cpp
|
||||
StackedScaleElement.cpp
|
||||
StackedTransform.cpp
|
||||
StackedTranslateElement.cpp
|
||||
StatsVisitor.cpp
|
||||
StatsHandler.cpp
|
||||
Target.cpp
|
||||
TimelineAnimationManager.cpp
|
||||
Timeline.cpp
|
||||
UpdateBone.cpp
|
||||
UpdateMaterial.cpp
|
||||
UpdateMatrixTransform.cpp
|
||||
VertexInfluence.cpp
|
||||
${OPENSCENEGRAPH_VERSIONINFO_RC}
|
||||
)
|
||||
|
||||
LINK_INTERNAL(${LIB_NAME}
|
||||
osg
|
||||
osgText
|
||||
osgGA
|
||||
osgViewer
|
||||
OpenThreads
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -15,15 +15,16 @@
|
||||
#include <osgAnimation/Channel>
|
||||
using namespace osgAnimation;
|
||||
|
||||
Channel::Channel() { _weight=1; }
|
||||
Channel::Channel() {}
|
||||
Channel::~Channel() {}
|
||||
Channel::Channel(const Channel& channel) : osg::Referenced(channel),
|
||||
_targetName(channel._targetName),
|
||||
_name(channel._name)
|
||||
{
|
||||
}
|
||||
|
||||
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;}
|
||||
|
||||
|
||||
87
src/osgAnimation/LinkVisitor.cpp
Normal file
87
src/osgAnimation/LinkVisitor.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/LinkVisitor>
|
||||
#include <osgAnimation/AnimationUpdateCallback>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Geode>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
LinkVisitor::LinkVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
_nbLinkedTarget = 0;
|
||||
}
|
||||
|
||||
void LinkVisitor::reset()
|
||||
{
|
||||
_nbLinkedTarget = 0;
|
||||
}
|
||||
|
||||
AnimationList& LinkVisitor::getAnimationList()
|
||||
{
|
||||
return _animations;
|
||||
}
|
||||
void LinkVisitor::link(AnimationUpdateCallbackBase* cb)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < (int)_animations.size(); i++)
|
||||
{
|
||||
result += cb->link(_animations[i].get());
|
||||
_nbLinkedTarget += result;
|
||||
}
|
||||
osg::notify(osg::NOTICE) << "LinkVisitor links " << result << " for \"" << cb->getName() << '"' << std::endl;
|
||||
}
|
||||
|
||||
void LinkVisitor::handle_stateset(osg::StateSet* stateset)
|
||||
{
|
||||
if (!stateset)
|
||||
return;
|
||||
osg::StateSet::AttributeList& attr = stateset->getAttributeList();
|
||||
for (osg::StateSet::AttributeList::iterator it = attr.begin(); it != attr.end(); ++it)
|
||||
{
|
||||
osg::StateAttribute* sattr = it->second.first.get();
|
||||
osgAnimation::AnimationUpdateCallbackBase* cb = dynamic_cast<osgAnimation::AnimationUpdateCallbackBase*>(sattr->getUpdateCallback());
|
||||
if (cb)
|
||||
link(cb);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkVisitor::apply(osg::Node& node)
|
||||
{
|
||||
osg::StateSet* st = node.getStateSet();
|
||||
if (st)
|
||||
handle_stateset(st);
|
||||
|
||||
osg::NodeCallback* cb = node.getUpdateCallback();
|
||||
while (cb)
|
||||
{
|
||||
osgAnimation::AnimationUpdateCallbackBase* cba = dynamic_cast<osgAnimation::AnimationUpdateCallbackBase*>(cb);
|
||||
if (cba)
|
||||
link(cba);
|
||||
cb = cb->getNestedCallback();
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void LinkVisitor::apply(osg::Geode& node)
|
||||
{
|
||||
for (unsigned int i = 0; i < node.getNumDrawables(); i++)
|
||||
{
|
||||
osg::Drawable* drawable = node.getDrawable(i);
|
||||
if (drawable && drawable->getStateSet())
|
||||
handle_stateset(drawable->getStateSet());
|
||||
}
|
||||
apply(static_cast<osg::Node&>(node));
|
||||
}
|
||||
277
src/osgAnimation/MorphGeometry.cpp
Normal file
277
src/osgAnimation/MorphGeometry.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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:
|
||||
*
|
||||
* Roland Smeenk
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
*/
|
||||
#include <osg/Geode>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
MorphGeometry::MorphGeometry() :
|
||||
_dirty(false),
|
||||
_method(NORMALIZED),
|
||||
_morphNormals(true)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
setUseVertexBufferObjects(true);
|
||||
}
|
||||
|
||||
MorphGeometry::MorphGeometry(const osg::Geometry& b) :
|
||||
osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS),
|
||||
_dirty(false),
|
||||
_method(NORMALIZED),
|
||||
_morphNormals(true)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
setUseVertexBufferObjects(true);
|
||||
if (b.getInternalOptimizedGeometry())
|
||||
computeInternalOptimizedGeometry();
|
||||
}
|
||||
|
||||
MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) :
|
||||
osg::Geometry(b,copyop),
|
||||
_dirty(b._dirty),
|
||||
_method(b._method),
|
||||
_morphTargets(b._morphTargets),
|
||||
_positionSource(b._positionSource),
|
||||
_normalSource(b._normalSource),
|
||||
_morphNormals(b._morphNormals)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUseVertexBufferObjects(true);
|
||||
if (b.getInternalOptimizedGeometry())
|
||||
computeInternalOptimizedGeometry();
|
||||
}
|
||||
|
||||
void MorphGeometry::transformSoftwareMethod()
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
// See if we have an internal optimized geometry
|
||||
osg::Geometry* morphGeometry = this;
|
||||
if (_internalOptimizedGeometry.valid())
|
||||
morphGeometry = _internalOptimizedGeometry.get();
|
||||
|
||||
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(morphGeometry->getVertexArray());
|
||||
if (pos && _positionSource.size() != pos->size())
|
||||
{
|
||||
_positionSource = std::vector<osg::Vec3>(pos->begin(),pos->end());
|
||||
pos->setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
|
||||
osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(morphGeometry->getNormalArray());
|
||||
if (normal && _normalSource.size() != normal->size())
|
||||
{
|
||||
_normalSource = std::vector<osg::Vec3>(normal->begin(),normal->end());
|
||||
normal->setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
|
||||
|
||||
if (!_positionSource.empty())
|
||||
{
|
||||
bool initialized = false;
|
||||
if (_method == NORMALIZED)
|
||||
{
|
||||
// base * 1 - (sum of weights) + sum of (weight * target)
|
||||
float baseWeight = 0;
|
||||
for (unsigned int i=0; i < _morphTargets.size(); i++)
|
||||
{
|
||||
baseWeight += _morphTargets[i].getWeight();
|
||||
}
|
||||
baseWeight = 1 - baseWeight;
|
||||
|
||||
if (baseWeight != 0)
|
||||
{
|
||||
initialized = true;
|
||||
for (unsigned int i=0; i < pos->size(); i++)
|
||||
{
|
||||
(*pos)[i] = _positionSource[i] * baseWeight;
|
||||
}
|
||||
if (_morphNormals)
|
||||
{
|
||||
for (unsigned int i=0; i < normal->size(); i++)
|
||||
{
|
||||
(*normal)[i] = _normalSource[i] * baseWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else //if (_method == RELATIVE)
|
||||
{
|
||||
// base + sum of (weight * target)
|
||||
initialized = true;
|
||||
for (unsigned int i=0; i < pos->size(); i++)
|
||||
{
|
||||
(*pos)[i] = _positionSource[i];
|
||||
}
|
||||
if (_morphNormals)
|
||||
{
|
||||
for (unsigned int i=0; i < normal->size(); i++)
|
||||
{
|
||||
(*normal)[i] = _normalSource[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i < _morphTargets.size(); i++)
|
||||
{
|
||||
if (_morphTargets[i].getWeight() > 0)
|
||||
{
|
||||
// See if any the targets use the internal optimized geometry
|
||||
osg::Geometry* targetGeometry = _morphTargets[i].getGeometry()->getInternalOptimizedGeometry();
|
||||
if (!targetGeometry)
|
||||
targetGeometry = _morphTargets[i].getGeometry();
|
||||
|
||||
osg::Vec3Array* targetPos = dynamic_cast<osg::Vec3Array*>(targetGeometry->getVertexArray());
|
||||
osg::Vec3Array* targetNormals = dynamic_cast<osg::Vec3Array*>(targetGeometry->getNormalArray());
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
// If vertices are initialized, add the morphtargets
|
||||
for (unsigned int j=0; j < pos->size(); j++)
|
||||
{
|
||||
(*pos)[j] += (*targetPos)[j] * _morphTargets[i].getWeight();
|
||||
}
|
||||
|
||||
if (_morphNormals)
|
||||
{
|
||||
for (unsigned int j=0; j < normal->size(); j++)
|
||||
{
|
||||
(*normal)[j] += (*targetNormals)[j] * _morphTargets[i].getWeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not initialized, initialize with this morph target
|
||||
initialized = true;
|
||||
for (unsigned int j=0; j < pos->size(); j++)
|
||||
{
|
||||
(*pos)[j] = (*targetPos)[j] * _morphTargets[i].getWeight();
|
||||
}
|
||||
|
||||
if (_morphNormals)
|
||||
{
|
||||
for (unsigned int j=0; j < normal->size(); j++)
|
||||
{
|
||||
(*normal)[j] = (*targetNormals)[j] * _morphTargets[i].getWeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos->dirty();
|
||||
if (_morphNormals)
|
||||
{
|
||||
for (unsigned int j=0; j < normal->size(); j++)
|
||||
{
|
||||
(*normal)[j].normalize();
|
||||
}
|
||||
normal->dirty();
|
||||
}
|
||||
}
|
||||
|
||||
dirtyBound();
|
||||
_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) :
|
||||
osg::Object(apc, copyop),
|
||||
AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback<osg::NodeCallback>(name)
|
||||
{
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
void UpdateMorph::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
|
||||
if (geode)
|
||||
{
|
||||
unsigned int numDrawables = geode->getNumDrawables();
|
||||
for (unsigned int i = 0; i != numDrawables; ++i)
|
||||
{
|
||||
osgAnimation::MorphGeometry* morph = dynamic_cast<osgAnimation::MorphGeometry*>(geode->getDrawable(i));
|
||||
if (morph)
|
||||
{
|
||||
// Update morph weights
|
||||
std::map<int, osg::ref_ptr<osgAnimation::FloatTarget> >::iterator iter = _weightTargets.begin();
|
||||
while (iter != _weightTargets.end())
|
||||
{
|
||||
if (iter->second->getValue() >= 0)
|
||||
{
|
||||
morph->setWeight(iter->first, iter->second->getValue());
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool UpdateMorph::needLink() const
|
||||
{
|
||||
// the idea is to return true if nothing is linked
|
||||
return (_weightTargets.size() == 0);
|
||||
}
|
||||
|
||||
bool UpdateMorph::link(osgAnimation::Channel* channel)
|
||||
{
|
||||
// Typically morph geometries only have the weights for morph targets animated
|
||||
|
||||
// Expect a weight value
|
||||
// TODO Should we make this more generic to handle other things than single values?
|
||||
int weightIndex = atoi(channel->getName().c_str());
|
||||
|
||||
if (weightIndex >= 0)
|
||||
{
|
||||
osgAnimation::FloatTarget* ft = _weightTargets[weightIndex].get();
|
||||
if (!ft)
|
||||
{
|
||||
ft = new osgAnimation::FloatTarget;
|
||||
_weightTargets[weightIndex] = ft;
|
||||
}
|
||||
return channel->setTarget(ft);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,129 +1,209 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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:
|
||||
* 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.
|
||||
*
|
||||
* Cedric Pinson <mornifle@plopbyte.net>
|
||||
*
|
||||
* 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 <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/RigTransformSoftware>
|
||||
#include <sstream>
|
||||
#include <osg/GL2Extensions>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
// The idea is to compute a bounding box with a factor x of the first step we compute the bounding box
|
||||
class RigComputeBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback
|
||||
{
|
||||
public:
|
||||
RigComputeBoundingBoxCallback(double factor = 2.0) : _computed(false), _factor(factor) {}
|
||||
void reset() { _computed = false; }
|
||||
virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const
|
||||
{
|
||||
const osgAnimation::RigGeometry& rig = dynamic_cast<const osgAnimation::RigGeometry&>(drawable);
|
||||
|
||||
// if a valid inital bounding box is set we use it without asking more
|
||||
if (rig.getInitialBound().valid())
|
||||
return rig.getInitialBound();
|
||||
|
||||
if (_computed)
|
||||
return _boundingBox;
|
||||
|
||||
// if the computing of bb is invalid (like no geometry inside)
|
||||
// then dont tag the bounding box as computed
|
||||
osg::BoundingBox bb = rig.computeBound();
|
||||
if (!bb.valid())
|
||||
return bb;
|
||||
|
||||
|
||||
_boundingBox.expandBy(bb);
|
||||
osg::Vec3 center = _boundingBox.center();
|
||||
osg::Vec3 vec = (_boundingBox._max-center)*_factor;
|
||||
_boundingBox.expandBy(center + vec);
|
||||
_boundingBox.expandBy(center - vec);
|
||||
_computed = true;
|
||||
// osg::notify(osg::NOTICE) << "build the bounding box for RigGeometry " << rig.getName() << " " << _boundingBox._min << " " << _boundingBox._max << std::endl;
|
||||
return _boundingBox;
|
||||
}
|
||||
protected:
|
||||
mutable bool _computed;
|
||||
double _factor;
|
||||
mutable osg::BoundingBox _boundingBox;
|
||||
};
|
||||
|
||||
RigGeometry::RigGeometry()
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
_supportsDisplayList = false;
|
||||
setUseVertexBufferObjects(true);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_needToComputeMatrix = true;
|
||||
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||
|
||||
// disable the computation of boundingbox for the rig mesh
|
||||
setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback);
|
||||
}
|
||||
|
||||
RigGeometry::RigGeometry(const osg::Geometry& b) : osg::Geometry(b, osg::CopyOp::SHALLOW_COPY)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUpdateCallback(new UpdateVertex);
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
_needToComputeMatrix = true;
|
||||
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||
}
|
||||
|
||||
RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) :
|
||||
RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) :
|
||||
osg::Geometry(b,copyop),
|
||||
_positionSource(b._positionSource),
|
||||
_normalSource(b._normalSource),
|
||||
_geometry(b._geometry),
|
||||
_vertexInfluenceSet(b._vertexInfluenceSet),
|
||||
_vertexInfluenceMap(b._vertexInfluenceMap),
|
||||
_transformVertexes(b._transformVertexes),
|
||||
_needToComputeMatrix(b._needToComputeMatrix)
|
||||
_needToComputeMatrix(b._needToComputeMatrix)
|
||||
{
|
||||
// we dont copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ...
|
||||
// dont know yet what to do with a clone of a RigGeometry
|
||||
}
|
||||
|
||||
void RigGeometry::buildTransformer(Skeleton* root)
|
||||
|
||||
const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return _matrixFromSkeletonToGeometry; }
|
||||
const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;}
|
||||
|
||||
|
||||
void RigGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
Bone::BoneMap bm = root->getBoneMap();
|
||||
_transformVertexes.init(bm, _vertexInfluenceSet.getUniqVertexSetToBoneSetList());
|
||||
_root = root;
|
||||
osg::Geometry::drawImplementation(renderInfo);
|
||||
}
|
||||
|
||||
void RigGeometry::buildVertexSet()
|
||||
void RigGeometry::buildVertexInfluenceSet()
|
||||
{
|
||||
if (!_vertexInfluenceMap.valid())
|
||||
if (!_vertexInfluenceMap.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "buildVertexSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl;
|
||||
osg::notify(osg::WARN) << "buildVertexInfluenceSet 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++)
|
||||
++it)
|
||||
_vertexInfluenceSet.addVertexInfluence(it->second);
|
||||
|
||||
_vertexInfluenceSet.buildVertex2BoneList();
|
||||
_vertexInfluenceSet.buildUniqVertexSetToBoneSetList();
|
||||
std::cout << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl;
|
||||
osg::notify(osg::NOTICE) << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl;
|
||||
}
|
||||
|
||||
void RigGeometry::computeMatrixFromRootSkeleton()
|
||||
void RigGeometry::computeMatrixFromRootSkeleton()
|
||||
{
|
||||
if (!_root.valid())
|
||||
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];
|
||||
osg::Matrix notRoot = _root->getMatrix();
|
||||
_matrixFromSkeletonToGeometry = mtxList[0] * osg::Matrix::inverse(notRoot);
|
||||
_invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(_matrixFromSkeletonToGeometry);
|
||||
_needToComputeMatrix = false;
|
||||
}
|
||||
|
||||
void RigGeometry::transformSoftwareMethod()
|
||||
void RigGeometry::update()
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUseVertexBufferObjects(true);
|
||||
|
||||
// std::cout << getName() << " _matrixFromSkeletonToGeometry" << _matrixFromSkeletonToGeometry << std::endl;
|
||||
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(getVertexArray());
|
||||
if (pos && _positionSource.size() != pos->size())
|
||||
if (!getRigTransformImplementation())
|
||||
{
|
||||
_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);
|
||||
_rigTransformImplementation = new RigTransformSoftware;
|
||||
}
|
||||
|
||||
if (!_positionSource.empty())
|
||||
{
|
||||
_transformVertexes.compute<osg::Vec3>(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_positionSource.front(), &pos->front());
|
||||
pos->dirty();
|
||||
}
|
||||
if (!_normalSource.empty())
|
||||
{
|
||||
_transformVertexes.computeNormal<osg::Vec3>(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_normalSource.front(), &normal->front());
|
||||
normal->dirty();
|
||||
}
|
||||
if (getUseDisplayList())
|
||||
dirtyDisplayList();
|
||||
dirtyBound();
|
||||
RigTransform& implementation = *getRigTransformImplementation();
|
||||
(implementation)(*this);
|
||||
}
|
||||
|
||||
const osgAnimation::Skeleton* RigGeometry::getSkeleton() const { return _root.get(); }
|
||||
osgAnimation::Skeleton* RigGeometry::getSkeleton() { return _root.get(); }
|
||||
void RigGeometry::copyFrom(osg::Geometry& from)
|
||||
{
|
||||
bool copyToSelf = (this==&from);
|
||||
|
||||
osg::Geometry& target = *this;
|
||||
|
||||
if (!copyToSelf) target.setStateSet(from.getStateSet());
|
||||
|
||||
// copy over primitive sets.
|
||||
if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList();
|
||||
|
||||
if (from.getVertexArray())
|
||||
{
|
||||
if (!copyToSelf) target.setVertexArray(from.getVertexArray());
|
||||
}
|
||||
|
||||
target.setNormalBinding(from.getNormalBinding());
|
||||
if (from.getNormalArray())
|
||||
{
|
||||
if (!copyToSelf) target.setNormalArray(from.getNormalArray());
|
||||
}
|
||||
|
||||
target.setColorBinding(from.getColorBinding());
|
||||
if (from.getColorArray())
|
||||
{
|
||||
if (!copyToSelf) target.setColorArray(from.getColorArray());
|
||||
}
|
||||
|
||||
target.setSecondaryColorBinding(from.getSecondaryColorBinding());
|
||||
if (from.getSecondaryColorArray())
|
||||
{
|
||||
if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray());
|
||||
}
|
||||
|
||||
target.setFogCoordBinding(from.getFogCoordBinding());
|
||||
if (from.getFogCoordArray())
|
||||
{
|
||||
if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray());
|
||||
}
|
||||
|
||||
for(unsigned int ti=0;ti<from.getNumTexCoordArrays();++ti)
|
||||
{
|
||||
if (from.getTexCoordArray(ti))
|
||||
{
|
||||
if (!copyToSelf) target.setTexCoordArray(ti,from.getTexCoordArray(ti));
|
||||
}
|
||||
}
|
||||
|
||||
ArrayDataList& arrayList = from.getVertexAttribArrayList();
|
||||
for(unsigned int vi=0;vi< arrayList.size();++vi)
|
||||
{
|
||||
ArrayData& arrayData = arrayList[vi];
|
||||
if (arrayData.array.valid())
|
||||
{
|
||||
if (!copyToSelf) target.setVertexAttribData(vi,arrayData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const VertexInfluenceSet& RigGeometry::getVertexInfluenceSet() const { return _vertexInfluenceSet;}
|
||||
|
||||
const Skeleton* RigGeometry::getSkeleton() const { return _root.get(); }
|
||||
Skeleton* RigGeometry::getSkeleton() { return _root.get(); }
|
||||
void RigGeometry::setSkeleton(Skeleton* root) { _root = root;}
|
||||
RigTransform* RigGeometry::getRigTransformImplementation() { return _rigTransformImplementation.get(); }
|
||||
void RigGeometry::setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; }
|
||||
|
||||
osg::Geometry* RigGeometry::getSourceGeometry() { return _geometry.get(); }
|
||||
const osg::Geometry* RigGeometry::getSourceGeometry() const { return _geometry.get(); }
|
||||
void RigGeometry::setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; }
|
||||
|
||||
272
src/osgAnimation/RigTransformHardware.cpp
Normal file
272
src/osgAnimation/RigTransformHardware.cpp
Normal file
@@ -0,0 +1,272 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/RigTransformHardware>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/BoneMapVisitor>
|
||||
#include <sstream>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
|
||||
RigTransformHardware::RigTransformHardware()
|
||||
{
|
||||
_needInit = true;
|
||||
_bonesPerVertex = 0;
|
||||
_nbVertexes = 0;
|
||||
}
|
||||
|
||||
osg::Vec4Array* RigTransformHardware::getVertexAttrib(int index)
|
||||
{
|
||||
if (index >= (int)_boneWeightAttribArrays.size())
|
||||
return 0;
|
||||
return _boneWeightAttribArrays[index].get();
|
||||
}
|
||||
|
||||
int RigTransformHardware::getNumVertexAttrib()
|
||||
{
|
||||
return _boneWeightAttribArrays.size();
|
||||
}
|
||||
|
||||
osg::Uniform* RigTransformHardware::getMatrixPaletteUniform()
|
||||
{
|
||||
return _uniformMatrixPalette.get();
|
||||
}
|
||||
|
||||
|
||||
void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry)
|
||||
{
|
||||
for (int i = 0; i < (int)_bonePalette.size(); i++)
|
||||
{
|
||||
osg::ref_ptr<Bone> bone = _bonePalette[i].get();
|
||||
const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||
const osg::Matrix& boneMatrix = bone->getMatrixInSkeletonSpace();
|
||||
osg::Matrix resultBoneMatrix = invBindMatrix * boneMatrix;
|
||||
osg::Matrix result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry;
|
||||
if (!_uniformMatrixPalette->setElement(i, result))
|
||||
osg::notify(osg::WARN) << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;}
|
||||
int RigTransformHardware::getNumVertexes() const { return _nbVertexes;}
|
||||
|
||||
bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap)
|
||||
{
|
||||
typedef std::map<std::string, int> BoneNameCountMap;
|
||||
typedef std::map<std::string, int> BoneNamePaletteIndex;
|
||||
BoneNamePaletteIndex bname2palette;
|
||||
BonePalette palette;
|
||||
BoneNameCountMap boneNameCountMap;
|
||||
|
||||
// init vertex attribute data
|
||||
VertexIndexWeightList vertexIndexWeight;
|
||||
vertexIndexWeight.resize(nbVertexes);
|
||||
|
||||
int maxBonePerVertex = 0;
|
||||
for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator it = vertexIndexToBoneWeightMap.begin(); it != vertexIndexToBoneWeightMap.end(); ++it)
|
||||
{
|
||||
int vertexIndex = it->first;
|
||||
const VertexInfluenceSet::BoneWeightList& boneWeightList = it->second;
|
||||
int bonesForThisVertex = 0;
|
||||
for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it)
|
||||
{
|
||||
const VertexInfluenceSet::BoneWeight& bw = *it;
|
||||
if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end())
|
||||
{
|
||||
boneNameCountMap[bw.getBoneName()]++;
|
||||
bonesForThisVertex++; // count max number of bones per vertexes
|
||||
vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(bname2palette[bw.getBoneName()],bw.getWeight()));
|
||||
}
|
||||
else if (fabs(bw.getWeight()) > 1e-2) // dont use bone with weight too small
|
||||
{
|
||||
if (boneMap.find(bw.getBoneName()) == boneMap.end())
|
||||
{
|
||||
osg::notify(osg::INFO) << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl;
|
||||
continue;
|
||||
}
|
||||
boneNameCountMap[bw.getBoneName()] = 1; // for stats
|
||||
bonesForThisVertex++;
|
||||
palette.push_back(boneMap[bw.getBoneName()]);
|
||||
bname2palette[bw.getBoneName()] = palette.size()-1;
|
||||
vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(bname2palette[bw.getBoneName()],bw.getWeight()));
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl;
|
||||
}
|
||||
}
|
||||
maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex);
|
||||
}
|
||||
osg::notify(osg::INFO) << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl;
|
||||
osg::notify(osg::INFO) << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl;
|
||||
|
||||
for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it)
|
||||
{
|
||||
osg::notify(osg::INFO) << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl;
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO) << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl;
|
||||
|
||||
|
||||
for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++)
|
||||
vertexIndexWeight[i].resize(maxBonePerVertex);
|
||||
|
||||
_nbVertexes = nbVertexes;
|
||||
_bonesPerVertex = maxBonePerVertex;
|
||||
_bonePalette = palette;
|
||||
_vertexIndexMatrixWeightList = vertexIndexWeight;
|
||||
_uniformMatrixPalette = createVertexUniform();
|
||||
_boneWeightAttribArrays = createVertexAttribList();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// create vertex attribute by 2 bones
|
||||
// vec4(boneIndex0, weight0, boneIndex1, weight1)
|
||||
// if more bones are needed then other attributes are created
|
||||
// vec4(boneIndex2, weight2, boneIndex3, weight3)
|
||||
// the idea is to use this format to have a granularity smaller
|
||||
// than the 4 bones using two vertex attributes
|
||||
//
|
||||
RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAttribList()
|
||||
{
|
||||
BoneWeightAttribList arrayList;
|
||||
int nbArray = static_cast<int>(ceilf(getNumBonesPerVertex() * 0.5));
|
||||
if (!nbArray)
|
||||
return arrayList;
|
||||
|
||||
arrayList.resize(nbArray);
|
||||
for (int i = 0; i < nbArray; i++)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array;
|
||||
arrayList[i] = array;
|
||||
int nbVertexes = getNumVertexes();
|
||||
array->resize(nbVertexes);
|
||||
for (int j = 0; j < nbVertexes; j++)
|
||||
{
|
||||
for (int b = 0; b < 2; b++)
|
||||
{
|
||||
// the granularity is 2 so if we have only one bone
|
||||
// it's convenient to init the second with a weight 0
|
||||
int boneIndexInList = i*2 + b;
|
||||
int boneIndexInVec4 = b*2;
|
||||
(*array)[j][0 + boneIndexInVec4] = 0;
|
||||
(*array)[j][1 + boneIndexInVec4] = 0;
|
||||
if (boneIndexInList < getNumBonesPerVertex())
|
||||
{
|
||||
float boneIndex = static_cast<float>(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex());
|
||||
float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight();
|
||||
// fill the vec4
|
||||
(*array)[j][0 + boneIndexInVec4] = boneIndex;
|
||||
(*array)[j][1 + boneIndexInVec4] = boneWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
|
||||
osg::Uniform* RigTransformHardware::createVertexUniform()
|
||||
{
|
||||
osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size());
|
||||
return uniform;
|
||||
}
|
||||
|
||||
|
||||
void RigTransformHardware::setShader(osg::Shader* shader)
|
||||
{
|
||||
_shader = shader;
|
||||
}
|
||||
|
||||
bool RigTransformHardware::init(RigGeometry& geom)
|
||||
{
|
||||
osg::Geometry& source = *geom.getSourceGeometry();
|
||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
|
||||
if (!positionSrc)
|
||||
{
|
||||
osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!geom.getSkeleton())
|
||||
{
|
||||
osg::notify(osg::WARN) << "RigTransformHardware no skeleton set in geometry " << geom.getName() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// copy shallow from source geometry to rig
|
||||
geom.copyFrom(source);
|
||||
|
||||
|
||||
BoneMapVisitor mapVisitor;
|
||||
geom.getSkeleton()->accept(mapVisitor);
|
||||
BoneMap bm = mapVisitor.getBoneMap();
|
||||
|
||||
if (!createPalette(positionSrc->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList()))
|
||||
return false;
|
||||
|
||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||
program->setName("HardwareSkinning");
|
||||
if (!_shader.valid())
|
||||
_shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert");
|
||||
|
||||
if (!_shader.valid()) {
|
||||
osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// replace max matrix by the value from uniform
|
||||
{
|
||||
std::string str = _shader->getShaderSource();
|
||||
std::string toreplace = std::string("MAX_MATRIX");
|
||||
std::size_t start = str.find(toreplace);
|
||||
std::stringstream ss;
|
||||
ss << getMatrixPaletteUniform()->getNumElements();
|
||||
str.replace(start, toreplace.size(), ss.str());
|
||||
_shader->setShaderSource(str);
|
||||
osg::notify(osg::INFO) << "Shader " << str << std::endl;
|
||||
}
|
||||
|
||||
int attribIndex = 11;
|
||||
int nbAttribs = getNumVertexAttrib();
|
||||
for (int i = 0; i < nbAttribs; i++)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "boneWeight" << i;
|
||||
program->addBindAttribLocation(ss.str(), attribIndex + i);
|
||||
geom.setVertexAttribData(attribIndex + i, osg::Geometry::ArrayData(getVertexAttrib(i),osg::Geometry::BIND_PER_VERTEX));
|
||||
osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl;
|
||||
}
|
||||
program->addShader(_shader.get());
|
||||
|
||||
osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
|
||||
ss->addUniform(getMatrixPaletteUniform());
|
||||
ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex()));
|
||||
ss->setAttributeAndModes(program.get());
|
||||
geom.setStateSet(ss.get());
|
||||
_needInit = false;
|
||||
return true;
|
||||
}
|
||||
void RigTransformHardware::operator()(RigGeometry& geom)
|
||||
{
|
||||
if (_needInit)
|
||||
if (!init(geom))
|
||||
return;
|
||||
computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry());
|
||||
}
|
||||
144
src/osgAnimation/RigTransformSoftware.cpp
Normal file
144
src/osgAnimation/RigTransformSoftware.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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 <osgAnimation/RigTransformSoftware>
|
||||
#include <osgAnimation/BoneMapVisitor>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
RigTransformSoftware::RigTransformSoftware()
|
||||
{
|
||||
_needInit = true;
|
||||
}
|
||||
|
||||
bool RigTransformSoftware::init(RigGeometry& geom)
|
||||
{
|
||||
if (!geom.getSkeleton())
|
||||
return false;
|
||||
|
||||
BoneMapVisitor mapVisitor;
|
||||
geom.getSkeleton()->accept(mapVisitor);
|
||||
BoneMap bm = mapVisitor.getBoneMap();
|
||||
initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList());
|
||||
|
||||
if (geom.getSourceGeometry())
|
||||
geom.copyFrom(*geom.getSourceGeometry());
|
||||
geom.setVertexArray(0);
|
||||
geom.setNormalArray(0);
|
||||
|
||||
_needInit = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RigTransformSoftware::operator()(RigGeometry& geom)
|
||||
{
|
||||
if (_needInit)
|
||||
if (!init(geom))
|
||||
return;
|
||||
|
||||
if (!geom.getSourceGeometry()) {
|
||||
osg::notify(osg::WARN) << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl;
|
||||
return;
|
||||
}
|
||||
osg::Geometry& source = *geom.getSourceGeometry();
|
||||
osg::Geometry& destination = geom;
|
||||
|
||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
|
||||
osg::Vec3Array* positionDst = dynamic_cast<osg::Vec3Array*>(destination.getVertexArray());
|
||||
if (positionSrc && (!positionDst || (positionDst->size() != positionSrc->size()) ) )
|
||||
{
|
||||
if (!positionDst)
|
||||
{
|
||||
positionDst = new osg::Vec3Array;
|
||||
positionDst->setDataVariance(osg::Object::DYNAMIC);
|
||||
destination.setVertexArray(positionDst);
|
||||
}
|
||||
*positionDst = *positionSrc;
|
||||
}
|
||||
|
||||
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(source.getNormalArray());
|
||||
osg::Vec3Array* normalDst = dynamic_cast<osg::Vec3Array*>(destination.getNormalArray());
|
||||
if (normalSrc && (!normalDst || (normalDst->size() != normalSrc->size()) ) )
|
||||
{
|
||||
if (!normalDst)
|
||||
{
|
||||
normalDst = new osg::Vec3Array;
|
||||
normalDst->setDataVariance(osg::Object::DYNAMIC);
|
||||
destination.setNormalArray(normalDst);
|
||||
destination.setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
}
|
||||
*normalDst = *normalSrc;
|
||||
}
|
||||
|
||||
if (positionDst && !positionDst->empty())
|
||||
{
|
||||
compute<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||
&positionSrc->front(),
|
||||
&positionDst->front());
|
||||
positionDst->dirty();
|
||||
}
|
||||
|
||||
if (normalDst && !normalDst->empty())
|
||||
{
|
||||
computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||
&normalSrc->front(),
|
||||
&normalDst->front());
|
||||
normalDst->dirty();
|
||||
}
|
||||
}
|
||||
|
||||
void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
|
||||
{
|
||||
_boneSetVertexSet.clear();
|
||||
|
||||
int size = influence.size();
|
||||
_boneSetVertexSet.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
|
||||
int nbBones = inf.getBones().size();
|
||||
BoneWeightList& boneList = _boneSetVertexSet[i].getBones();
|
||||
|
||||
double sumOfWeight = 0;
|
||||
for (int b = 0; b < nbBones; b++)
|
||||
{
|
||||
const std::string& bname = inf.getBones()[b].getBoneName();
|
||||
float weight = inf.getBones()[b].getWeight();
|
||||
BoneMap::const_iterator it = map.find(bname);
|
||||
if (it == map.end())
|
||||
{
|
||||
osg::notify(osg::WARN) << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <<bname << std::endl;
|
||||
continue;
|
||||
}
|
||||
Bone* bone = it->second.get();
|
||||
boneList.push_back(BoneWeight(bone, weight));
|
||||
sumOfWeight += weight;
|
||||
}
|
||||
// if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0
|
||||
// so we check it and renormalize the all weight bone
|
||||
const double threshold = 1e-4;
|
||||
if (!_boneSetVertexSet[i].getBones().empty() &&
|
||||
(sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold))
|
||||
{
|
||||
for (int b = 0; b < (int)boneList.size(); b++)
|
||||
boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
|
||||
}
|
||||
_boneSetVertexSet[i].getVertexes() = inf.getVertexes();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -14,29 +14,29 @@
|
||||
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/Notify>
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
Skeleton::Skeleton() {}
|
||||
Skeleton::Skeleton(const Skeleton& b, const osg::CopyOp& copyop) : osg::MatrixTransform(b,copyop) {}
|
||||
|
||||
struct updateMatrixVisitor : public osg::NodeVisitor
|
||||
Skeleton::UpdateSkeleton::UpdateSkeleton() : _needValidate(true) {}
|
||||
Skeleton::UpdateSkeleton::UpdateSkeleton(const UpdateSkeleton& us, const osg::CopyOp& copyop= osg::CopyOp::SHALLOW_COPY) : osg::Object(us, copyop), osg::NodeCallback(us, copyop)
|
||||
{
|
||||
osg::Matrix _skeleton;
|
||||
updateMatrixVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
void apply(osg::Node& node) { return ;}
|
||||
_needValidate = true;
|
||||
}
|
||||
bool Skeleton::UpdateSkeleton::needToValidate() const
|
||||
{
|
||||
return _needValidate;
|
||||
}
|
||||
|
||||
|
||||
class ValidateSkeletonVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
ValidateSkeletonVisitor(): 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
|
||||
@@ -44,45 +44,50 @@ struct updateMatrixVisitor : public osg::NodeVisitor
|
||||
if (!bone)
|
||||
return;
|
||||
|
||||
Bone* parent = bone->getBoneParent();
|
||||
if (bone->needToComputeBindMatrix())
|
||||
bool foundNonBone = false;
|
||||
|
||||
for (unsigned int i = 0; i < bone->getNumChildren(); ++i)
|
||||
{
|
||||
computeBindMatrixVisitor visitor;
|
||||
bone->accept(visitor);
|
||||
if (dynamic_cast<Bone*>(bone->getChild(i)))
|
||||
{
|
||||
if (foundNonBone)
|
||||
{
|
||||
osg::notify(osg::WARN) <<
|
||||
"Warning: a Bone was found after a non-Bone child "
|
||||
"within a Skeleton. Children of a Bone must be ordered "
|
||||
"with all child Bones first for correct update order." << std::endl;
|
||||
setTraversalMode(TRAVERSE_NONE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foundNonBone = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent)
|
||||
bone->setMatrixInSkeletonSpace(bone->getMatrixInBoneSpace() * bone->getBoneParent()->getMatrixInSkeletonSpace());
|
||||
else
|
||||
bone->setMatrixInSkeletonSpace(bone->getMatrixInBoneSpace());
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
void Skeleton::UpdateSkeleton::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
Skeleton* b = dynamic_cast<Skeleton*>(node);
|
||||
if (b)
|
||||
Skeleton* skeleton = dynamic_cast<Skeleton*>(node);
|
||||
if (_needValidate && skeleton)
|
||||
{
|
||||
// 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;
|
||||
b->accept(visitor);
|
||||
ValidateSkeletonVisitor visitor;
|
||||
for (unsigned int i = 0; i < skeleton->getNumChildren(); ++i)
|
||||
{
|
||||
osg::Node* child = skeleton->getChild(i);
|
||||
child->accept(visitor);
|
||||
}
|
||||
_needValidate = false;
|
||||
}
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
|
||||
Skeleton::Skeleton()
|
||||
{
|
||||
}
|
||||
|
||||
void Skeleton::setDefaultUpdateCallback()
|
||||
{
|
||||
setUpdateCallback(new Skeleton::UpdateSkeleton );
|
||||
|
||||
40
src/osgAnimation/StackedMatrixElement.cpp
Normal file
40
src/osgAnimation/StackedMatrixElement.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedMatrixElement>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StackedMatrixElement::StackedMatrixElement() {}
|
||||
StackedMatrixElement::StackedMatrixElement(const std::string& name, const osg::Matrix& matrix) : StackedTransformElement(), _matrix(matrix) { setName(name); }
|
||||
StackedMatrixElement::StackedMatrixElement(const osg::Matrix& matrix) : _matrix(matrix) { setName("matrix"); }
|
||||
|
||||
StackedMatrixElement::StackedMatrixElement(const StackedMatrixElement& rhs, const osg::CopyOp& c) : StackedTransformElement(rhs, c), _matrix(rhs._matrix)
|
||||
{
|
||||
if (rhs._target.valid())
|
||||
_target = new MatrixTarget(*rhs._target);
|
||||
}
|
||||
|
||||
Target* StackedMatrixElement::getOrCreateTarget()
|
||||
{
|
||||
if (!_target.valid())
|
||||
_target = new MatrixTarget(_matrix);
|
||||
return _target.get();
|
||||
}
|
||||
|
||||
void StackedMatrixElement::update()
|
||||
{
|
||||
if (_target.valid())
|
||||
_matrix = _target->getValue();
|
||||
}
|
||||
53
src/osgAnimation/StackedQuaternionElement.cpp
Normal file
53
src/osgAnimation/StackedQuaternionElement.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedQuaternionElement>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StackedQuaternionElement::StackedQuaternionElement(const std::string& name, const osg::Quat& quaternion) : _quaternion(quaternion) { setName(name); }
|
||||
|
||||
StackedQuaternionElement::StackedQuaternionElement(const StackedQuaternionElement& rhs, const osg::CopyOp&) : StackedTransformElement(rhs), _quaternion(rhs._quaternion)
|
||||
{
|
||||
if (rhs._target.valid())
|
||||
_target = new QuatTarget(*rhs._target);
|
||||
}
|
||||
|
||||
|
||||
StackedQuaternionElement::StackedQuaternionElement(const osg::Quat& quat) : _quaternion(quat) { setName("quaternion"); }
|
||||
|
||||
StackedQuaternionElement::StackedQuaternionElement()
|
||||
{
|
||||
}
|
||||
const osg::Quat& StackedQuaternionElement::getQuaternion() const { return _quaternion; }
|
||||
void StackedQuaternionElement::setQuaternion(const osg::Quat& q) { _quaternion = q; }
|
||||
|
||||
void StackedQuaternionElement::applyToMatrix(osg::Matrix& matrix) const {matrix.preMultRotate(_quaternion);}
|
||||
osg::Matrix StackedQuaternionElement::getAsMatrix() const { return osg::Matrix(_quaternion); }
|
||||
bool StackedQuaternionElement::isIdentity() const { return (_quaternion[0] == 0 && _quaternion[1] == 0 && _quaternion[2] == 0 && _quaternion[3] == 1.0); }
|
||||
|
||||
void StackedQuaternionElement::update()
|
||||
{
|
||||
if (_target.valid())
|
||||
_quaternion = _target->getValue();
|
||||
}
|
||||
|
||||
Target* StackedQuaternionElement::getOrCreateTarget()
|
||||
{
|
||||
if (!_target.valid())
|
||||
_target = new QuatTarget(_quaternion);
|
||||
return _target.get();
|
||||
}
|
||||
Target* StackedQuaternionElement::getTarget() {return _target.get();}
|
||||
const Target* StackedQuaternionElement::getTarget() const {return _target.get();}
|
||||
55
src/osgAnimation/StackedRotateAxisElement.cpp
Normal file
55
src/osgAnimation/StackedRotateAxisElement.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedRotateAxisElement>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StackedRotateAxisElement::StackedRotateAxisElement(const std::string& name, const osg::Vec3& axis, double angle) : StackedTransformElement(), _axis(axis), _angle(angle) { setName(name); }
|
||||
StackedRotateAxisElement::StackedRotateAxisElement(const osg::Vec3& axis, double angle) : _axis(axis), _angle(angle) { setName("rotateaxis"); }
|
||||
StackedRotateAxisElement::StackedRotateAxisElement() {}
|
||||
StackedRotateAxisElement::StackedRotateAxisElement(const StackedRotateAxisElement& rhs, const osg::CopyOp&) : StackedTransformElement(rhs), _axis(rhs._axis), _angle(rhs._angle)
|
||||
{
|
||||
if (rhs._target.valid())
|
||||
_target = new FloatTarget(*rhs._target);
|
||||
}
|
||||
|
||||
|
||||
osg::Matrix StackedRotateAxisElement::getAsMatrix() const { return osg::Matrix::rotate(osg::Quat(_angle, _axis)); }
|
||||
void StackedRotateAxisElement::update()
|
||||
{
|
||||
if (_target.valid())
|
||||
_angle = _target->getValue();
|
||||
}
|
||||
|
||||
const osg::Vec3& StackedRotateAxisElement::getAxis() const { return _axis; }
|
||||
const double StackedRotateAxisElement::getAngle() const { return _angle; }
|
||||
void StackedRotateAxisElement::setAxis(const osg::Vec3& axis)
|
||||
{
|
||||
_axis = axis;
|
||||
}
|
||||
|
||||
void StackedRotateAxisElement::setAngle(const double& angle)
|
||||
{
|
||||
_angle = angle;
|
||||
}
|
||||
|
||||
Target* StackedRotateAxisElement::getOrCreateTarget()
|
||||
{
|
||||
if (!_target.valid())
|
||||
_target = new FloatTarget(_angle);
|
||||
return _target.get();
|
||||
}
|
||||
|
||||
void StackedRotateAxisElement::applyToMatrix(osg::Matrix& matrix) const { matrix.preMultRotate(osg::Quat(_angle, _axis)); }
|
||||
56
src/osgAnimation/StackedScaleElement.cpp
Normal file
56
src/osgAnimation/StackedScaleElement.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedScaleElement>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StackedScaleElement::StackedScaleElement(const std::string& name, const osg::Vec3& scale) : _scale(scale) { setName(name); }
|
||||
StackedScaleElement::StackedScaleElement(const osg::Vec3& scale) : _scale(scale) { setName("scale"); }
|
||||
|
||||
StackedScaleElement::StackedScaleElement(const StackedScaleElement& rhs, const osg::CopyOp&) : StackedTransformElement(rhs), _scale(rhs._scale)
|
||||
{
|
||||
if (rhs._target.valid())
|
||||
_target = new Vec3Target(*rhs._target);
|
||||
}
|
||||
|
||||
const osg::Vec3& StackedScaleElement::getScale() const { return _scale; }
|
||||
void StackedScaleElement::setScale(const osg::Vec3& scale) { _scale = scale; }
|
||||
|
||||
Target* StackedScaleElement::getTarget() {return _target.get();}
|
||||
const Target* StackedScaleElement::getTarget() const {return _target.get();}
|
||||
|
||||
bool StackedScaleElement::isIdentity() const { return (_scale.x() == 1 && _scale.y() == 1 && _scale.z() == 1); }
|
||||
|
||||
osg::Matrix StackedScaleElement::getAsMatrix() const { return osg::Matrix::scale(_scale); }
|
||||
|
||||
void StackedScaleElement::applyToMatrix(osg::Matrix& matrix) const { matrix.preMultScale(_scale); }
|
||||
|
||||
StackedScaleElement::StackedScaleElement()
|
||||
{
|
||||
_scale = osg::Vec3(1,1,1);
|
||||
}
|
||||
|
||||
void StackedScaleElement::update()
|
||||
{
|
||||
if (_target.valid())
|
||||
_scale = _target->getValue();
|
||||
}
|
||||
|
||||
Target* StackedScaleElement::getOrCreateTarget()
|
||||
{
|
||||
if (!_target.valid())
|
||||
_target = new Vec3Target(_scale);
|
||||
return _target.get();
|
||||
}
|
||||
66
src/osgAnimation/StackedTransform.cpp
Normal file
66
src/osgAnimation/StackedTransform.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedTransform>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StackedTransform::StackedTransform() {}
|
||||
|
||||
StackedTransform::StackedTransform(const StackedTransform& rhs, const osg::CopyOp& co)
|
||||
{
|
||||
reserve(rhs.size());
|
||||
for (StackedTransform::const_iterator it = rhs.begin(); it != rhs.end(); ++it)
|
||||
{
|
||||
const StackedTransformElement* element = it->get();
|
||||
if (element)
|
||||
push_back(osg::clone(element,co));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StackedTransform::update()
|
||||
{
|
||||
int dirty = 0;
|
||||
for (StackedTransform::iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
|
||||
StackedTransformElement* element = it->get();
|
||||
if (!element)
|
||||
continue;
|
||||
// update and check if there are changes
|
||||
element->update();
|
||||
if (element->isIdentity())
|
||||
continue;
|
||||
dirty++;
|
||||
}
|
||||
if (!dirty)
|
||||
return;
|
||||
|
||||
|
||||
// dirty update matrix
|
||||
_matrix.makeIdentity();
|
||||
for (StackedTransform::iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
StackedTransformElement* element = it->get();
|
||||
if (!element || element->isIdentity())
|
||||
continue;
|
||||
element->applyToMatrix(_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
const osg::Matrix& StackedTransform::getMatrix() const
|
||||
{
|
||||
return _matrix;
|
||||
}
|
||||
50
src/osgAnimation/StackedTranslateElement.cpp
Normal file
50
src/osgAnimation/StackedTranslateElement.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedTranslateElement>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
|
||||
StackedTranslateElement::StackedTranslateElement(const std::string& name, const osg::Vec3& translate) : _translate(translate) { setName(name); }
|
||||
StackedTranslateElement::StackedTranslateElement(const osg::Vec3& translate) : _translate(translate) { setName("translate"); }
|
||||
|
||||
|
||||
StackedTranslateElement::StackedTranslateElement() {}
|
||||
StackedTranslateElement::StackedTranslateElement(const StackedTranslateElement& rhs, const osg::CopyOp&) : StackedTransformElement(rhs), _translate(rhs._translate)
|
||||
{
|
||||
if (rhs._target.valid())
|
||||
_target = new Vec3Target(*rhs._target);
|
||||
}
|
||||
|
||||
void StackedTranslateElement::applyToMatrix(osg::Matrix& matrix) const {matrix.preMultTranslate(_translate);}
|
||||
osg::Matrix StackedTranslateElement::getAsMatrix() const { return osg::Matrix::translate(_translate); }
|
||||
bool StackedTranslateElement::isIdentity() const { return (_translate[0] == 0 && _translate[1] == 0 && _translate[2] == 0); }
|
||||
const osg::Vec3& StackedTranslateElement::getTranslate() const { return _translate; }
|
||||
void StackedTranslateElement::setTranslate(const osg::Vec3& value) { _translate = value; }
|
||||
|
||||
Target* StackedTranslateElement::getOrCreateTarget()
|
||||
{
|
||||
if (!_target.valid())
|
||||
_target = new Vec3Target(_translate);
|
||||
return _target.get();
|
||||
}
|
||||
Target* StackedTranslateElement::getTarget() {return _target.get();}
|
||||
const Target* StackedTranslateElement::getTarget() const {return _target.get();}
|
||||
|
||||
void StackedTranslateElement::update()
|
||||
{
|
||||
if (_target.valid())
|
||||
_translate = _target->getValue();
|
||||
}
|
||||
722
src/osgAnimation/StatsHandler.cpp
Normal file
722
src/osgAnimation/StatsHandler.cpp
Normal file
@@ -0,0 +1,722 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* 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 <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgViewer/Renderer>
|
||||
#include <osgAnimation/StatsHandler>
|
||||
#include <osgAnimation/EaseMotion>
|
||||
#include <osgAnimation/StatsVisitor>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgViewer/Renderer>
|
||||
#include <osgAnimation/TimelineAnimationManager>
|
||||
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Geometry>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
static unsigned int getRandomValueinRange(unsigned int v)
|
||||
{
|
||||
return static_cast<unsigned int>((rand() * 1.0 * v)/(RAND_MAX-1));
|
||||
}
|
||||
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
|
||||
osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color)
|
||||
{
|
||||
osg::StateSet *ss = new osg::StateSet;
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
geometry->setUseDisplayList(false);
|
||||
geometry->setStateSet(ss);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
geometry->setVertexArray(vertices);
|
||||
|
||||
vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
|
||||
vertices->push_back(osg::Vec3(pos.x(), pos.y()-height,0));
|
||||
vertices->push_back(osg::Vec3(pos.x()+width, pos.y()-height,0));
|
||||
vertices->push_back(osg::Vec3(pos.x()+width, pos.y(),0));
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
geometry->setColorArray(colors);
|
||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::DrawElementsUInt *base = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);
|
||||
base->push_back(0);
|
||||
base->push_back(1);
|
||||
base->push_back(2);
|
||||
base->push_back(3);
|
||||
|
||||
geometry->addPrimitiveSet(base);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
struct StatsGraph : public osg::MatrixTransform
|
||||
{
|
||||
StatsGraph(osg::Vec3 pos, float width, float height)
|
||||
: _pos(pos), _width(width), _height(height),
|
||||
_statsGraphGeode(new osg::Geode)
|
||||
{
|
||||
_pos = pos - osg::Vec3(0, _height, 0.1);
|
||||
setMatrix(osg::Matrix::translate(_pos));
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
addChild(_statsGraphGeode.get());
|
||||
_statsGraphGeode->setCullingActive(false);
|
||||
}
|
||||
|
||||
void changeYposition(float y)
|
||||
{
|
||||
osg::Vec3 _pos = getMatrix().getTrans();
|
||||
_pos[1] = y - _height;
|
||||
setMatrix(osg::Matrix::translate(_pos));
|
||||
}
|
||||
|
||||
void addStatGraph(osg::Stats* viewerStats, osg::Stats* stats, const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
||||
{
|
||||
_statsGraphGeode->addDrawable(new Graph(_width, _height, viewerStats, stats, color, max, nameBegin, nameEnd));
|
||||
}
|
||||
|
||||
osg::Vec3 _pos;
|
||||
float _width;
|
||||
float _height;
|
||||
|
||||
osg::ref_ptr<osg::Geode> _statsGraphGeode;
|
||||
|
||||
struct NeverCull : public osg::Drawable::CullCallback
|
||||
{
|
||||
NeverCull() {}
|
||||
bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const { return false;}
|
||||
};
|
||||
|
||||
|
||||
struct Graph : public osg::Geometry
|
||||
{
|
||||
Graph(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
|
||||
const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
||||
{
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
setUseDisplayList(false);
|
||||
|
||||
setVertexArray(new osg::Vec3Array);
|
||||
getVertexArray()->setDataVariance(osg::Object::DYNAMIC);
|
||||
setColor(color);
|
||||
|
||||
setUpdateCallback(new GraphUpdateCallback(width, height, viewerStats, stats, max, nameBegin, nameEnd));
|
||||
setCullCallback(new NeverCull);
|
||||
}
|
||||
|
||||
void setColor(const osg::Vec4& color) {
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
setColorArray(colors);
|
||||
setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct GraphUpdateCallback : public osg::Drawable::UpdateCallback
|
||||
{
|
||||
|
||||
const unsigned int _width;
|
||||
const unsigned int _height;
|
||||
mutable unsigned int _curX;
|
||||
osg::Stats* _viewerStats;
|
||||
osg::Stats* _stats;
|
||||
const float _max;
|
||||
const std::string _nameBegin;
|
||||
const std::string _nameEnd;
|
||||
mutable int _frameNumber;
|
||||
|
||||
GraphUpdateCallback(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
|
||||
float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
||||
: _width((unsigned int)width), _height((unsigned int)height), _curX(0),
|
||||
_viewerStats(viewerStats), _stats(stats), _max(max), _nameBegin(nameBegin), _nameEnd(nameEnd), _frameNumber(0)
|
||||
{
|
||||
}
|
||||
virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
|
||||
{
|
||||
if (nv->getVisitorType() != osg::NodeVisitor::UPDATE_VISITOR)
|
||||
return;
|
||||
|
||||
osg::Geometry* geometry = const_cast<osg::Geometry*>(drawable->asGeometry());
|
||||
if (!geometry) return;
|
||||
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
|
||||
if (!vertices) return;
|
||||
|
||||
int frameNumber = nv->getFrameStamp()->getFrameNumber();
|
||||
if (frameNumber == _frameNumber)
|
||||
return;
|
||||
|
||||
|
||||
// Get stats
|
||||
double value;
|
||||
if (_nameEnd.empty())
|
||||
{
|
||||
if (!_stats->getAttribute(_stats->getLatestFrameNumber(), _nameBegin, value ))
|
||||
{
|
||||
value = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double beginValue, endValue;
|
||||
if (_stats->getAttribute( frameNumber, _nameBegin, beginValue) &&
|
||||
_stats->getAttribute( frameNumber, _nameEnd, endValue) )
|
||||
{
|
||||
value = endValue - beginValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = 0.0;
|
||||
}
|
||||
}
|
||||
// Add new vertex for this frame.
|
||||
value = osg::clampTo(value, 0.0, double(_max));
|
||||
|
||||
if (!vertices->size()) {
|
||||
for (int i = 0; i < (int)_width; i++)
|
||||
vertices->push_back(osg::Vec3(float(_curX++), 0, 0));
|
||||
// Create primitive set if none exists.
|
||||
if (geometry->getNumPrimitiveSets() == 0)
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, 0));
|
||||
osg::DrawArrays* drawArrays = dynamic_cast<osg::DrawArrays*>(geometry->getPrimitiveSet(0));
|
||||
drawArrays->setFirst(0);
|
||||
drawArrays->setCount(vertices->size());
|
||||
}
|
||||
vertices->push_back(osg::Vec3(float(_curX), float(_height) / _max * value, 0));
|
||||
|
||||
unsigned int excedent = vertices->size() - _width;
|
||||
vertices->erase(vertices->begin(), vertices->begin() + excedent);
|
||||
|
||||
// Make the graph scroll when there is enough data.
|
||||
// Note: We check the frame number so that even if we have
|
||||
// many graphs, the transform is translated only once per
|
||||
// frame.
|
||||
static const float increment = -1.0;
|
||||
if (_frameNumber != frameNumber)
|
||||
{
|
||||
// We know the exact layout of this part of the scene
|
||||
// graph, so this is OK...
|
||||
osg::MatrixTransform* transform =
|
||||
geometry->getParent(0)->getParent(0)->asTransform()->asMatrixTransform();
|
||||
if (transform)
|
||||
{
|
||||
transform->setMatrix(transform->getMatrix() * osg::Matrix::translate(osg::Vec3(increment, 0, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
_curX++;
|
||||
_frameNumber = frameNumber;
|
||||
|
||||
geometry->dirtyBound();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Drawcallback to draw averaged attribute
|
||||
struct ValueTextDrawCallback : public virtual osg::Drawable::DrawCallback
|
||||
{
|
||||
ValueTextDrawCallback(osg::Stats* stats, const std::string& name):
|
||||
_stats(stats),
|
||||
_attributeName(name),
|
||||
_frameNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** do customized draw code.*/
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
||||
{
|
||||
osgText::Text* text = (osgText::Text*)drawable;
|
||||
|
||||
int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
|
||||
if (frameNumber == _frameNumber) {
|
||||
text->drawImplementation(renderInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
double value;
|
||||
if (_stats->getAttribute(_stats->getLatestFrameNumber(), _attributeName, value))
|
||||
{
|
||||
sprintf(_tmpText,"%4.2f",value);
|
||||
text->setText(_tmpText);
|
||||
}
|
||||
else
|
||||
{
|
||||
text->setText("");
|
||||
}
|
||||
_frameNumber = frameNumber;
|
||||
text->drawImplementation(renderInfo);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
std::string _attributeName;
|
||||
mutable char _tmpText[128];
|
||||
mutable int _frameNumber;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct StatAction
|
||||
{
|
||||
double _lastTime;
|
||||
std::string _name;
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
osg::ref_ptr<osg::Geode> _label;
|
||||
osg::ref_ptr<osg::MatrixTransform> _graph;
|
||||
osg::ref_ptr<osgText::Text> _textLabel;
|
||||
osgAnimation::OutCubicMotion _fade;
|
||||
|
||||
StatAction() { _lastTime = 0; _fade = osgAnimation::OutCubicMotion(0,5); }
|
||||
void init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float heigh, const osg::Vec4& color);
|
||||
void setPosition(const osg::Vec3& pos);
|
||||
#if 0
|
||||
void touch()
|
||||
{
|
||||
_lastTime = osg::Timer::instance()->time_s();
|
||||
float a = 1.0 - _fade.getValueAt(0.0);
|
||||
setAlpha(a);
|
||||
}
|
||||
bool update() {
|
||||
double t = osg::Timer::instance()->time_s();
|
||||
float alpha = 1.0 - _fade.getValueAt(t-_lastTime);
|
||||
if (t - _lastTime > _fade.getDuration())
|
||||
return true;
|
||||
setAlpha(alpha);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void setAlpha(float v);
|
||||
};
|
||||
|
||||
|
||||
struct StatsTimeline : public osg::NodeCallback
|
||||
{
|
||||
static float _statsHeight;
|
||||
static float _statsWidth;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _background;
|
||||
osg::ref_ptr<osgAnimation::Timeline> _timeline;
|
||||
osg::ref_ptr<osg::MatrixTransform> _group;
|
||||
std::map<std::string, StatAction > _actions;
|
||||
|
||||
StatsTimeline()
|
||||
{
|
||||
_statsHeight = 1024;
|
||||
_statsWidth = 1280;
|
||||
}
|
||||
osg::MatrixTransform* createStatsForTimeline(osgAnimation::Timeline* timeline)
|
||||
{
|
||||
_timeline = timeline;
|
||||
|
||||
std::string font("fonts/arial.ttf");
|
||||
|
||||
float leftPos = 10.0f;
|
||||
float startBlocks = 150.0f;
|
||||
float characterSize = 20.0f;
|
||||
|
||||
|
||||
osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3);
|
||||
float backgroundMargin = 5;
|
||||
//float backgroundSpacing = 3;
|
||||
|
||||
osg::Vec4 color(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
_group = new osg::MatrixTransform;
|
||||
_group->setDataVariance(osg::Object::DYNAMIC);
|
||||
|
||||
{
|
||||
osg::Vec3 pos(leftPos, _statsHeight-24.0f,0.0f);
|
||||
//float topOfViewerStats = pos.y() + characterSize;
|
||||
osg::ref_ptr<osg::Stats> stats = _timeline->getStats();
|
||||
pos.y() -= characterSize + backgroundMargin;
|
||||
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
_group->addChild(geode);
|
||||
osg::ref_ptr<osgText::Text> timeLabel = new osgText::Text;
|
||||
geode->addDrawable( timeLabel.get() );
|
||||
|
||||
timeLabel->setColor(color);
|
||||
timeLabel->setFont(font);
|
||||
timeLabel->setCharacterSize(characterSize);
|
||||
timeLabel->setPosition(pos);
|
||||
timeLabel->setText("Time: ");
|
||||
|
||||
osg::ref_ptr<osgText::Text> timeLabelValue = new osgText::Text;
|
||||
geode->addDrawable( timeLabelValue.get() );
|
||||
|
||||
timeLabelValue->setColor(color);
|
||||
timeLabelValue->setFont(font);
|
||||
timeLabelValue->setCharacterSize(characterSize);
|
||||
timeLabelValue->setPosition(pos + osg::Vec3(startBlocks, 0,0));
|
||||
timeLabelValue->setText("0.0");
|
||||
|
||||
timeLabelValue->setDrawCallback(new ValueTextDrawCallback(stats.get(),"Timeline"));
|
||||
}
|
||||
}
|
||||
{
|
||||
osg::Vec3 pos(leftPos, _statsHeight - 24.0f ,0.0f);
|
||||
//float topOfViewerStats = pos.y();
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
_background = createBackgroundRectangle(
|
||||
pos + osg::Vec3(-backgroundMargin, backgroundMargin, 0),
|
||||
_statsWidth - 2 * backgroundMargin,
|
||||
(3 + 4.5 * 1) * characterSize + 2 * backgroundMargin,
|
||||
backgroundColor);
|
||||
geode->addDrawable(_background.get());
|
||||
_group->addChild(geode);
|
||||
}
|
||||
|
||||
return _group.get();
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) {
|
||||
updateGraph();
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
void updateGraph()
|
||||
{
|
||||
osgAnimation::StatsActionVisitor* visitor = _timeline->getStatsVisitor();
|
||||
if (!visitor)
|
||||
return;
|
||||
|
||||
std::string font("fonts/arial.ttf");
|
||||
float leftPos = 10.0f;
|
||||
float characterSize = 20.0f;
|
||||
|
||||
float backgroundMargin = 5;
|
||||
//float backgroundSpacing = 3;
|
||||
float graphSpacing = 5;
|
||||
|
||||
float width = _statsWidth - 4 * backgroundMargin;
|
||||
float height = characterSize;
|
||||
osg::Vec3 pos(leftPos, _statsHeight-24.0f,0.0f);
|
||||
pos.y() -= characterSize *2 + backgroundMargin;
|
||||
|
||||
for (std::map<std::string, StatAction >::iterator it = _actions.begin(); it != _actions.end(); ++it) {
|
||||
(*it).second._group->setNodeMask(~osg::Node::NodeMask(1));
|
||||
}
|
||||
|
||||
const std::vector<std::string>& channels = visitor->getChannels();
|
||||
std::map<std::string,int> size;
|
||||
for (int i = 0; i < (int)channels.size(); i++) {
|
||||
std::string name = channels[i];
|
||||
if (_actions.find(name) == _actions.end()) {
|
||||
osg::Vec4 color(getRandomValueinRange(255)/255.0, getRandomValueinRange(255)/255.0, getRandomValueinRange(255)/255.0, 1.0);
|
||||
_actions[name].init(visitor->getStats(), name, pos, width, height, color);
|
||||
_group->addChild(_actions[name]._group.get());
|
||||
//_actions[name].touch();
|
||||
} else {
|
||||
_actions[name].setPosition(pos);
|
||||
//_actions[name].touch();
|
||||
}
|
||||
_actions[name]._group->setNodeMask(~osg::Node::NodeMask(0x0));
|
||||
size[name] = 0;
|
||||
pos.y() -= characterSize + graphSpacing;
|
||||
}
|
||||
|
||||
pos.y() -= backgroundMargin;
|
||||
osg::Vec3Array* array = dynamic_cast<osg::Vec3Array*>(_background->getVertexArray());
|
||||
float y = (*array)[0][1];
|
||||
y = y - (pos.y() + backgroundMargin); //(2 * backgroundMargin + (size.size() * (characterSize + graphSpacing)));
|
||||
(*array)[1][1] = pos.y();
|
||||
(*array)[2][1] = pos.y();
|
||||
array->dirty();
|
||||
_background->dirtyBound();
|
||||
}
|
||||
};
|
||||
float StatsTimeline::_statsHeight;
|
||||
float StatsTimeline::_statsWidth;
|
||||
|
||||
|
||||
|
||||
struct FindTimelineStats : public osg::NodeVisitor
|
||||
{
|
||||
std::vector<osg::ref_ptr<osgAnimation::Timeline> > _timelines;
|
||||
|
||||
FindTimelineStats() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
|
||||
void apply(osg::Node& node) {
|
||||
osg::NodeCallback* cb = node.getUpdateCallback();
|
||||
while (cb) {
|
||||
osgAnimation::TimelineAnimationManager* tam = dynamic_cast<osgAnimation::TimelineAnimationManager*>(cb);
|
||||
if (tam)
|
||||
_timelines.push_back(tam->getTimeline());
|
||||
cb = cb->getNestedCallback();
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
StatsHandler::StatsHandler():
|
||||
_keyEventTogglesOnScreenStats('a'),
|
||||
_keyEventPrintsOutStats('A'),
|
||||
_statsType(NO_STATS),
|
||||
_initialized(false),
|
||||
_statsWidth(1280.0f),
|
||||
_statsHeight(1024.0f)
|
||||
{
|
||||
_camera = new osg::Camera;
|
||||
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
||||
_camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||
}
|
||||
|
||||
bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
||||
{
|
||||
osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
|
||||
if (!myview) return false;
|
||||
|
||||
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(myview->getViewerBase());
|
||||
|
||||
if (!viewer->getSceneData())
|
||||
return false;
|
||||
if (ea.getHandled()) return false;
|
||||
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||
{
|
||||
if (ea.getKey()==_keyEventTogglesOnScreenStats)
|
||||
{
|
||||
if (viewer->getViewerStats())
|
||||
{
|
||||
|
||||
if (!_switch.get()) {
|
||||
FindTimelineStats finder;
|
||||
viewer->getSceneData()->accept(finder);
|
||||
if (finder._timelines.empty())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
setUpHUDCamera(viewer);
|
||||
setUpScene(dynamic_cast<osgViewer::Viewer*>(viewer));
|
||||
}
|
||||
|
||||
++_statsType;
|
||||
|
||||
if (_statsType==LAST) _statsType = NO_STATS;
|
||||
|
||||
|
||||
switch(_statsType)
|
||||
{
|
||||
case(NO_STATS):
|
||||
{
|
||||
_camera->setNodeMask(0x0);
|
||||
_switch->setAllChildrenOff();
|
||||
break;
|
||||
}
|
||||
case(FRAME_RATE):
|
||||
{
|
||||
_camera->setNodeMask(0xffffffff);
|
||||
_switch->setAllChildrenOn();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (ea.getKey()==_keyEventPrintsOutStats)
|
||||
{
|
||||
FindTimelineStats finder;
|
||||
viewer->getSceneData()->accept(finder);
|
||||
if (!finder._timelines.empty()) {
|
||||
osg::notify(osg::NOTICE)<<std::endl<<"Stats report:"<<std::endl;
|
||||
typedef std::vector<osg::Stats*> StatsList;
|
||||
StatsList statsList;
|
||||
|
||||
for (int i = 0; i < (int)finder._timelines.size(); i++)
|
||||
statsList.push_back(finder._timelines[i]->getStats());
|
||||
|
||||
for(int i = statsList[0]->getEarliestFrameNumber(); i<= statsList[0]->getLatestFrameNumber()-1; ++i)
|
||||
{
|
||||
for(StatsList::iterator itr = statsList.begin();
|
||||
itr != statsList.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr==statsList.begin()) (*itr)->report(osg::notify(osg::NOTICE), i);
|
||||
else (*itr)->report(osg::notify(osg::NOTICE), i, " ");
|
||||
}
|
||||
osg::notify(osg::NOTICE)<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void StatsHandler::reset()
|
||||
{
|
||||
_initialized = false;
|
||||
_camera->setGraphicsContext(0);
|
||||
_camera->removeChildren( 0, _camera->getNumChildren() );
|
||||
}
|
||||
|
||||
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
|
||||
{
|
||||
osgViewer::GraphicsWindow* window = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
|
||||
|
||||
if (!window)
|
||||
{
|
||||
osgViewer::Viewer::Windows windows;
|
||||
viewer->getWindows(windows);
|
||||
|
||||
if (windows.empty()) return;
|
||||
|
||||
window = windows.front();
|
||||
}
|
||||
|
||||
_camera->setGraphicsContext(window);
|
||||
|
||||
_camera->setViewport(0, 0, window->getTraits()->width, window->getTraits()->height);
|
||||
|
||||
_camera->setRenderOrder(osg::Camera::POST_RENDER, 10);
|
||||
|
||||
_camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,0.0,_statsHeight));
|
||||
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_camera->setViewMatrix(osg::Matrix::identity());
|
||||
|
||||
// only clear the depth buffer
|
||||
_camera->setClearMask(0); //GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //-1);
|
||||
_camera->setAllowEventFocus(false);
|
||||
_camera->setCullMask(0x1);
|
||||
osgViewer::Viewer* v = dynamic_cast<osgViewer::Viewer*>(viewer);
|
||||
v->getSceneData()->asGroup()->addChild(_camera.get());
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void StatsHandler::setUpScene(osgViewer::Viewer* viewer)
|
||||
{
|
||||
if (!viewer->getSceneData())
|
||||
return;
|
||||
|
||||
FindTimelineStats finder;
|
||||
viewer->getSceneData()->accept(finder);
|
||||
if (finder._timelines.empty())
|
||||
return;
|
||||
|
||||
_switch = new osg::Switch;
|
||||
osg::StateSet* stateset = _switch->getOrCreateStateSet();
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
|
||||
stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
|
||||
|
||||
_group = new osg::Group;
|
||||
_camera->addChild(_switch.get());
|
||||
_switch->addChild(_group.get());
|
||||
|
||||
for (int i = 0; i < (int)finder._timelines.size(); i++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void StatAction::init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float height, const osg::Vec4& color)
|
||||
{
|
||||
std::string font("fonts/arial.ttf");
|
||||
float characterSize = 20.0f;
|
||||
float startBlocks = 150.0f;
|
||||
|
||||
_name = name;
|
||||
_group = new osg::Group;
|
||||
|
||||
_label = new osg::Geode;
|
||||
_textLabel = new osgText::Text;
|
||||
_label->addDrawable(_textLabel.get());
|
||||
_textLabel->setDataVariance(osg::Object::DYNAMIC);
|
||||
_textLabel->setColor(color);
|
||||
_textLabel->setFont(font);
|
||||
_textLabel->setCharacterSize(characterSize);
|
||||
_textLabel->setPosition(pos - osg::Vec3(0, height, 0));
|
||||
_textLabel->setText(name);
|
||||
|
||||
StatsGraph* graph = new StatsGraph(pos + osg::Vec3(startBlocks, 0,0) , width-startBlocks, height);
|
||||
graph->setCullingActive(false);
|
||||
graph->addStatGraph(stats, stats, color, 1.0, name);
|
||||
_graph = graph;
|
||||
|
||||
_group->addChild(_label.get());
|
||||
_group->addChild(_graph.get());
|
||||
}
|
||||
void StatAction::setAlpha(float v)
|
||||
{
|
||||
std::cout << this << " color alpha " << v << std::endl;
|
||||
StatsGraph* gfx = dynamic_cast<StatsGraph*>(_graph.get());
|
||||
osg::Vec4 color = _textLabel->getColor();
|
||||
color[3] = v;
|
||||
_textLabel->setColor(color);
|
||||
for (int i = 0; i < (int) gfx->_statsGraphGeode->getNumDrawables(); i++) {
|
||||
StatsGraph::Graph* g = dynamic_cast<StatsGraph::Graph*>(gfx->_statsGraphGeode->getDrawable(0));
|
||||
g->setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void StatAction::setPosition(const osg::Vec3& pos)
|
||||
{
|
||||
float characterSize = 20.0f;
|
||||
StatsGraph* gfx = dynamic_cast<StatsGraph*>(_graph.get());
|
||||
gfx->changeYposition(pos[1]);
|
||||
_textLabel->setPosition(pos - osg::Vec3(0, characterSize,0));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void StatsHandler::getUsage(osg::ApplicationUsage& usage) const
|
||||
{
|
||||
usage.addKeyboardMouseBinding("s","On screen stats.");
|
||||
usage.addKeyboardMouseBinding("S","Output stats to console.");
|
||||
}
|
||||
|
||||
}
|
||||
86
src/osgAnimation/StatsVisitor.cpp
Normal file
86
src/osgAnimation/StatsVisitor.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StatsVisitor>
|
||||
#include <osgAnimation/Timeline>
|
||||
#include <osgAnimation/ActionBlendIn>
|
||||
#include <osgAnimation/ActionBlendOut>
|
||||
#include <osgAnimation/ActionStripAnimation>
|
||||
#include <osgAnimation/ActionAnimation>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
StatsActionVisitor::StatsActionVisitor() {}
|
||||
void StatsActionVisitor::reset() { _channels.clear(); }
|
||||
|
||||
StatsActionVisitor::StatsActionVisitor(osg::Stats* stats,unsigned int frame)
|
||||
{
|
||||
_frame = frame;
|
||||
_stats = stats;
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(Timeline& tm)
|
||||
{
|
||||
_stats->setAttribute(_frame,"Timeline", tm.getCurrentTime());
|
||||
tm.traverse(*this);
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(Action& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
_channels.push_back(action.getName());
|
||||
_stats->setAttribute(_frame,action.getName(),1);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(ActionBlendIn& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
_channels.push_back(action.getName());
|
||||
_stats->setAttribute(_frame,action.getName(), action.getWeight());
|
||||
}
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(ActionBlendOut& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
_channels.push_back(action.getName());
|
||||
_stats->setAttribute(_frame,action.getName(), action.getWeight());
|
||||
}
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(ActionAnimation& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
_channels.push_back(action.getName());
|
||||
_stats->setAttribute(_frame,action.getName(), action.getAnimation()->getWeight());
|
||||
}
|
||||
}
|
||||
|
||||
void StatsActionVisitor::apply(ActionStripAnimation& action)
|
||||
{
|
||||
if (isActive(action))
|
||||
{
|
||||
_channels.push_back(action.getName());
|
||||
double value;
|
||||
std::string name = action.getName();
|
||||
if (_stats->getAttribute(_frame, name, value))
|
||||
name += "+";
|
||||
_stats->setAttribute(_frame, action.getName(), action.getAnimation()->getAnimation()->getWeight());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -18,5 +18,4 @@
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
Target::Target() { reset();}
|
||||
Target::~Target() {}
|
||||
Target::Target() : _weight(0), _priorityWeight(0), _lastPriority(0) {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <osgAnimation/Timeline>
|
||||
#include <osgAnimation/StatsVisitor>
|
||||
#include <limits.h>
|
||||
|
||||
using namespace osgAnimation;
|
||||
@@ -29,11 +30,14 @@ Timeline::Timeline()
|
||||
_previousFrameEvaluated = 0;
|
||||
_evaluating = 0;
|
||||
_numberFrame = UINT_MAX; // something like infinity
|
||||
_collectStats = false;
|
||||
_stats = new osg::Stats("Timeline");
|
||||
setName("Timeline");
|
||||
}
|
||||
|
||||
Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op) : osg::Object(nc, op),
|
||||
_actions(nc._actions)
|
||||
Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
|
||||
: Action(nc, op),
|
||||
_actions(nc._actions)
|
||||
{
|
||||
_lastUpdate = 0;
|
||||
_currentFrame = 0;
|
||||
@@ -44,5 +48,204 @@ Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op) : osg::Object(nc, o
|
||||
_previousFrameEvaluated = 0;
|
||||
_evaluating = 0;
|
||||
_numberFrame = UINT_MAX; // something like infinity
|
||||
_collectStats = false;
|
||||
_stats = new osg::Stats("Timeline");
|
||||
setName("Timeline");
|
||||
}
|
||||
|
||||
void Timeline::setAnimationManager(AnimationManagerBase* manager)
|
||||
{
|
||||
_animationManager = manager;
|
||||
}
|
||||
|
||||
void Timeline::traverse(ActionVisitor& visitor)
|
||||
{
|
||||
int layer = visitor.getCurrentLayer();
|
||||
visitor.pushTimelineOnStack(this);
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
|
||||
{
|
||||
visitor.setCurrentLayer(iterAnim->first);
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
visitor.pushFrameActionOnStack(list[i]);
|
||||
if (list[i].second) list[i].second->accept(visitor);
|
||||
visitor.popFrameAction();
|
||||
}
|
||||
}
|
||||
visitor.popTimeline();
|
||||
visitor.setCurrentLayer(layer);
|
||||
}
|
||||
|
||||
|
||||
void Timeline::setStats(osg::Stats* stats) { _stats = stats;}
|
||||
osg::Stats* Timeline::getStats() { return _stats.get();}
|
||||
void Timeline::collectStats(bool state) { _collectStats = state;}
|
||||
StatsActionVisitor* Timeline::getStatsVisitor() { return _statsVisitor.get(); }
|
||||
|
||||
void Timeline::clearActions()
|
||||
{
|
||||
_actions.clear();
|
||||
_addActionOperations.clear();
|
||||
_removeActionOperations.clear();
|
||||
}
|
||||
|
||||
void Timeline::update(double simulationTime)
|
||||
{
|
||||
// first time we call update we generate one frame
|
||||
UpdateActionVisitor updateTimeline;
|
||||
if (!_initFirstFrame)
|
||||
{
|
||||
_lastUpdate = simulationTime;
|
||||
_initFirstFrame = true;
|
||||
|
||||
|
||||
_animationManager->clearTargets();
|
||||
updateTimeline.setFrame(_currentFrame);
|
||||
accept(updateTimeline);
|
||||
|
||||
if (_collectStats)
|
||||
{
|
||||
if (!_statsVisitor)
|
||||
_statsVisitor = new StatsActionVisitor();
|
||||
_statsVisitor->setStats(_stats.get());
|
||||
_statsVisitor->setFrame(_currentFrame);
|
||||
_statsVisitor->reset();
|
||||
accept(*_statsVisitor);
|
||||
}
|
||||
|
||||
processPendingOperation();
|
||||
}
|
||||
|
||||
// find the number of frame pass since the last update
|
||||
double delta = (simulationTime - _lastUpdate);
|
||||
double nbframes = delta * _fps * _speed;
|
||||
unsigned int nb = static_cast<unsigned int>(floor(nbframes));
|
||||
|
||||
for (unsigned int i = 0; i < nb; i++)
|
||||
{
|
||||
if (_state == Play)
|
||||
_currentFrame++;
|
||||
|
||||
_animationManager->clearTargets();
|
||||
updateTimeline.setFrame(_currentFrame);
|
||||
accept(updateTimeline);
|
||||
if (_collectStats)
|
||||
{
|
||||
if (!_statsVisitor)
|
||||
_statsVisitor = new StatsActionVisitor;
|
||||
_statsVisitor->setStats(_stats.get());
|
||||
_statsVisitor->setFrame(_currentFrame);
|
||||
_statsVisitor->reset();
|
||||
accept(*_statsVisitor);
|
||||
}
|
||||
|
||||
processPendingOperation();
|
||||
}
|
||||
if (nb)
|
||||
{
|
||||
_lastUpdate += ((double)nb) / _fps;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::removeAction(Action* action)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_removeActionOperations.push_back(FrameAction(0, action));
|
||||
else
|
||||
internalRemoveAction(action);
|
||||
}
|
||||
|
||||
void Timeline::addActionAt(unsigned int frame, Action* action, int priority)
|
||||
{
|
||||
// skip if this action has already been added this frame
|
||||
for (CommandList::iterator it = _addActionOperations.begin(); it != _addActionOperations.end(); ++it)
|
||||
{
|
||||
Command& command = *it;
|
||||
if (command._action.second.get() == action) {
|
||||
osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already added this frame, declined" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isActive(action))
|
||||
{
|
||||
osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already active, remove the old" << std::endl;
|
||||
removeAction(action);
|
||||
}
|
||||
|
||||
if (getEvaluating())
|
||||
_addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
|
||||
else
|
||||
internalAddAction(priority, FrameAction(frame, action));
|
||||
}
|
||||
void Timeline::addActionAt(double t, Action* action, int priority)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
|
||||
addActionAt(frame, action, priority);
|
||||
}
|
||||
|
||||
void Timeline::addActionNow(Action* action, int priority)
|
||||
{
|
||||
addActionAt(getCurrentFrame()+1, action, priority);
|
||||
}
|
||||
|
||||
void Timeline::processPendingOperation()
|
||||
{
|
||||
// process all pending add action operation
|
||||
while( !_addActionOperations.empty())
|
||||
{
|
||||
internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
|
||||
_addActionOperations.pop_back();
|
||||
}
|
||||
|
||||
// process all pending remove action operation
|
||||
while( !_removeActionOperations.empty())
|
||||
{
|
||||
internalRemoveAction(_removeActionOperations.back().second.get());
|
||||
_removeActionOperations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::internalRemoveAction(Action* action)
|
||||
{
|
||||
for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); ++it)
|
||||
{
|
||||
ActionList& fa = it->second;
|
||||
for (unsigned int i = 0; i < fa.size(); i++)
|
||||
if (fa[i].second.get() == action)
|
||||
{
|
||||
fa.erase(fa.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::internalAddAction(int priority, const FrameAction& ftl)
|
||||
{
|
||||
_actions[priority].insert(_actions[priority].begin(), ftl);
|
||||
}
|
||||
|
||||
bool Timeline::isActive(Action* activeAction)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
Action* action = list[i].second.get();
|
||||
if (action == activeAction)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (_currentFrame >= firstFrame &&
|
||||
_currentFrame < (firstFrame + action->getNumFrames()) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -34,7 +34,7 @@ TimelineAnimationManager::TimelineAnimationManager(const TimelineAnimationManage
|
||||
|
||||
void TimelineAnimationManager::update(double time)
|
||||
{
|
||||
clearTargets();
|
||||
// clearTargets();
|
||||
_timeline->setAnimationManager(this);
|
||||
_timeline->update(time);
|
||||
normalizeTargets();
|
||||
}
|
||||
|
||||
54
src/osgAnimation/UpdateBone.cpp
Normal file
54
src/osgAnimation/UpdateBone.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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 <osg/NodeVisitor>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
|
||||
UpdateBone::UpdateBone(const std::string& name) : UpdateMatrixTransform(name)
|
||||
{
|
||||
}
|
||||
|
||||
UpdateBone::UpdateBone(const UpdateBone& apc,const osg::CopyOp& copyop) : osg::Object(apc,copyop), UpdateMatrixTransform(apc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
void UpdateBone::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
Bone* b = dynamic_cast<Bone*>(node);
|
||||
if (!b)
|
||||
{
|
||||
osg::notify(osg::WARN) << "Warning: UpdateBone set on non-Bone object." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// here we would prefer to have a flag inside transform stack in order to avoid update and a dirty state in matrixTransform if it's not require.
|
||||
_transforms.update();
|
||||
const osg::Matrix& matrix = _transforms.getMatrix();
|
||||
b->setMatrix(matrix);
|
||||
|
||||
Bone* parent = b->getBoneParent();
|
||||
if (parent)
|
||||
b->setMatrixInSkeletonSpace(b->getMatrixInBoneSpace() * parent->getMatrixInSkeletonSpace());
|
||||
else
|
||||
b->setMatrixInSkeletonSpace(b->getMatrixInBoneSpace());
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
63
src/osgAnimation/UpdateMaterial.cpp
Normal file
63
src/osgAnimation/UpdateMaterial.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/UpdateMaterial>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
UpdateMaterial::UpdateMaterial(const UpdateMaterial& apc,const osg::CopyOp& copyop)
|
||||
: osg::Object(apc, copyop),
|
||||
AnimationUpdateCallback<osg::StateAttributeCallback>(apc, copyop)
|
||||
{
|
||||
_diffuse = new osgAnimation::Vec4Target(apc._diffuse->getValue());
|
||||
}
|
||||
|
||||
UpdateMaterial::UpdateMaterial(const std::string& name):
|
||||
AnimationUpdateCallback<osg::StateAttributeCallback>(name)
|
||||
{
|
||||
_diffuse = new osgAnimation::Vec4Target(osg::Vec4(1,0,1,1));
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
void UpdateMaterial::operator()(osg::StateAttribute* sa, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
osg::Material* material = dynamic_cast<osg::Material*>(sa);
|
||||
if (material)
|
||||
update(*material);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
osgAnimation::Vec4Target* UpdateMaterial::getDiffuse() { return _diffuse.get(); }
|
||||
void UpdateMaterial::update(osg::Material& material)
|
||||
{
|
||||
osg::Vec4 diffuse = _diffuse->getValue();
|
||||
material.setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
bool UpdateMaterial::link(osgAnimation::Channel* channel)
|
||||
{
|
||||
if (channel->getName().find("diffuse") != std::string::npos)
|
||||
{
|
||||
return channel->setTarget(_diffuse.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class " << className() << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
67
src/osgAnimation/UpdateMatrixTransform.cpp
Normal file
67
src/osgAnimation/UpdateMatrixTransform.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/UpdateMatrixTransform>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
UpdateMatrixTransform::UpdateMatrixTransform( const UpdateMatrixTransform& apc,const osg::CopyOp& copyop) : osg::Object(apc,copyop), AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
|
||||
{
|
||||
_transforms = StackedTransform(apc.getStackedTransforms(), copyop);
|
||||
}
|
||||
|
||||
UpdateMatrixTransform::UpdateMatrixTransform(const std::string& name) : AnimationUpdateCallback<osg::NodeCallback>(name)
|
||||
{
|
||||
}
|
||||
|
||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||
void UpdateMatrixTransform::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
|
||||
{
|
||||
osg::MatrixTransform* matrixTransform = dynamic_cast<osg::MatrixTransform*>(node);
|
||||
if (matrixTransform)
|
||||
{
|
||||
// here we would prefer to have a flag inside transform stack in order to avoid update and a dirty state in matrixTransform if it's not require.
|
||||
_transforms.update();
|
||||
const osg::Matrix& matrix = _transforms.getMatrix();
|
||||
matrixTransform->setMatrix(matrix);
|
||||
}
|
||||
}
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
|
||||
bool UpdateMatrixTransform::link(osgAnimation::Channel* channel)
|
||||
{
|
||||
const std::string& channelName = channel->getName();
|
||||
|
||||
// check if we can link a StackedTransformElement to the current Channel
|
||||
for (StackedTransform::iterator it = _transforms.begin(); it != _transforms.end(); ++it)
|
||||
{
|
||||
StackedTransformElement* element = it->get();
|
||||
if (element && !element->getName().empty() && channelName == element->getName())
|
||||
{
|
||||
Target* target = element->getOrCreateTarget();
|
||||
if (target && channel->setTarget(target))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO) << "UpdateMatrixTransform::link Channel " << channel->getName() << " does not contain a symbolic name that can be linked to a StackedTransformElement." << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,20 +10,23 @@
|
||||
* 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 <osg/Notify>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
|
||||
const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;}
|
||||
// this class manage VertexInfluence database by mesh
|
||||
// reference bones per vertex ...
|
||||
void osgAnimation::VertexInfluenceSet::buildVertex2BoneList()
|
||||
void VertexInfluenceSet::buildVertex2BoneList()
|
||||
{
|
||||
_vertex2Bones.clear();
|
||||
for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); it++)
|
||||
for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it)
|
||||
{
|
||||
const VertexInfluence& vi = (*it);
|
||||
int size = vi.size();
|
||||
@@ -33,13 +36,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) << "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 +51,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
|
||||
{
|
||||
@@ -62,10 +65,10 @@ void osgAnimation::VertexInfluenceSet::buildVertex2BoneList()
|
||||
|
||||
|
||||
// sort by name and weight
|
||||
struct SortByNameAndWeight : public std::less<osgAnimation::VertexInfluenceSet::BoneWeight>
|
||||
struct SortByNameAndWeight : public std::less<VertexInfluenceSet::BoneWeight>
|
||||
{
|
||||
bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeight& b0,
|
||||
const osgAnimation::VertexInfluenceSet::BoneWeight& b1) const
|
||||
bool operator()(const VertexInfluenceSet::BoneWeight& b0,
|
||||
const VertexInfluenceSet::BoneWeight& b1) const
|
||||
{
|
||||
if (b0.getBoneName() < b1.getBoneName())
|
||||
return true;
|
||||
@@ -77,10 +80,10 @@ struct SortByNameAndWeight : public std::less<osgAnimation::VertexInfluenceSet::
|
||||
}
|
||||
};
|
||||
|
||||
struct SortByBoneWeightList : public std::less<osgAnimation::VertexInfluenceSet::BoneWeightList>
|
||||
struct SortByBoneWeightList : public std::less<VertexInfluenceSet::BoneWeightList>
|
||||
{
|
||||
bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeightList& b0,
|
||||
const osgAnimation::VertexInfluenceSet::BoneWeightList& b1) const
|
||||
bool operator()(const VertexInfluenceSet::BoneWeightList& b0,
|
||||
const VertexInfluenceSet::BoneWeightList& b1) const
|
||||
{
|
||||
if (b0.size() < b1.size())
|
||||
return true;
|
||||
@@ -100,14 +103,20 @@ struct SortByBoneWeightList : public std::less<osgAnimation::VertexInfluenceSet:
|
||||
}
|
||||
};
|
||||
|
||||
void osgAnimation::VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
|
||||
void VertexInfluenceSet::clear()
|
||||
{
|
||||
_bone2Vertexes.clear();
|
||||
_uniqVertexSetToBoneSet.clear();
|
||||
}
|
||||
|
||||
void VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
|
||||
{
|
||||
_uniqVertexSetToBoneSet.clear();
|
||||
|
||||
typedef std::map<BoneWeightList,UniqVertexSetToBoneSet, SortByBoneWeightList> UnifyBoneGroup;
|
||||
UnifyBoneGroup unifyBuffer;
|
||||
|
||||
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 vertexIndex = it->first;
|
||||
@@ -123,8 +132,9 @@ void osgAnimation::VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
|
||||
}
|
||||
|
||||
_uniqVertexSetToBoneSet.reserve(unifyBuffer.size());
|
||||
for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); it++)
|
||||
for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it)
|
||||
{
|
||||
_uniqVertexSetToBoneSet.push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
SET(TARGET_SRC
|
||||
ReaderWriter.cpp
|
||||
)
|
||||
FILE(GLOB TARGET_SRC *.cpp)
|
||||
FILE(GLOB TARGET_H *.h)
|
||||
|
||||
|
||||
SET(TARGET_ADDED_LIBRARIES osgAnimation )
|
||||
#### end var setup ###
|
||||
SETUP_PLUGIN(osganimation)
|
||||
|
||||
|
||||
|
||||
51
src/osgPlugins/osgAnimation/Matrix.cpp
Normal file
51
src/osgPlugins/osgAnimation/Matrix.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "Matrix.h"
|
||||
|
||||
|
||||
bool readMatrix(osg::Matrix& matrix, osgDB::Input& fr, const char* keyword)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
if (fr[0].matchWord(keyword) && fr[1].isOpenBracket())
|
||||
{
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
|
||||
fr += 2;
|
||||
|
||||
int row=0;
|
||||
int col=0;
|
||||
double v;
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
|
||||
{
|
||||
if (fr[0].getFloat(v))
|
||||
{
|
||||
matrix(row,col)=v;
|
||||
++col;
|
||||
if (col>=4)
|
||||
{
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
else fr.advanceOverCurrentFieldOrBlock();
|
||||
}
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
|
||||
bool writeMatrix(const osg::Matrix& matrix, osgDB::Output& fw, const char* keyword)
|
||||
{
|
||||
fw.indent() << keyword <<" {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.indent() << matrix(0,0) << " " << matrix(0,1) << " " << matrix(0,2) << " " << matrix(0,3) << std::endl;
|
||||
fw.indent() << matrix(1,0) << " " << matrix(1,1) << " " << matrix(1,2) << " " << matrix(1,3) << std::endl;
|
||||
fw.indent() << matrix(2,0) << " " << matrix(2,1) << " " << matrix(2,2) << " " << matrix(2,3) << std::endl;
|
||||
fw.indent() << matrix(3,0) << " " << matrix(3,1) << " " << matrix(3,2) << " " << matrix(3,3) << std::endl;
|
||||
fw.moveOut();
|
||||
fw.indent() << "}"<< std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
13
src/osgPlugins/osgAnimation/Matrix.h
Normal file
13
src/osgPlugins/osgAnimation/Matrix.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef DOTOSG_MATRIX
|
||||
#define DOTOSG_MATRIX
|
||||
|
||||
#include <osg/Matrix>
|
||||
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
extern bool readMatrix(osg::Matrix& matrix, osgDB::Input& fr, const char* keyword="Matrix");
|
||||
|
||||
extern bool writeMatrix(const osg::Matrix& matrix, osgDB::Output& fw, const char* keyword="Matrix");
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -10,23 +10,30 @@
|
||||
* 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 <osg/io_utils>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/BasicAnimationManager>
|
||||
#include <osgAnimation/TimelineAnimationManager>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/UpdateCallback>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
#include <osgAnimation/StackedTransform>
|
||||
#include <osgAnimation/StackedTranslateElement>
|
||||
#include <osgAnimation/StackedRotateAxisElement>
|
||||
#include <osgAnimation/StackedMatrixElement>
|
||||
#include <osgAnimation/StackedScaleElement>
|
||||
#include "Matrix.h"
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
@@ -41,7 +48,7 @@ bool Bone_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
osg::Quat att;
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr.matchSequence("bindQuaternion %f %f %f %f"))
|
||||
if (fr.matchSequence("bindQuaternion %f %f %f %f"))
|
||||
{
|
||||
fr[1].getFloat(att[0]);
|
||||
fr[2].getFloat(att[1]);
|
||||
@@ -50,10 +57,11 @@ bool Bone_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
fr += 5;
|
||||
iteratorAdvanced = true;
|
||||
osg::notify(osg::WARN) << "Old osgAnimation file format update your data file" << std::endl;
|
||||
}
|
||||
|
||||
osg::Vec3d pos(0,0,0);
|
||||
if (fr.matchSequence("bindPosition %f %f %f"))
|
||||
if (fr.matchSequence("bindPosition %f %f %f"))
|
||||
{
|
||||
fr[1].getFloat(pos[0]);
|
||||
fr[2].getFloat(pos[1]);
|
||||
@@ -61,10 +69,11 @@ bool Bone_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
fr += 4;
|
||||
iteratorAdvanced = true;
|
||||
osg::notify(osg::WARN) << "Old osgAnimation file format update your data file" << std::endl;
|
||||
}
|
||||
|
||||
osg::Vec3d scale(1,1,1);
|
||||
if (fr.matchSequence("bindScale %f %f %f"))
|
||||
if (fr.matchSequence("bindScale %f %f %f"))
|
||||
{
|
||||
fr[1].getFloat(scale[0]);
|
||||
fr[2].getFloat(scale[1]);
|
||||
@@ -72,31 +81,45 @@ bool Bone_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
fr += 4;
|
||||
iteratorAdvanced = true;
|
||||
osg::notify(osg::WARN) << "Old osgAnimation file format update your data file" << std::endl;
|
||||
}
|
||||
|
||||
bone.setBindMatrixInBoneSpace( osg::Matrix(att) * osg::Matrix::translate(pos));
|
||||
if (fr.matchSequence("InvBindMatrixInSkeletonSpace {"))
|
||||
{
|
||||
Matrix matrix;
|
||||
if (readMatrix(matrix,fr, "InvBindMatrixInSkeletonSpace"))
|
||||
{
|
||||
bone.setInvBindMatrixInSkeletonSpace(matrix);
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr.matchSequence("MatrixInSkeletonSpace {"))
|
||||
{
|
||||
Matrix matrix;
|
||||
if (readMatrix(matrix,fr, "MatrixInSkeletonSpace"))
|
||||
{
|
||||
bone.setMatrixInSkeletonSpace(matrix);
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool Bone_writeLocalData(const Object& obj, Output& fw)
|
||||
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;
|
||||
bool res1 = writeMatrix(bone.getInvBindMatrixInSkeletonSpace(), fw, "InvBindMatrixInSkeletonSpace");
|
||||
// write this field for debug only
|
||||
// because it's recompute at each update
|
||||
bool res2 = writeMatrix(bone.getMatrixInSkeletonSpace(), fw, "MatrixInSkeletonSpace");
|
||||
return (res1 || res2);
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_atkBoneProxy
|
||||
RegisterDotOsgWrapperProxy g_BoneProxy
|
||||
(
|
||||
new osgAnimation::Bone,
|
||||
"osgAnimation::Bone",
|
||||
"Object Node Transform osgAnimation::Bone Group",
|
||||
"Object Node MatrixTransform osgAnimation::Bone Group",
|
||||
&Bone_readLocalData,
|
||||
&Bone_writeLocalData
|
||||
);
|
||||
@@ -111,23 +134,94 @@ bool Skeleton_writeLocalData(const Object& obj, Output& fr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
RegisterDotOsgWrapperProxy g_atkRootSkeletonProxy
|
||||
RegisterDotOsgWrapperProxy g_SkeletonProxy
|
||||
(
|
||||
new osgAnimation::Skeleton,
|
||||
"osgAnimation::Skeleton",
|
||||
"Object Node Transform osgAnimation::Bone osgAnimation::Skeleton Group",
|
||||
"Object Node MatrixTransform osgAnimation::Skeleton Group",
|
||||
&Skeleton_readLocalData,
|
||||
&Skeleton_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
// Helper method for reading channels
|
||||
bool Animation_readChannel(osgAnimation::Channel* pChannel, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
std::string name = "unknown";
|
||||
if (fr.matchSequence("name %s"))
|
||||
{
|
||||
if (fr[1].getStr())
|
||||
name = fr[1].getStr();
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
pChannel->setName(name);
|
||||
|
||||
std::string target = "unknown";
|
||||
if (fr.matchSequence("target %s"))
|
||||
{
|
||||
if (fr[1].getStr())
|
||||
target = fr[1].getStr();
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
pChannel->setTargetName(target);
|
||||
|
||||
// we dont need this info
|
||||
float weight = 1.0;
|
||||
if (fr.matchSequence("weight %f"))
|
||||
{
|
||||
fr[1].getFloat(weight);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
// pChannel->setWeight(weight);
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool Animation_readLocalData(Object& obj, Input& fr)
|
||||
bool Animation_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::Animation& anim = dynamic_cast<osgAnimation::Animation&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
if (fr.matchSequence("playmode %w"))
|
||||
{
|
||||
if (fr[1].matchWord("ONCE")) anim.setPlaymode(osgAnimation::Animation::ONCE);
|
||||
else if (fr[1].matchWord("STAY")) anim.setPlaymode(osgAnimation::Animation::STAY);
|
||||
else if (fr[1].matchWord("LOOP")) anim.setPlaymode(osgAnimation::Animation::LOOP);
|
||||
else if (fr[1].matchWord("PPONG")) anim.setPlaymode(osgAnimation::Animation::PPONG);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
if (fr.matchSequence("weight %f"))
|
||||
{
|
||||
float weight;
|
||||
fr[1].getFloat(weight);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
anim.setWeight(weight);
|
||||
}
|
||||
|
||||
if (fr.matchSequence("duration %f"))
|
||||
{
|
||||
float duration;
|
||||
fr[1].getFloat(duration);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
anim.setDuration(duration);
|
||||
}
|
||||
|
||||
if (fr.matchSequence("starttime %f"))
|
||||
{
|
||||
float starttime;
|
||||
fr[1].getFloat(starttime);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
anim.setStartTime(starttime);
|
||||
}
|
||||
|
||||
int nbChannels = 0;
|
||||
if (fr.matchSequence("num_channels %i"))
|
||||
{
|
||||
@@ -138,30 +232,267 @@ bool Animation_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
for (int i = 0; i < nbChannels; i++)
|
||||
{
|
||||
if (fr.matchSequence("Channel {"))
|
||||
if (fr.matchSequence("DoubleLinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::DoubleLinearChannel* channel = new osgAnimation::DoubleLinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
double v;
|
||||
float time;
|
||||
if (fr.matchSequence("key %f %f"))
|
||||
{
|
||||
fr[1].getFloat(time);
|
||||
fr[2].getFloat(v);
|
||||
fr += 3;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::DoubleKeyframe(time, v));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
else if (fr.matchSequence("FloatLinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::FloatLinearChannel* channel = new osgAnimation::FloatLinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
float v;
|
||||
float time;
|
||||
if (fr.matchSequence("key %f %f"))
|
||||
{
|
||||
fr[1].getFloat(time);
|
||||
fr[2].getFloat(v);
|
||||
fr += 3;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(time, v));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
else if (fr.matchSequence("Vec2LinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::Vec2LinearChannel* channel = new osgAnimation::Vec2LinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
osg::Vec2 v;
|
||||
float time;
|
||||
if (fr.matchSequence("key %f %f %f"))
|
||||
{
|
||||
fr[1].getFloat(time);
|
||||
fr[2].getFloat(v[0]);
|
||||
fr[3].getFloat(v[1]);
|
||||
fr += 4;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec2Keyframe(time, v));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
else if (fr.matchSequence("Vec3LinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::Vec3LinearChannel* channel = new osgAnimation::Vec3LinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
osg::Vec3 v;
|
||||
float time;
|
||||
if (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;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(time, v));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
else if (fr.matchSequence("Vec4LinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::Vec4LinearChannel* channel = new osgAnimation::Vec4LinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
osg::Vec4 v;
|
||||
float time;
|
||||
if (fr.matchSequence("key %f %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].getFloat(v[3]);
|
||||
fr += 6;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec4Keyframe(time, v));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
else if (fr.matchSequence("QuatSphericalLinearChannel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
osgAnimation::QuatSphericalLinearChannel* channel = new osgAnimation::QuatSphericalLinearChannel;
|
||||
|
||||
if (Animation_readChannel(channel, fr))
|
||||
iteratorAdvanced = true;
|
||||
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %i {"))
|
||||
{
|
||||
fr[1].getInt(nbKeys);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
for (int k = 0; k < nbKeys; k++)
|
||||
{
|
||||
osg::Quat q;
|
||||
float time;
|
||||
if (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;
|
||||
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::QuatKeyframe(time, q));
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
anim.addChannel(channel);
|
||||
|
||||
if (fr.matchSequence("}")) // keyframes
|
||||
fr += 1;
|
||||
}
|
||||
if (fr.matchSequence("}")) // channel
|
||||
fr += 1;
|
||||
}
|
||||
// Deprecated
|
||||
// Reading of old channel info
|
||||
// Kept here for easy conversion of old .osg data to new format
|
||||
else if (fr.matchSequence("Channel {"))
|
||||
{
|
||||
fr += 2;
|
||||
|
||||
std::string name = "unknown";
|
||||
if (fr.matchSequence("name %s"))
|
||||
{
|
||||
name = fr[1].getStr();
|
||||
if (fr[1].getStr())
|
||||
name = fr[1].getStr();
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
std::string target = "unknown";
|
||||
if (fr.matchSequence("target %s"))
|
||||
{
|
||||
target = fr[1].getStr();
|
||||
if (fr[1].getStr())
|
||||
target = fr[1].getStr();
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
std::string type;
|
||||
std::string type = "unknown";
|
||||
int nbKeys;
|
||||
if (fr.matchSequence("Keyframes %s %i {"))
|
||||
{
|
||||
type = fr[1].getStr();
|
||||
if (fr[1].getStr())
|
||||
type = fr[1].getStr();
|
||||
fr[2].getInt(nbKeys);
|
||||
fr += 4;
|
||||
iteratorAdvanced = true;
|
||||
@@ -175,11 +506,11 @@ bool Animation_readLocalData(Object& obj, Input& fr)
|
||||
}
|
||||
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++)
|
||||
@@ -229,60 +560,130 @@ bool Animation_readLocalData(Object& obj, Input& fr)
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
// Helper method for writing channels
|
||||
template <typename ChannelType, typename ContainerType>
|
||||
void Animation_writeChannel(const std::string& channelString, ChannelType* pChannel, Output& fw)
|
||||
{
|
||||
fw.indent() << channelString.c_str() << " {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.indent() << "name \"" << pChannel->getName() << "\"" << std::endl;
|
||||
fw.indent() << "target \"" << pChannel->getTargetName() << "\"" << std::endl;
|
||||
|
||||
// fw.indent() << "weight " << pChannel->getWeight() << std::endl;
|
||||
|
||||
ContainerType* kfc = pChannel->getSamplerTyped()->getKeyframeContainerTyped();
|
||||
if (kfc)
|
||||
{
|
||||
fw.indent() << "Keyframes " << kfc->size() << " {" << std::endl;
|
||||
fw.moveIn();
|
||||
for (unsigned int k = 0; k < kfc->size(); k++)
|
||||
{
|
||||
fw.indent() << "key " << (*kfc)[k].getTime() << " " << (*kfc)[k].getValue() << std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool Animation_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::Animation& anim = dynamic_cast<const osgAnimation::Animation&>(obj);
|
||||
|
||||
switch (anim.getPlayMode())
|
||||
{
|
||||
case osgAnimation::Animation::ONCE:
|
||||
fw.indent() << "playmode ONCE" << std::endl;
|
||||
break;
|
||||
case osgAnimation::Animation::STAY:
|
||||
fw.indent() << "playmode STAY" << std::endl;
|
||||
break;
|
||||
case osgAnimation::Animation::LOOP:
|
||||
fw.indent() << "playmode LOOP" << std::endl;
|
||||
break;
|
||||
case osgAnimation::Animation::PPONG:
|
||||
fw.indent() << "playmode PPONG" << std::endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fw.indent() << "weight " << anim.getWeight() << std::endl;
|
||||
fw.indent() << "duration " << anim.getDuration() << std::endl;
|
||||
fw.indent() << "starttime " << anim.getStartTime() << std::endl;
|
||||
|
||||
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;
|
||||
osgAnimation::Channel* pChannel = anim.getChannels()[i].get();
|
||||
|
||||
std::string type = "unknown";
|
||||
if (anim.getChannels()[i]->getName() == std::string("quaternion"))
|
||||
osgAnimation::DoubleLinearChannel* pDlc = dynamic_cast<osgAnimation::DoubleLinearChannel*>(pChannel);
|
||||
if (pDlc)
|
||||
{
|
||||
type = "Quat";
|
||||
Animation_writeChannel<osgAnimation::DoubleLinearChannel, osgAnimation::DoubleKeyframeContainer>("DoubleLinearChannel", pDlc, fw);
|
||||
continue;
|
||||
}
|
||||
else if (anim.getChannels()[i]->getName() == std::string("rotation"))
|
||||
osgAnimation::FloatLinearChannel* pFlc = dynamic_cast<osgAnimation::FloatLinearChannel*>(pChannel);
|
||||
if (pFlc)
|
||||
{
|
||||
type = "Quat";
|
||||
Animation_writeChannel<osgAnimation::FloatLinearChannel, osgAnimation::FloatKeyframeContainer>("FloatLinearChannel", pFlc, fw);
|
||||
continue;
|
||||
}
|
||||
else if (anim.getChannels()[i]->getName() == std::string("euler"))
|
||||
osgAnimation::Vec2LinearChannel* pV2lc = dynamic_cast<osgAnimation::Vec2LinearChannel*>(pChannel);
|
||||
if (pV2lc)
|
||||
{
|
||||
type = "Vec3";
|
||||
Animation_writeChannel<osgAnimation::Vec2LinearChannel, osgAnimation::Vec2KeyframeContainer>("Vec2LinearChannel", pV2lc, fw);
|
||||
continue;
|
||||
}
|
||||
else if (anim.getChannels()[i]->getName() == std::string("scale"))
|
||||
osgAnimation::Vec3LinearChannel* pV3lc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(pChannel);
|
||||
if (pV3lc)
|
||||
{
|
||||
type = "Vec3";
|
||||
Animation_writeChannel<osgAnimation::Vec3LinearChannel, osgAnimation::Vec3KeyframeContainer>("Vec3LinearChannel", pV3lc, fw);
|
||||
continue;
|
||||
}
|
||||
else if (anim.getChannels()[i]->getName() == std::string("position"))
|
||||
osgAnimation::Vec4LinearChannel* pV4lc = dynamic_cast<osgAnimation::Vec4LinearChannel*>(pChannel);
|
||||
if (pV4lc)
|
||||
{
|
||||
type = "Vec3";
|
||||
Animation_writeChannel<osgAnimation::Vec4LinearChannel, osgAnimation::Vec4KeyframeContainer>("Vec4LinearChannel", pV4lc, fw);
|
||||
continue;
|
||||
}
|
||||
|
||||
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++)
|
||||
osgAnimation::QuatSphericalLinearChannel* pQslc = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(pChannel);
|
||||
if (pQslc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
Animation_writeChannel<osgAnimation::QuatSphericalLinearChannel, osgAnimation::QuatKeyframeContainer>("QuatSphericalLinearChannel", pQslc, fw);
|
||||
continue;
|
||||
}
|
||||
osgAnimation::FloatCubicBezierChannel* pFcbc = dynamic_cast<osgAnimation::FloatCubicBezierChannel*>(pChannel);
|
||||
if (pFcbc)
|
||||
{
|
||||
Animation_writeChannel<osgAnimation::FloatCubicBezierChannel, osgAnimation::FloatCubicBezierKeyframeContainer>("FloatCubicBezierChannel", pFcbc, fw);
|
||||
continue;
|
||||
}
|
||||
osgAnimation::DoubleCubicBezierChannel* pDcbc = dynamic_cast<osgAnimation::DoubleCubicBezierChannel*>(pChannel);
|
||||
if (pDcbc)
|
||||
{
|
||||
Animation_writeChannel<osgAnimation::DoubleCubicBezierChannel, osgAnimation::DoubleCubicBezierKeyframeContainer>("DoubleCubicBezierChannel", pDcbc, fw);
|
||||
continue;
|
||||
}
|
||||
osgAnimation::Vec2CubicBezierChannel* pV2cbc = dynamic_cast<osgAnimation::Vec2CubicBezierChannel*>(pChannel);
|
||||
if (pV2cbc)
|
||||
{
|
||||
Animation_writeChannel<osgAnimation::Vec2CubicBezierChannel, osgAnimation::Vec2CubicBezierKeyframeContainer>("Vec2CubicBezierChannel", pV2cbc, fw);
|
||||
continue;
|
||||
}
|
||||
osgAnimation::Vec3CubicBezierChannel* pV3cbc = dynamic_cast<osgAnimation::Vec3CubicBezierChannel*>(pChannel);
|
||||
if (pV3cbc)
|
||||
{
|
||||
Animation_writeChannel<osgAnimation::Vec3CubicBezierChannel, osgAnimation::Vec3CubicBezierKeyframeContainer>("Vec3CubicBezierChannel", pV3cbc, fw);
|
||||
continue;
|
||||
}
|
||||
osgAnimation::Vec4CubicBezierChannel* pV4cbc = dynamic_cast<osgAnimation::Vec4CubicBezierChannel*>(pChannel);
|
||||
if (pV4cbc)
|
||||
{
|
||||
Animation_writeChannel<osgAnimation::Vec4CubicBezierChannel, osgAnimation::Vec4CubicBezierKeyframeContainer>("Vec4CubicBezierChannel", pV4cbc, fw);
|
||||
continue;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -344,7 +745,7 @@ bool AnimationManagerBase_writeLocalData(const osgAnimation::AnimationManagerBas
|
||||
const osgAnimation::AnimationList& animList = manager.getAnimationList();
|
||||
|
||||
fw.indent() << "num_animations " << animList.size() << std::endl;
|
||||
for (osgAnimation::AnimationList::const_iterator it = animList.begin(); it != animList.end(); it++)
|
||||
for (osgAnimation::AnimationList::const_iterator it = animList.begin(); it != animList.end(); ++it)
|
||||
{
|
||||
if (!fw.writeObject(**it))
|
||||
osg::notify(osg::WARN)<<"Warning: can't write an animation object"<< std::endl;
|
||||
@@ -437,6 +838,13 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr)
|
||||
if (!vmap->empty())
|
||||
geom.setInfluenceMap(vmap.get());
|
||||
|
||||
if (fr.matchSequence("Geometry {"))
|
||||
{
|
||||
osg::Geometry* source = dynamic_cast<osg::Geometry*>(fr.readObject());
|
||||
geom.setSourceGeometry(source);
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
@@ -448,7 +856,7 @@ bool RigGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
return true;
|
||||
fw.indent() << "num_influences " << vm->size() << std::endl;
|
||||
fw.moveIn();
|
||||
for (osgAnimation::VertexInfluenceMap::const_iterator it = vm->begin(); it != vm->end(); it++)
|
||||
for (osgAnimation::VertexInfluenceMap::const_iterator it = vm->begin(); it != vm->end(); ++it)
|
||||
{
|
||||
std::string name = it->first;
|
||||
if (name.empty())
|
||||
@@ -464,6 +872,8 @@ bool RigGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
|
||||
fw.writeObject(*geom.getSourceGeometry());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -471,15 +881,135 @@ RegisterDotOsgWrapperProxy g_atkRigGeometryProxy
|
||||
(
|
||||
new osgAnimation::RigGeometry,
|
||||
"osgAnimation::RigGeometry",
|
||||
"Object Drawable osgAnimation::RigGeometry Geometry",
|
||||
"Object osgAnimation::RigGeometry Drawable Geometry",
|
||||
&RigGeometry_readLocalData,
|
||||
&RigGeometry_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
bool MorphGeometry_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::MorphGeometry& geom = dynamic_cast<osgAnimation::MorphGeometry&>(obj);
|
||||
|
||||
bool UpdateBone_readLocalData(Object& obj, Input& fr)
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
if (fr[0].matchWord("method"))
|
||||
{
|
||||
if (fr[1].matchWord("NORMALIZED"))
|
||||
{
|
||||
geom.setMethod(osgAnimation::MorphGeometry::NORMALIZED);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
else if (fr[1].matchWord("RELATIVE"))
|
||||
{
|
||||
geom.setMethod(osgAnimation::MorphGeometry::RELATIVE);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("morphNormals"))
|
||||
{
|
||||
if (fr[1].matchWord("TRUE"))
|
||||
{
|
||||
geom.setMorphNormals(true);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
else if (fr[1].matchWord("FALSE"))
|
||||
{
|
||||
geom.setMorphNormals(false);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
int num_morphTargets = 0;
|
||||
if (fr.matchSequence("num_morphTargets %i"))
|
||||
{
|
||||
fr[1].getInt(num_morphTargets);
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_morphTargets; i++)
|
||||
{
|
||||
if (fr.matchSequence("MorphTarget {"))
|
||||
{
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
fr += 2;
|
||||
iteratorAdvanced = true;
|
||||
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
|
||||
{
|
||||
|
||||
float weight = 1.0;
|
||||
if (fr.matchSequence("weight %f"))
|
||||
{
|
||||
fr[1].getFloat(weight);
|
||||
fr += 2;
|
||||
}
|
||||
osg::Drawable* drawable = NULL;
|
||||
drawable = fr.readDrawable();
|
||||
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
|
||||
if (geometry)
|
||||
geom.addMorphTarget(geometry, weight);
|
||||
}
|
||||
if (fr.matchSequence("}"))
|
||||
fr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool MorphGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::MorphGeometry& geom = dynamic_cast<const osgAnimation::MorphGeometry&>(obj);
|
||||
|
||||
switch(geom.getMethod())
|
||||
{
|
||||
case(osgAnimation::MorphGeometry::NORMALIZED): fw.indent() << "method NORMALIZED"<<std::endl; break;
|
||||
case(osgAnimation::MorphGeometry::RELATIVE): fw.indent() << "method RELATIVE"<<std::endl; break;
|
||||
}
|
||||
|
||||
fw.indent() << "morphNormals ";
|
||||
if (geom.getMorphNormals())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
const osgAnimation::MorphGeometry::MorphTargetList& morphTargets = geom.getMorphTargetList();
|
||||
fw.indent() << "num_morphTargets " << morphTargets.size() << std::endl;
|
||||
for (unsigned int i = 0; i < morphTargets.size(); i++)
|
||||
{
|
||||
fw.indent() << "MorphTarget {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.indent() << "weight " << morphTargets[i].getWeight() <<std::endl;
|
||||
fw.writeObject(*morphTargets[i].getGeometry());
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_osgAnimationMorphGeometryProxy
|
||||
(
|
||||
new osgAnimation::MorphGeometry,
|
||||
"osgAnimation::MorphGeometry",
|
||||
"Object Drawable osgAnimation::MorphGeometry Geometry",
|
||||
&MorphGeometry_readLocalData,
|
||||
&MorphGeometry_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool UpdateBone_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
return iteratorAdvanced;
|
||||
@@ -490,11 +1020,11 @@ bool UpdateBone_writeLocalData(const Object& obj, Output& fw)
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_atkUpdateBoneProxy
|
||||
RegisterDotOsgWrapperProxy g_UpdateBoneProxy
|
||||
(
|
||||
new osgAnimation::Bone::UpdateBone,
|
||||
new osgAnimation::UpdateBone,
|
||||
"osgAnimation::UpdateBone",
|
||||
"Object NodeCallback osgAnimation::UpdateBone",
|
||||
"Object NodeCallback osgAnimation::UpdateMatrixTransform osgAnimation::UpdateBone",
|
||||
&UpdateBone_readLocalData,
|
||||
&UpdateBone_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
@@ -513,7 +1043,7 @@ bool UpdateSkeleton_writeLocalData(const Object& obj, Output& fw)
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_atkUpdateSkeletonProxy
|
||||
RegisterDotOsgWrapperProxy g_UpdateSkeletonProxy
|
||||
(
|
||||
new osgAnimation::Skeleton::UpdateSkeleton,
|
||||
"osgAnimation::UpdateSkeleton",
|
||||
@@ -524,25 +1054,24 @@ RegisterDotOsgWrapperProxy g_atkUpdateSkeletonProxy
|
||||
);
|
||||
|
||||
|
||||
|
||||
bool UpdateTransform_readLocalData(Object& obj, Input& fr)
|
||||
bool UpdateMorph_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool UpdateTransform_writeLocalData(const Object& obj, Output& fw)
|
||||
bool UpdateMorph_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_atkUpdateTransformProxy
|
||||
RegisterDotOsgWrapperProxy g_UpdateMorphProxy
|
||||
(
|
||||
new osgAnimation::UpdateTransform,
|
||||
"osgAnimation::UpdateTransform",
|
||||
"Object NodeCallback osgAnimation::UpdateTransform",
|
||||
&UpdateTransform_readLocalData,
|
||||
&UpdateTransform_writeLocalData,
|
||||
new osgAnimation::UpdateMorph,
|
||||
"osgAnimation::UpdateMorph",
|
||||
"Object NodeCallback osgAnimation::UpdateMorph",
|
||||
&UpdateMorph_readLocalData,
|
||||
&UpdateMorph_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
228
src/osgPlugins/osgAnimation/StackedTransform.cpp
Normal file
228
src/osgPlugins/osgAnimation/StackedTransform.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/StackedTranslateElement>
|
||||
#include <osgAnimation/StackedMatrixElement>
|
||||
#include <osgAnimation/StackedScaleElement>
|
||||
#include <osgAnimation/StackedRotateAxisElement>
|
||||
#include <osgAnimation/StackedQuaternionElement>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include "Matrix.h"
|
||||
|
||||
using namespace osgDB;
|
||||
using namespace osg;
|
||||
|
||||
bool readStackedTranslateElement(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::StackedTranslateElement& element = dynamic_cast<osgAnimation::StackedTranslateElement&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr.matchSequence("translate %f %f %f"))
|
||||
{
|
||||
++fr;
|
||||
osg::Vec3 translate;
|
||||
fr[0].getFloat(translate.x());
|
||||
fr[1].getFloat(translate.y());
|
||||
fr[2].getFloat(translate.z());
|
||||
element.setTranslate(translate);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool writeStackedTranslateElement(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::StackedTranslateElement& element = dynamic_cast<const osgAnimation::StackedTranslateElement&>(obj);
|
||||
fw.indent() << "translate " << element.getTranslate() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_StackedTranslateElementProxy
|
||||
(
|
||||
new osgAnimation::StackedTranslateElement,
|
||||
"osgAnimation::StackedTranslateElement",
|
||||
"Object osgAnimation::StackedTranslateElement",
|
||||
&readStackedTranslateElement,
|
||||
&writeStackedTranslateElement,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
bool readStackedScaleElement(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::StackedScaleElement& element = dynamic_cast<osgAnimation::StackedScaleElement&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr.matchSequence("scale %f %f %f"))
|
||||
{
|
||||
++fr;
|
||||
osg::Vec3 scale;
|
||||
fr[0].getFloat(scale.x());
|
||||
fr[1].getFloat(scale.y());
|
||||
fr[2].getFloat(scale.z());
|
||||
element.setScale(scale);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool writeStackedScaleElement(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::StackedScaleElement& element = dynamic_cast<const osgAnimation::StackedScaleElement&>(obj);
|
||||
fw.indent() << "scale " << element.getScale() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
RegisterDotOsgWrapperProxy g_StackedScaleElementProxy
|
||||
(
|
||||
new osgAnimation::StackedScaleElement,
|
||||
"osgAnimation::StackedScaleElement",
|
||||
"Object osgAnimation::StackedScaleElement",
|
||||
&readStackedScaleElement,
|
||||
&writeStackedScaleElement,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool readStackedMatrixElement(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::StackedMatrixElement& element = dynamic_cast<osgAnimation::StackedMatrixElement&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr[0].matchWord("Matrix"))
|
||||
{
|
||||
osg::Matrix matrix;
|
||||
matrix.makeIdentity();
|
||||
iteratorAdvanced = readMatrix(matrix, fr);
|
||||
element.setMatrix(matrix);
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool writeStackedMatrixElement(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::StackedMatrixElement& element = dynamic_cast<const osgAnimation::StackedMatrixElement&>(obj);
|
||||
writeMatrix(element.getMatrix(), fw);
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_StackedMatrixElementProxy
|
||||
(
|
||||
new osgAnimation::StackedMatrixElement,
|
||||
"osgAnimation::StackedMatrixElement",
|
||||
"Object osgAnimation::StackedMatrixElement",
|
||||
&readStackedMatrixElement,
|
||||
&writeStackedMatrixElement,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
bool writeStackedRotateAxisElement(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::StackedRotateAxisElement& element = dynamic_cast<const osgAnimation::StackedRotateAxisElement&>(obj);
|
||||
fw.indent() << "axis " << element.getAxis() << std::endl;
|
||||
fw.indent() << "angle " << element.getAngle() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readStackedRotateAxisElement(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::StackedRotateAxisElement& element = dynamic_cast<osgAnimation::StackedRotateAxisElement&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr.matchSequence("axis %f %f %f"))
|
||||
{
|
||||
++fr;
|
||||
osg::Vec3 axis;
|
||||
fr[0].getFloat(axis.x());
|
||||
fr[1].getFloat(axis.y());
|
||||
fr[2].getFloat(axis.z());
|
||||
element.setAxis(axis);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
if (fr.matchSequence("angle %f"))
|
||||
{
|
||||
++fr;
|
||||
double angle = 0;
|
||||
fr[0].getFloat(angle);
|
||||
++fr;
|
||||
element.setAngle(angle);
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_StackedRotateAxisElementProxy
|
||||
(
|
||||
new osgAnimation::StackedRotateAxisElement,
|
||||
"osgAnimation::StackedRotateAxisElement",
|
||||
"Object osgAnimation::StackedRotateAxisElement",
|
||||
&readStackedRotateAxisElement,
|
||||
&writeStackedRotateAxisElement,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool readStackedQuaternionElement(Object& obj, Input& fr)
|
||||
{
|
||||
osgAnimation::StackedQuaternionElement& element = dynamic_cast<osgAnimation::StackedQuaternionElement&>(obj);
|
||||
bool iteratorAdvanced = false;
|
||||
if (fr.matchSequence("quaternion %f %f %f %f"))
|
||||
{
|
||||
++fr;
|
||||
osg::Quat quaternion;
|
||||
fr[0].getFloat(quaternion[0]);
|
||||
fr[1].getFloat(quaternion[1]);
|
||||
fr[2].getFloat(quaternion[2]);
|
||||
fr[3].getFloat(quaternion[3]);
|
||||
element.setQuaternion(quaternion);
|
||||
fr += 4;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool writeStackedQuaternionElement(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::StackedQuaternionElement& element = dynamic_cast<const osgAnimation::StackedQuaternionElement&>(obj);
|
||||
fw.indent() << "quaternion " << element.getQuaternion() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_StackedQuaternionElementProxy
|
||||
(
|
||||
new osgAnimation::StackedQuaternionElement,
|
||||
"osgAnimation::StackedQuaternionElement",
|
||||
"Object osgAnimation::StackedQuaternionElement",
|
||||
&readStackedQuaternionElement,
|
||||
&writeStackedQuaternionElement,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
47
src/osgPlugins/osgAnimation/UpdateMaterial.cpp
Normal file
47
src/osgPlugins/osgAnimation/UpdateMaterial.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/Input>
|
||||
#include <osgDB/Output>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osg/io_utils>
|
||||
#include <osgAnimation/UpdateMaterial>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgDB;
|
||||
|
||||
|
||||
bool UpdateMaterial_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool UpdateMaterial_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterDotOsgWrapperProxy g_UpdateMaterialProxy
|
||||
(
|
||||
new osgAnimation::UpdateMaterial,
|
||||
"osgAnimation::UpdateMaterial",
|
||||
"Object StateAttribute::Callback osgAnimation::UpdateMaterial",
|
||||
&UpdateMaterial_readLocalData,
|
||||
&UpdateMaterial_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
70
src/osgPlugins/osgAnimation/UpdateMatrixTransform.cpp
Normal file
70
src/osgPlugins/osgAnimation/UpdateMatrixTransform.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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/Input>
|
||||
#include <osgDB/Output>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osg/io_utils>
|
||||
#include <osgAnimation/StackedTransformElement>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgDB;
|
||||
|
||||
bool UpdateMatrixTransform_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
osgAnimation::UpdateMatrixTransform& updateCallback = dynamic_cast<osgAnimation::UpdateMatrixTransform&>(obj);
|
||||
osgAnimation::StackedTransform& stackedTransform = updateCallback.getStackedTransforms();
|
||||
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets() == entry && fr.matchSequence("%w {"))
|
||||
{
|
||||
osgAnimation::StackedTransformElement* element = dynamic_cast<osgAnimation::StackedTransformElement*>(fr.readObject());
|
||||
if (element)
|
||||
stackedTransform.push_back(element);
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool UpdateMatrixTransform_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const osgAnimation::UpdateMatrixTransform* uc = dynamic_cast<const osgAnimation::UpdateMatrixTransform*>(&obj);
|
||||
const osgAnimation::StackedTransform& transforms = uc->getStackedTransforms();
|
||||
for (osgAnimation::StackedTransform::const_iterator it = transforms.begin(); it != transforms.end(); ++it)
|
||||
{
|
||||
osgAnimation::StackedTransformElement* element = it->get();
|
||||
if (element)
|
||||
fw.writeObject(*element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
RegisterDotOsgWrapperProxy g_UpdateMatrixTransformProxy
|
||||
(
|
||||
new osgAnimation::UpdateMatrixTransform,
|
||||
"osgAnimation::UpdateMatrixTransform",
|
||||
"Object NodeCallback osgAnimation::UpdateMatrixTransform",
|
||||
&UpdateMatrixTransform_readLocalData,
|
||||
&UpdateMatrixTransform_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user