Implementação OSG sky dome

Depois de pesquisar na Internet por um longo tempo, não encontrei o skydome do OSG. Havia apenas um arquivo chamado skydome.osgt. A resolução do efeito de nuvem do céu dentro era muito baixa. As outras caixas do céu são um pouco falsas. Os mestres do OSG não gostam de escrever isso. Como exercício, implementaremos uma cúpula do céu dinâmica hoje. Se alguém vir, adicione uma textura de sombreamento para fazer a bola se transformar em nuvens.
Se o ambiente OSG estiver configurado, crie um novo projeto c ++ na forma de um documento vazio, adicione o caminho do arquivo de inclusão de osg em include e defina o caminho de lib de osg em lib; depois disso, adicione o seguinte código a um arquivo main.cpp: OK, você verá Uma cúpula do céu girando lentamente. Não, obrigado!

Escreva a descrição da imagem aqui


#include <osg/io_utils>
#include <osgDB/WriteFile>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osgViewer/Viewer>
#include <osg/Projection>
#include <osg/MatrixTransform>
#include <osgText/Text>
#include <osgUtil/Optimizer>
#include<osgUtil/SmoothingVisitor>
#include<osg/PositionAttitudeTransform>


#ifdef _DEBUG
#pragma comment(lib, "User32.lib")     
#pragma comment(lib, "glu32.lib")   
#pragma comment(lib, "opengl32.lib")   
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgGAd.lib")
#pragma comment(lib,"osgManipulatord.lib")
#pragma comment(lib,"osgUtild.lib")
#pragma comment(lib,"osgViewerd.lib")
#pragma comment(lib,"osgWidgetd.lib")
#pragma comment(lib,"osgFXd.lib")
#pragma comment(lib,"osgShadowd.lib")
#pragma comment(lib,"OpenThreadsd.lib")
#pragma comment(lib, "osgAnimationd.lib")
#pragma comment(lib, "osgParticled.lib")
#pragma comment(lib, "osgTerraind.lib")
#pragma comment(lib, "osgPresentationd.lib")
#pragma comment(lib, "osgSimd.lib")
#pragma comment(lib, "osgVolumed.lib")
#pragma comment(lib, "osgTextd.lib")
#pragma comment(lib,"osgdb_gdald.lib")
#pragma comment(lib,"osgdb_ogrd.lib")
//#pragma comment(lib,"osgUId.lib")
#pragma comment(lib,"osgWidgetd.lib")
#else
#pragma comment(lib, "User32.lib")     
#pragma comment(lib, "glu32.lib")   
#pragma comment(lib, "opengl32.lib")   
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgDB.lib")
#pragma comment(lib,"osgGA.lib")
#pragma comment(lib,"osgManipulator.lib")
#pragma comment(lib,"osgUtil.lib")
#pragma comment(lib,"osgViewer.lib")
#pragma comment(lib,"osgWidget.lib")
#pragma comment(lib,"osgFX.lib")
#pragma comment(lib,"osgShadow.lib")
#pragma comment(lib,"OpenThreads.lib")
#pragma comment(lib, "osgAnimation.lib")
#pragma comment(lib, "osgParticle.lib")
#pragma comment(lib, "osgTerrain.lib")
#pragma comment(lib, "osgPresentation.lib")
#pragma comment(lib, "osgSim.lib")
#pragma comment(lib, "osgVolume.lib")
#pragma comment(lib, "osgText.lib")
#pragma comment(lib,"osgdb_gdal.lib")
#pragma comment(lib,"osgdb_ogr.lib")
#pragma comment(lib,"osgUI.lib")
#pragma comment(lib,"osgWidget.lib")
#endif //_debug



class KeyboardEventHandler : public osgGA::GUIEventHandler
{ // extra event handler traps 'n' key to re-tessellate any tessellated geodes.
public:

    KeyboardEventHandler(osg::Node *nd):
        _scene(nd) {}

        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
        {
            switch(ea.getEventType())
            {
                case(osgGA::GUIEventAdapter::KEYDOWN):
                {
                    if (_scene && ea.getKey()=='n')
                    {
                    ///////////////////////////


                       return true;
                    }
                    break;
                }
                default:
                    break;
            }
            return false;
        }

        osg::Node *_scene;

};


float toRadians(float angle)
{
    return angle/180*osg::PI;
}



osg::ref_ptr<osg::Geode>skydemo (float radius,osg::Vec3 postioncenter)
{
    osg::ref_ptr<osg::Geode>skygeode=new osg::Geode();

    osg::ref_ptr<osg::Geometry>gskydome= new osg::Geometry;

    osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array;
    osg::ref_ptr<osg::Vec3Array> nrms = new osg::Vec3Array;
    osg::ref_ptr<osg::Vec2Array> tcs = new osg::Vec2Array;
    osg::Vec3 nrm(0,-1,0);

    //*************************************///
    float ANGLE_SPAN=18;//切分间隔
        float angleV=90;//纵向上的起始度数
        //获取切分整图的纹理数组
        int bw=(int)(360/ANGLE_SPAN);//纹理图切分的列数
        int bh= (int)(angleV/ANGLE_SPAN);  //纹理图切分的行数
        float *result=new float[bw*bh*6*2];//数组

        float sizew=1.0f/bw;//列数
        float sizeh=1.0f/bh;//行数
        int c=0;
        for(int i=0;i<bh;i++)
        {
            for(int j=0;j<bw;j++)
            {
                //每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标
                float s=j*sizew;
                float t=i*sizeh;

                result[c++]=s;
                result[c++]=t;

                result[c++]=s+sizew;
                result[c++]=t;

                result[c++]=s;
                result[c++]=t+sizeh;

                result[c++]=s;
                result[c++]=t+sizeh;

                result[c++]=s+sizew;
                result[c++]=t;

                result[c++]=s+sizew;
                result[c++]=t+sizeh;                
            }
        }
        int tc=0;
        int ts=bw*bh*6*2;//纹理数组长度
        float tx1,tx2;


      for(float vAngle=angleV;vAngle>0;vAngle=vAngle-ANGLE_SPAN)//垂直方向angleSpan度一份
        {
            for(float hAngle=360;hAngle>0;hAngle=hAngle-ANGLE_SPAN)//水平方向angleSpan度一份
            {
                //纵向横向各到一个角度后计算对应的此点在球面上的四边形顶点坐标
                //并构建两个组成四边形的三角形
                double xozLength=radius*cos(toRadians(vAngle));
                float x1=(float)(xozLength*cos(toRadians(hAngle)));
                float z1=(float)(xozLength*sin(toRadians(hAngle)));
                float y1=(float)(radius*sin(toRadians(vAngle)));

                xozLength=radius*cos(toRadians(vAngle-ANGLE_SPAN));
                float x2=(float)(xozLength*cos(toRadians(hAngle)));
                float z2=(float)(xozLength*sin(toRadians(hAngle)));
                float y2=(float)(radius*sin(toRadians(vAngle-ANGLE_SPAN)));

                xozLength=radius*cos(toRadians(vAngle-ANGLE_SPAN));
                float x3=(float)(xozLength*cos(toRadians(hAngle-ANGLE_SPAN)));
                float z3=(float)(xozLength*sin(toRadians(hAngle-ANGLE_SPAN)));
                float y3=(float)(radius*sin(toRadians(vAngle-ANGLE_SPAN)));

                xozLength=radius*cos(toRadians(vAngle));
                float x4=(float)(xozLength*cos(toRadians(hAngle-ANGLE_SPAN)));
                float z4=(float)(xozLength*sin(toRadians(hAngle-ANGLE_SPAN)));
                float y4=(float)(radius*sin(toRadians(vAngle)));   



                coords->push_back(osg::Vec3(x1,-z1,y1));
                coords->push_back(osg::Vec3(x4,-z4,y4));
                coords->push_back(osg::Vec3(x2,-z2,y2));
                //构建第一三角形


                //构建第二三角形

                coords->push_back(osg::Vec3(x2,-z2,y2));
                coords->push_back(osg::Vec3(x4,-z4,y4));
                coords->push_back(osg::Vec3(x3,-z3,y3));


                //第一三角形3个顶点的6个纹理坐标


                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));
                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));
                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));




                //第二三角形3个顶点的6个纹理坐标

                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));
                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));
                tx1=result[tc++%ts];
                tx2=result[tc++%ts];
                tcs->push_back(osg::Vec2(tx1,tx2));

            }
        }

     delete result;result=NULL;//删除纹理数组

      nrms->push_back(nrm);


      gskydome->setVertexArray(coords.get());
      gskydome->setTexCoordArray(0,tcs.get());

      //三角形
      gskydome->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,coords->size()));
//自动生成法线吧,这样看起来更自然
      osgUtil::SmoothingVisitor::smooth(*(gskydome.get()));


      skygeode->addDrawable(gskydome.get());

      //背景图片;
    osg::ref_ptr<osg::Texture2D> baseTex = new osg::Texture2D;
    osg::ref_ptr<osg::Image> iamge = osgDB::readImageFile("sky.jpg");
    baseTex->setImage(iamge);
    baseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
    baseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
    skygeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, baseTex, 1);


      return skygeode.get();
}


class RoateCallback: public osg::NodeCallback
{
public:
    RoateCallback():_rotateZ(0.0){}

    virtual void operator()(osg::Node* node,osg::NodeVisitor* nv)
    {
        osg::PositionAttitudeTransform *pat=
            dynamic_cast<osg::PositionAttitudeTransform*>(node);
        if(pat)
        {
            osg::Quat quat(osg::DegreesToRadians(_rotateZ),osg::Z_AXIS);
            pat->setAttitude(quat);
            _rotateZ+=0.030;
        }
        traverse(node,nv);
    }


protected:
    double _rotateZ;
};

class InfoCallback: public osg::NodeCallback
{
public:
    virtual void operator()(osg::Node*node,osg::NodeVisitor* nv)
    {
        osg::PositionAttitudeTransform* pat=
            dynamic_cast<osg::PositionAttitudeTransform*>(node);

        if(pat)
        {
            double angle=0.0;
            osg::Vec3 axis;
            pat->getAttitude().getRotate(angle,axis);
            std::cout<<"node roat axis "<<axis<<", "<<"angle "<<angle<<std::endl;
        }
        traverse(node,nv);
    }

};




int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // construct the viewer.
    osgViewer::Viewer viewer;

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Group> root = new osg::Group();

    osg::ref_ptr<osg::PositionAttitudeTransform>pat =new osg::PositionAttitudeTransform;

    pat->addChild(skydemo(3000.0f,osg::Vec3(1,1,1)).get());

    pat->setUpdateCallback(new RoateCallback);
    pat->addUpdateCallback(new InfoCallback);

    root->addChild(pat.get());

    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get() );

    // set the scene to render
    viewer.setSceneData(root.get());

    viewer.addEventHandler(new KeyboardEventHandler(root.get()));

    osgDB::writeNodeFile(*(root.get()), "saved_model.osgt");

    return viewer.run();
}

o que? Nenhum adesivo sky.jpg?

Neste:
Escreva a descrição da imagem aqui

Agradecimentos: Wu Yafeng é usado aqui: o algoritmo de geração de cúpula do céu no Android openglES2.0, obrigado!

Acho que você gosta

Origin blog.csdn.net/sun19890716/article/details/51084180
Recomendado
Clasificación