zoukankan      html  css  js  c++  java
  • OSG动画学习

    OSG动画学习

    转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9

     

    学习动画,看了osganimationskinning这个例子,感觉OSG的动画实现的太灵活了.
    一个简单的模型节点变换动画过程如下:

    1.定义一些变换位置
    2.定义动画关键帧,包含了时间,位置,旋转等数据
    这里可以设置受变化作用的节点
    3.给节点设置一个动画管理器,这个动画管理器是继承自Osg::NodeCallback,所以其实是个Callback类.
    4.把定义的关键帧的数据,送给动画管理器
    5.创建一个等待变化的节点
    6.把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
    7.开始动画


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

      1  
      2 /*  -*-c++-*- 
      3 *  Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
      4 *
      5 * This library is open source and may be redistributed and/or modified under  
      6 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
      7 * (at your option) any later version.  The full license is in LICENSE file
      8 * included with this distribution, and on the openscenegraph.org website.
      9 * 
     10 * This library is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13 * OpenSceneGraph Public License for more details.
     14 */
     15 #include <iostream>
     16 #include <osg/Geometry>
     17 #include <osg/MatrixTransform>
     18 #include <osg/Geode>
     19 #include <osgViewer/Viewer>
     20 #include <osgGA/TrackballManipulator>
     21 #include <osgUtil/SmoothingVisitor>
     22 #include <osg/io_utils>
     23 #include <osgAnimation/Bone>
     24 #include <osgAnimation/Skeleton>
     25 #include <osgAnimation/RigGeometry>
     26 #include <osgAnimation/Skinning>
     27 #include <osgAnimation/BasicAnimationManager>
     28 
     29 // 创建的是些辅助的线条,跟随节点的运动
     30 osg::Geode* createAxis()
     31 {
     32     osg::Geode* geode (new osg::Geode());  
     33     osg::Geometry* geometry (new osg::Geometry());
     34     osg::Vec3Array* vertices (new osg::Vec3Array());
     35     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
     36     vertices->push_back (osg::Vec3 ( 1.0, 0.0, 0.0));
     37     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
     38     vertices->push_back (osg::Vec3 ( 0.0, 1.0, 0.0));
     39     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
     40     vertices->push_back (osg::Vec3 ( 0.0, 0.0, 1.0));
     41     geometry->setVertexArray (vertices);
     42     osg::Vec4Array* colors (new osg::Vec4Array());
     43     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
     44     colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
     45     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
     46     colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
     47     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
     48     colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
     49     geometry->setColorArray (colors);
     50     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);    
     51     geometry->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:INES,0,6));
     52     geode->addDrawable( geometry );
     53     return geode;
     54 }
     55 // 创建了一个等待变换的BOX
     56 osgAnimation::RigGeometry* createTesselatedBox(int nsplit, float size)
     57 {
     58     osgAnimation::RigGeometry* geometry = new osgAnimation::RigGeometry;
     59     osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
     60     osg::ref_ptr<osg::Vec3Array> colors (new osg::Vec3Array());
     61     geometry->setVertexArray (vertices.get());
     62     geometry->setColorArray (colors.get());
     63     geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);    
     64   
     65     float step = size / nsplit;
     66     float s = 0.5/4.0;
     67     for (int i = 0; i < nsplit; i++) 
     68     {
     69         float x = -1 + i * step;
     70         std::cout << x << std::endl;
     71         vertices->push_back (osg::Vec3 ( x, s, s));
     72         vertices->push_back (osg::Vec3 ( x, -s, s));
     73         vertices->push_back (osg::Vec3 ( x, -s, -s));
     74         vertices->push_back (osg::Vec3 ( x, s, -s));
     75         osg::Vec3 c (0,0,0);
     76         c[i%3] = 1;
     77         colors->push_back (c);
     78         colors->push_back (c);
     79         colors->push_back (c);
     80         colors->push_back (c);
     81     }
     82     osg::ref_ptr<osg::UIntArray> array = new osg::UIntArray;
     83     for (int i = 0; i < nsplit - 1; i++) 
     84     {
     85         int base = i * 4;
     86         array->push_back(base);
     87         array->push_back(base+1);
     88         array->push_back(base+4);
     89         array->push_back(base+1);
     90         array->push_back(base+5);
     91         array->push_back(base+4);
     92         array->push_back(base+3);
     93         array->push_back(base);
     94         array->push_back(base+4);
     95         array->push_back(base+7);
     96         array->push_back(base+3);
     97         array->push_back(base+4);
     98         array->push_back(base+5);
     99         array->push_back(base+1);
    100         array->push_back(base+2);
    101         array->push_back(base+2);
    102         array->push_back(base+6);
    103         array->push_back(base+5);
    104         array->push_back(base+2);
    105         array->push_back(base+3);
    106         array->push_back(base+7);
    107         array->push_back(base+6);
    108         array->push_back(base+2);
    109         array->push_back(base+7);
    110     }
    111   
    112     geometry->addPrimitiveSet(new osg:rawElementsUInt(osg:rimitiveSet::TRIANGLES, array->size(), &array->front()));
    113     geometry->setUseDisplayList( false );
    114     return geometry;
    115 }
    116 // 把变化节点的顶点数据与给出的变换位置进行映射,此时定义的是这些节点中每个顶点的变化方式
    117 void initVertexMap(osgAnimation::Bone* b0,
    118                    osgAnimation::Bone* b1,
    119                    osgAnimation::Bone* b2,
    120                    osgAnimation::RigGeometry* geom,
    121                    osg::Vec3Array* array)
    122 {
    123     osgAnimation::VertexInfluenceSet vertexesInfluences;
    124     osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap;
    125     (*vim)[b0->getName()].setName(b0->getName());
    126     (*vim)[b1->getName()].setName(b1->getName());
    127     (*vim)[b2->getName()].setName(b2->getName());
    128     for (int i = 0; i < (int)array->size(); i++) 
    129     {
    130         float val = (*array)[0];
    131         std::cout << val << std::endl;
    132         // 把每个顶点的变换分配给变换节点
    133         if (val >= -1 && val <= 0)
    134             (*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
    135         else if ( val > 0 && val <= 1)
    136             (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
    137         else if ( val > 1)
    138             (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1));
    139     }
    140     geom->setInfluenceMap(vim);
    141 }
    142 
    143 int main (int argc, char* argv[])
    144 {
    145     osg::ArgumentParser arguments(&argc, argv);
    146     osgViewer::Viewer viewer(arguments);
    147     viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    148     osg::ref_ptr<osgAnimation::Skeleton> skelroot = new osgAnimation::Skeleton;
    149     skelroot->setDefaultUpdateCallback();
    150     // 定义一些变换位置,这些位置会在关键帧的设置用到
    151     osg::ref_ptr<osgAnimation::Bone> root = new osgAnimation::Bone;
    152     {
    153         root->setBindMatrixInBoneSpace(osg::Matrix::identity());
    154         root->setBindMatrixInBoneSpace(osg::Matrix::translate(-1,0,0));
    155         root->setName("root");
    156         root->setDefaultUpdateCallback();
    157     }
    158     osg::ref_ptr<osgAnimation::Bone> right0 = new osgAnimation::Bone;
    159     right0->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
    160     right0->setName("right0");
    161     right0->setDefaultUpdateCallback("right0");
    162     osg::ref_ptr<osgAnimation::Bone> right1 = new osgAnimation::Bone;
    163     right1->setBindMatrixInBoneSpace(osg::Matrix::translate(1,0,0));
    164     right1->setName("right1");
    165     right1->setDefaultUpdateCallback("right1");
    166     // 定义变换点之间的父子关系,也就是相对变换的关系
    167     root->addChild(right0.get());
    168     right0->addChild(right1.get());
    169     skelroot->addChild(root.get());
    170     osg::Group* scene = new osg::Group;
    171     osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager;
    172     scene->setUpdateCallback(manager.get());
    173 // 关键帧的定义,时间和位置,现在给的是旋转运动方式,更多的变换方式,可以看一下osgAnimation中的数据结构定义
    174     // 定义right0的关键帧,时间和旋转
    175     osgAnimation::Animation* anim = new osgAnimation::Animation;
    176     {
    177         osgAnimation:uatKeyframeContainer* keys0 = new osgAnimation:uatKeyframeContainer;
    178         osg:uat rotate;
    179         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
    180         // osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1))中第一个参数是时间点,单位是秒,第二个参数就是这个时间点,要旋转到的位置,本例中是旋转,也可以换成其它变换方式
    181         keys0->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
    182         keys0->push_back(osgAnimation:uatKeyframe(3,rotate));
    183         keys0->push_back(osgAnimation:uatKeyframe(6,rotate));
    184         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
    185         sampler->setKeyframeContainer(keys0);
    186         // osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right0->getUpdateCallback());
    187         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
    188         channel->setName("quaternion");
    189         channel->setTargetName("right0");
    190         anim->addChannel(channel);
    191     }
    192     // 定义right1的关键帧
    193     {
    194         osgAnimation:uatKeyframeContainer* keys1 = new osgAnimation:uatKeyframeContainer;
    195         osg:uat rotate;
    196         rotate.makeRotate(osg:I_2, osg::Vec3(0,0,1));
    197         keys1->push_back(osgAnimation:uatKeyframe(0,osg:uat(0,0,0,1)));
    198         keys1->push_back(osgAnimation:uatKeyframe(3,osg:uat(0,0,0,1)));
    199         keys1->push_back(osgAnimation:uatKeyframe(6,rotate));
    200         osgAnimation:uatSphericalLinearSampler* sampler = new osgAnimation:uatSphericalLinearSampler;
    201         sampler->setKeyframeContainer(keys1);
    202         osgAnimation:uatSphericalLinearChannel* channel = new osgAnimation:uatSphericalLinearChannel(sampler);
    203         //osgAnimation::AnimationUpdateCallback* cb = dynamic_cast<osgAnimation::AnimationUpdateCallback*>(right1->getUpdateCallback());
    204         channel->setName("quaternion");
    205         channel->setTargetName("right1");
    206         anim->addChannel(channel);
    207     }
    208 
    209     // 把时间和位置告诉动画管理器
    210     manager->registerAnimation(anim);
    211     manager->buildTargetReference();
    212   
    213     // let's start !   开始动画
    214     manager->playAnimation(anim);
    215     // we will use local data from the skeleton
    216     osg::MatrixTransform* rootTransform = new osg::MatrixTransform;
    217     rootTransform->setMatrix(osg::Matrix::rotate(osg:I_2,osg::Vec3(1,0,0)));
    218     // 把创建的线条指示放到变换节点中,主要是一个指示作用
    219     right0->addChild(createAxis());
    220     // 使节点数据更新完毕后,再进行渲染动作
    221     right0->setDataVariance(osg::Object:YNAMIC);
    222     right1->addChild(createAxis());
    223     right1->setDataVariance(osg::Object:YNAMIC);
    224     // 
    225     osg::MatrixTransform* trueroot = new osg::MatrixTransform;
    226     trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr()));
    227     trueroot->addChild(createAxis());
    228     trueroot->addChild(skelroot.get());
    229     trueroot->setDataVariance(osg::Object:YNAMIC);
    230     // trueroot也是节点,需要加到场景中去,现在是把它设置为rootTransform的一个子节点
    231     rootTransform->addChild(trueroot);
    232     scene->addChild(rootTransform);
    233   
    234     // 现在创建等待变换的盒子
    235     osgAnimation::RigGeometry* geom = createTesselatedBox(4, 4.0);
    236     osg::Geode* geode = new osg::Geode;
    237     geode->addDrawable(geom);
    238     skelroot->addChild(geode);
    239     osg::ref_ptr<osg::Vec3Array> src = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
    240     geom->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
    241     geom->setDataVariance(osg::Object:YNAMIC);
    242     // 给盒子的每个顶点设置变换方式
    243     initVertexMap(root.get(), right0.get(), right1.get(), geom, src.get());
    244     // let's run !
    245     viewer.setSceneData( scene );
    246     viewer.realize();
    247     // 开始运行了
    248     while (!viewer.done())
    249     {
    250         viewer.frame();
    251     }
    252     return 0;
    253 }
    View Code

     

     

  • 相关阅读:
    .NET Core命令行
    1 Android Studio项目目录结构简介
    Ubuntu 16.04 安装 python3.8
    LINUX环境搭建流程
    linux基础命令
    FPGA入门总结
    快速失败和安全失败
    删除64位ODBC数据源DNS
    记录常用的adb命令
    解决adb:error: unknown host service
  • 原文地址:https://www.cnblogs.com/flylong0204/p/4560703.html
Copyright © 2011-2022 走看看