您的位置:首页 > 其它

osg示例解析之osganimationsolid(1)

2014-03-27 16:55 183 查看

简介

osganimationsolid示例主要使用了osgAnimation中的动画管理器来管理多个动画Animtion,这其中还涉及到一些其他的概念,比如动画中包含了一个或者多个频道Channel,频道设置作用对象setTargetName等等。

创建坐标系

osg::ref_ptr<osg::Geode> createAxis()
{
    osg::ref_ptr<osg::Geode> geode (new osg::Geode());
    osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry());

    //设置三个坐标轴线坐标值
	osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 10.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 10.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 10.0));
    geometry->setVertexArray (vertices.get());

    //设置三个坐标轴线的颜色
	osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
	
    geometry->setColorArray (colors.get(), osg::Array::BIND_PER_VERTEX);
    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,6));
    geode->addDrawable( geometry.get() );
	//关闭光照
    geode->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
    return geode;
}
创建坐标系的代码很简单,设置顶点、颜色数组并以线段(GL_LINES)的方式绘制

创建作用对象

osgAnimation::UpdateMatrixTransform* updatecb = new osgAnimation::UpdateMatrixTransform("AnimatedCallback");
	//设置两个变换平移和旋转
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("osition"));
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("euler",osg::Vec3(1,0,0),0));
 
    trans->setUpdateCallback(updatecb);
创建作用对象,设置它的名称必须与Animation中Channel的名字相对应,也就是设置Channel的setTargetName和UpdateMatrixTransform的名称一致,设置Channel中的Name和UpdateMatrixTransform中数组元素的名称一致,也就是设置Channel的名称为"osition"和"euler",这样才能正确创建执行对象。

创建动画频道

osgAnimation::Vec3LinearChannel* channelAnimation1 = new osgAnimation::Vec3LinearChannel;
    channelAnimation1->setTargetName("AnimatedCallback");
    channelAnimation1->setName("osition");
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(0, osg::Vec3(0,0,0)));
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(2, osg::Vec3(1,1,0)));
    osgAnimation::Animation* anim1 = new osgAnimation::Animation;
    anim1->addChannel(channelAnimation1);
    anim1->setPlayMode(osgAnimation::Animation::PPONG);

    osgAnimation::FloatLinearChannel* channelAnimation2 = new osgAnimation::FloatLinearChannel;
    channelAnimation2->setTargetName("AnimatedCallback");
    channelAnimation2->setName("euler");
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(0, 0));
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(1.5, 2*osg::PI));
    osgAnimation::Animation* anim2 = new osgAnimation::Animation;
    anim2->addChannel(channelAnimation2);
    anim2->setPlayMode(osgAnimation::Animation::LOOP);
动画频道创建它的TargetName设置和作用对象一致,另外它的Name也需要和作用对象数组中元素的名称一致

创建管理器

osg::Group* grp = new osg::Group;
	//BasicAnimationManager必须设置为需要动画子场景(在这个例子中是立方体)的父节点
	//因为BasicAnimationManager会遍历它的子节点并设置子节点中的执行对象Target
    osgAnimation::BasicAnimationManager* mng = new osgAnimation::BasicAnimationManager();
    grp->setUpdateCallback(mng);
    grp->addChild(root);
管理器必须设置为需要动画场景的父节点的UpdateCallback

最后注册动画、播放动画,代码如下:

mng->registerAnimation(anim1);
    mng->registerAnimation(anim2);

    mng->playAnimation(anim1);
    mng->playAnimation(anim2);


思考:我们将创建作用对象的两个元素修改一下位置会怎么样?也就是将源码修改为:

updatecb->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("euler",osg::Vec3(1,0,0),0));
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("osition"));
运行之后发现立方体运行的轨迹完全变换了,这是什么原因呢?从字面意思看StackedTransform,也就是类似于栈一样LIFO(后进先出)的模式,因此如果是例子中先平移后旋转,那么更新矩阵就等于M = Mr(旋转) * Mt(平移),而修改之后就变成先平移之后旋转,M=Mt(平移) * Mr(旋转),矩阵没有交换律,因此计算的结果就大相径庭了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: