Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Алгоритмы / Графика / demodesign 3D programming FAQ /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Удаление невидимых частей - Программирование от RIN.RU
Удаление невидимых частей



Порталы


Этот метод предназначен для т.н. indoor environments - в буквальном переводе "комнатная среда"; это как бы внутренность какого-то здания. В качестве примера могут служить Doom, Quake.


В этом случае сцена составляется из комнат. Комнаты связаны друг с другом какими-то проходами - дверями, окнами, чем угодно. На каждый такой проход вешается обычный полигон, называемый порталом. Для отрисовки сцены достаточно нарисовать текущую комнату вместе с тем, что из нее видно. Но то, что из нее видно, может быть видно *только* через порталы.


Таким образом, для отрисовки всей сцены мы просто берем и рисуем текущую комнату, используя любые методы удаления невидимых частей (например, алгоритм художника и отброс нелицевых граней). А если в процессе отрисовки нам встречается полигон, помеченный как портал, то мы рисуем комнату, которую видно через этот портал, причем отсекаем ее уже по проекции этого портала.


Как обычно, кусок кода для уяснения:



// ...
void drawRoom(int roomID, polygon *clipArea) {
int i;


for (i = 0; i < rooms[roomID].numFaces; i++)
drawFace(&rooms[roomID].face[i], clipArea);
}


void drawFace(polygon *face, polygon *clipArea) {
polygon *newClipArea;


if (face->isPortal) {
if (isVisible(face, clipArea) {
newClipArea = clipPolygon(face, clipArea);
drawRoom(face->destinationRoom, newClipArea);
}
} else drawClippedPolygon(face, clipArea);
}


// ...


drawRoom(currentRoom, fullScreen);


// ...




Здесь функция isVisible(face, clipArea) возвращает false, если грань face и область отсечения clipArea не пересекаются; функция clipPolygon возвращает пересечение полигонов face и clipArea (то есть отсекает face в clipArea и наоборот); fullScreen - полигон размером с экран (или любую нужную область отрисовки).


В природе есть Alpha 2 - готовый engine, использующий порталы и написанный на TMT Pascal, причем, что приятно, доступный в исходниках. Есть, впрочем, надежда, что найти этот engine особых проблем не составит.


Осталось упомянуть, что несмотря на то, что в изложенной форме метод и требует возможности отрисовки произвольной грани, отсеченной в произвольную грань, можно обойтись и отсечением по bounding box проекции портала.


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, чтобы избежать проблем при проецировании.


<<<  НазадВперед  >>>
 1  2  3 


 8  Комментарии к статье  8  Обсудить в форуме  8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь