Слишком часто я вижу, как способный разработчик исследует новую структуру данных или алгоритм, но его сдерживают инструменты визуализации, которыми он обладает. Часто они заканчивают тем, что пытаются визуализировать сложные 3D-среды в 2D-картах OpenCV в градациях серого, потому что они никогда не сталкивались с нужными инструментами.

OpenSceneGraph много раз помогал мне отлаживать мои алгоритмы. Во многих случаях визуальные тесты алгоритма более полезны и менее подвержены ошибкам, чем программные тесты (хотя рекомендуются оба). А поскольку OSG является кросс-платформенной и с открытым исходным кодом, мне не нужно беспокоиться о смене окружения.

Это руководство предназначено в качестве трамплина, чтобы помочь тем разработчикам, которые хотят визуализировать 3D-сцены практичным и эффективным способом, не беспокоясь о реалистичных тенях, прозрачности и других эффектах. Если это похоже на вас, продолжайте читать!

Введение

Это руководство задумано как трамплин для новых разработчиков, желающих изучить OpenSceneGraph. Таким образом, это не самое полное и подробное руководство по множеству возможностей OpenSceneGraph, но оно поможет вам встать на ноги, чтобы вы, по крайней мере, знали, что искать в Google и как анализировать форумы. Я не буду вдаваться в установку OpenSceneGraph — надеюсь, вы разберетесь с этим самостоятельно.

Для справки: после установки, если вы не знаете, как связать свои практические примеры с библиотекой OpenSceneGraph, вот пример файла CMakeLists.txt, который поможет вам начать работу.

Умные указатели

Прежде чем мы углубимся в графы сцен, просто имейте в виду, что OSG поставляется с собственным брендом интеллектуальных указателей, который называется osg::ref_ptr<>. Как и std::shared_ptr<>, к которому вы, возможно, привыкли, эти указатели ведут подсчет количества ссылок на объект и автоматически удаляют объект, когда его счетчик ссылок падает до нуля. В отличие от std::shared_ptr<>, счетчик ссылок в OSG также увеличивается, когда объект добавляется в граф сцены, и аналогичным образом уменьшается, когда объект удаляется. Как правило, рекомендуется использовать эти интеллектуальные указатели как можно чаще. В примерах вы обнаружите, что даже вспомогательные методы для создания объектов OSG обычно возвращают интеллектуальный указатель на созданный объект, а не обычный указатель. Такие хорошие практики помогут предотвратить удаление наших объектов под нами, когда мы меньше всего этого ожидаем.

Узлы

Прежде всего, OpenSceneGraph предназначен для построения графика, и для целей этого руководства мы можем абстрагироваться от особенностей того, как этот график на самом деле визуализируется в 2D-изображение, которое появляется на вашем экране, и вместо этого беспокоиться о создании только этого графика. На самом деле, давайте еще больше упростим: для большинства целей ваш граф сцены будет просто деревом сцены.

Теперь дерево состоит из узлов, один из которых является корнем. Это корень вашей сцены, и позже вы увидите, что мы указываем setSceneData(root), чтобы определить точку, с которой начинается рендеринг. Все остальные узлы будут иметь одного родителя (по крайней мере, в этом руководстве) и ноль или более дочерних узлов. Существует два основных типа узлов: групповые узлы и листовые узлы. У групп может быть один или несколько дочерних элементов, и они могут применять какое-либо преобразование или специальные свойства ко всем нижестоящим дочерним элементам. Листовые узлы, с другой стороны, не могут иметь потомков. Они описывают какую-то геометрию или конкретный 2D/3D-объект в сцене, например треугольник или модель .obj или .3ds, импортированную из программы САПР.

Жеоды

Итак, давайте сразу приступим к делу. Жеоды — это особый тип узлов, которые содержат геометрию; на самом деле geode является сокращением от узла геометрии. Способ их использования состоит в том, чтобы создать один или несколько osg::Drawable, определяющих некоторую геометрию (например, линию, треугольник, сферу, текст и т. д.), и добавить их к вашему жеоде с помощью geode->addDrawable(geom). Затем добавьте свою геодезию в граф сцены под групповым узлом с помощью group->addChild(geode).

Давайте остановимся на трех типах рисунков, которые вы можете использовать внутри жеодов — геометрии, формы (да, они разные) и текст.

Геометрии

Геометрии — это настраиваемые пользователем формы. Комбинируя отдельные фигуры, такие как треугольники и четырехугольники, вы можете создавать такие простые фигуры, как шестиугольники, или такие сложные, как пятиугольные трапецеэдры, или любые формы, которые вы можете себе представить, включая облака точек и невыпуклые полумесяцы. Начнем с создания треугольника.

Если вы создадите и запустите это, вы сможете запустить окно с зеленым треугольником, который вы можете вращать, щелкая и перетаскивая мышь. Поиграйте с этим. Попробуйте добавить 6 вершин вместо 3 и изменить тип примитива с TRIANGLES на LINE_LOOP. Теперь переключите его на LINES или LINE_STRIP Можете ли вы сказать, что они делают?

В данном случае мы выбрали BIND_OVERALL, что означает, что мы назначили один цвет для всей геометрии. Но на самом деле мы можем назначить отдельные цвета для каждой вершины — OSG смешивает цвета для вас, если вы добавите еще два цвета в массив colors и замените BIND_OVERALL на BIND_PER_VERTEX.

Освещение используется для затемнения и осветления объектов сцены в зависимости от направления источника света сцены. Для наших целей они просто затрудняют просмотр деталей, поэтому мы отключаем их. Смешивание позволяет использовать полезные эффекты, такие как прозрачность, поэтому мы оставляем его включенным.

Указав TRIANGLES для геометрии, мы определили, что хотим интерпретировать каждые три вершины как новый треугольник. Конечно, есть много других примитивных типов. Вот неполный список для начала:

Формы

Существует множество других базовых фигур для быстрого добавления 3D-объектов в сцены, например Sphere, Box, Cone и Cylinder. Они ведут себя аналогично геометриям в том смысле, что присоединяются к жеодам с помощью addDrawable().

Текст

Добавление текста в сцены осуществляется с использованием пространства имен osgText. Просто создайте объект osgText::Text и прикрепите его к жеоде с помощью addDrawable(). Общие методы, используемые с текстом:

  • setText()
  • setPosition()
  • setFont()
  • setColor()
  • setAxisAlignment() Разместите текст на XY, YZ, XZ или других плоскостях.
  • setAlignment() Параметры здесь включают центрирование, выравнивание по левому краю, выравнивание по правому краю и т. д.
  • setCharacterSize()

Группы

Как упоминалось ранее, группы — это просто тип узла в графе сцены, который содержит дочерние элементы. Некоторые группы, такие как osg::Group, не имеют каких-либо особых свойств — они просто помогают организовать график вашей сцены понятным образом. Другие применяют специальные свойства к своим потомкам.

Ниже приведен фрагмент кода с кратким примером того, как использовать группы в графе сцены. Чтобы запустить фрагмент кода, вам нужно скачать пример набора данных для вашей версии OpenSceneGraph здесь, разархивировать его в папку и указать переменную среды OSG с именем $OSG_FILE_PATH в эту папку, чтобы файлы можно было найти во время выполнения. . Если вы не установите $OSG_FILE_PATH, вам придется указать пути к каждой модели, например, cessna.osg.

Превращает

«Это закрывает объекты в сцене, но как вы на самом деле перемещаете их по сцене?» Вы можете быть удивлены. Ну, есть два основных способа преобразования объектов в OSG: PositionAttitudeTransform и MatrixTransform. Оба идентичны по своим функциональным возможностям, но их интерфейсы различаются.

Для PositionAttitudeTransforms или сокращенно PAT вы применяете setPosition(), setAttitude() и/или setScale() для преобразования всех дочерних элементов ниже по течению в графе сцены. Вы можете себе представить, как это можно использовать для создания руки робота в OSG — относительно линейного графа сцены, где каждое соединение руки будет добавляться под своим собственным osg::PositionAttitudeTransform, который сам будет потомком предыдущего соединения руки. Изменение положения или положения любой связи автоматически трансформирует последующие связи.

MatrixTransforms ведут себя так же, но вместо установки положения или отношения вы устанавливаете Matrix.

В этом случае мы видим, что планер перемещается по оси x и вращается относительно начала сцены, отмеченного набором осей. Обратите внимание, что viewer.run() в предыдущих примерах автоматически прикреплял для нас к сцене манипулятор. Когда мы используем viewer.frame(), мы должны создать и прикрепить свои собственные, чтобы включить масштабирование и панорамирование.

Переключатели

Переключатели используются для выборочного скрытия или отображения объектов на сцене. Трудно найти где-либо записанное это, но, как правило, не рекомендуется часто использовать removeChildren() из графа сцены — скорее, вам следует использовать osg::Switch или node->setNodeMask(), чтобы скрывать и показывать свои узлы. Чтобы использовать переключатель, инициализируйте переключатель, добавьте его в сцену, дайте ему несколько дочерних элементов и используйте setChildValue() или setSingleChildOn(), чтобы сделать их видимыми или невидимыми.

LOD (уровень детализации)

Узлы группы LOD используются для того, чтобы сделать объекты видимыми или невидимыми в зависимости от расстояния камеры от объекта. Когда вы добавляете ребенка, вы также указываете диапазон, например: lod->addChild(node, 0, 1000). Узлы уровня детализации часто используются для подкачки данных ландшафта — например, при значительном увеличении масштаба некоторые тайлы ландшафта с высоким разрешением могут быть заменены фрагментами с более низким разрешением, что снижает нагрузку на систему и приводит к более плавной сцене (все без пользователь знает).

Вывод

Что ж, это краткий обзор OpenSceneGraph. Конечно, это гораздо больше, включая обработку взаимодействий с мышью с помощью пересечений, взаимодействие с клавиатурой с помощью обработчиков событий, другие типы манипуляторов, а также автопреобразования и рекламные щиты — возможно, для другой записи в блоге. До тех пор одни только эти принципы помогут вам быстро создавать сложные трехмерные среды для визуализации ваших алгоритмов. Подробнее см. в Кратком руководстве по OSG. По мере того, как вы будете более знакомы, вы даже сможете воспользоваться преимуществом открытого исходного кода OSG и изучить исходный код таких приложений, как osgViewer, утилита командной строки, поставляемая с OSG. Пожалуйста, не стесняйтесь делиться своими приключениями и помните: игра делает совершенным!