| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
Rotate2PowJaenis 21.09.04 19:42 Aikonaan väsätty 2d kuvan pyörittelijä. Toimi kivasti 486:lla, nyt portattu SDL:lle
/* Suhteellisen pitkälle optimoitu C:llä tehty 2d kuvan pyrörittelijä funktio. Pitäs toimia SDL:n kanssa, ainaski windowsissa. Tässä on kasa rajoituksia optimoinnin takia. Kuvan leveyden ja korkeuden on oltava sama - eli kuva on oltava neliö - ja leveyden ja korkeuden täytyy olla myös kahden potenssi. Eli koot 2,4,8,16,32... käyvät. Kulma annetaan välillä 0-255, tälle ei ole muuta syytä kuin se että laiskana käytin unsigned char (8bit) muuttujaa kulman säilömiseen. Etuna oli että ei tarvinnut itse tarkistella yli tai alivuotoja. Sini ja kosini on taulukoitu erilliseen taulukkoonsa nopeuden tavoittelun takia. Sinille ja kosinille on sitten tehty definet mitkä hakevat oikean arvon taulukosta, paluuarvo on 16.16 fixedpoint. Tämä koodi on jaettu kahteen tiedostoon ja sen käyttäminen pitäisi olla SDL:n kanssa suht helppoa. Lisää vain #include <rotate.h> tiedostoosi, kutsu InitSinCos()-funktiota kerran alustuksessa ja ala käyttämään rotate-funktiota. Rotate.cpp:n alussa olevat slock ja sulock on repäisty lähes suoraan SLD:n esimerkeistä ja ne eivät oikeasti kuulu tähän rotate.cpp:hen, vaan erilliseen tiedostoon. Mutta laitoin ne selvyyden vuoksi mukaan. Lisäksi Rotate funktion kommentit on kirjoitettu tässä ja nyt, niissä voi olla virheitä, kun ei enää muista mitä toi vanha koodi pitää sisällään. Yleisön pyynnöstä -- Jaenis */ /******************************* Tiedosto: rotate.h *******************************/ // Pyörityssysteemin headeri #ifndef ROTATE_H_INCLUDED #define ROTATE_H_INCLUDED /*--------------------------------------------------------------------------*/ // Includet #include <SDL/SDL.h> /*--------------------------------------------------------------------------*/ // Definet // Sini-kosini taulukon koko #define SIN_COS_SIZE (256+64) // Sini ja kosini funktio #define Sin(x) (SinCosTable[(unsigned char)x]) #define Cos(x) (SinCosTable[(x&0xFF)+64]) /*--------------------------------------------------------------------------*/ // Muuttujat // Sini-kosini taulukko extern int SinCosTable[SIN_COS_SIZE]; /*--------------------------------------------------------------------------*/ // Funktiot // Laskee sini-kosini taulukon void InitSinCosTable(void); // Pyöritysrutiini void Rotate2Pow(SDL_Surface *OsSurf, unsigned char Angle, SDL_Surface *TargetSurf); /*--------------------------------------------------------------------------*/ #endif // ROTATE_H_INCLUDED /******************************* Tiedosto: rotate.cpp *******************************/ // Pyörityskirjasto #include <math.h> #include "rotate.h" /*--------------------------------------------------------------------------*/ // Muuttujat // Sini-kosini taulukko int SinCosTable[SIN_COS_SIZE]; /*--------------------------------------------------------------------------*/ // Slock(screen); // // Lukitsee ruudun että sen pikseleitä voi tökkiä // void Slock(SDL_Surface *screen) { if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) { return; } } } /*--------------------------------------------------------------------------*/ // Sulock(screen); // // Vapauttaa lukituksen // void Sulock(SDL_Surface *screen) { if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } } /*--------------------------------------------------------------------------*/ // InitSinCos(); // // Laskee sini-kosini taulukon // void InitSinCosTable(void) { int c; double Temp; for (c=0;c<SIN_COS_SIZE;c++) { Temp=(c&0xFF)*360*3.14159265359; Temp/=180*256.0; SinCosTable[c]=(int)( (sin(Temp)*65536)+0.5 ); } } /*--------------------------------------------------------------------------*/ // Rotate2Pos(Pic, Angle, TargetPic); // // Kääntää kuvan annettuun kulmaan. // Kuvan täytyy olla neliö ja sen leveys kahden potenssi // // Argumentit: // Pic - Alkuperäinen kuva // Angle - Kohdekulma // TargetPic - Kohde kuva // void Rotate2Pow(SDL_Surface *OsSurf, Uint8 Angle, SDL_Surface *TargetSurf) { int X,Y; // Silmukkamuuttujat register int Edi; // Kirjoituskohta (Mitä, asmikoodaustako?) register int u,v,Pos; // Apukoordinaatit ja lukukohta int ddx,ddy,d2x,d2y; // Käännetyn X ja Y akselin "koordinaatit" int i,j; // Piste missä ollaan käännetyissä koordinaateissa int Limit; // Kohde taulukon koko int Xsize,Ysize; // Kohde kuvan koko int Mask; // Maski, poistaa kertolaskut Uint32 Color; // Luettu Väri Uint32 Back=OsSurf->format->colorkey; // Taustan väri, musta Uint32 *Os=(Uint32 *)OsSurf->pixels; // Osoitin alkuperäisen kuvan pikseleihin Uint32 *Target=(Uint32 *)TargetSurf->pixels; // ...ja kohdekuvan pikselit Xsize=OsSurf->w; // Luetaan kuvan koko Ysize=OsSurf->h; Mask=(Xsize-1)^0xFFFFFFFF; // Lasketaan maski Limit=Xsize*Ysize; // ...ja kuvan koko ddx=Cos(Angle)>>8; // Lasketaan uudet koordinaatit ddy=Sin(Angle)>>8; d2x=Cos(Angle+64)>>8; // Angle+64 tarkoittaa 90 asteen kulmaa d2y=Sin(Angle+64)>>8; i=(0x100-ddx-d2x)*(Xsize/2); // Lasketaan koordinaatti, 8.8 fixed point luku j=(0x100-ddy-d2y)*(Ysize/2); ddy*=Xsize; // Tekemällä nämä kertomiset (Y kertaa Xsize) j*=Xsize; // säästymme tekemästä kertolaskuja itse silmukassa, d2y*=Xsize; // riittää kuhan lisäilemme näitä lukuja Y koordinaattiin. Slock(TargetSurf); // Lukitaan ruutu // Käydään kaikki pikselit läpi for (Y=Ysize,Edi=0;Y;Y--) { u=i; // Liikutetaan koodrinaatteja v=j; for (X=Xsize;X;X--,Edi++) { u+=ddx; // Liikutetaan koodrinaatteja v+=ddy; Color=Back; // Otetaan vakiona musta väri Pos=(u>>8)+((v>>8)&Mask); // Lasketaan kohta missä ollaan if (0<=Pos && Pos<Limit && 0<=(u>>8) && (u>>8)<Xsize) Color=Os[Pos]; // Jos ollaan kuvan alueella, niin luetaan väri Target[Edi]=Color; // Talletetaan } i+=d2x; // Liikutetaan koodrinaatteja j+=d2y; } Sulock(TargetSurf); // Vapautetaan lukitus } empty 14:01 23.9.04 Aika mukavan näköstä koodia. Hyödyllinen pätkä. Helposti uudelleenkäytettävää. Jokseenkin tehokasta. Plussaa. BlueByte 15:06 23.9.04 jep jep kiva Jaenis 17:45 23.9.04 Kas, kiitoksia kehuista :) Tuolla on näköjään yksi kirjotusvirhe, josta en pääse eroon muokkaamalla. Headeri osuudessa lukee tälläistä: #define Cos(x) (SinCosTable[(x&0xFF)+64]) Kun sen pitäs olla: #define Cos(x) (SinCosTable[(x&0xFF)+64]) Siis siellä ei pitäs lukea & vaan ihan vaan &. Jossain pätkii ton &-merkin kanssa, etenkin kun se näkyy ihan oikein mulle jos editoin koodia Rabidus 14:31 29.9.04 Jeps, kiitokset koodista |
![]() Haku
|