Previous Entry Share Next Entry
Быстрое введение в OpenSceneGraph. Часть 1.
alex_bobkov

Это введение предназначено для людей, которые хорошо умеют программировать на 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<osg::GraphicsContext::Traits> 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<osg::GraphicsContext> 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);


  • 1
В OSG есть классы-манипуляторы из пространства osgGA, например, TrackballManipulator. Они предназначены для управления виртуальной камерой. TrackballManipulator позволяет вращать камеру вокруг модели так, что создается иллюзия будто это модель вращается, а камера неподвижна.

А если вы хотите вращать саму модель, то можно либо написать собственный UpdateCallback или EventCallback (пример osgcallback), либо использовать класс AnimationPath (пример osganimate), либо использовать классы из пространства имен osgAnimation, либо если вы хотите вращать модель именно мышкой, то можно использовать классы из пространства имен osgManipulator (пример osgmanipulator).

  • 1
?

Log in