Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
8. Трехмерное моделирование полигональными сетк...doc
Скачиваний:
9
Добавлен:
23.11.2019
Размер:
310.27 Кб
Скачать

8. Трехмерное моделирование полигональными сетками

8.1. Полигональная сетка

Полигональная сетка – набор полигонов или «граней», которые в совокупности образуют форму объекта. Полигональная сетка является (практически во всех графических системах) стандартным способом представления широкого класса объемных форм.

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

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

glBegin(GL_POLYGON);

glNormal3f (x, y, z); // n1

glVertex3f (x, y, z); // v1

glNormal3f (n1);

glVertex3f (v2);

glNormal3f (n1);

glVertex3f (v3);

glNormal3f (n1);

glVertex3f (v4);

glEnd();

Функция glNormal3f(x, y, z) устанавливает вектор нормали текущим. В режиме glBegin(GL_POLYGON) текущий вектор нормали посылается в конвейер вместе с каждой вершиной полигона. Поэтому предыдущую конструкцию можно записать так:

glBegin(GL_POLYGON);

glNormal3f (x, y, z); // n1

glVertex3f (v1);

glVertex3f (v2);

glVertex3f (v3);

glVertex3f (v4);

glEnd();

Таким образом, полигональная сетка – совокупность полигонов вместе с нормальными векторами, связанными с каждой вершиной этих полигонов. При этом вектора нормалей всегда должны показывать внешнее направление от граней.

OpenGL не содержит средств моделирования геометрических объектов полигональной сеткой. Это – забота программиста. OpenGL также не содержит средств расчета нормалей. Это тоже забота программиста.

Вектора нормалей должны быть единичными (нормированными). Функция glEnable() с параметром GL_NORMALIZE включает нормирование векторов нормалей, функция glDisable() с тем же параметром – отключает.

Вектора нормалей подвергаются преобразованию матрицей VM.

8.2. Нахождение нормальных векторов

Если грань плоская, достаточно найти нормальный вектор к самой грани и связать его с каждой вершиной. Один из прямых способов показан на рис. 8.2:

После этого вектор n может быть нормирован. Здесь две проблемы:

1) если векторы (v1v2) и (v3v2) почти параллельны, то |n| будет малым и возможна погрешность вычислений;

2) полигон может оказаться неплоским и тогда за нормаль необходимо принимать усредненные значения.

Обе эти проблемы решает метод, разработанный Мартином Ньюэллом. Этот метод рассчитывает компоненты nx, ny и nz по следующим формулам:

N

Рис. 83. Нормальный вектор показывает направление наружу от грани при обходе вершин против часовой стрелки

– число вершин грани, xi, yi, zi – координаты i-й вершины грани, next(i)=(i+1)mod(N) – индекс следующей после i-й вершины при обходе грани. При этом если обход против часовой стрелки с наружной стороны грани совпадает с ростом i, то полученный вектор показывает направление наружу от грани (рис.8.3).

Грани тетраэдра являются его полигонами. Описание тетраэдра как списка полигонов приведено в листинге 8.1.

Листинг 8.1. Описание тетраэдра в OpenGL

//грань 0

glBegin(GL_POLYGON);

glNormal3f(0.577, 0.577, 0.577);

glVertex3f(1, 0, 0);

glVertex3f(0, 1, 0);

glVertex3f(0, 0, 1);

glEnd();

//грань 1

glBegin(GL_POLYGON);

glNormal3f(0, 0, -1);

glVertex3f(0, 0, 0);

glVertex3f(0, 1, 0);

glVertex3f(1, 0, 0);

glEnd();

//грань 2

glBegin(GL_POLYGON);

glNormal3f(-1, 0, 0);

glVertex3f(0, 0, 0);

glVertex3f(0, 0, 1);

glVertex3f(0, 1, 0);

glEnd();

//грань 3

glBegin(GL_POLYGON);

glNormal3f(0, -1, 0);

glVertex3f(1, 0, 0);

glVertex3f(0, 0, 1);

glVertex3f(0, 0, 0);

glEnd();

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]