OSG 关键帧动画

/*
1.创建一个AnimManager  一般继承于osg::NodeCallback
2.在AnimManager中创建一个采样器sampler(例如Vec3LinearSampler,OSG提供了各种sammpler)
3.sammpler 配置了各种Interpolator(插值器,如Vec3LinearInterpolator)
4.sampler 中有KeyframeContainer(关键帧容器,如Vec3KeyframeContainer)
5.向keyframeContainer中插入对应的关键帧(如Vec3Keyframe 关键帧中包含时间戳和对应的数据类型(如Vec3));
6.取值 sampler->getValueAt(time t,p1) t 为时间,p1为对应的数据类型如Vec3,当传进的时间超出sampler的结束时间,则取值p1永远是最后一帧数据。
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 AnimManager : public osg::NodeCallback
{
public:
	AnimManager()
	{
		_sampler = new osgAnimation::Vec3LinearSampler;
		_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();
					}
					_sampler->getValueAt(t, result);
					std::cout<<"result "<<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<osgAnimation::Vec3LinearSampler> _sampler;
	osg::Timer_t _startTime;
	osg::Timer_t _currentTime;
	bool _playing;
	unsigned int _lastUpdate;
};
osg::MatrixTransform* createAnimtkNode() 
{

	osg::MatrixTransform* node = new osg::MatrixTransform();
	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);


	AnimManager* callback = new AnimManager();
	osgAnimation::Vec3KeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();

	keys->push_back( osgAnimation::Vec3Keyframe(0.0,osg::Vec3(1,0,0)));
	keys->push_back( osgAnimation::Vec3Keyframe(1.0,osg::Vec3(5,0,9)));
	keys->push_back( osgAnimation::Vec3Keyframe(2.0,osg::Vec3(1,8,0)));
	keys->push_back( osgAnimation::Vec3Keyframe(6.0,osg::Vec3(1,8,-5)));

	callback->start();
	node->setUpdateCallback(callback);
	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();
 
	 root->setInitialBound(osg::BoundingSphere(osg::Vec3(10,0,20), 50)); 
	root->addChild(createAnimtkNode());
 
	viewer.setSceneData(root);
	return viewer.run();
}


你可能感兴趣的:(OSG 关键帧动画)