| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- <!--
- demo.design 3D programming FAQ
- Idea, texts, screenshots:
- Andrew A. Aksyonoff,
- shodan@chat.ru
- Web-design, illustrations:
- Andrey Samoilov,
- asy@sense.simbirsk.su
- -->
- <html>
- <head>
- <title>demo.design 3D programming FAQ. Удаление невидимых частей. Отброс нелицевых граней.</title>
- <link rel=stylesheet href="../style.css" type="text/css">
- </head>
- <script language="javascript">
- <!--//
- browser = navigator.appName;
- version = parseFloat(navigator.appVersion);
- if (browser == "Netscape" && version >= 3.0) { jsenabled = 1; } else
- if (browser == "Microsoft Internet Explorer" && version >= 3.0) { jsenabled = 1; } else { jsenabled = 0; }
- function swap(img,ref) { if (jsenabled) {document.images[img].src = ref;} }
- function loadtocache(img,ref) { cache[img] = new Image(); cache[img].src = ref; }
- if (jsenabled) {
- cache = new Array();
- loadtocache(0,"../img/xdl.gif");
- loadtocache(1,"../img/xfaq.gif");
- loadtocache(2,"../img/xlinks.gif");
- loadtocache(3,"../img/xauthor.gif");
- loadtocache(4,"../img/xe.gif");
- loadtocache(5,"../img/xprev.gif");
- loadtocache(6,"../img/xnext.gif");}
- //-->
- </script>
- <body bgcolor=white><center>
- <!-- Title -->
- <img src="../img/b.gif" width=500 height=1 alt=""><br>
- <img src="../img/t.gif" width=500 height=1 alt=""><br>
- <img src="../img/b.gif" width=500 height=1 alt=""><br>
- <img src="../img/t.gif" width=500 height=2 alt=""><br>
- <table width=500 cellpadding=0 cellspacing=0 border=0>
- <td><img src="../img/t.gif" width=5 height=1 alt=""><a href="../main.htm" onmouseover="swap('logo','../img/xe.gif');" onmouseout="swap('logo','../img/e.gif');"><img src="../img/e.gif" name=logo width=60 height=50 hspace=10 border=0 alt=" в самое начало "></a></td>
- <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
- <td align=center><p class=navy><a href="../download.htm" onmouseover="swap('dl','../img/xdl.gif');" onmouseout="swap('dl','../img/dl.gif');"><img src="../img/dl.gif" name=dl width=40 height=40 border=0 hspace=5 alt=" download "></a><br>download</td>
- <td align=center><p class=navy><a href="../links.htm" onmouseover="swap('links','../img/xlinks.gif');" onmouseout="swap('links','../img/links.gif');"><img src="../img/links.gif" name=links width=40 height=40 border=0 hspace=5 alt=" коллекция линков "></a><br>links</td>
- <td align=center><p class=navy><a href="../author.htm" onmouseover="swap('author','../img/xauthor.gif');" onmouseout="swap('author','../img/author.gif');"><img src="../img/author.gif" name=author width=40 height=40 border=0 hspace=5 alt=" автора! "></a><br>author</td>
- </table>
- <img src="../img/t.gif" width=500 height=4 alt=""><br><img src="../img/b.gif" width=500 height=1 alt=""><br>
- <!-- Head -->
- <table width=500 cellpadding=0 cellspacing=10 border=0><td><div align=justify>
- <p class=title>
- <img src="../img/b3.gif" width=70 height=70 align=left hspace=0 alt="">
- <img src="../img/t.gif" width=5 height=70 align=left hspace=0 alt="">
- УДАЛЕНИЕ НЕВИДИМЫХ ЧАСТЕЙ<br>3.1. Отброс нелицевых граней
- <!-- Article -->
- <p>Пусть у нас есть объект, внутри которого камера заведомо не окажется. Обычно
- такие объекты составляют большую часть или всю сцену. Тогда для каждой грани
- мы можем увидеть только одну ее сторону - лицевую. Грань - плоскость, она
- делит все 3D пространство на два полупространства. Так вот, лицевую сторону
- видно только из одного полупространства, из того, в которое "смотрит" нормаль
- к этой грани, направленная *из* объекта. Проверив, в какое полупространство
- попадает камера, можно сразу определить, является ли грань лицевой (то есть,
- может ли камера увидеть лицевую сторону этой грани) и надо ли ее рисовать.
- <p>Пусть грань имеет вершины v1, v2, v3 и нормаль (nx,ny,nz). Тогда уравнение
- плоскости, в которой она лежит, будет иметь вид
- <p class=expression>nx*x+ny*y+nz*z+d = 0.
- <p>d находим из того факта, что v1 в плоскости лежит:
- <p class=expression>nx*v1.x+ny*v1.y+nz*v1.z+d = 0,<br>
- d = -(nx*v1.x+ny*v1.y+nz*v1.z).<br>
- <p>Функция nx*x+ny*y+nz*z+d принимает положительные значения по одну сторону от
- плоскости, отрицательные по другую и равна нулю на самой плоскости. Точка
- (v1.x+nx,v1.y+ny,v1.z+nz) лежит, очевидно, в том полупространстве, откуда
- грань видно. Значение функции (назовем ее функцией видимости) в этой точке
- равно
- <p class=expression>nx*(v1.x+nx)+ny*(v1.y+ny)+nz*(v1.z+nz)+d =<br>
- nx*(v1.x+nx)+ny*(v1.y+ny)+nz*(v1.z+nz)-(nx*v1.x+ny*v1.y+nz*v1.z) =<br>
- nx*nx+ny*ny+nz*nz > 0.<br>
- <p>Таким образом, если значение функции в какой-то точке больше нуля, то грань
- из этой точки потенциально видна. Нас интересует видимость грани из нашей
- камеры, а камера у нас зафиксирована в точке (0,0,-dist). Таким образом,
- получаем, что грани, для которых
- <p class=expression>-nz*dist-(nx*v1.x+ny*v1.y+nz*v1.z) < 0,
- <p>или, что равносильно,
- <p class=expression>nz*dist+nx*v1.x+ny*v1.y+nz*v1.z > 0,
- <p>заведомо не видны и время на их обработку и отрисовку тратить не стоит.
- <p>Отдельный вопрос - как считать нормали к граням. Точнее, как выбрать одну
- из двух нормалей, которая будет смотреть из объекта. Обычно эта проблема
- решается еще на этапе построения 3D моделей - например, пакет 3D Studio
- записывает вершины граней в порядке A-B-C так, чтобы векторное произведение
- BA*CA и было нормалью. Еще один способ - выбрать внутренную точку для объекта
- (либо вручную, либо взять его центр тяжести, либо еще как-нибудь - методов
- может быть придумано сколько угодно) и использовать ее: если для этой точки
- функция видимости положительна, то есть грань якобы видна, то надо поменять
- знак nx, ny и nz.
- <p>Осталось отметить, что для выпуклых объектов этот метод полностью решает
- задачу об удалении невидимых частей. Для невыпуклых же он позволяет быстро и
- просто сократить число граней, подлежащих дальнейшей проверке на видимость и
- собственно отрисовке.
- </div>
- </td></table>
- <!-- Bottom Navigation -->
- <img src="../img/b.gif" width=500 height=1 alt=""><br><img src="../img/t.gif" width=500 height=2 alt=""><br>
- <table width=500 cellpadding=0 cellspacing=0 border=0>
- <td><img src="../img/t.gif" width=5 height=1 alt=""><a href="../main.htm" onmouseover="swap('logo2','../img/xe.gif');" onmouseout="swap('logo2','../img/e.gif');"><img src="../img/e.gif" name=logo2 width=60 height=50 hspace=10 border=0 alt=" в самое начало "></a></td>
- <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
- <td align=center><p class=navy><a href="25.htm" onmouseover="swap('prev','../img/xprev.gif');" onmouseout="swap('prev','../img/prev.gif');"><img src="../img/prev.gif" name=prev width=40 height=40 border=0 hspace=5 alt=" предыдущая статья "></a><br>previous</td>
- <td align=center><p class=navy><a href="../content.htm" onmouseover="swap('faq','../img/xfaq.gif');" onmouseout="swap('faq','../img/faq.gif');"><img src="../img/faq.gif" name=faq width=40 height=40 border=0 hspace=5 alt=" содержание "></a><br>content</td>
- <td align=center><p class=navy><a href="32.htm" onmouseover="swap('next','../img/xnext.gif');" onmouseout="swap('next','../img/next.gif');"><img src="../img/next.gif" name=next width=40 height=40 border=0 hspace=5 alt=" следующая статья "></a><br>next</td>
- </table>
- <img src="../img/t.gif" width=500 height=4 alt=""><br>
- <img src="../img/b.gif" width=500 height=1 alt=""><br>
- <img src="../img/t.gif" width=500 height=1 alt=""><br>
- <img src="../img/b.gif" width=500 height=1 alt=""><br>
- </center></body>
- </html>
|