一、开篇
在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();
}