Из журнала Scenergy #2, Новгород, 2000 ;----------------------------------------- ;-TEXTURE MAPPING- ESPECIALLY 4 SCENERGY ;----------------------------------------- (C) 1999 SaiR00S/EI Суть линейного текстурного мэппинга заключается в линейной интерполяции координат полигона и соответствующим им текстурных координат. В качестве полигона чаще всего выбирается треугольник, хотя описанный ниже алгоритм подходит для любого полигона. Итак, полигоном является треугольник, все вершины которого имеют пары координат (X,Y) и связанные с ними текстурные координаты (U,V). По полигону мы будем двигаться сверху-вниз и слева-направо , т.е при движении сверху-вниз мы будем увеличивать на каждом вертикальном шаге координату Y треугольника при одновременной линейной интерполяции координаты X и текстурных координат (в итоге получится контур полигона и соответствующий ему контур треугольника в текстуре), а при движении слева-направо, увеличивая координату X-координату от левой границы контура до правой на единицу, проводим линейную интерполяцию по текстуре и ставим в координату Xi,Yj значение цвета из текстуры по координатам Up,Vq. Первое , что необходимо сделать - это отсортировать координаты треугольника вmeсте с текстурными координатами в порядке возрастания координаты Y, т.е. If vert1.y > vert2.y then swap (vert1,vert2); If vert2.y > vert3.y then swap (vert2,vert3); If vert3.y > vert1.y then swap (vert3,vert1); Или (лексика STORM'a): LD HL,(VERT1); Берем X,Y координа- LD DE,(VERT2); ты треугольника LD BC,(VERT3); EXX LD HL,(VERT1+2); Берем текстурные LD DE,(VERT2+2); координаты U,V LD BC,(VERT3+2); EXX LD A,D CP H JR NC,NOSWAP1 EX DE,HL EXX EX DE,HL EXX NOSWAP1 LD A,B CP H JR NC,NOSWAP2 LD A,L,L,C,C,A LD A,H,H,B,B,A EXX LD A,L,L,C,C,A LD A,H,H,B,B,A EXX NOSWAP2 LD A,B CP D JR NC,NOSWAP3 LD A,E,E,C,C,A LD A,D,D,B,B,A EXX LD A,E,E,C,C,A LD A,D,D,B,B,A EXX NOSWAP3 LD (VERT1),HL LD (VERT2),DE LD (VERT3),BC EXX LD (VERT1+2),HL LD (VERT2+2),DE LD (VERT3+2),BC EXX В результате получается картина, изображенная на рисунке. В данном случае точка перегиба находится слева, соответственно, в левой половине треугольника имеем 2 грани, а в правой - одну.
Ha рисунке: H - максимальная высота треугольника H1 - высота ребра (vert1,vert2); H2 - высота ребра (vert2,vert3); W - наибольшая ширина треугольника треугольника по X. Определяется она следующим образом: t=(vert2.y-vert1.y)/(vert3.y-vert1.y) w=(vert1.x+t*(vert3.x-vert1.x))-vert2.x Если H и/или W равны нулю, то треугольник рисовать не нужно. Далее определяется с какой стороны находится точка перегиба в треугольнике. Делается это проверкой знака величины W. Если эта величина положительна, то точка перегиба - слева, отрицательна - справа. If w>0 then "point" on left else "point" on right Затем проводим линейную интерполяцию координаты X треугольника и текстурных координат U,V. Интерполяцию можно проводить по нижеприведенным формулам или по Брезенхему - кому как нравится,но второй вариант быстрее (хотя, при малом количестве полигонов, что мы имеем на Спектруме, это практически не заметно). Итак, если точка перегиба слева (W>0), то нужно отрисовать две грани слева и одну справа: Строим левую сторону треугольника: h1=vert2.y-vert1.y DeltaLeftX1=(vert2.x-vert1.x)/h1 DeltaLeftU1=(vert2.u-vert1.u)/h1 DeltaLeftV1=(vert2.v-vert1.v)/h1 h2=vert3.y-vert2.y DeltaLeftX2=(vert3.x-vert2.x)/h2 DeltaLeftU2=(vert3.u-vert2.u)/h2 DeltaLeftV2=(vert3.v-vert2.v)/h2 X:=vert1.x; For i=0 to h1 do Begin TableLeftX[i]:=X; TableU[i]:=U; TableV[i]:=V; X:=X+DeltaLeftX; U:=U+DeltaLeftU; V:=V+DeltaLeftV; End; For i=h1 to h2 do Begin TableLeftX[i]:=X; TableU[i]:=U; TableV[i]:=V; X:=X+DeltaLeftX2; U:=U+DeltaLeftU2; V:=V+DeltaLeftV2; End; Строим правую сторону треугольника: h=vert3.y-vert1.y; DeltaRightX=(vert3.x-vert1.x)/h; For i=0 to h do Begin TableRightX[i]:=X; X:=X+DeltaRightX; End; Здесь: TableLeftX[] - таблица, содержащая X координаты левой поло- вины треугольника; TableRightX[]- то же для правой поло- вины; ТableU[] - таблица, содержащая U координаты левой поло- вины треугльника; TableV[] - то же для V-координаты DeltaLeftX - константа интерполяции (на ZX должна считать- ся с fixed point 8.8); DeltaRightX - то же. Если же точка перегиба находится справа (W<0), то все аналогично, только слева отрисовываем одно ребро треугольника , а справа - два. Далее определяем шаги по текстуре , которые являются постоянными для всего полигона (на ZX будем считать их с fixed point 8.8, причем со знаком!): DeltaU=(t*(u3-u1)+(u1-u2))/w DeltaV=(t*(v3-v1)+(v1-v2))/w Далее непосредственно рисуем полигон: i:=0; For Y:=vert1.y to (vert1.y+H) do Begin U:=TableU[i]; V:=TableV[i]; For X:=TableLeftX[i] to TableRigtX[i] do Begin {ставим точку в координату (X,Y) цвета из текстуры по координате (U,V)} PutPixel(X,Y,Texture[U,V]) X:=X+1; U:=U+DeltaU; V:=V+DeltaV End; i:=i+1 End; Внутренний цикл будет выглядеть следующим образом (кстати, возможно быстрее...): LD A,H; V-координата в текстуре ADD HL,DE; вычисляем следующую ко- ; ординату V EXX LD B,A LD C,H ; U-координата в текстуре ADD HL,DE; вычисляем следующую ко- ; ординату U LD A,(BC); берем тексель EXX LD (BC),A; помещаем тексель в бу- ; фер INC C ; увеличиваем X-координа- ; ту Следует напомнить, что все (почти) вычисления проводятся с fixed point 8.8, например: HL=H.L, т.е H содержит целую часть числа, а L - дробную. Ну вот, вроде и все, удачи в кодинге.