Быстрое введение в OpenSceneGraph. Часть 1.

Apr 16, 2013 19:33


Это введение предназначено для людей, которые хорошо умеют программировать на C++, у которых есть опыт использования OpenGL, DirectX или игровых движков, и которые понимают базовые вещи в компьютерной графике.

Здесь будут описаны основные классы, связи между ними и кратко примеры использования.

Начнем с полезных утилит, которые входят в состав OSG.

i. osgviewer - просмотр 3д-моделей. Пример использования из командной строки:

osgviewer cow.osg

Можно настроить в Windows так, чтобы по клику на файле с 3д-моделью запускался osgviewer. osgviewer поддерживает кучу аргументов командной строки.

ii. osgconv - конвертация между разными форматами 3д-моделей, которые поддерживает OSG. Пример использования из командной строки:

osgconv inputfile outputfile

Есть полезный аргумент -compressed, который при конвертации сжимает текстуры. Рекомендуется использовать всегда:

osgconv -compressed inputfile outputfile

Аргументы командной строки.

Переходим к служебным классам, которые формируют каркас приложения.

1. OpenSceneGraph поддерживает работу с несколькими окнами, несколькими мониторами и даже с несколькими видеокартами одновременно. Поэтому главной структурной единицей приложения является вид. Каждый вид включает в себя отдельную трехмерную сцену, свою независимую виртуальную камеру (или несколько) и графический контекст (или несколько). Рендеринг в разные контексты может выполняться в разных потоках.

Вид реализуется в 2х классах. Класс osg::View содержит ссылку на виртуальную камеру и возможно на камеры-слейвы (о них позже). От него наследуется класс osgViewer::View, который дополнительно содержит ссылки на граф сцены, на объект-манипулятор (для перемещения по сцене) и имеет методы для быстрого создания графического контекста, взаимодействия с ним и несколько вспомогательных методов.

Метод setSceneData устанавливает ссылку на граф сцены.

Методы setUpViewAcrossAllScreens, setUpViewInWindow, setUpViewOnSingleScreen предназначены для быстрого создания графического контекста.

2. Вьюер - главный организационный объект. Должен быть только один в приложении (это не синглтон, но все равно создавать несколько вьюеров не желательно). Запускает цикл рендеринга и контролирует многопоточность.

В OSG имеется 2 класса-вьюера, производные от базового osgViewer::ViewerBase.

osgViewer::Viewer - для простых приложений, где имеется только один вид. Поэтому для удобства использования osgViewer::Viewer дополнительно наследуется от класса osgViewer::View.

osgViewer::CompositeViewer - для приложений, в которых несколько видов.

Метод realize нужен для автоматического создания графического контекста (выбирает один из 3х методов osgViewer::View).

Метод frame рендерит один кадр.

Метод run запускает цикл рендеринга (вызов метода frame в цикле).

Диаграмма классов выглядит так:



3.  Класс osg::ArgumentParser позволяет удобно разбирать аргументы командной строки. Есть куча примеров использования.

Итого простейшая программа на OpenSceneGraph будет выглядеть так:

int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc, argv);

osgViewer::Viewer viewer(arguments);

osg::Node* root = …;

viewer.setSceneData(root);
    viewer.realize();   
    return viewer.run();
}

4. Класс osg::Camera, как видно из названия, соответствует виртуальной камере и содержит множество настроек камеры: матрицы вида, проекции, вьюпорт, параметры очистки буферов.

Матрицу вида можно задавать/получать как через osg::Matrix, так и с помощью 3х векторов eye, center, up.

Матрицу проекции можно задавать/получать 4 способами: напрямую через osg::Matrix, а также через asOrtho, asFrustum, AsPerspective.

Метод setGraphicsContext устанавливает графический контекст.

Можно рендерить в текстуру, если задать RenderTargetImplementationи прикрепить к камере нужные текстуры с помощью метода attach.

Можно прикрепить функции обратного вызова для получения результата рендеринга (например, чтобы сделать скриншот).

Нужно отметить, что среди базовых классов osg::Cameraесть класс osg::Node. В целом, в приложении экземпляры класса osg::Cameraмогут встречаться в 3х разных местах:
  • Главная камера вида. Камера прикреплена к osg::View. Об этом говорилось раньше.
  • Подчиненная камера (slave). Также прикреплена к osg::View, но через метод addSlave. Об этом позже.
  • Один из узлов графа сцены (благодаря наследованию от osg::Node). Об этом позже.

5. Графический контекст - экземпляр одного из классов, производных от osg::GraphicsContext. Отвечает за взаимодействие с операционной системой: создание графического окна, контроль размеров окна, выделение памяти под буферы кадра, получение от операционной системы входных данных от клавиатуры и мыши. В разных ОС это осуществляется по разному, поэтому для каждой ОС есть своя реализация и свой производный класс от osg::GraphicsContext. Есть также производный класс для встраивания в интерфейс Qt.

Графический контекст может быть автоматически создан в методе вьюераrealizeлибо с помощью методов класса osgViewer::View. Но иногда его необходимо настраивать вручную. Пример:

osg::ref_ptr traits = newosg::GraphicsContext::Traits(osg::DisplaySettings::instance().get());
traits->screenNum = 0;
traits->x = 0;
traits->y = 0;
traits->width = 1920;
traits->height = 1080;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;

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

camera->setGraphicsContext(gc.get());
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));

camera->setDrawBuffer(GL_BACK);
camera->setReadBuffer(GL_BACK);

Здесь через класс osg::GraphicsContext::Traitsустанавливаются свойства контекста: номер экрана, размеры окна в пикселях и т.д. Статический метод createGraphicsContextавтоматически выбирает реализацию контекста в зависимости от операционной системы.

После создания контекста вся работа с ним происходит “под капотом”.

6. Класс osg::DisplaySettings инкапсулирует некоторые настройки приложения. Похож на синглтон в том смысле, что есть один выделенный экземпляр, доступный из любой точки приложения с помощью статического метода instance. Но при этом можно создавать новые экземпляры этого класса для изменения поведения отдельных видов.

Кратко список настроек:
  • Настройки буферов кадра
  • Настройки параметров стерео
  • Настройки количества потоков для подгрузки данных

osg::DisplaySettings может инициализировать параметры стереорежима на основе переменных окружения или аргументов командной строки. После этого параметры доступны на чтение. Можно также их задавать вручную.

Пример включения сглаживания и буфера трафарета. Эти строки нужно поместить в начало функции main:

osg::DisplaySettings::instance()->setNumMultiSamples(4);
osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);

Previous post Next post
Up