zoukankan      html  css  js  c++  java
  • osgAnimation例子的注释的注释

    osgAnimation例子的注释的注释

    转自:http://www.cnblogs.com/sunliming/archive/2011/12/12/2284995.html

      1 #include <osg/Notify>
      2 #include <osg/MatrixTransform>
      3 #include <osg/PositionAttitudeTransform>
      4 #include <osg/Geometry>
      5 #include <osg/Geode>
      6 
      7 #include <osgUtil/Optimizer>
      8 
      9 #include <osgDB/Registry>
     10 #include <osgDB/ReadFile>
     11 
     12 #include <osgGA/TrackballManipulator>
     13 #include <osgGA/FlightManipulator>
     14 #include <osgGA/DriveManipulator>
     15 
     16 #include <osgSim/OverlayNode>
     17 
     18 #include <osgViewer/Viewer>
     19 #include <iostream>
     20 
     21 // 创建动画路径,参数有中心点,半径,以及循环时间
     22 osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
     23 {
     24     // 实例化动画路径类
     25     // set up the animation path
     26     osg::AnimationPath* animationPath = new osg::AnimationPath;
     27     // 设置动画路径的播放模式,当前使用循环模式(SWING LOOP NO_LOOPING )SWING就是在一个区间内顺逆方向循环,LOOP是顺一个方向循环
     28     animationPath->setLoopMode(osg::AnimationPath::LOOP);
     29    
     30 
     31     // 分40个阶段 这个意思就是分为四十个控制点,犹如四十条边的多边形,沿着这个路线飞行
     32     int numSamples = 40;
     33     float yaw = 0.0f;
     34     // 偏航的分量,这是一个角度分量,算出来每一个多边形的边对应的角度分量2*PI/(n-1)
     35     float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
     36     // 旋转角度为30度
     37     float roll = osg::inDegrees(30.0f);
     38    
     39     // 时间分量
     40     double time=0.0f;
     41     //平均的两个控制点之间的时间
     42     double time_delta = looptime/(double)numSamples;
     43     // 将时间控制点与位置坐标插入到动画路径中
     44     for(int i=0;i<numSamples;++i)
     45     {
     46         //这儿是计算出来每个多边形的顶点的坐标,(sinx*r,cosx*r,0.0)是相当于中心点的增量
     47         osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
     48         //四元数表示方向,表示在3D空间中的旋转方向**四元数很复杂**这个表示,绕x轴旋转roll,y轴旋转-(yaw+90),z轴0
     49         osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0)));
     50        
     51         //和flash动画类似,控制点有位置和转动角度,这样控制点之间是均匀运动
     52         animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
     53 
     54         //递增yaw和time
     55         yaw += yaw_delta;
     56         time += time_delta;
     57 
     58     }
     59     return animationPath;   
     60 }
     61 
     62 
     63 // 创建底板,中心点位置在center,半径为radius
     64 osg::Node* createBase(const osg::Vec3& center,float radius)
     65 {
     66 
     67     // 一个10x10的底板
     68     int numTilesX = 10;
     69     int numTilesY = 10;
     70    
     71     // 长度与宽度的尺寸
     72     float width = 2*radius;
     73     float height = 2*radius;
     74    
     75     // 计算初始位置与x、y的分量
     76     osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
     77     osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
     78     osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f));
     79    
     80     // 计算每个小格子的顶点坐标并压入数组中
     81     // fill in vertices for grid, note numTilesX+1 * numTilesY+1...
     82     osg::Vec3Array* coords = new osg::Vec3Array;
     83     int iy;
     84     for(iy=0;iy<=numTilesY;++iy)
     85     {
     86         for(int ix=0;ix<=numTilesX;++ix)
     87         {
     88             coords->push_back(v000+dx*(float)ix+dy*(float)iy);
     89         }
     90     }
     91    
     92     // 设置颜色的数组,当前为黑白色两种颜色
     93     //Just two colours - black and white.
     94     osg::Vec4Array* colors = new osg::Vec4Array;
     95     colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
     96     colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
     97     int numColors=colors->size();
     98    
     99     // 设置绘制四边形的顶点索引与每个四边形的颜色
    100     int numIndicesPerRow=numTilesX+1;
    101     osg::UByteArray* coordIndices = new osg::UByteArray; // assumes we are using less than 256 points...
    102     osg::UByteArray* colorIndices = new osg::UByteArray;
    103     for(iy=0;iy<numTilesY;++iy)
    104     {
    105         for(int ix=0;ix<numTilesX;++ix)
    106         {
    107             // four vertices per quad.
    108             coordIndices->push_back(ix    +(iy+1)*numIndicesPerRow);
    109             coordIndices->push_back(ix    +iy*numIndicesPerRow);
    110             coordIndices->push_back((ix+1)+iy*numIndicesPerRow);
    111             coordIndices->push_back((ix+1)+(iy+1)*numIndicesPerRow);
    112            
    113             // one color per quad
    114             colorIndices->push_back((ix+iy)%numColors);
    115         }
    116     }
    117    
    118 
    119     // 设置法线向量
    120     // set up a single normal
    121     osg::Vec3Array* normals = new osg::Vec3Array;
    122     normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
    123    
    124 
    125     // 设置顶点坐标数组
    126     osg::Geometry* geom = new osg::Geometry;
    127     geom->setVertexArray(coords);
    128     geom->setVertexIndices(coordIndices);
    129    
    130     // 设置颜色数组
    131     geom->setColorArray(colors);
    132     geom->setColorIndices(colorIndices);
    133     geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
    134    
    135     // 设置法线数组
    136     geom->setNormalArray(normals);
    137     geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
    138    
    139     // 需要绘制什么形状的图形,当前为四边形
    140     geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size()));
    141    
    142     // 将绘制的的图形添加到osg::Geode中
    143     osg::Geode* geode = new osg::Geode;
    144     geode->addDrawable(geom);
    145    
    146     return geode;
    147 }
    148 
    149 // 创建移动的模型,中心点在center,半径为radius
    150 osg::Node* createMovingModel(const osg::Vec3& center, float radius)
    151 {
    152     float animationLength = 10.0f;
    153 
    154     // 创建动画路径,中心点在center,半径为radius,循环时间为10.0f
    155     osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
    156 
    157     osg::Group* model = new osg::Group;
    158 
    159     // 从外部读取一个模型glider.osg作为飞行的模型
    160     osg::Node* glider = osgDB::readNodeFile("glider.osg");
    161     if (glider)
    162     {
    163         // 根据模型的包围球来计算矩阵
    164         // 平移到原点,缩放模型,然后沿z轴旋转-90度
    165         const osg::BoundingSphere& bs = glider->getBound();
    166 
    167         float size = radius/bs.radius()*0.3f;
    168         osg::MatrixTransform* positioned = new osg::MatrixTransform;
    169         //设置这个值在对象生命周期内为静态的不可改变的数值,或者动态的在对象生命周期内变化的值
    170         positioned->setDataVariance(osg::Object::STATIC);
    171         //设置转移矩阵参数
    172         positioned->setMatrix(osg::Matrix::translate(-bs.center())*         /*表示平移物体,注意osg的坐标系是z轴是向上的*/
    173                                      osg::Matrix::scale(size,size,size)*    /*x,y,z轴的放缩比例*/
    174                                      osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));   /*x,y,z轴的旋转角度*/
    175    
    176         positioned->addChild(glider);
    177    
    178         // 设置动画路径的回调函数,使在渲染循环中不停的沿动画路径移动,设置坐标系变换
    179         osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;   
    180         xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
    181         xform->addChild(positioned);
    182 
    183         model->addChild(xform);
    184     }
    185 
    186     // 从外部读取一个模型cessna.osg
    187     // 操作同上,设置动画路径的回调函数,使在渲染的循环中不停的沿动画路径移动
    188     osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
    189     if (cessna)
    190     {
    191         const osg::BoundingSphere& bs = cessna->getBound();
    192 
    193         float size = radius/bs.radius()*0.3f;
    194         osg::MatrixTransform* positioned = new osg::MatrixTransform;
    195         positioned->setDataVariance(osg::Object::STATIC);
    196         positioned->setMatrix(osg::Matrix::translate(-bs.center())*
    197                                      osg::Matrix::scale(size,size,size)*
    198                                      osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f));
    199    
    200         positioned->addChild(cessna);
    201    
    202         osg::MatrixTransform* xform = new osg::MatrixTransform;
    203         xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
    204         xform->addChild(positioned);
    205 
    206         model->addChild(xform);
    207     }
    208    
    209     return model;
    210 }
    211 
    212 // 创建覆盖图,根据覆盖的实现技术来设置
    213 osg::Node* createModel(bool overlay, osgSim::OverlayNode::OverlayTechnique technique)
    214 {
    215     osg::Vec3 center(0.0f,0.0f,0.0f);
    216     float radius = 100.0f;
    217 
    218     osg::Group* root = new osg::Group;
    219 
    220     // 创建底板与飞行的模型
    221     float baseHeight = center.z()-radius*0.5;
    222     osg::Node* baseModel = createBase(osg::Vec3(center.x(), center.y(), baseHeight),radius);
    223     osg::Node* movingModel = createMovingModel(center,radius*0.8f);
    224 
    225     // 是否设置覆盖图
    226     if (overlay)
    227     {
    228         // 根据命令行传入的参数来设置
    229         osgSim::OverlayNode* overlayNode = new osgSim::OverlayNode(technique);
    230         overlayNode->setContinuousUpdate(true);
    231         // 需要设置的覆盖的图的模型为飞行的模型,当前为从外部加载的模型
    232         overlayNode->setOverlaySubgraph(movingModel);
    233         // 设置覆盖图距离底板的高度
    234         overlayNode->setOverlayBaseHeight(baseHeight-0.01);
    235         overlayNode->addChild(baseModel);
    236         // 将覆盖图的节点加入到根节点中
    237         root->addChild(overlayNode);
    238     }
    239     else
    240     {
    241         // 不设置覆盖图
    242         root->addChild(baseModel);
    243     }
    244    
    245     root->addChild(movingModel);
    246 
    247     return root;
    248 }
    249 
    250 
    251 int main( int argc, char **argv )
    252 {
    253     // 是否使用覆盖模拟
    254     bool overlay = false;
    255     // 使用命令行参数实例化osg::ArgumentParset类,方便以后的操作
    256     osg::ArgumentParser arguments(&argc,argv);
    257     while (arguments.read("--overlay")) overlay = true;
    258    
    259     // 获得覆盖节点采用哪种技术实现,提供三种实现技术
    260     osgSim::OverlayNode::OverlayTechnique technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY;
    261     while (arguments.read("--object")) { technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
    262     while (arguments.read("--ortho") || arguments.read("--orthographic")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
    263     while (arguments.read("--persp") || arguments.read("--perspective")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY; overlay=true; }
    264    
    265 
    266     // initialize the viewer.
    267     osgViewer::Viewer viewer;
    268 
    269     // 创建底板与飞行的物体,飞行物体通过外部读取
    270     // load the nodes from the commandline arguments.
    271     osg::Node* model = createModel(overlay, technique);
    272     if (!model)
    273     {
    274         return 1;
    275     }
    276    
    277     // 创建一个osg::MatrixTransform并设置场景沿x轴旋转30度
    278     // tilt the scene so the default eye position is looking down on the model.
    279     osg::MatrixTransform* rootnode = new osg::MatrixTransform;
    280     rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
    281     rootnode->addChild(model);
    282 
    283     /// 对整个场景进行优化
    284     // run optimization over the scene graph
    285     osgUtil::Optimizer optimzer;
    286     optimzer.optimize(rootnode);
    287     
    288     // 将整个节点设置到场景中进行渲染
    289     // set the scene to render
    290     viewer.setSceneData(rootnode);
    291 
    292     // 设置相机的操作器,当前使用跟踪球的模式进行操作
    293     viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    294 
    295     // viewer.setUpViewOnSingleScreen(1);
    296 
    297     // 提供两中渲染的循环模式
    298     // 第一中采用老式的模式
    299     // 第二中采用封装模式
    300 #if 0
    301 
    302     // use of custom simulation time.
    303    
    304     viewer.realize();
    305    
    306     double simulationTime = 0.0;
    307    
    308     while (!viewer.done())
    309     {
    310         viewer.frame(simulationTime);
    311         simulationTime += 0.001;
    312     }
    313    
    314     return 0;
    315 #else
    316 
    317     // normal viewer usage.
    318     return viewer.run();
    319 
    320 #endif
    321 }
    View Code
  • 相关阅读:
    敏捷开发之Scrum扫盲篇
    select选项框特效
    jquery 实现 点击按钮后倒计时效果,多用于实现发送手机验证码
    如何使用CSS实现小三角形效果
    轻松学习Ionic (四) 修改应用图标及添加启动画面(更新官方命令行工具自动生成)
    轻松学习Ionic (三) 安装sass并在webstorm中为scss添加watcher
    轻松学习Ionic (二) 为Android项目集成Crosswalk(更新官方命令行工具)
    轻松学习Ionic (一) 搭建开发环境,并创建工程
    cmake时选择的VS生成器
    mysql更改密码
  • 原文地址:https://www.cnblogs.com/flylong0204/p/4616242.html
Copyright © 2011-2022 走看看