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).

A négyezetrács a végtelenített textúrát hivatott jelképezni, az elforgatott négyszög pedig a képernyőt. Az x,y -al jelölt sarok a képernyő bal felső sarka. 0,0 -val a textúra közepét jelöljük, a további számítások során ezt tekintjük origónak. A textúra bal felső sarka azért -160,100, mert az egyszerűség kedvéért egy 320X200-as textúrát forgatunk. (A felbontás is 320X200 lesz) Tehát mi látszik az ábrábán? Először is az, hogy baromi ronda, mert paintbrushban készült, ráadásul feleakkorában, mint itt látszik. Ezen túl még annak is kéne látszani, amit szemléltetni akar, az pedig a képernyő elforgatása a textúrán.

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 új é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 tex0ystep-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ár 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ával nem akartam senkit utatni.