您的位置:首页 > 其它

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

2016-01-12 10:52 603 查看
#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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: