УДАЛЕНИЕ НЕВИДИМЫХ ЧАСТЕЙ
3.5. Z-отсечение
Необходимость в этой процедуре возникает, когда, в конце концов, оказывается,
что надо нарисовать грань, у которой часть вершин лежит перед камерой, а
часть - за камерой. То есть грань, пересекающуюся с экраном. Сама по себе
она правильно не нарисуется.
Поскольку камера видит только то, что перед ней находится, все те точки, для
которых z < -dist, рисовать не надо. То есть, каждую грань надо обрезать
плоскостью z = -dist. Принципиально различных случаев расположения грани
относительно этой плоскости может быть всего четыре; когда перед камерой
находятся соответственно 0, 1, 2 или 3 вершины. Первый и последний случаи
тривиальны - если перед камерой находится 0 вершин, то грань просто не видна
и рисовать ее не надо; если 3 вершины, то грань видна целиком и полностью и
ее достаточно просто взять и нарисовать. Рассмотрим оставшиеся два случая.
Случай первый, когда перед камерой находится только одна вершина:
В этом случае перед камерой находится только треугольник CDE. Его и надо
будет нарисовать вместо грани.
Случай второй, когда перед камерой находятся две вершины:
Здесь уже надо будет нарисовать трапецию DABE; она разбивается на два
треугольника, DAB и DBE. Их и рисуем вместо грани.
Координаты и текстурные координаты для точек D, E считаются совсем просто:
с одной стороны, D лежит на AC, с другой стороны, D.z = -dist. Для точки D
как лежащей на AC любая величина t (вместо t подставляем x/y/u/v) считается
следующим образом:
D.t = A.t + (C.t - A.t) * (D.z - A.z) / (C.z - A.z) =
A.t + (C.t - A.t) * (-dist - A.z) / (C.z - A.z)
Все это сводится в следующий алгоритм отрисовки грани:
- выясняем, сколько вершин лежит перед камерой; то есть - какой из случаев мы имеем;
- ставим точки A, B, C в соответствие с вершинами (то есть, если
вершина v0 находится перед камерой, а вершины v1, v2 - нет, то
имеем первый случай, где C = v0, A = v1, B = v2);
- считаем, если нужно, координаты D, E;
- рисуем (или добавляем в список отрисовки) полученные треугольники.
Осталось только добавить, что обрезание на самом деле надо проводить не
плокостью z = -dist, а плоскостью z = -dist + smallvalue, smallvalue > 0,
чтобы избежать проблем при проецировании.