Rotate2Pow

Jaenis 21.09.04 19:42

Aikonaan väsätty 2d kuvan pyörittelijä. Toimi kivasti 486:lla, nyt portattu SDL:lle

 Tekstiversio  Arvo: 5 (11 ääntä)  Äänestä: +  -
/*
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&amp;0xFF)+64])

Kun sen pitäs olla:
#define Cos(x)  (SinCosTable[(x&0xFF)+64])


Siis siellä ei pitäs lukea &amp; 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