您的位置:首页 > 其它

OSG 自定义数据类型 关键帧动画

2015-06-08 13:36 169 查看

OSG 自定义数据类型 关键帧动画

转自:/article/1603916.html

/*
1.创建一个AnimManager一般继承于osg::NodeCallback
2.在AnimManager中创建一个采样器sampler(例如Vec3LinearSampler,有各种sammpler)
3. sammpler 配置了各种Interpolator(插值器,如Vec3LinearInterpolator)
4.sampler 中有KeyframeContainer(关键帧容器,如Vec3KeyframeContainer)
5.向keyframeContainer中插入对应的关键帧(如Vec3Keyframe 关键帧中包含时间戳和对应的数据类型(如Vec3));
6.取值 sampler->getValueAt(time t,p1) t 为时间,p1为对应的数据类型如Vec3,当时间超出sampler的结束时间,或取值永远是最后一帧。
7.取出的p1 用到你想用的地方。
*/

#include <iostream>
#include <osg/io_utils>
#include <osg/Geometry>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/MatrixTransform>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgAnimation/Sampler>

class MyNode
{
public:
MyNode(std::string f,float x,float y,float z)
{
id = f;
_v = osg::Vec3(x,y,z);
}
MyNode(){ id = "";}
MyNode( const MyNode&no)
{
id = no.id;
_v = no._v;

}
MyNode & operator = (const MyNode&no)
{
id = no.id;
_v = no._v;

return *this;
}
const  MyNode    operator * (float  v) const //不能返回引用,因为no是临时对象
{
MyNode no;
no.id = id;
no._v = _v*v;
return  no;
}
inline float operator * (const MyNode  rhs) const
{
return  _v*rhs._v;
}

inline MyNode operator + (const MyNode & rhs) const//不能返回引用,因为no是临时对象
{
MyNode no;
no.id = id;
no._v = _v+rhs._v;
return no;
}
std::string id;
osg::Vec3 _v;
};
typedef osgAnimation::TemplateKeyframe<MyNode> MyNodeKeyframe;
typedef osgAnimation::TemplateKeyframeContainer<MyNode> MyNodeKeyframeContainer;
typedef osgAnimation::TemplateLinearInterpolator<MyNode, MyNode> MyNodeLinearInterpolator;
typedef osgAnimation::TemplateSampler<MyNodeLinearInterpolator> MyNodeLinearSampler;

class AnimManager : public osg::NodeCallback
{
public:

AnimManager()
{
_sampler = new MyNodeLinearSampler;
_playing = false;
_lastUpdate = 0;

}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR &&
nv->getFrameStamp() &&
nv->getFrameStamp()->getFrameNumber() != _lastUpdate)
{

_lastUpdate = nv->getFrameStamp()->getFrameNumber();

_currentTime = osg::Timer::instance()->tick();

if (_playing && _sampler.get() && _sampler->getKeyframeContainer())
{
osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
if (transform) {
osg::Vec3 result;
float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
//float duration = _sampler->getEndTime() - _sampler->getStartTime();
//t = fmod(t, duration);//循环

if(t> _sampler->getEndTime())
{
stop();
}

MyNode no;

_sampler->getValueAt(t, no );
result = no._v;

std::cout<<no.id<<"  "<<result.x()<<" "<<result.y()<<"  "<<result.z()<<std::endl;
transform->setMatrix(osg::Matrix::translate(result));
}
}
}

traverse(node,nv);
}

void start() { _startTime = osg::Timer::instance()->tick(); _currentTime = _startTime; _playing = true;}
void stop() { _currentTime = _startTime; _playing = false;}

osg::ref_ptr<MyNodeLinearSampler> _sampler;
osg::Timer_t _startTime;
osg::Timer_t _currentTime;
bool _playing;
unsigned int _lastUpdate;
};
osg::MatrixTransform* setupAnimtkNode(osg::Geode* staticGeode)
{
osg::MatrixTransform* node = new osg::MatrixTransform();

AnimManager* callback = new AnimManager();
MyNodeKeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();

keys->push_back( MyNodeKeyframe(0.0,MyNode("A",1,0,0)));
keys->push_back( MyNodeKeyframe(1.0,MyNode("B",5,0,9)));
keys->push_back( MyNodeKeyframe(2.0,MyNode("C",1,8,0)));
keys->push_back( MyNodeKeyframe(3.0,MyNode("D",1,8,-5)));

callback->start();
node->setUpdateCallback(callback);

osg::Geode* geode = new osg::Geode();
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 2)));

node->addChild(geode);

return node;
}

int main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);

osgGA::TrackballManipulator* tbm = new osgGA::TrackballManipulator();

viewer.setCameraManipulator(tbm);

viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());

osg::Group* root = new osg::Group();
osg::Geode* geode = new osg::Geode();

root->setInitialBound(osg::BoundingSphere(osg::Vec3(10,0,20), 50));
root->addChild(setupAnimtkNode(geode));
root->addChild(geode);

viewer.setSceneData(root);
return viewer.run();
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: