【osg】OSG开发(04)—创建多个场景视图

一、开篇

在osg中,有时候需要使用到多个场景视图,每一个场景视图中有不一样的操作:例如:漫游器、照相机、粒子效果、多个模型组合等。

在OSG中,提供了osgViewer::CompositeViewer类来实现这个需求。

二、实现原理

(1)创建一个osgViewer::CompositeViewer实例
(2)使用osgViewer::View代表一个具体的View视图
(3)使用osgViewer::CompositeViewer的addView()方法将创建的osgViewer::View添加到osgViewer::CompositeViewer中

(2-1)首先读取一个模型文件:

osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/glider.osgt");

(2-2)创建一个osgViewer::CompositeViewer实例:

osgViewer::CompositeViewer viewer;

(2-3)创建一个osg::GraphicsContext::WindowingSystemInterface来获取窗口系统的信息,这里主要获取:主窗口id、长、宽等信息:

osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
if (!wsi)
{
    osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
    return 1;
}

unsigned int width, height;
osg::GraphicsContext::ScreenIdentifier main_screen_id;

main_screen_id.readDISPLAY();
main_screen_id.setUndefinedScreenDetailsToDefaultScreen();

//获取窗口的id号和对应的分辨率(长宽比)
wsi->getScreenResolution(main_screen_id, width, height);

(2-4)使用osg::GraphicsContext::Traits来创建一个窗口配置对象,最后使用osg::GraphicsContext的createGraphicsContext()创建显示图像的上下文:

osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 100;
traits->y = 100;
traits->width = 1000;
traits->height = 800;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->readDISPLAY();
traits->setUndefinedScreenDetailsToDefaultScreen();

osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());

(2-5)创建四个视图

// 第一个视图
{
    osgViewer::View* view = new osgViewer::View;

    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/fountain.osgt");

    view->setName("View three");
    viewer.addView(view);

    view->setSceneData(scene);

    view->getCamera()->setName("Cam three");
    view->getCamera()->setProjectionMatrixAsPerspective(30.0, double(traits->width) / double(traits->height/2), 1.0, 1000.0);
    view->getCamera()->setViewport(new osg::Viewport(0, traits->height/2, traits->width/2,traits->height/2));
    view->getCamera()->setGraphicsContext(gc.get());
    view->setCameraManipulator(new osgGA::TerrainManipulator);
}

// 第二个视图
{
    osgViewer::View* view = new osgViewer::View;
    view->setName("View two");

    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/cow.osgt");
    viewer.addView(view);

    view->setSceneData(scene);
    view->getCamera()->setName("Cam two");
    view->getCamera()->setViewport(new osg::Viewport(traits->width/2, traits->height/2, traits->width/2,traits->height/2));
    view->getCamera()->setGraphicsContext(gc.get());
    view->setCameraManipulator(new osgGA::TerrainManipulator);

}

// 第三个视图
{
    osgViewer::View* view = new osgViewer::View;
    view->setName("View one");
    viewer.addView(view);

    view->setSceneData(scene);
    view->getCamera()->setName("Cam one");
    view->getCamera()->setViewport(new osg::Viewport(0,0, traits->width/2, traits->height/2));
    view->getCamera()->setGraphicsContext(gc.get());

    osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
    statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet());

    view->setCameraManipulator(new osgGA::TerrainManipulator);
    view->addEventHandler( statesetManipulator.get() );

    view->addEventHandler( new osgViewer::StatsHandler );
    view->addEventHandler( new osgViewer::HelpHandler );
    view->addEventHandler( new osgViewer::WindowSizeHandler );
    view->addEventHandler( new osgViewer::ThreadingHandler );
    view->addEventHandler( new osgViewer::RecordCameraPathHandler );
}


// 第四个视图
{
    osgViewer::View* view = new osgViewer::View;
    view->setName("View one");
    viewer.addView(view);

    view->setSceneData(scene);
    view->getCamera()->setName("Cam one");
    view->getCamera()->setViewport(new osg::Viewport(traits->width/2, 0, traits->width/2,traits->height/2));
    view->getCamera()->setGraphicsContext(gc.get());

    // 添加状态操作器
    osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
    statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet());

    view->setCameraManipulator(new osgGA::TerrainManipulator);
    view->addEventHandler( statesetManipulator.get() );

    view->addEventHandler( new osgViewer::StatsHandler );
    view->addEventHandler( new osgViewer::HelpHandler );
    view->addEventHandler( new osgViewer::WindowSizeHandler );
    view->addEventHandler( new osgViewer::ThreadingHandler );
    view->addEventHandler( new osgViewer::RecordCameraPathHandler );
}

三、效果

四、完整代码

#include <iostream>

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/FrontFace>

#include <osgText/Text>

#include <osgGA/TerrainManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>

#include <osgViewer/CompositeViewer>

#include <osg/io_utils>

int main( int argc, char **argv )
{
    //读取模型文件
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/glider.osgt");

    //创建CompositeViewer
    osgViewer::CompositeViewer viewer;

    if (viewer.getNumViews()==0)
    {

        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
        if (!wsi)
        {
            osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
            return 1;
        }

        unsigned int width, height;
        osg::GraphicsContext::ScreenIdentifier main_screen_id;

        main_screen_id.readDISPLAY();
        main_screen_id.setUndefinedScreenDetailsToDefaultScreen();
        wsi->getScreenResolution(main_screen_id, width, height);

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->x = 100;
        traits->y = 100;
        traits->width = 1000;
        traits->height = 800;
        traits->windowDecoration = true;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;
        traits->readDISPLAY();
        traits->setUndefinedScreenDetailsToDefaultScreen();

        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());

        // 第一个视图
        {
            osgViewer::View* view = new osgViewer::View;

            osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/fountain.osgt");

            view->setName("View three");
            viewer.addView(view);

            view->setSceneData(scene);

            view->getCamera()->setName("Cam three");
            view->getCamera()->setProjectionMatrixAsPerspective(30.0, double(traits->width) / double(traits->height/2), 1.0, 1000.0);
            view->getCamera()->setViewport(new osg::Viewport(0, traits->height/2, traits->width/2,traits->height/2));
            view->getCamera()->setGraphicsContext(gc.get());
            view->setCameraManipulator(new osgGA::TerrainManipulator);
        }

        // 第二个视图
        {
            osgViewer::View* view = new osgViewer::View;
            view->setName("View two");

            osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("osgDatas/cow.osgt");
            viewer.addView(view);

            view->setSceneData(scene);
            view->getCamera()->setName("Cam two");
            view->getCamera()->setViewport(new osg::Viewport(traits->width/2, traits->height/2, traits->width/2,traits->height/2));
            view->getCamera()->setGraphicsContext(gc.get());
            view->setCameraManipulator(new osgGA::TerrainManipulator);

        }

        // 第三个视图
        {
            osgViewer::View* view = new osgViewer::View;
            view->setName("View one");
            viewer.addView(view);

            view->setSceneData(scene);
            view->getCamera()->setName("Cam one");
            view->getCamera()->setViewport(new osg::Viewport(0,0, traits->width/2, traits->height/2));
            view->getCamera()->setGraphicsContext(gc.get());

            osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
            statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet());

            view->setCameraManipulator(new osgGA::TerrainManipulator);
            view->addEventHandler( statesetManipulator.get() );

            view->addEventHandler( new osgViewer::StatsHandler );
            view->addEventHandler( new osgViewer::HelpHandler );
            view->addEventHandler( new osgViewer::WindowSizeHandler );
            view->addEventHandler( new osgViewer::ThreadingHandler );
            view->addEventHandler( new osgViewer::RecordCameraPathHandler );
        }


        // 第四个视图
        {
            osgViewer::View* view = new osgViewer::View;
            view->setName("View one");
            viewer.addView(view);

            view->setSceneData(scene);
            view->getCamera()->setName("Cam one");
            view->getCamera()->setViewport(new osg::Viewport(traits->width/2, 0, traits->width/2,traits->height/2));
            view->getCamera()->setGraphicsContext(gc.get());

            // add the state manipulator
            osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
            statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet());

            view->setCameraManipulator(new osgGA::TerrainManipulator);
            view->addEventHandler( statesetManipulator.get() );

            view->addEventHandler( new osgViewer::StatsHandler );
            view->addEventHandler( new osgViewer::HelpHandler );
            view->addEventHandler( new osgViewer::WindowSizeHandler );
            view->addEventHandler( new osgViewer::ThreadingHandler );
            view->addEventHandler( new osgViewer::RecordCameraPathHandler );
        }

    }

    return viewer.run();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值