• Learning OSG programing---osgAnimation(2)


     1 osg::Node* createBase(const osg::Vec3& center,float radius)
     2 {
     3 
     4 
     5 
     6     int numTilesX = 10;
     7     int numTilesY = 10;
     8 
     9     float width = 2*radius;
    10     float height = 2*radius;
    11 
    12     osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
    13     osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
    14     osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f));
    15 
    16     // fill in vertices for grid, note numTilesX+1 * numTilesY+1...
    17     osg::Vec3Array* coords = new osg::Vec3Array;
    18     int iy;
    19     for(iy=0;iy<=numTilesY;++iy)
    20     {
    21         for(int ix=0;ix<=numTilesX;++ix)
    22         {
    23             coords->push_back(v000+dx*(float)ix+dy*(float)iy);
    24         }
    25     }
    26 
    27     //Just two colours - black and white.
    28     osg::Vec4Array* colors = new osg::Vec4Array;
    29     colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
    30     colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
    31 
    32     osg::ref_ptr<osg::DrawElementsUShort> whitePrimitives = new osg::DrawElementsUShort(GL_QUADS);
    33     osg::ref_ptr<osg::DrawElementsUShort> blackPrimitives = new osg::DrawElementsUShort(GL_QUADS);
    34 
    35     int numIndicesPerRow=numTilesX+1;
    36     for(iy=0;iy<numTilesY;++iy)
    37     {
    38         for(int ix=0;ix<numTilesX;++ix)
    39         {
    40             osg::DrawElementsUShort* primitives = ((iy+ix)%2==0) ? whitePrimitives.get() : blackPrimitives.get();
    41             primitives->push_back(ix    +(iy+1)*numIndicesPerRow);
    42             primitives->push_back(ix    +iy*numIndicesPerRow);
    43             primitives->push_back((ix+1)+iy*numIndicesPerRow);
    44             primitives->push_back((ix+1)+(iy+1)*numIndicesPerRow);
    45         }
    46     }
    47 
    48     // set up a single normal
    49     osg::Vec3Array* normals = new osg::Vec3Array;
    50     normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
    51 
    52     osg::Geometry* geom = new osg::Geometry;
    53     geom->setVertexArray(coords);
    54 
    55     geom->setColorArray(colors, osg::Array::BIND_PER_PRIMITIVE_SET);
    56 
    57     geom->setNormalArray(normals, osg::Array::BIND_OVERALL);
    58 
    59     geom->addPrimitiveSet(whitePrimitives.get());
    60     geom->addPrimitiveSet(blackPrimitives.get());
    61 
    62     osg::Geode* geode = new osg::Geode;
    63     geode->addDrawable(geom);
    64 
    65     return geode;
    66 }

    createBase函数用于建立模型模拟时的地板,作为飞机飞行的参照。

    23行中,循环向变量coords中添加坐标点,作为地板的控制点。

    36-46行中,交替取出白色面元和黑色面元,并向其中每次添加四个顶点(索引值),指示面元的角点坐标(按照索引值从coords数组中取出)。

    随后设置所有面元的法向量,并将黑白面元分别添加进绘制几何节点中,并将绘制几何节点添加到集合节点中,由函数返回。

    接下来分析第三个函数:

     1 osg::Node* createMovingModel(const osg::Vec3& center, float radius)
     2 {
     3     float animationLength = 10.0f;
     4 
     5     osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
     6 
     7     osg::ref_ptr<osg::Group> model = new osg::Group;
     8 
     9     osg::ref_ptr<osg::Node> glider = osgDB::readRefNodeFile("glider.osgt");
    10     if (glider)
    11     {
    12         const osg::BoundingSphere& bs = glider->getBound();
    13 
    14         float size = radius/bs.radius()*0.3f;
    15         osg::MatrixTransform* positioned = new osg::MatrixTransform;
    16         positioned->setDataVariance(osg::Object::STATIC);
    17         positioned  ->setMatrix(osg::Matrix::translate(-bs.center())*
    18                                      osg::Matrix::scale(size,size,size)*
    19                                      osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));
    20 
    21         positioned->addChild(glider);
    22 
    23         osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;
    24         xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
    25         xform->addChild(positioned);
    26 
    27         model->addChild(xform);
    28     }
    29 
    30     osg::ref_ptr<osg::Node> cessna = osgDB::readRefNodeFile("cessna.osgt");
    31     if (cessna)
    32     {
    33         const osg::BoundingSphere& bs = cessna->getBound();
    34 
    35         float size = radius/bs.radius()*0.3f;
    36         osg::MatrixTransform* positioned = new osg::MatrixTransform;
    37         positioned->setDataVariance(osg::Object::STATIC);
    38         positioned->setMatrix(osg::Matrix::translate(-bs.center())*
    39                                      osg::Matrix::scale(size,size,size)*
    40                                      osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f));
    41 
    42         positioned->addChild(cessna);
    43 
    44         osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform;
    45         xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
    46         xform->addChild(positioned);
    47 
    48         model->addChild(xform);
    49     }
    50 
    51     #ifndef OSG_GLES2_AVAILABLE
    52     model->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
    53     #endif
    54 
    55     return model.release();
    56 }

    这个函数的作用是创建运动模型。

      首先利用上一节介绍的createAnimationPath 函数创建模拟路径,并以此为基础加载模型,并控制模型的运动。

      动态更新的核心就是设置数据变度属性DataVariance,它决定了OSG在多线程渲染的过程中的执行策略:只有所有DYNAMIC属性的对象被渲染 完毕之后,OSG才会开始执行下一帧的用户更新操作;这样有效地可以避免数据的过快更新造成当前的渲染动作出错,以致系统崩溃。

      将模型进行平移,缩放,并绕z轴旋转180度。创建转换函数,并设置其更新回调函数。AnimationPathCallback的构造函数为:

    osg::AnimationPathCallback::AnimationPathCallback     (     AnimationPath *      ap,
            double      timeOffset = 0.0,
            double      timeMultiplier = 1.0     
        )     

    该函数的第三个参数决定了节点旋转的速度。因此cessna模型的旋转速度是glider的二倍。这两个模型的加载和回调更新函数的设定过程相同,只是参数有所不同。

  • 相关阅读:
    Finding Palindromes POJ
    吉哥系列故事——完美队形II HDU
    Period II FZU
    生日礼物&&Supermarket
    炮兵阵地[状态压缩DP]
    最小表示法 P1368
    Period
    最长异或路径
    Luogu P5490 扫描线
    解方程
  • 原文地址:https://www.cnblogs.com/SupremeGIS-Developer/p/10666705.html
Copyright © 2020-2023  润新知