Jól hangzik nem?
Ez a név annyit takar, hogy egy egész képet forgatunk a képernyőn, közben meg még zoomolgatunk is. Persze ez a kép (továbbiakban textura) végelenítve van. Szóval gondoljuk meg:
Csináljunk olyat, hogy forgassuk az
egész képet. Jobb esetben azt a csekély 320*200=64000 pontot, amit ugyi
mi látunk. Ez nem biztos, hogy olyan nagyon gyorsan fog menni realtime.
Ez nem nyert. Most jön a csel: ha a a képet nem tudjuk forgatni a képernyôn,
forgassuk a képernyôt a képen. (Persze a monitor a helyén maradhat) Ez
esetben a hatás ugyanaz. Aki nem érti, rajzoljon egy képet, majd vágjon
ki papírból egy akkora téglelapot amekkora a kép, (ez a képernyô) ezt forgassa
a képen, és próbáljon vele együtt forogni. (egészségügyi okok miatt max
45 fok ajánlott).
Ha az egész képernyôt texture mappingelni akarjuk elôször azt kéne tudni, hogy honnan kell kezdeni. Tehát a képernyô bal felsô sarkának a helyét a végtelenített textúrán. Ez az x,y. Az ábráról jól láthatóan az (x,y) a (-160,100) ból származtatható egy a szög? elforgatással.
A függvénytáblában találunk is egy képletet, ami asszongya, hogy pont origó körüli forgatása:
u=x*cos(a) +y*sin(a)
v=-x*sin(a) +y*cos(a)
tehát esetünkben:
x=-160*cos(a)+100*sin(a)
y=160*sin(a)+100*cos(a)
Na, azt már tudjuk, hogy honnan indulunk. Tehét benn álunk az elsô scanline elején, és haladni kéne a textúrán. A scanline minden egyes pontjához meg kellene találni az általa takart textúrakoordinátát. Be kell vezetni egy pár uj értéket.
tex0x,tex0y Tulajdonképpen a képernyô bal oldala által leírt egyenest
tex0xstep,tex0ystep határozzák meg a textúrán, errôl az egyenesrôl indul minden scanline
texx,texy a scanline adott pontjának textúrakoordinátája
texxstep,texystep scnaline-on belüli lépésköz a textúrán
Szóval a scanline-on belül minden egyes pontnál texxstep-et lépünk a textúrán x irábnyba, texystep-et lépünk y irányba, és az aktuális értéket tároljuk a texx-ben, meg a texy-ban. A texx, és texy által meghatározott textúrapontot rakjuk ki a képernyôre.
A Scanline-ok kezdetét hasonlóképpen határozzuk meg, tex0xstep -el, és texoystep-el lépegetünk, tex0-ben és texy0-ban tároljuk az aktuális értéket.
Ezeket viszont ki is kéne számolni.
Az ábráról látszik, hogy a képernyô bal oldala (90-a) szöget zár be a vízszintessel. Tehát:
tex0xstep=cos(90-a)=-sin(a)
tex0ystep=sin(90-a)=cos(a)
Az meg már egyenesen magától értetôdô, hogy a scanline-ok a szöget zárnak be a vízszintessel. Tehát:
texxstep=cos(a)
texystep=sin(a)
Ennek fényében átírhatjuk a képletet, ami a kezdôpontot határozza meg:
texx0=-160*texxstep-100*texx0step;
texy0=-160*texystep-100*texy0step;
Akkor már tudunk minden értéket. Elvileg m?ködik is, de mi ennyivel nem elégszünk meg. Zoomolni is akarunk. Egyszer?. Csak a zoomolás arányában kell növelni a lépésközöket. A Zoomolást vezérlô paraméter legyen dist
tex0xstep=-sin(a)-sin(a)*dist
tex0ystep=cos(a)+cos(a)*dist
texxstep=cos(a)+cos(a)*dist
texystep=sin(a)+sin(a)*dist
Aztán még egy pár simítás:
Mivel a valóságban a textúra közepe sohasem lesz 0,0 , csak a bal felsô sarka, ezért módosítsuk a képletet tetszôleges középpontra, a textúra valódi középpontjait pedig rakjuk be mán egy konstansba:
texx0=x-XCENTER*texxstep-YCENTER*texx0step
texy0=y-XCENTER*texystep-YCENTER*texy0step
Ennyi lenne az elméleti alap. Ezek a képletek persze a gyakorlatban nem teljesen így m?ködnek. Azaz nagyon is jól m?ködnének, ha lebegôpontosan számolnánk. De ez helyett, inkább a már megszokott megoldást választjuk. Pár bittel feljebb nyomjuk az értékeket.(fix pontos számolás). Ez a pár bit általában 8 vagy 16, attól függôen, hogy mekkora értékeket kell tárolnunk, és hány byte-on. Itt nálam most 8. A szögfüggvényeket, pedig, mint az már természzetes táblázatból vesszük.
void wallpaper (int x, int y, int dist, int rot)
{
int texx,texy,texxstep,texystep; //scanlinenon belul
int texx0,texy0,texx0step,texy0step; //scanlineok kozott
int line,xpos;
char *scp; //screen pointer
scp=screen;
rot&=511;
//scanline-on beluli lepeskoz a texturan:
texxstep=cost[rot]+((cost[rot]*dist)>>8); //8 bit fel
texystep=sint[rot]+((sint[rot]*dist)>>8); //8 bit fel
//scanline-ok kozti lepeskoz a texturan:
texx0step=-sint[rot]-((sint[rot]*dist)>>8); //8 bit fel
texy0step=cost[rot]+((cost[rot]*dist)>>8); //8 bit fel
//bal felso sarok melyik texturapont:
texx0=(x<<8)-XCENTER*texxstep-YCENTER*texx0step; //8 bit
fel
texy0=(y<<8)-XCENTER*texystep-YCENTER*texy0step; //8 bit
fel
//vegtelenites
while (texx0<0) texx0+=TEX_X_SIZE*256;
while (texy0<0) texy0+=TEX_Y_SIZE*256;
while (texx0>=TEX_X_SIZE*256) texx0-=TEX_X_SIZE*256;
while (texy0>=TEX_Y_SIZE*256) texy0-=TEX_Y_SIZE*256;
for(line=0;line<200;line++)
{
texx=texx0;
texy=texy0;
for(xpos=0;xpos<320;xpos++)
{
*scp=map[(texy >> 8)*TEX_X_SIZE+(texx >> 8)]; //texture map -> screen
scp++;
texy+=texystep;
texx+=texxstep;
if (texx<0) texx+=TEX_X_SIZE*256; //vegtelenites
if (texy<0) texy+=TEX_Y_SIZE*256;
if (texx>=TEX_X_SIZE*256) texx-=TEX_X_SIZE*256;
if (texy>=TEX_Y_SIZE*256) texy-=TEX_Y_SIZE*256;
}
texy0+=texy0step;
texx0+=texx0step;
if (texx0<0) texx0+=TEX_X_SIZE*256; //vegtelenites
if (texy0<0) texy0+=TEX_Y_SIZE*256;
if (texx0>=TEX_X_SIZE*256) texx0-=TEX_X_SIZE*256;
if (texy0>=TEX_Y_SIZE*256) texy0-=TEX_Y_SIZE*256;
}
}
Ennyi lenne a code C-ben.
Annyit tud, hogy tetszôleges középpont körül forgat egy 320X200-as textúrát, tetszôleges zoomolással, tetszôleges fokban.
Persze elég lassú, de nálam még pont jól megy. Azon kívül, hogy nem assembly, még egy pár hibája azért van. pl.: a scanline-ok kezdôpontjait el lehetne tárolni egy tömbben, és ebbôl dolgozni. Sokkal rövidebb, és gyorsabb belsô ciklust eredményezne. Ezen kívül Ha nem 320X200-as textúrát használna, hanem 256X256 -ost akkor nem kellene álandóan végtelenítgetni, hiszen ha byte-on tárolnánk a cuccokat, azok maguktól körbeforognának. Aztán lehetne törôdni a képernyô torzításával is, igaz ez csak 1.2 ebben a video módban, de akkor is szebb lenne.
Valamit az olvasóra is kell hagyni.
Persze a program megint Watcom C-ben sikerült, valahogy nem fekszik nekem a Borland. Ebbôl kifojólag, ha netán valaki megpróbálja átírni az int-eket cserélje long int-re, mert a watcom 4 byte-os integerekkel számol.
A program a képet egy pcx-bôl veszi. Ennek részletes leírását nem tartottam szükségesnek, de, ha valakit érdekel a pcx normális beolvasása (ez a program csak 320X200X256-osat at tud kezelni) , vagy bármi más, megkérem írjon mán valamit!
CSÁ