Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Алгоритмы / Графика / 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
Текстурирование






Точное


Задача текстурирования формулируется таким образом: есть грань - согласно предположениям, треугольная - с наложенной на нее текстурой. То есть каждая точка грани окрашена цветом соответствующей ей точки в текстуре. Текстура накладывается линейным образом. Есть точка экрана с координатами на экране (sx,sy), принадлежащая проекции грани. Требуется найти ее цвет, то есть цвет соответствующей этой точке экрана точки текстуры. А для этого надо найти координаты текстуры для этой точки - точнее, для той точки, проекцией которой на экран является наша (sx,sy).


Пусть вершины грани есть точки A(Ax,Ay,Az), B(Bx,By,Bz) и C(Cx,Cy,Cz), а соответствующие им точки текстуры - (Au,Av), (Bu,Bv) и (Cu,Cv). Найдем координаты текстуры для точки, проекцией которой является (sx,sy).


Для точек (x,y,z), проекцией которых является (sx,sy) имеем:


sx = xSize/2+x*dist/(z+dist), sy = ySize/2-y*dist/(z+dist).


Для упрощения формул будем использовать обозначения


i = sx-XSize/2, j = YSize/2-sy, Z = z+dist.


Тогда эти формулы примут вид


i = x*dist/Z, j = y*dist/Z,


или, что равносильно:


i*Z = x*dist, j*Z = y*dist.


Рассмотрим точку D, принадлежащую грани. Для нее D = A+a*(B-A)+b*(C-A), так как она лежит в грани. D однозначно задается парой (a,b). Для нее координаты текстуры (из того, что текстура накладывается линейно) будут такие:


Du = Au+a*(Bu-Au)+b*(Cu-Au), Dv = Av+a*(Bv-Av)+b*(Cv-Av).


Пусть проекция D на экран как раз и имеет координаты (sx,sy), тогда для нее выполнены написанные выше соотношения:


i*DZ = Dx*dist, j*DZ = Dy*dist.


Подставим сюда координаты D, выраженные через координаты A, B и неизвестныекоэффициенты a, b:


i*(Az+a*(Bz-Az)+b*(Cz-Az)+dist) = dist*(Ax+a*(Bx-Ax)+b*(Cx-Ax)),
j*(Az+a*(Bz-Az)+b*(Cz-Az)+dist) = dist*(Ay+a*(By-Ay)+b*(Cy-Ay)),


т.к. мы договорились, что AZ = Az+dist, и, кстати, поэтому BZ-AZ = Bz-Az, это можно чуть укоротить:


i*(AZ+a*(BZ-AZ)+b*(CZ-AZ)) = dist*(Ax+a*(Bx-Ax)+b*(Cx-Ax)),
j*(AZ+a*(BZ-AZ)+b*(CZ-AZ)) = dist*(Ay+a*(By-Ay)+b*(Cy-Ay)).


Выделим a и b:


a*(i*(BZ-AZ)-dist*(Bx-Ax))+b*(i*(CZ-AZ)-dist*(Cx-Ax)) = dist*Ax-i*AZ,
a*(j*(BZ-AZ)-dist*(By-Ay))+b*(j*(CZ-AZ)-dist*(Cy-Ay)) = dist*Ay-j*AZ.


Получили систему двух линейных уравнений, из которой можно найти a и b, а по ним немедленно вычисляются u и v. Введем вектор M = BA (Mx = Bx-Ax и т.д.) и вектор N = CA, обозначим d = dist (все это для краткости записи). Тогда эти два уравнения перепишутся в виде:


a*(i*Mz-d*Mx)+b*(i*Nz-d*Nx) = d*Ax-i*AZ,
a*(j*Mz-d*My)+b*(j*Nz-d*Ny) = d*Ay-j*AZ,


и решая систему (например, по формулам Крамера) получаем:



(dAx-iAZ)(jNz-dNy)-(dAy-jAZ)(iNz-dNx)
a = ------------------------------------- =
(iMz-dMx)(jNz-dNy)-(iNz-dNx)(jMz-dMy)


djAxNz-ddAxNy-ijAZNz+idAZNy-diAyNz+ddAyNx+ijNzAZ-djAZNx
= ------------------------------------------------------- =
ijMzNz-idMzNy-djMxNz+ddMxNy-ijMzNz+idNzMy+djNxMz-ddNxMy


dj(AxNz-AZNx)+dd(AyNx-AxNy)+id(AZNy-AyNz)
= ----------------------------------------- =
id(MyNz-MzNy)+dj(NxMz-MxNz)+dd(MxNy-NxMy)


i(AZNy-AyNz)+j(AxNz-AZNx)+d(AyNx-AxNy)
= --------------------------------------
i(MyNz-MzNy)+j(NxMz-MxNz)+d(MxNy-NxMy)




аналогично получаем



i(AZMy-AyMz)+j(AxMz-AZMx)+d(AyMx-AxMy)
b = --------------------------------------
i(MyNz-MzNy)+j(NxMz-MxNz)+d(MxNy-NxMy)




Знаки умножения здесь везде опущены, иначе читать это все совсем невозможно.


Осталось немного, подставить Mx = Bx-Ax и так далее, а потом подставить эти a и b в формулы для Du и Dv. В процессе подстановок что-то сократится, что-то упростится, но формулы для Du и Dv все равно получатся длиной в несколько строк.


Но из этих формул видно кое-что интересное. А именно, то, что


u = (C1*sx+C2*sy+C3) / (C4*sx+C5*sy+C6),
v = (C7*sx+C8*sy+C9) / (C4*sx+C5*sy+C6),


причем C1, ..., C9 - просто какие-то коэффициенты, зависящие от грани. То есть, можно посчитать эти коэффициенты один раз на грань, а потом считать u, v по написанным пару строк выше формулам. Но все равно получается как минимум одно деление на точку. Это слишком медленно. Поэтому все методы текстурирования на самом деле используют приближенные вычисления, хотя и именно по этим формулам.


Стоит отметить тот факт, что на самом деле здесь грань не обязательно должна быть треугольной - можно взять любые три вершины многоугольной грани. То же самое справедливо и для остальных описанных методов текстурирования.


Вперед  >>>
 1  2  3  4  5  6 


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

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