24.htm 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <!--
  2. demo.design 3D programming FAQ
  3. Idea, texts, screenshots:
  4. Andrew A. Aksyonoff,
  5. shodan@chat.ru
  6. Web-design, illustrations:
  7. Andrey Samoilov,
  8. asy@sense.simbirsk.su
  9. -->
  10. <html>
  11. <head>
  12. <title>demo.design 3D programming FAQ. Основы 3D графики. Рисование одноцветного треугольника.</title>
  13. <link rel=stylesheet href="../style.css" type="text/css">
  14. </head>
  15. <script language="javascript">
  16. <!--//
  17. browser = navigator.appName;
  18. version = parseFloat(navigator.appVersion);
  19. if (browser == "Netscape" && version >= 3.0) { jsenabled = 1; } else
  20. if (browser == "Microsoft Internet Explorer" && version >= 3.0) { jsenabled = 1; } else { jsenabled = 0; }
  21. function swap(img,ref) { if (jsenabled) {document.images[img].src = ref;} }
  22. function loadtocache(img,ref) { cache[img] = new Image(); cache[img].src = ref; }
  23. if (jsenabled) {
  24. cache = new Array();
  25. loadtocache(0,"../img/xdl.gif");
  26. loadtocache(1,"../img/xfaq.gif");
  27. loadtocache(2,"../img/xlinks.gif");
  28. loadtocache(3,"../img/xauthor.gif");
  29. loadtocache(4,"../img/xe.gif");
  30. loadtocache(5,"../img/xprev.gif");
  31. loadtocache(6,"../img/xnext.gif");}
  32. //-->
  33. </script>
  34. <body bgcolor=white><center>
  35. <!-- Title -->
  36. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  37. <img src="../img/t.gif" width=500 height=1 alt=""><br>
  38. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  39. <img src="../img/t.gif" width=500 height=2 alt=""><br>
  40. <table width=500 cellpadding=0 cellspacing=0 border=0>
  41. <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>
  42. <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
  43. <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>
  44. <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>
  45. <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>
  46. </table>
  47. <img src="../img/t.gif" width=500 height=4 alt=""><br><img src="../img/b.gif" width=500 height=1 alt=""><br>
  48. <!-- Head -->
  49. <table width=500 cellpadding=0 cellspacing=10 border=0><td><div align=justify>
  50. <p class=title>
  51. <img src="../img/b2.gif" width=70 height=70 align=left hspace=0 alt="">
  52. <img src="../img/t.gif" width=5 height=70 align=left hspace=0 alt="">
  53. ОСНОВЫ 3D ГРАФИКИ<br>2.4. Рисование одноцветного треугольника
  54. <!-- Article -->
  55. <p>Без понимания того, как рисовать залитый одним цветом треугольник, дальше
  56. лезть в 3D графику явно не стоит. Поэтому вот объяснение.
  57. <p>Возьмем любой треугольник. Его изображение на экране - набор горизонтальных
  58. отрезков, причем из-за того, что треугольник - фигура выпуклая, каждой
  59. строке экрана соответствует не более одного отрезка. Поэтому достаточно
  60. пройтись по всем строкам экрана, с которыми пересекается треугольник (то
  61. есть, от минимального до максимального значения y для вершин треугольника),
  62. и нарисовать соответствующие горизонтальные отрезки.
  63. <p><center>
  64. <img src="illu/illu24a.gif" width=180 height=180 alt="рисунок (illu/illu24a.gif)">
  65. <img src="../img/t.gif" width=20 height=180 alt"">
  66. <img src="illu/illu24b.gif" width=180 height=180 alt="рисунок (illu/illu24b.gif)">
  67. </center>
  68. <p>Отсортируем вершины так, чтобы вершина A была верхней, C - нижней, тогда у
  69. нас min_y = A.y, max_y = C.y, и нам надо пройтись по всем линиям от min_y
  70. до max_y. Рассмотрим какую-то линию sy, A.y <= sy <= C.y. Если sy < B.y, то
  71. она пересекает стороны AB и AC; если sy >= B.y - то стороны BC и AC. Мы знаем
  72. координаты всех вершин, поэтому мы можем написать уравнения сторон и найти
  73. пересечение нужной стороны с прямой y = sy. Получим два конца отрезка. Так
  74. как мы не знаем, какой из них левый, а какой правый, сравним их координаты
  75. по x и обменяем значения, если надо. Рисуем этот отрезок, повторяем процедуру
  76. для каждой строки - и вуаля, трегуольник нарисован.
  77. <p>Остановимся более подробно на нахождении пересечения прямой y = sy (текущей
  78. строки) и стороны треугольника, например AB. Напишем уравнение прямой AB в
  79. форме x = k*y+b:
  80. <p class=expression>x = A.x+(y-A.y)*(B.x-A.x)/(B.y-A.y)
  81. <p>Подставляем сюда известное для текущей прямой значение y = sy:
  82. <p class=expression>x = A.x+(sy-A.y)*(B.x-A.x)/(B.y-A.y)
  83. <p>Вот, в общем-то, и все. Для других сторон пересечение ищется совершенно точно
  84. так же. А вот и пример кода.
  85. <pre class=source>
  86. // ...
  87. // здесь сортируем вершины (A,B,C)
  88. // ...
  89. for (sy = A.y; sy <= C.y; sy++) {
  90. x1 = A.x + (sy - A.y) * (C.x - A.x) / (C.y - A.y);
  91. if (sy < B.y)
  92. x2 = A.x + (sy - A.y) * (B.x - A.x) / (B.y - A.y);
  93. else
  94. x2 = B.x + (sy - B.y) * (C.x - B.x) / (C.y - B.y);
  95. if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
  96. drawHorizontalLine(sy, x1, x2);
  97. }
  98. // ...
  99. </pre>
  100. <p>Надо, правда, защититься от случая, когда B.y = C.y - в этом (и только этом,
  101. потому как если C.y = A.y, то треугольник пустой и рисовать его не стоит,
  102. или можно рисовать горизонтальную линию; а если B.y = A.y, то sy >= A.y и
  103. до деления на B.y - A.y не дойдет) случае произойдет попытка деления на ноль.
  104. Код изменится совсем чуть-чуть:
  105. <pre class=source>
  106. // ...
  107. // здесь сортируем вершины (A,B,C)
  108. // ...
  109. for (sy = A.y; sy <= C.y; sy++) {
  110. x1 = A.x + (sy - A.y) * (C.x - A.x) / (C.y - A.y);
  111. if (sy < B.y)
  112. x2 = A.x + (sy - A.y) * (B.x - A.x) / (B.y - A.y);
  113. else {
  114. if (C.y == B.y)
  115. x2 = B.x;
  116. else
  117. x2 = B.x + (sy - B.y) * (C.x - B.x) / (C.y - B.y);
  118. }
  119. if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
  120. drawHorizontalLine(sy, x1, x2);
  121. }
  122. // ...
  123. </pre>
  124. <p>Вот и все. Ну, горизонтальную линию, надеюсь, нарисовать сумеют все желающие.
  125. </div>
  126. </td></table>
  127. <!-- Bottom Navigation -->
  128. <img src="../img/b.gif" width=500 height=1 alt=""><br><img src="../img/t.gif" width=500 height=2 alt=""><br>
  129. <table width=500 cellpadding=0 cellspacing=0 border=0>
  130. <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>
  131. <td><p class=pagetitle><img src="../img/t.gif" width=265 height=1 alt=""><br>demo.design<br>3D programming FAQ</td>
  132. <td align=center><p class=navy><a href="23.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>
  133. <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>
  134. <td align=center><p class=navy><a href="25.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>
  135. </table>
  136. <img src="../img/t.gif" width=500 height=4 alt=""><br>
  137. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  138. <img src="../img/t.gif" width=500 height=1 alt=""><br>
  139. <img src="../img/b.gif" width=500 height=1 alt=""><br>
  140. </center></body>
  141. </html>