Введение
В настоящее время одними из приоритетных направлений информационных технологий является трёхмерная графика и 3D-моделирование. Трёхмерная графика оперирует с объектами в трёхмерном пространстве, отображаемыми, как правило, на двумерном устройстве.
Компьютерная графика нашла широкое практическое применение. Речь идёт о компьютерных играх, пространственных моделях, удобном представлении изображений деталей устройств и машин, решении математических задач, связанных со свойствами поверхностей и геометрических тел, и т.д.
Инженеры и архитекторы используют трёхмерную графику для создания виртуальных моделей. Кинематографисты и разработчики компьютерных игр создают спецэффекты и анимацию, реалистичные ландшафты и прочие изображения объектов реального мира.
При разработке 3D-моделей в настоящее время часто применяется программный интерфейс OpenGL, который стандартизирует доступ к графической аппаратуре путём смещения ответственности за создание аппаратного драйвера на производителя графического устройства. [1] Это позволяет разработчикам программного обеспечения использовать более высокий уровень абстракции от графического оборудования, что значительно ускорило создание новых программных продуктов и снизило на них затраты. Например, не требуется предусматривать функции проецирования трёхмерных объектов на двумерную систему координат устройства вывода [3], что пришлось бы делать, например, если выполнять разработку, используя чисто функции GDI.
В данном проекте рассматривается работа с 3D-моделью лабиринта с помощью OpenGL, а также создание некоторых спецэффектов - тумана, снега, динамического освещения.
Техническое задание
В рамках данного курсового проекта требуется создать 3D-модель лабиринта с вертикальными стенами. Разработка программы должна осуществляться в любой визуальной среде с обязательным использованием графических библиотек OpenGL или аналогичных (например, DirectX). Необходимо обеспечить возможность рассмотреть сцену с разных сторон.
Разработка структур данных
Иерархия объектов в пространстве
Модель лабиринта целесообразно представить как иерархическую, то есть состоящую из двух типов объектов: 1) отдельные полигоны; 2) модели частей лабиринта, состоящие из полигонов или моделей более малых частей. При такой формулировке естественно представить модель лабиринта в виде дерева (см. рис. 2.1). Отдельные полигоны в данном случае хранятся в листьях. Корень соответствует всей модели.
данная тип графический алгоритм
Рис. 2.1 - Дерево модели лабиринта
Пользовательские типы данных
Целесообразно ввести ряд пользовательских типов данных.
. Структура данных точка - в принципе не предоставляет некоторых новых функций, но позволяет работать с координатами точки как с данными одного объекта, а не разрозненными данными, а также задействовать элементы объектно-ориентированного программирования для более удобной работы с 3D-моделями.
struct Point3D /* структура ТОЧКА */
{x, y, z;
/* основные методы */
/* заполнение полей структуры */
void FillFields(double x, double y, double z)
{>x = x;>y = y;
this->z = z;
}
/* отрисовка точки либо выбор вершины полигона */
void Vertex() { glVertex3f(x, y, z); }
… /* другие методы */
};
Структура данные о клетке лабиринта - хранит данные о том, какие изображения будут использоваться на каждом из 4 кусков стен, соответствующих данной клетке. Каждому изображению соответствует его номер, а если соответствующего куска стены нет (например, если данная клетка находится у входа в лабиринт, то как минимум одного куска нет), то в качестве номера берётся специальное значение.
FieldInfo /* структура ДАННЫЕ О КЛЕТКЕ ЛАБИРИНТА */
{
/* номер изображений каждой из стенок
(0, если стенки нет) */
int TextureBack, TextureRight, TextureFront, TextureLeft;
… /* методы */
};
Структура данные о модели лабиринта - хранит данные обо всех клетках лабиринта. Содержит размеры лабиринта и матрицу типа FieldInfo. Такая организация данных может на первый взгляд показаться избыточной - если у двух клеток лабиринта есть общая стена, то факт её наличия указывается в двух местах. Но при такой организации данных можно предусмотреть ситуацию, когда эта общая стена выглядит по-разному со стороны каждой из клеток - например, с одной стороны это просто деревянная стена, с другой стороны на стене что-то нарисовано.
ModelInfo /* структура ДАННЫЕ О МОДЕЛИ ЛАБИРИНТА */
{Nx, Nz; /* размеры (всего будет Nx * Nz клеток) */FIELDS[10][10]; /* данные о клетках */
… /* методы */
};
Структура данных узел дерева модели - в случае листа хранит вершины соответствующего полигона и номер изображения, накладываемого на полигон, а в случае внутреннего узла - указатели на дочерние узлы и счётчик дочерних узлов. Теоретически дерево модели можно представить с помощью двух типов узлов - полезные (листья, хранят полигоны) и вспомогательные (внутренние узлы, хранят ссылки на другие узлы), но с точки зрения программной реализации проще ограничиться одним типом узлов, в качестве полей предусмотрев все возможные данных - как ссылочные, так и полезные. В этом случае признаком листа является нулевое значение счётчика дочерних узлов.
Node /* структура данных УЗЕЛ ДЕРЕВА МОДЕЛИ */
{D Square[4]; /* вершины соответствующего полигона (нужны только для листьев) */texture_type; /* номер изображения, которое нужно наложить на полигон (нужен только для листьев) */n_children; /* количество детей (для листьев равно 0, для остальных узлов чему угодно) */*Children[100]; /* дети (не используется при обработки листьев) */Draw(); /* отрисовка для поддерева, где текущий узел - корень */() {n_children = 0; } /* конструктор */
};
В файле лабиринт, содержащий m x n клеток, целесообразно хранить как таблицу из m x n четвёрок номеров. В каждой четвёрке - номера изображений стен соответствующей клетки. Если какая-то стена отсутствует, соответствующий номер приобретает специальное значение (в данной работе - нулевое).