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的二倍。这两个模型的加载和回调更新函数的设定过程相同,只是参数有所不同。

posted @ 2019-04-07 19:52  技术狂人djc  阅读(294)  评论(0编辑  收藏  举报