Введение в OpenSceneGraph: Оконный и композитный режимы отображения
Отображение сцены в оконном режиме
Класс osgViewer::Viewer может быть очень быстро перенастроен на отображение в оконном режиме. Как вы заметили, все предыдущие наши примеры отображались в полноэкранном режиме. Для переключения вьювера в оконный режим существует метод setUpViewInWindow(), который принимает в качестве параметров координаты левого верхнего угла окна, его ширину и высоту в пикселях
viewer.setUpViewInWindow(50, 50, 800, 600);
Опциоанльно этот метод принимает пятый параметр - номер экрана, на который следует выводить окно, для того случая, если у вас не один монитор. Наверняка работая с несколькими мониторами в Windows вы наблюдали, что сцена расползается на все мониторы в полноэкранном режиме (в Linux такое не наблюдается).
Кроме того, в настройках проекта можно задать переменную окружения OSG_WINDOW таким образом
что будет эквивалентно вызову setUpViewInWindow(), который в таком случае можно и не выполнять.
Для явного указания экрана, на который следует выводить вьювер в полноэкранном режиме можно воспользоваться методом setUpViewOnSingleScreen() указав в качестве параметра номер экрана (по-умолчанию 0).
OSG поддерживает также демонстрационные сферические дисплеи. Для настройки отображения на таком дисплее можно использвать метод setUpViewFor3DSphericalDisplay().
Композитный вьювер
Класс osgViewer::Viewer управляет одним видом, отображающим один граф сцены. Кроме него существует класс osgViewer::CompositeViewer который поддерживает несколько видов и несколько сцен. Он имеет те же методы run(), frame() и done() для управления процессом рендеринга, но при этом позволяет добавлять и удалять независимые виды с помощью методов addView() и removeView(), а также получение видов по их индексу методом getView(). Объект вида описывается классом osgViewer::View.
Класс osgViewer::View является базовым для класса osgViewer::Viewer. Он позволяет добалять корневой узел с данными сцены, манипулятор камеры и обработчики событий. Основное отличие этого класса (вид) от класса вьювера - он не позволяет рендерить сцену вызовами run() или frame(). Типичный сценарий добавления вида выглядит так
osgViewer::CompositeViewer multiviewer;
multiviewer.addView( view );
Композитный вьювер позволяет отображать одну сцену в разных ракурсах, обображая эти ракурсы в разных окнах. Он так же позволяет отображать в разных окнах независимые сцены. Напишем простой пример использования композитного вьювера
main.h
#ifndef MAIN_H
#define MAIN_H
#include <osgDB/ReadFile>
#include <osgViewer/CompositeViewer>
#endif
main.cpp
#include "main.h"
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
osgViewer::View *createView(int x, int y, int w, int h,
osg::Node *scene)
{
osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
view->setSceneData(scene);
view->setUpViewInWindow(x, y, w, h);
return view.release();
}
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
(void) argc; (void) argv;
osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("../data/cessna.osg");
osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("../data/cow.osg");
osg::ref_ptr<osg::Node> model3 = osgDB::readNodeFile("../data/glider.osg");
osgViewer::View *view1 = createView(50, 50, 320, 240, model1);
osgViewer::View *view2 = createView(380, 50, 320, 240, model2);
osgViewer::View *view3 = createView(185, 330, 320, 240, model3);
osgViewer::CompositeViewer viewer;
viewer.addView(view1);
viewer.addView(view2);
viewer.addView(view3);
return viewer.run();
}
Создание отдельного вида поместим в функцию, принимающую в качестве параметров положение и размеры окна, а также сцену в виде указателя на её корневой узел
osgViewer::View *createView(int x, int y, int w, int h,
osg::Node *scene)
{
osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
view->setSceneData(scene);
view->setUpViewInWindow(x, y, w, h);
return view.release();
}
Здесь мы создаем вид, управляемый умным указателем на объект osgViewer::View
osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
задаем данные отображаемой сцены и оконный режим отображения в окне с заданным положением и размерами
view->setSceneData(scene);
view->setUpViewInWindow(x, y, w, h);
Вид возвращаем из функции по правилам возврата умных указателей
return view.release();
Теперь в основной программе загружаем три разных модели
osgViewer::View *view1 = createView(50, 50, 320, 240, model1);
osgViewer::View *view2 = createView(380, 50, 320, 240, model2);
osgViewer::View *view3 = createView(185, 330, 320, 240, model3);
создаем три разных вида
osgViewer::View *view1 = createView(50, 50, 320, 240, model1);
osgViewer::View *view2 = createView(380, 50, 320, 240, model2);
osgViewer::View *view3 = createView(185, 330, 320, 240, model3);
создаем композитный вьювер и добавляем в него созданные ранее виды
osgViewer::CompositeViewer viewer;
viewer.addView(view1);
viewer.addView(view2);
viewer.addView(view3);
и запускаем рендеринг абсолютно аналогично тому, как мы это делали в случае с одной сценой
return viewer.run();
Всё! При запуске программы мы получим три разный окна. Содержимым каждого окна можно управлять независимо. Любое из окон можно закрыть стандартным способом, а из приложения целиком выйти по нажатию Esc.