查看: 3790|回复: 3

OSG动画学习

[复制链接]

该用户从未签到

发表于 2010-7-22 09:45:38 | 显示全部楼层 |阅读模式
本帖最后由 fosky 于 2010-7-22 09:52 编辑

学习动画,看了osganimationskinning这个例子,感觉OSG的动画实现的太灵活了.
一个简单的模型节点变换动画过程如下:
1.定义一些变换位置
2.定义动画关键帧,包含了时间,位置,旋转等数据
这里可以设置受变化作用的节点
3.给节点设置一个动画管理器,这个动画管理器是继承自Osg::NodeCallback,所以其实是个Callback类.
4.把定义的关键帧的数据,送给动画管理器
5.创建一个等待变化的节点
6.把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
7.开始动画


好的东西写不出来,只把这个程序的一些理解记录一下.
这个例子来自OSG的代码中的Example->osganimationskinning

  1. /*  -*-c++-*-
  2. *  Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
  3. *
  4. * This library is open source and may be redistributed and/or modified under  
  5. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  6. * (at your option) any later version.  The full license is in LICENSE file
  7. * included with this distribution, and on the openscenegraph.org website.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. * OpenSceneGraph Public License for more details.
  13. */
  14. #include <iostream>
  15. #include <osg/Geometry>
  16. #include <osg/MatrixTransform>
  17. #include <osg/Geode>
  18. #include <osgViewer/Viewer>
  19. #include <osgGA/TrackballManipulator>
  20. #include <osgUtil/SmoothingVisitor>
  21. #include <osg/io_utils>
  22. #include <osgAnimation/Bone>
  23. #include <osgAnimation/Skeleton>
  24. #include <osgAnimation/RigGeometry>
  25. #include <osgAnimation/Skinning>
  26. #include <osgAnimation/BasicAnimationManager>

  27. // 创建的是些辅助的线条,跟随节点的运动
  28. osg::Geode* createAxis()
  29. {
  30.     osg::Geode* geode (new osg::Geode());  
  31.     osg::Geometry* geometry (new osg::Geometry());
  32.     osg::Vec3Array* vertices (new osg::Vec3Array());
  33.     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
  34.     vertices->push_back (osg::Vec3 ( 1.0, 0.0, 0.0));
  35.     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
  36.     vertices->push_back (osg::Vec3 ( 0.0, 1.0, 0.0));
  37.     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
  38.     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 1.0));
  39.     geometry->setVertexArray (vertices);
  40.     osg::Vec4Array* colors (new osg::Vec4Array());
  41.     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
  42.     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
  43.     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
  44.     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
  45.     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
  46.     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
  47.     geometry->setColorArray (colors);
  48.     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);   
  49.     geometry->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:INES,0,6));
  50.     geode->addDrawable( geometry );
  51.     return geode;
  52. }
  53. // 创建了一个等待变换的BOX
  54. osgAnimation::RigGeometry* createTesselatedBox(int nsplit, float size)
  55. {
  56.     osgAnimation::RigGeometry* geometry = new osgAnimation::RigGeometry;
  57.     osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
  58.     osg::ref_ptr<osg::Vec3Array> colors (new osg::Vec3Array());
  59.     geometry->setVertexArray (vertices.get());
  60.     geometry->setColorArray (colors.get());
  61.     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);   
  62.   
  63.     float step = size / nsplit;
  64.     float s = 0.5/4.0;
  65.     for (int i = 0; i < nsplit; i++)
  66.     {
  67.         float x = -1 + i * step;
  68.         std::cout << x << std::endl;
  69.         vertices->push_back (osg::Vec3 ( x, s, s));
  70.         vertices->push_back (osg::Vec3 ( x, -s, s));
  71.         vertices->push_back (osg::Vec3 ( x, -s, -s));
  72.         vertices->push_back (osg::Vec3 ( x, s, -s));
  73.         osg::Vec3 c (0,0,0);
  74.         c[i%3] = 1;
  75.         colors->push_back (c);
  76.         colors->push_back (c);
  77.         colors->push_back (c);
  78.         colors->push_back (c);
  79.     }
  80.     osg::ref_ptr<osg::UIntArray> array = new osg::UIntArray;
  81.     for (int i = 0; i < nsplit - 1; i++)
  82.     {
  83.         int base = i * 4;
  84.         array->push_back(base);
  85.         array->push_back(base+1);
  86.         array->push_back(base+4);
  87.         array->push_back(base+1);
  88.         array->push_back(base+5);
  89.         array->push_back(base+4);
  90.         array->push_back(base+3);
  91.         array->push_back(base);
  92.         array->push_back(base+4);
  93.         array->push_back(base+7);
  94.         array->push_back(base+3);
  95.         array->push_back(base+4);
  96.         array->push_back(base+5);
  97.         array->push_back(base+1);
  98.         array->push_back(base+2);
  99.         array->push_back(base+2);
  100.         array->push_back(base+6);
  101.         array->push_back(base+5);
  102.         array->push_back(base+2);
  103.         array->push_back(base+3);
  104.         array->push_back(base+7);
  105.         array->push_back(base+6);
  106.         array->push_back(base+2);
  107.         array->push_back(base+7);
  108.     }
  109.   
  110.     geometry->addPrimitiveSet(new osg:rawElementsUInt(osg:rimitiveSet::TRIANGLES, array->size(), &array->front()));
  111.     geometry->setUseDisplayList( false );
  112.     return geometry;
  113. }
  114. // 把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
  115. void initVertexMap(osgAnimation::Bone* b0,
  116.                    osgAnimation::Bone* b1,
  117.                    osgAnimation::Bone* b2,
  118.                    osgAnimation::RigGeometry* geom,
  119.                    osg::Vec3Array* array)
  120. {
  121.     osgAnimation::VertexInfluenceSet vertexesInfluences;
  122.     osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap;
  123.     (*vim)[b0->getName()].setName(b0->getName());
  124.     (*vim)[b1->getName()].setName(b1->getName());
  125.     (*vim)[b2->getName()].setName(b2->getName());
  126.     for (int i = 0; i < (int)array->size(); i++)
  127.     {
  128.         float val = (*array)[0];
  129.         std::cout << val << std::endl;
  130.         // 把每个顶点的变换分配给变换节点
  131.         if (val >= -1 && val <= 0)
  132.             (*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
  133.         else if ( val > 0 && val <= 1)
  134.             (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
  135.         else if ( val > 1)
  136.             (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
  137.     }
  138.     geom->setInfluenceMap(vim);
  139. }

  140. int main (int argc, char* argv[])
  141. {
  142.     osg::ArgumentParser arguments(&argc, argv);
  143.     osgViewer::Viewer viewer(arguments);
  144.     viewer.setCameraManipulator(new osgGA::TrackballManipulator());
  145.     osg::ref_ptr<osgAnimation::Skeleton> skelroot = new osgAnimation::Skeleton;
  146.     skelroot->setDefaultUpdateCallback();
  147.     // 定义一些变换位置,这些位置会在关键帧的设置用到
  148.     osg::ref_ptr<osgAnimation::Bone> root = new osgAnimation::Bone;
  149.     {
  150.         root->setBindMatrixInBoneSpace(osg::Matrix::identity());
  151.         root->setBindMatrixInBoneSpace(osg::Matrix::translate(-1,0,0));
  152.         root->setName("root");
  153.         root->setDefaultUpdateCallback();
  154.     }
  155.     osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone;
  156.     right0->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
  157.     right0->setName("right0");
  158.     right0->setDefaultUpdateCallback("right0");
  159.     osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone;
  160.     right1->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
  161.     right1->setName("right1");
  162.     right1->setDefaultUpdateCallback("right1");
  163.     // 定义变换点之间的父子关系,也就是相对变换的关系
  164.     root->addChild(right0.get());
  165.     right0->addChild(right1.get());
  166.     skelroot->addChild(root.get());
  167.     osg::Group* scene = new osg::Group;
  168.     osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager;
  169.     scene->setUpdateCallback(manager.get());
  170. // 关键帧的定义,时间和位置,现在给的是旋转运动方式,更多的变换方式,可以看一下osgAnimation中的数据结构定义
  171.     // 定义right0的关键帧,时间和旋转
  172.     osgAnimation::Animation* anim = new osgAnimation::Animation;
  173.     {
  174.         osgAnimation:uatKeyframeContainer* keys0 = new osgAnimation:uatKeyframeContainer;
  175.         osg:uat rotate;
  176.         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
  177.         // osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))中第一个参数是时间点,单位是秒,第二个参数就是这个时间点,要旋转到的位置,本例中是旋转,也可以换成其它变换方式
  178.         keys0->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
  179.         keys0->push_back(osgAnimation:uatKeyframe(3,rotate));
  180.         keys0->push_back(osgAnimation:uatKeyframe(6,rotate));
  181.         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
  182.         sampler->setKeyframeContainer(keys0);
  183.         // osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right0->getUpdateCallback());
  184.         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
  185.         channel->setName("quaternion");
  186.         channel->setTargetName("right0");
  187.         anim->addChannel(channel);
  188.     }
  189.     // 定义right1的关键帧
  190.     {
  191.         osgAnimation:uatKeyframeContainer* keys1 = new osgAnimation:uatKeyframeContainer;
  192.         osg:uat rotate;
  193.         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
  194.         keys1->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
  195.         keys1->push_back(osgAnimation:uatKeyframe(3,osg:uat(0,0,0,1)));
  196.         keys1->push_back(osgAnimation:uatKeyframe(6,rotate));
  197.         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
  198.         sampler->setKeyframeContainer(keys1);
  199.         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
  200.         //osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right1->getUpdateCallback());
  201.         channel->setName("quaternion");
  202.         channel->setTargetName("right1");
  203.         anim->addChannel(channel);
  204.     }

  205.     // 把时间和位置告诉动画管理器
  206.     manager->registerAnimation(anim);
  207.     manager->buildTargetReference();
  208.   
  209.     // let's start !   开始动画
  210.     manager->playAnimation(anim);
  211.     // we will use local data from the skeleton
  212.     osg::MatrixTransform* rootTransform = new osg::MatrixTransform;
  213.     rootTransform->setMatrix(osg::Matrix::rotate(osg:I_2,osg::Vec3(1,0,0)));
  214.     // 把创建的线条指示放到变换节点中,主要是一个指示作用
  215.     right0->addChild(createAxis());
  216.     // 使节点数据更新完毕后,再进行渲染动作
  217.     right0->setDataVariance(osg::Object:YNAMIC);
  218.     right1->addChild(createAxis());
  219.     right1->setDataVariance(osg::Object:YNAMIC);
  220.     //
  221.     osg::MatrixTransform* trueroot = new osg::MatrixTransform;
  222.     trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr()));
  223.     trueroot->addChild(createAxis());
  224.     trueroot->addChild(skelroot.get());
  225.     trueroot->setDataVariance(osg::Object:YNAMIC);
  226.     // trueroot也是节点,需要加到场景中去,现在是把它设置为rootTransform的一个子节点
  227.     rootTransform->addChild(trueroot);
  228.     scene->addChild(rootTransform);
  229.   
  230.     // 现在创建等待变换的盒子
  231.     osgAnimation::RigGeometry* geom = createTesselatedBox(4, 4.0);
  232.     osg::Geode* geode = new osg::Geode;
  233.     geode->addDrawable(geom);
  234.     skelroot->addChild(geode);
  235.     osg::ref_ptr<osg::Vec3Array> src = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
  236.     geom->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
  237.     geom->setDataVariance(osg::Object:YNAMIC);
  238.     // 给盒子的每个顶点设置变换方式
  239.     initVertexMap(root.get(), right0.get(), right1.get(), geom, src.get());
  240.     // let's run !
  241.     viewer.setSceneData( scene );
  242.     viewer.realize();
  243.     // 开始运行了
  244.     while (!viewer.done())
  245.     {
  246.         viewer.frame();
  247.     }
  248.     return 0;
  249. }


复制代码

该用户从未签到

发表于 2010-7-22 10:37:15 | 显示全部楼层
支持一下

该用户从未签到

发表于 2010-7-22 16:52:03 | 显示全部楼层
支持两下

该用户从未签到

发表于 2010-7-22 20:34:08 | 显示全部楼层
支持支持
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表