osg示例程序解析1----osganimate

来源:互联网 发布:大数据工程师累不累 编辑:程序博客网 时间:2024/05/18 11:45

#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>  //位置属性变换节点( PositionAttitudeTransform),使用 PositionAttitudeTransform 节点可以实现使用 Vec3 位置坐标和一个四元数完成的变换操作
#include <osg/Geometry>
#include <osg/Geode>

#include <osgUtil/Optimizer>//操作器

#include <osgDB/Registry>   //osgDB::Registry 可以自动管理插件链接库
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>  //轨迹追踪操作器,可用于捕捉鼠标、键盘的的输入等
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>

#include <osgSim/OverlayNode>

#include <osgViewer/Viewer>
#include <iostream>


osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
{
    // 建立动画路径
    osg::AnimationPath* animationPath = new osg::AnimationPath;
    animationPath->setLoopMode(osg::AnimationPath::LOOP);
   
    int numSamples = 40;
    float yaw = 0.0f;
    float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
    float roll = osg::inDegrees(30.0f);
   
    double time=0.0f;
    double time_delta = looptime/(double)numSamples;
    for(int i=0;i<numSamples;++i)
    {
        osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
        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)));
       
        animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));

        yaw += yaw_delta;
        time += time_delta;

    }
    return animationPath;   
}


//创建底色纹路
osg::Node* createBase(const osg::Vec3& center,float radius)
{
    int numTilesX = 10;
    int numTilesY = 10;
   
    float width = 2*radius;
    float height = 2*radius;
   
    osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
    osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
    osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f));
   
    // 填充格子坐标
    osg::Vec3Array* coords = new osg::Vec3Array;
    int iy;
    for(iy=0;iy<=numTilesY;++iy)
    {
        for(int ix=0;ix<=numTilesX;++ix)
        {
            coords->push_back(v000+dx*(float)ix+dy*(float)iy);
        }
    }
   
    //两种颜色——黑与白
    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
    colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
    int numColors=colors->size();
   
   
    int numIndicesPerRow=numTilesX+1;
    osg::UByteArray* coordIndices = new osg::UByteArray; //假设我们使用的点数少于256
    osg::UByteArray* colorIndices = new osg::UByteArray;
    for(iy=0;iy<numTilesY;++iy)
    {
        for(int ix=0;ix<numTilesX;++ix)
        {
            // 4个顶点画一个格,组成大棋盘
            coordIndices->push_back(ix    +(iy+1)*numIndicesPerRow);
            coordIndices->push_back(ix    +iy*numIndicesPerRow);
            coordIndices->push_back((ix+1)+iy*numIndicesPerRow);
            coordIndices->push_back((ix+1)+(iy+1)*numIndicesPerRow);
           
            // 每个格压入颜色索引
            colorIndices->push_back((ix+iy)%numColors);
        }
    }
   

    // 建立法线
    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
   

    osg::Geometry* geom = new osg::Geometry;
    geom->setVertexArray(coords);
    geom->setVertexIndices(coordIndices);
   
    geom->setColorArray(colors);
    geom->setColorIndices(colorIndices);
    geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
   
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
   
 //由保存的数据绘制四个顶点的多边形
    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size()));
   
    osg::Geode* geode = new osg::Geode;
    geode->addDrawable(geom);
   
    return geode;
}

osg::Node* createMovingModel(const osg::Vec3& center, float radius)
{
    float animationLength = 10.0f;

    osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);

    osg::Group* model = new osg::Group;

    osg::Node* glider = osgDB::readNodeFile("glider.osg");
    if (glider)
    {
        const osg::BoundingSphere& bs = glider->getBound();//获取小飞机的包围盒

        float size = radius/bs.radius()*0.3f;
        osg::MatrixTransform* positioned = new osg::MatrixTransform;//建立一个位置转换矩阵
        positioned->setDataVariance(osg::Object::STATIC);//指定此数据变量更新回调时不会改变,为静态的
        positioned->setMatrix(osg::Matrix::translate(-bs.center())*
                                     osg::Matrix::scale(size,size,size)*
                                     osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));//位置变换
   
        positioned->addChild(glider);
   
        osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;   
        xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));//更新回调
        xform->addChild(positioned);

        model->addChild(xform);
    }
 
    osg::Node* cessna = osgDB::readNodeFile("cessna.osgt");
    if (cessna)
    {
        const osg::BoundingSphere& bs = cessna->getBound();

        float size = radius/bs.radius()*0.3f;
        osg::MatrixTransform* positioned = new osg::MatrixTransform;
  //OSG 将确保绘制遍历,在所有的 DYNAMIC 节点和数据处理完成后才会返回。同样,由于绘制遍历在函数返回后仍然可以继续渲染场景图形, OSG 将确保此时只有 STATIC 数据可以
  // 继续进行图形渲染。
        positioned->setDataVariance(osg::Object::STATIC);
        positioned->setMatrix(osg::Matrix::translate(-bs.center())*
                                     osg::Matrix::scale(size,size,size)*
                                     osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f));
   
        positioned->addChild(cessna);
   
        osg::MatrixTransform* xform = new osg::MatrixTransform;

  //回调---在拣选和绘制遍历时进行回调,动态的改变物体的运动路径
        xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
        xform->addChild(positioned);

        model->addChild(xform);
    }
   
    return model;
}

//创建模型
osg::Node* createModel(bool overlay, osgSim::OverlayNode::OverlayTechnique technique)
{
    osg::Vec3 center(0.0f,0.0f,0.0f);
    float radius = 100.0f;

    osg::Group* root = new osg::Group;

    float baseHeight = center.z()-radius*0.5;
    osg::Node* baseModel = createBase(osg::Vec3(center.x(), center.y(), baseHeight),radius);//创建底色
    osg::Node* movingModel = createMovingModel(center,radius*0.8f);//创建一个正在移动的模型

 //是否创建模型投影
    if (overlay)
    {
  //OverlayNode在场景上生成纹理覆盖,提前渲染一个Overlay子图到纹理从而生成overlay纹理,然后将它映射到场景上
        osgSim::OverlayNode* overlayNode = new osgSim::OverlayNode(technique);
        overlayNode->setContinuousUpdate(true);//每一帧都更新overlay的纹理
        overlayNode->setOverlaySubgraph(movingModel);//渲染到纹理上覆盖子图
        overlayNode->setOverlayBaseHeight(baseHeight-0.01);//设置映射的高度,设成比地面低一点即可
        overlayNode->addChild(baseModel);
        root->addChild(overlayNode);
    }
    else
    {
        root->addChild(baseModel);
    }
   
    root->addChild(movingModel);

    return root;
}


int main( int argc, char **argv )
{
   
    bool overlay = true;//当其为true时,出现在其盘面上运动的物体


 //判断有没有输入指定的参数
    osg::ArgumentParser arguments(&argc,argv);
    while (arguments.read("--overlay")) overlay = true;
   
 //osgSim::OverlayNode在场景图中创建一个纹理,投影覆盖场景--HUD
    osgSim::OverlayNode::OverlayTechnique technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY;

    while (arguments.read("--object")) { technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
    while (arguments.read("--ortho") || arguments.read("--orthographic")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay=true; }
    while (arguments.read("--persp") || arguments.read("--perspective")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY; overlay=true; }
   

    // 初始化场景.
    osgViewer::Viewer viewer;

    // 从命令行参数中加载节点。是否创建模型
    osg::Node* model = createModel(overlay, technique);
    if (!model)
    {
        return 1;
    }
   
    // 倾斜场景使视线可以看到场景.
    osg::MatrixTransform* rootnode = new osg::MatrixTransform;
    rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
    rootnode->addChild(model);

    // 场景优化
    osgUtil::Optimizer optimzer;
    optimzer.optimize(rootnode);
    
    // 设置根节点至场景
    viewer.setSceneData(rootnode);

 //添加个漫游器,移动视图主相机位置
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

 //创建单一的视图,程序运行在单一屏上单一场景

    viewer.setUpViewOnSingleScreen(0);

#if 0

    //使用自定义模拟时间
   
    viewer.realize();
   
    double simulationTime = 0.0;
   
    while (!viewer.done())
    {
        viewer.frame(simulationTime);
        simulationTime += 0.001;
    }
   
    return 0;
#else

    // 标准视图用法
    return viewer.run();

#endif
}

0 0
原创粉丝点击