Rotate,Scale,Translate a texture from pixels.

Rotate,Scale,Translate a texture from pixels.

See version :

Dépendances (dans l'archive) :
mur.bmp

Download :

#include <string.h>
#include <math.h>
#include <sdl/sdl.h>

#ifdef WIN32
#pragma comment(lib,"sdl.lib")
#pragma comment(lib,"sdlmain.lib")
#endif

typedef struct 
{
    float x[2],y[2],o[2];
} Matrix2D;

void InitMatScale(Matrix2D* mat,float sc)
{
    memset(mat,0,sizeof(Matrix2D));
    mat->x[0] = sc;
    mat->y[1] = sc;
}

void InitMatTranslate(Matrix2D* mat,float x,float y)
{
    InitMatScale(mat,1); // ID
    mat->o[0] = x;
    mat->o[1] = y;
}

void InitMatRotate(Matrix2D* mat,float a)
{
    memset(mat,0,sizeof(Matrix2D));
    mat->x[0] = (float)cos(a);
    mat->x[1] = (float)sin(a);
    mat->y[0] = - mat->x[1];
    mat->y[1] = mat->x[0];
};

void SDL_PutPixel32(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    Uint8 *p;
    if (x<0 || y<0 || x>=surface->w || y>=surface->h)
        return;
    p = (Uint8*)surface->pixels + y * surface->pitch + x * 4;
    *(Uint32*)p = pixel;
}

Uint32 SDL_GetPixel32(SDL_Surface *surface, int x, int y)
{
    Uint8 *p;
    if (x<0 || y<0 || x>=surface->w || y>=surface->h)
        return 0;
    p = (Uint8*)surface->pixels + y * surface->pitch + x * 4;
    return *(Uint32*)p;
}

int InverseMatrix(Matrix2D* in,Matrix2D* out)
{
    float den = in->x[0]*in->y[1] - in->x[1]*in->y[0];
    out->x[0] = in->y[1]/den;
    out->x[1] = - in->x[1]/den;
    out->y[0] = - in->y[0]/den;
    out->y[1] = in->x[0]/den;
    out->o[0] = (in->o[1]*in->y[0]-in->o[0]*in->y[1])/den;
    out->o[1] = (in->o[0]*in->x[1]-in->o[1]*in->x[0])/den;
    return 0;
}

int Multiply(Matrix2D* A,Matrix2D* B,Matrix2D* out)
{
    out->x[0] = B->x[1]*A->y[0] + B->x[0]*A->x[0];
    out->x[1] = B->x[1]*A->y[1] + B->x[0]*A->x[1];
    out->y[0] = B->y[1]*A->y[0] + B->y[0]*A->x[0];
    out->y[1] = B->y[1]*A->y[1] + B->y[0]*A->x[1];
    out->o[0] = B->o[1]*A->y[0] + B->o[0]*A->x[0] + A->o[0];
    out->o[1] = B->o[1]*A->y[1] + B->o[0]*A->x[1] + A->o[1];
    return 0;
}

int GetBoundingBox(Matrix2D* mat,int *xmin,int* xmax,int *ymin,int* ymax)
{
    float coords[4][2];
    int i;
    for(i=0;i<2;i++)
    {
        coords[0][i] = mat->o[i];
        coords[1][i] = mat->o[i] + mat->x[i];
        coords[2][i] = mat->o[i] + mat->y[i];
        coords[3][i] = mat->o[i] + mat->x[i] +  + mat->y[i];
    }
    *xmin = *xmax = (int)coords[0][0];
    *ymin = *ymax = (int)coords[0][1];
    for(i=1;i<4;i++)
    {
        if (coords[i][0]<*xmin)
            *xmin = (int)coords[i][0];
        if (coords[i][0]>*xmax)
            *xmax = (int)coords[i][0];
        if (coords[i][1]<*ymin)
            *ymin = (int)coords[i][1];
        if (coords[i][1]>*ymax)
            *ymax = (int)coords[i][1];
    }
    return 0;
}

int TransfoPoint(Matrix2D* mat,float i,float j,float* x,float* y)
{
    *x = j*mat->y[0] + i*mat->x[0] + mat->o[0];
    *y = j*mat->y[1] + i*mat->x[1] + mat->o[1];
    return 0;
}

int RenderTransformed(SDL_Surface* screen,SDL_Surface* image,Matrix2D* mat)
{
    Matrix2D inversed;
    float x,y;
    int i,j,xmin,xmax,ymin,ymax;
    GetBoundingBox(mat,&xmin,&xmax,&ymin,&ymax);
    InverseMatrix(mat,&inversed);
    for(i=xmin;i<xmax+1;i++)
    {
        for(j=ymin;j<ymax+1;j++)
        {
            Uint32 pix;
            TransfoPoint(&inversed,(float)i,(float)j,&x,&y);
            pix = SDL_GetPixel32(image,(int)(x*image->w),(int)(y*image->h));
            SDL_PutPixel32(screen,i,j,pix);
        }
    }
    return 0;
}

SDL_Surface* Charger(const char* fic)
{
    SDL_Surface *res;
    SDL_Surface* tmp = SDL_LoadBMP(fic);
    if (tmp==NULL)
    {
        printf("Erreur chargement %s\n",fic);
        exit(-1);
    }
    res = SDL_DisplayFormat(tmp);
    SDL_FreeSurface(tmp);
    return res;
}

int Controle(Uint8* keys,Matrix2D* mat)
{
    Matrix2D copy = *mat;
    Matrix2D trans;
    int sens = 1;
    InitMatScale(&trans,1);
    if (keys[SDLK_RIGHT])
        InitMatTranslate(&trans,1,0);
    if (keys[SDLK_LEFT])
        InitMatTranslate(&trans,-1,0);
    if (keys[SDLK_DOWN])
        InitMatTranslate(&trans,0,1);
    if (keys[SDLK_UP])
        InitMatTranslate(&trans,0,-1);
    if (keys[SDLK_a])
    {
        InitMatScale(&trans,1.05f);
        sens = 0;
    }
    if (keys[SDLK_q])
    {
        InitMatScale(&trans,0.95f);
        sens = 0;
    }
    if (keys[SDLK_r])
    {
        InitMatRotate(&trans,0.05f);
        sens = 0;
    }

    if (keys[SDLK_c])
    {
        Matrix2D rotate,T,TI,temp;
        float med = 0.5;
        InitMatRotate(&rotate,0.05f);
        InitMatTranslate(&T,med,med);
        InitMatTranslate(&TI,-med,-med);
        Multiply(&rotate,&TI,&temp);
        Multiply(&T,&temp,&trans);
        sens = 0;
    }

    if (sens==0)
        Multiply(&copy,&trans,mat);
    else
        Multiply(&trans,&copy,mat);
    return 0;
}

int main(int argc,char** argv)
{
    SDL_Surface* screen,*image;
    int numkeys;
    Uint8 * keys;
    Uint32 timer,elapsed;
    Matrix2D mat;
    InitMatScale(&mat,200);
    SDL_Init(SDL_INIT_VIDEO);
    screen=SDL_SetVideoMode(400,320,32,SDL_SWSURFACE|SDL_DOUBLEBUF);
    image = Charger("mur.bmp");
    SDL_LockSurface(image);
    if (!image)
        return -1;
    do 
    {
        timer = SDL_GetTicks();
        SDL_FillRect(screen,NULL,0);
        SDL_PumpEvents();
        keys = SDL_GetKeyState(&numkeys);
        Controle(keys,&mat);
        RenderTransformed(screen,image,&mat);
        SDL_Flip(screen);
        elapsed = SDL_GetTicks() - timer;
        if (elapsed<20)
            SDL_Delay(20-elapsed);
    } while (!keys[SDLK_ESCAPE]);
    SDL_FreeSurface(image);
    SDL_Quit();
    return 0;
}



Explanations

	No explanations yet.

	Use keys a,q for scale ;
	Arrows for moving
	r for rotation from the upper bound
	c for rotation from the center.