Document 198400

advertisement
В предыдущем разделе была представлена концепция управления памятью в OSG. Если вам не знаком подсчет
ссылок памяти, то лучше посмотреть на реальные OSG примеры, для лучшего понимания. В этом разделе
представлена простая OSG программа, которая использует технику управления памятью описанную ранее, и
знакомит вас с построением графа сцены с помощью OSG классов содержащих геометрию. На первый взгляд
код может показаться громоздким, поскольку вы еще не знакомы со многими классами. Подробное объяснение
геометрических классов дается в комментариях в исходном коде.
Листинг 2-1 широко использует шаблонный класс ref_ptr<>, описанный в предыдущем разделе. Все выделения
памяти в Листинге 2-1 с подсчетом ссылок. Даже функция createSceneGraph() возвращает ref_ptr<>, созданного
графа сцены. (Проще говоря, код в Листинге 2-1 мог бы быть написан полностью с использованием обычных
C++ указателей, а возвращенный указатель сохранялся бы в ref_ptr<>. Тем не менее, является хорошей
практикой использование ref_ptr<> в вашем приложении, поскольку это автоматизирует освобождение памяти
даже в случае исключений или преждевременного выхода из функции. В примерах кода этой книги
используется ref_ptr<> для поддержки этой хорошей практики.)
Листинг 2-1
Построение простого графа сцены
Это отрывок из кода Простого примера идущего вместе с книгой. Функция createSceneGraph() определяет
геометрию для единственного прямоугольного примитива. Прямоугольник имеет разный цвет вершин, но
общую нормаль для всего примитива.
#include <osg/Geode>
#include <osg/Geometry>
osg::ref_ptr<osg::Node> createSceneGraph()
{
// Создать объект для хранения в нем геометрии.
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// Создать массив для хранения четырех вершин.
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray( v.get() );
v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );
// Создать массив их четырех цветов
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
geom->setColorArray( c.get() );
geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );
c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
// Создать массив содержащий одну нормаль.
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
geom->setNormalArray( n.get() );
geom->setNormalBinding( osg::Geometry::BIND_OVERALL );
n->push_back( osg::Vec3( 0.f, -1.f, 0.f ) );
// Получить прямоугольник из четырех вершин из ранее подготовленных данных.
geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
// Добавить Geometry (Drawable) в Geode и вернуть Geode.
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable( geom.get() );
return geode.get();
}
Код в Листинге 2-1 создает граф сцены с одним узлом. На рисунке 2-3 показан этот предельно простой граф
сцены. Этот один узел графа сцены имеет образовательную цель для новичков. Реальные графы сцен гораздо
сложнее.
Обратите внимание, что код в Листинге 2-1 определяет четыре вершины в плоскости y=0. Подобно OpenGL,
OSG не налагает ограничений на систему координат, используемую приложением. Тем не менее, по умолчанию
Рисунок 2-3
Листинг 2-1 графа сцены
В Листинге 2-1 создается граф сцены состоящий из одного Geode.
библиотека osgViewer использует мировую систему координат, которая ориентированна положительный x
вправо, положительный z вверх, и положительный y в экран. Это работает в большинстве приложений, в
которых земная поверхность находится в xy плоскости. Глава 3, Использование OpenSceneGraph в Вашем
Приложении, описывается как изменить систему мировых координат на отличную от по умолчанию. Код в
Листинге 2-1 использует ориентацию по умолчанию для отображения четырехугольника, обращенного к
наблюдателю.
В дополнение к созданному графу сцены, как показано в Листинге 2-1, вы так же захотите его отобразить или
анимировать. Примеры в этой главе используют приложение osgviewer для отображения графа сцены,
поскольку написание кода для отображения будет представлено только в Глава 3, Использование
OpenSceneGraph в Вашем Приложении. Для отображения графа сцены в приложении osgviewer, вам
необходимо записать его на диск. В Листинге 2-2 показан код, который вызывает функцию из Листинга 2-1, и
записывает граф сцены на диск в .osg файл. После того как граф сцены записан на диск, вы можете
использовать osgviewer для просмотра того, как выглядит результат.
Листинг 2-2
Запись графа сцены на диск
В этом листинге показана точка входа main() примера Простой программы. Из main() вызывается
createSceneGraph() из Листинга 2-1, где создается граф сцены, затем этот граф сцены записывается на диск в
файл с именем “Simple.osg”.
#include <osg/ref_ptr>
#include <osgDB/Registry>
#include <osgDB/WriteFile>
#include <osg/Notify>
#include <iostream>
using std::endl;
osg::ref_ptr<osg::Node> createSceneGraph();
int main( int, char** )
{
osg::ref_ptr<osg::Node> root = createSceneGraph();
if (!root.valid())
osg::notify(osg::FATAL) << "Failed in createSceneGraph()." << endl;
bool result = osgDB::writeNodeFile(
*(root.get()), "Simple.osg" );
if ( !result )
osg::notify(osg::FATAL) << "Failed in osgDB::writeNodeFile()." << endl;
}
После вызова функции из Листинга 2-1 создающего граф сцены, код из Листинга 2-2 записывает его на диск в
виде файла с именем “Simple.osg”. Формат файла .osg это принадлежащий OSG текстовой ASCII формат
файла. Поскольку это ASCII файл, файлы .osg медленно загружаются да к тому же еще и велики, поэтому это
формат редко используется в промышленном коде. Тем не менее, очень полезно для отладки в процессе
разработки и быстрой демонстрации.
Код в Листинге 2-1 и 2-2 из Простого примера идущего вместе книгой. Если вы этого еще не сделали, скачайте
исходный код примера с Web сайта этой книги, откомпилируйте и запустите его. После запуска примера вы
найдете выходной файл Simple.osg в вашей рабочей директории. Для того чтобы посмотреть, как выглядит граф
сцены, используйте osgviewer:
osgviewer Simple.osg
osgviewer должен дать результат похожий представленному на Картинке 2-4. В Главе 1 описывается osgviewer
и как им пользоваться. Например, вы можете вращать отображаемую геометрию с помощью левой кнопки
мыши и приближать или удалять с помощью правой.
Код из Листинга 2-1 широко использует классы геометрии OSG. Далее дается на более высоком уровне
объяснение как пользоваться этими классами.
Рисунок 2-4
Простой пример графа сцены отображаемый в osgviewer’е
На картинке показан квадрат созданный в Листинге 2-1, а после записанный в файл .osg в коде Листинга 2-2 и
отображенный с помощью osgviewer’a.
2.2.1 Обзор Классов Геометрии
Код в Листинге 2-1 может сбивать с толку, но в сущности в нем выполняется только три операции.
1. Он создает массив вершин, нормалей и данные о цвете
2. Он создает объект osg::Geometry и добавляет в него массивы. Он так же добавляет объект
osg::DrawArrays для определения как рисовать данные.
3. Он создает узел графа сцены osg::Geode и добавляет объект Geometry в него.
В этом разделе рассматривается каждый из этих шагов подробно.
Классы Vector и Array
В OSG определен богатый набор классов для хранения векторных данных, таких как вершины, нормали, цвета и
текстурные координаты. osg::Vec3 это массив трехкомпонентных чисел с плавающей запятой; используйте его
для определения данных векторов и нормалей. Используйте osg::Vec4 для определения данных цвета и
osg::Vec2 для 2D текстурных координат. В дополнение к простому хранению эти классы обеспечивают полный
набор методов для расчета длины, векторного и скалярного произведения, сложения векторов и векторноматричного умножения.
В OSG определены шаблонные классы массивов для хранения объектов. Наиболее часто используемые
шаблонные классы массивов предназначены для хранения векторных данных. В связи с тем фактом что они
часто используются OSG предоставляет определение типов для массивов векторных данных - osg::Vec2Array,
osg::Vec3Array, и osg::Vec4Array.
В Листинге 2-1 создаются отдельные трехкомпонентные вектора для каждой xyz вершины с помощью Vec3,
затем каждый Vec3 сохраняется в конец Vec3Array. Код использует Vec3Array похожим образом для
хранения xyz данных нормалей. В Листинге 2-1 используется Vec4 и Vec4Array для данных о цвете,
поскольку цвет определяется четырьмя компонентами (красный, зеленый, синий и альфа). Позже в этой главе
будет представлен код примера, который использует Vec2 и Vec2Array для хранения двухэлементных
текстурных координат.
Типы массивов наследуются от std::vector, поэтому они поддерживают метод push_back() для добавления
новых элементов, как показано в Листинге 2-1. Как дочерний класс std::vector, классы массивов так же
поддерживают методы resize() и operator[]().
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray( v.get() );
v->resize( 4 );
(*v)[ 0 ] = osg::Vec3( -1.f, 0.f, -1.f );
(*v)[ 1 ] = osg::Vec3( 1.f, 0.f, -1.f );
(*v)[ 2 ] = osg::Vec3( 1.f, 0.f, 1.f );
(*v)[ 3 ] = osg::Vec3( -1.f, 0.f, 1.f );
Рисуемые
OSG определяет класс osg::Drawable, для хранения данных отображения. Drawable это виртуальный базовый
класс, который не создается непосредственно. OSG предоставляет три производных класса от Drawable.



osg::DrawPixels—DrawPixels это надстройка вокруг команды glDrawPixels().
osg::ShapeDrawable—ShapeDrawable предоставляет доступ к нескольким предопределенным
геометрическим формам, таким как цилиндры и сферы.
osg::Geometry—Geometry это гибкий класс для хранения и отображения геометрии общего
назначения. Пример кода использует Geometry, который является наиболее часто используемым
производным классом.
Если вы уже знакомы с массивами вершин в OpenGL, класс Geometry вам будет легко использовать. Geometry
предоставляет интерфейс, который позволяет вашему приложению определять массивы данных вершин, как их
интерпретировать и отображать. Аналогично с определением данных массива вершин в OpenGL (с помощью
glVertexPointer() и glNormalPointer()) и отображением массива вершин (с помощью glDrawArrays() и
glDrawElements()). Код из Листинга 2-1 использует следующие методы Geometry:
Download