- •«Северный (Арктический) федеральный университет имени м.В. Ломоносова»
- •«Северный (Арктический) Федеральный Университет имени м.В. Ломоносова»
- •Постановка задачи
- •Алгоритм удаления невидимых граней
- •Определение лицевых и не лицевых граней с помощью вектора нормали
- •2.4 Закраска трехмерного объекта с использованием простой модели освещения
- •Основные переменные и их предназначение
- •Результат
-
Алгоритм удаления невидимых граней
Так как в двумерном пространстве строится трехмерная модель, то из-за этого возникает эффект перекрытия граней, то есть грани отрисовываются в одном и том же месте. Чтобы этого избежать, следует показывать только лицевые грани, а невидимые грани удалять. Для этого воспользуемся алгоритмом Ньюла-Ньюэла-Санча, иначе называющимся алгоритм художника. Идея алгоритма художника, состоит в том, что, используя упорядоченность граней по глубине, выводится с закраской грани, начиная с дальних граней. При этом грани, которые выводятся позже, закрывают собою невидимые части более дальних граней. Часть этого метода работает в пространстве объекта, а часть в пространстве изображения. Он также работает для параллельной проекции, то есть с учетом того, что произведено перспективное преобразование.
Метод состоит из трех основных шагов:
1. упорядочение всех полигонов в соответствии с их наибольшими z-координатами;
2. разрешение всех неопределенностей, которые возникают при перекрытии z-оболочек многоугольников;
3. прорисовка каждого полигона, производимая в порядке уменьшения их наибольшей z-координаты.
Для нахождения среднего значения по координате Z, необходимо сложить значения координаты Z каждой из вершин полигона и поделить эту сумму на количество вершин. Это и будет среднее значение координаты Z полигона. Далее создадим массив, содержащий все средние значения, и попарно будем сравнивать их. Если данное значение будет меньше предыдущего, то значит, что полигон находится ближе к наблюдателю, а значит, будет рисоваться в последнюю очередь. Таким образом, грани будут появляться в порядке уменьшения значения Z.
Данный алгоритм отличается чрезмерной простотой реализации, и, как следствие, недостаточно эффективен. В самом деле, если трехмерная сцена состоит из большого количества объектов, в среднем половина полигонов будет не видна в текущем кадре. А значит, их отображение на экране и не требуется. Недостаток «алгоритма художника» состоит в том, что отображаются все полигоны.
-
Определение лицевых и не лицевых граней с помощью вектора нормали
Для сокращения числа полигонов можно вычислить для каждой грани вектор нормали, и по его значению определить грани, которые будут видны. Сразу стоит отметить то, что наша сцена состоит из прозрачного объекта и непрозрачного, поэтому немного модернизируем данный алгоритм.
Идея алгоритма состоит в том, что по углу между направлением взгляда и нормалью к поверхности можно определить расположение граней, лицевая она или же нет. Нормаль к поверхности находится с помощью трех точек, так как через любые три точки можно провести плоскость. Координаты вектора нормали следующие: N(Nx, Ny, Nz). Три точки поверхности имеют следующие координаты: A(Ax, Ay, Az), B(Bx, By, Bz), C(Cx, Cy, Cz). Уравнение плоскости задается в виде:
Nx * X + Ny * Y + Nz * Z + d = 0.
В результате получим следующую систему уравнений:

Преобразуем данную систему в матрицу размером 4Х4.

Найдем определитель данной матрицы по первой строке. Так как данная система уравнений имеет нетривиальное решение, то определитель данной матрицы равен 0. В результате получаем:
Nx =
,
Ny =
,
Nz =
.
Значение d для определения координат вектора не нужно. Итак, координаты вектора нормали имеют вид:
Nx = Ay(Bz - Cz) + By(Cz - Az) + Cy(Az - Bz);
Ny = Az(Bx - Cx) + Bz(Cx - Ax) + Cz(Ax - Bx);
Nz = Ax(By - Cy) + Bx(Cy - Ay) + Cx(Ay - By).
Осталось привести вектор нормали к единичной длине, так как для определения косинуса угла между векторами проще использовать единичные векторы. Для этого нужно определить длину вектора и разделить на нее каждую координату. Для каждой грани при инициализации объекта нужно посчитать вектор нормали, привести к единичной длине и сохранить его координаты в структуре соответствующей грани. Кроме того, при каждом повороте сцены векторы нормали нужно тоже пересчитывать (но перспективную проекцию находить не следует).
Для реализации данного алгоритма нам потребуется только координата Nz. Значение получим по формуле: Nz = Nz/ (Корень(Nx*Nx + Ny*Ny + Nz*Nz)).
Если Nz > 0, то грань не видна, если Nz < 0, то грань видна. Так как у нас на сцене имеется прозрачный объект, у которого должны прорисовываться все грани, то выполним оба условия на проверку видимости граней.
