• osg:多方位观察牛~


    透视投影与正视投影图:

    正视投影正上方观察牛的代码:

    #include <osg/Camera>
    #include <osgDB/ReadFile>
    #include <osgViewer/Viewer>
    
    osg::Camera* createBirdsEye( const osg::BoundingSphere& bs )
    {
        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
        
        double viewDistance = 2.0 * bs.radius();
        double znear = viewDistance - bs.radius();
        double zfar = viewDistance + bs.radius();
        float top = bs.radius();
        float right = bs.radius();
        float bottom = top;
        float left = right;
        //osg左手系坐标(z+向上,x+向右,y+向里)
    
        camera->setProjectionMatrixAsOrtho( -left, right, -bottom, top, znear, zfar );//设置正投影
    
        //牛的身长变短了(在视口大小没有变化的情况下,加大left和right(原本是6.3),牛的左右相对于裁剪区域来说,就缩小了,我是这么理解。)
        //camera->setProjectionMatrixAsOrtho( -10, 10, -bottom, top, znear, zfar );
    
        //牛的身长变窄了(同上理)
        //camera->setProjectionMatrixAsOrtho( -left, right, -20, 20, znear, zfar );
    
        //改变了znear和zfar,好像没什么变化,为什么呢,待找答案。****
         //camera->setProjectionMatrixAsOrtho( -left, right, -bottom, top, 1, 1 );
    
        /********* openGL解释***************************************************************************
            setProjectionMatrixAsOrtho(left,right,bottom,top,zNear,zFar);
    
            left和right表示最小和最大x值,top和bottom是最小和最大的y值,near和far是最小和最大的z值。
    
            left:裁剪区域最左边的坐标。
            right:裁剪区域最右边的坐标。
    
            bottom:最底部的坐标。
            top:最顶部的坐标。
    
            near:从原点距离观察者的最小位置。
            far:从原点距离观察者的最大位置。
        **************************************************************************************************/
        
        osg::Vec3d upDirection( 0.0,1.0,0.0 );
        osg::Vec3d viewDirection( 0.0,0.0,1.0 );
        osg::Vec3d center = bs.center();
        osg::Vec3d eyePoint = center + viewDirection * viewDistance;
        //从前面看牛
        //eyePoint.set(0.77,-10,0.5);
    
        //从牛头看牛
        //upDirection.set(0.0,0.0,1.0);
        //eyePoint.set(10,-0.4,0.5);
    
        //从牛下巴看牛
        //upDirection.set(1.0,0.0,-1.0);
        //eyePoint.set(100,-0.4,-100);
    
        camera->setViewMatrixAsLookAt( eyePoint, center, upDirection );//相机位置(眼睛位置,眼睛看到的场景中心位置,视点向上的量)
        //eyePoint(0.77,-0.4,12.7) center(0.77,-0.4,0.0) upDirection(0,1,0) zfar = 19,redius = 6.3
        
        return camera.release();
    }
    
    int main( int argc, char** argv )
    {
        osg::ArgumentParser arguments( &argc, argv );
        osg::Node* model = osgDB::readNodeFiles( arguments );
        if ( !model ) model = osgDB::readNodeFile( "cow.osg" );
        
        osg::Camera* camera = createBirdsEye( model->getBound() );
        camera->addChild( model );
        
        osgViewer::Viewer viewer;
        viewer.setSceneData( camera );
        viewer.setUpViewInWindow(40,40,800,600);
        return viewer.run();
    }

    代码执行效果:

      

    放开代码中相应的注释,可以看到下面的效果:

    从前面看牛

        

    从牛头看牛:

      

    从牛下巴看牛:

      

    再加入一头牛,使两头牛的坐标分别为(0.0,-10.0,0.0)、(0.0,-30.0,0.0),改用透视投影,视点的坐标为(0.0,-50.0,5)。代码如下:

     1 #include <osg/Camera>
     2 #include <osgDB/ReadFile>
     3 #include <osgViewer/Viewer>
     4 #include <osg/PositionAttitudeTransform>
     5 
     6 osg::Camera* createBirdsEye( const osg::BoundingSphere& bs )
     7 {
     8     osg::ref_ptr<osg::Camera> camera = new osg::Camera;
     9     camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    10     camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
    11     
    12     double viewDistance = 2.0 * bs.radius();
    13     double znear = viewDistance - bs.radius();
    14     double zfar = viewDistance + bs.radius();
    15     float top = bs.radius();
    16     float right = bs.radius();
    17     float bottom = top;
    18     float left = right;
    19     //osg左手系坐标(z+向上,x+向右,y+向里)
    20 
    21     //透视投影
    22     camera->setProjectionMatrixAsFrustum( -left, right, -bottom, top, 18, 39.2 );
    23 
    24     osg::Vec3d upDirection( 0.0,1.0,0.0 );
    25     osg::Vec3d viewDirection( 0.0,0.0,1.0 );
    26     osg::Vec3d center = bs.center();
    27     osg::Vec3d eyePoint = center + viewDirection * viewDistance;
    28     //从前面看牛(视点)
    29     eyePoint.set(0.0,-50.0,5.0);
    30 
    31     //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
    32     camera->setViewMatrixAsLookAt( eyePoint, center, upDirection );//相机位置(眼睛位置,眼睛看到的场景中心位置,视点向上的量)
    33     // center(0.77,-0.4,0.0) upDirection(0,1,0) zfar = 19,redius = 6.3
    34     
    35     return camera.release();
    36 }
    37 
    38 int main( int argc, char** argv )
    39 {
    40     osg::ArgumentParser arguments( &argc, argv );
    41     osg::Node* model = osgDB::readNodeFiles( arguments );
    42     if ( !model ) model = osgDB::readNodeFile( "cow.osg" );
    43 
    44     
    45     osg::Camera* camera = createBirdsEye( model->getBound() );
    46 
    47     //牛1
    48     osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
    49     pat->setPosition(osg::Vec3(0.0,-30.0,0.0));
    50     pat->addChild(model);
    51 
    52     //牛2
    53     osg::ref_ptr<osg::PositionAttitudeTransform> pat2 = new osg::PositionAttitudeTransform;
    54     pat2->setPosition(osg::Vec3(0.0,-10.0,0.0));
    55     pat2->addChild(model);
    56 
    57 
    58 
    59     camera->addChild(pat);
    60     camera->addChild(pat2);
    61 
    62     osgViewer::Viewer viewer;
    63     viewer.setSceneData( camera );
    64     viewer.setUpViewInWindow(40,40,800,600);
    65     return viewer.run();
    66 }

    运行效果:

      

     如果打开31行的注释(如果不打开这个注释,osg默认对near、far不做裁剪),其运行效果如下:

      

    可以看到后边的牛只显示了半个,另外半个被裁剪掉了,图解如下:

      

    黄色区域为near、far所表示的裁剪区域,牛2被裁剪了。

     (有五个窗口)单个视景器多个从相机看一头牛:

      

    上述效果实现代码:

    #include <osg/Group>
    #include <osgDB/ReadFile>
    #include <osgViewer/Viewer>
    #include <osg/PositionAttitudeTransform>
    
    //为相机设置图形设备对象并返回相机
    osg::Camera* createCamera( int x, int y, int w, int h )
    {
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->windowDecoration = false;//是否设置标题栏,这里设定为否,有标题栏的话,中间会被标题难割开。
        traits->x = x;//左上角坐标x
        traits->y = y;//左上角坐标y
        traits->width = w; 
        traits->height = h;
        traits->doubleBuffer = true;
        
        osg::DisplaySettings* ds = osg::DisplaySettings::instance();
        traits->alpha = ds->getMinimumNumAlphaBits();
        traits->stencil = ds->getMinimumNumStencilBits(); //模板缓存
        traits->sampleBuffers = ds->getMultiSamples();//重采样缓存
        traits->samples = ds->getNumMultiSamples();//重采样数
    
        //构建图形设备对象
        osg::ref_ptr<osg::GraphicsContext> gc =osg::GraphicsContext::createGraphicsContext( traits.get() );
        
        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setGraphicsContext( gc.get() );//设置相机的图形设备对象
        camera->setViewport( new osg::Viewport(0,0, traits->width, traits->height) );
        return camera.release();
    }
    
    int main( int argc, char** argv )
    {
        osg::ArgumentParser arguments( &argc, argv );
        osg::Node* model = osgDB::readNodeFiles( arguments );
        if ( !model ) model = osgDB::readNodeFile( "cow.osg" );
        osgViewer::Viewer viewer;
        //不做投影偏移的牛
        viewer.addSlave( createCamera(900,300,600,450), osg::Matrixd::translate( 0.0,0,0.0), osg::Matrixd() );
    
        viewer.addSlave( createCamera(50,50,400,300), osg::Matrixd::translate( 1.0,-1.0,0.0), osg::Matrixd() );
        viewer.addSlave( createCamera(455,50,400,300), osg::Matrixd::translate(-1.0,-1.0,0.0), osg::Matrixd() );
        viewer.addSlave( createCamera(50,355,400,300), osg::Matrixd::translate( 1.0,1.0,0.0), osg::Matrixd() );
        viewer.addSlave( createCamera(455,355,400,300), osg::Matrixd::translate(-1.0, 1.0,0.0), osg::Matrixd() );
        viewer.setSceneData( model );
        osg::Vec3d center = model ->getBound().center();
        return viewer.run();
    }

    总结:一头牛,添加了五个从相机去观察,每个相机对应一个图像设备窗口。 

    (有两窗口)用多视景器多方位观察一头牛:

      

    实现代码:

      

    #include <osg/Group>
    #include <osgDB/ReadFile>
    #include <osgViewer/CompositeViewer>
    #include <osg/PositionAttitudeTransform>
    
    //回调函数,让其不断的旋转
    class RotateCallback : public osg::NodeCallback
    {
    public:
        RotateCallback() : _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 += 1.0;
            }
            traverse( node, nv );//访问器的下一个节点
        }
    
    protected:
        double _rotateZ;
    };
    
    osg::Camera* createCamera( const osg::BoundingSphere& bs )
    {
        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
    
        double viewDistance = 2.0 * bs.radius();
        double znear = viewDistance - bs.radius();
        double zfar = viewDistance + bs.radius();
        float top = bs.radius();
        float right = bs.radius();
        float bottom = top;
        float left = right;
        //osg左手系坐标(z+向上,x+向右,y+向里)
    
        //透视投影
        camera->setProjectionMatrixAsFrustum( -left, right, -bottom, top, znear, zfar );
    
        osg::Vec3d upDirection( 0.0,0.0,1.0 );
        osg::Vec3d center = bs.center();
        osg::Vec3d eyePoint ;
        eyePoint.set(0.0,0.0,10.0);
    
        camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
        camera->setViewMatrixAsLookAt( eyePoint, center, upDirection );//相机位置(眼睛位置,眼睛看到的场景中心位置,视点向上的量)
        return camera.release();
    }
    
    int main( int argc, char** argv )
    {
        //读牛
        osg::ArgumentParser arguments( &argc, argv );
        osg::Node* model = osgDB::readNodeFiles( arguments );
        if ( !model ) model = osgDB::readNodeFile( "cow.osg" );
    
        //创建投影相机
        osg::Camera* camera = createCamera( model->getBound() );
    
        //给牛模型设置回调,让其自动旋转
        osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
        pat->addChild( model );
        pat->setUpdateCallback( new RotateCallback );
    
        camera->addChild(pat.get());
    
        //视景器1显示第一个有设置特定相机的牛
        osg::ref_ptr<osgViewer::View> view1 = new osgViewer::View;
        view1->setUpViewInWindow( 0, 50, 320, 240 );
        view1->setSceneData( camera );
    
        //视景器2显示第二个默认相机的牛
        osg::ref_ptr<osgViewer::View> view2 = new osgViewer::View;
        view2->setUpViewInWindow( 340, 50, 320, 240 );
        view2->setSceneData( pat.get() );
    
        //多视景器进行管理并渲染
        osgViewer::CompositeViewer compositeViewer;
        compositeViewer.addView( view1.get() );
        compositeViewer.addView( view2.get() );
        return compositeViewer.run();
    }

    总结:一个图像设备,多视景器管理着两个视景器,每个视景器对应一个相机(camera本身也是一个矩阵)。 

    单窗口显示两头牛:

      

      实现代码:

      

    #include <osg/Group>
    #include <osgDB/ReadFile>
    #include <osgViewer/Viewer>
    #include <osg/PositionAttitudeTransform>
    #include <osgViewer/CompositeViewer>
    int main( int argc, char** argv )
    {
        osg::ArgumentParser arguments( &argc, argv );
        osg::Node* model = osgDB::readNodeFiles( arguments );
        if ( !model ) model = osgDB::readNodeFile( "cow.osg" );
    
    
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->windowDecoration = false;//是否设置标题栏,这里设定为否,有标题栏的话,中间会被标题难割开。
        traits->x = 0;//左上角坐标x
        traits->y = 0;//左上角坐标y
        traits->width = 800; 
        traits->height = 800;
        traits->doubleBuffer = true;
    
        osg::DisplaySettings* ds = osg::DisplaySettings::instance();
        traits->alpha = ds->getMinimumNumAlphaBits();
        traits->stencil = ds->getMinimumNumStencilBits(); //模板缓存
        traits->sampleBuffers = ds->getMultiSamples();//重采样缓存
        traits->samples = ds->getNumMultiSamples();//重采样数
    
        //构建图形设备对象
        osg::ref_ptr<osg::GraphicsContext> gc =osg::GraphicsContext::createGraphicsContext( traits.get() );
    
        osgViewer::CompositeViewer *v = new osgViewer::CompositeViewer();
        osg::ref_ptr<osg::Group> g = new osg::Group;
        osg::ref_ptr<osg::Group> g2 = new osg::Group;
    
        osgViewer::View  *v1 = new osgViewer::View();
        osgViewer::View  *v2 = new osgViewer::View();
    
        v->addView(v1);
        v->addView(v2);
    
        v1->setSceneData(model);
        v2->setSceneData(model);
    
        v1->getCamera()->setViewport(new osg::Viewport(0,0,400,600));
        v1->getCamera()->setGraphicsContext(gc.get());
    
        v2->getCamera()->setViewport(new osg::Viewport(410,0,400,600));
        v2->getCamera()->setGraphicsContext(gc.get());
    
        return v->run();
    }
  • 相关阅读:
    hi35183e增加exfat文件系统的支持(转)
    UDP 单播、广播和多播(转)
    linux系统中,kill -3查看java进程状态无效的解决方法
    js是用什么语言编写实现的
    云海天教程
    Docker下安装MySQL
    如何延长手机的使用寿命时间
    如何延长空调使用寿命?
    Linux 发送邮件
    Linux jstack命令
  • 原文地址:https://www.cnblogs.com/airduce/p/9835892.html
Copyright © 2020-2023  润新知