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();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM