Dépendances (dans l'archive) :
mur.bmp
#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(©,&trans,mat); else Multiply(&trans,©,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; }
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.