Si vous ne voulez pas utiliser les fonctions proposées pour la bibliothèque SDL pour effectuer une rotation (http://jeux.developpez.com/faq/sdl/?...ransformations)
mais que vous voulez programmer vous même votre propre rotation.
Si vous voulez voir comment réaliser une telle opération sous SDL, voici un code permettant de le faire :
Prototype (la surface de destination est automatiquement allouée et fait la même taille que la surface d'origine, donc n'oubliais pas le SDL_FreeSurface) :
SDL_Surface* SDL_RotationCentral(SDL_Surface* origine, float angle)
Je souligne que les calculs sont effectués par le CPU, donc il n'y a aucune optimisation de la carte graphique.
Si vous avez des suggestions, n'hésitez pas !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 /*permet de déterminer la valeur d'un pixel au position x,y*/ Uint32 inline SDL_LirePixel(SDL_Surface* surface, int x, int y) { int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) return p[0] << 16 | p[1] << 8 | p[2]; else return p[0] | p[1] << 8 | p[2] << 16; case 4: return *(Uint32 *)p; default: return 0; } } /*permet d'écrire un pixel au position x,y*/ void inline SDL_EcrirePixel(SDL_Surface* surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } } /*effectue une rotation centrale d'angle en degré, alloue automatiquement la mémoire*/ SDL_Surface* SDL_RotationCentral(SDL_Surface* origine, float angle) { SDL_Surface* destination; int i; int j; Uint32 couleur; int mx, my; float d; int bx, by; float angle_radian; /* détermine la valeur en radian de l'angle*/ angle_radian = -angle * M_PI / 180.0; /* * alloue la mémoire à l'espace de destination, attention, * la surface est de même taille */ destination = SDL_CreateRGBSurface(SDL_HWSURFACE, origine->w, origine->h, origine->format->BitsPerPixel, origine->format->Rmask, origine->format->Gmask, origine->format->Bmask, origine->format->Amask); /*on vérifie que la mémoire a été allouée*/ if(destination==NULL) return NULL; /* pour simplifier les notations*/ mx = origine->w/2; my = origine->h/2; for(j=0;j<origine->h;j++) for(i=0;i<origine->w;i++) { /* on détermine la valeur de pixel qui correspond le mieux pour la position * i,j de la surface de destination */ /* on détermine la meilleure position sur la surface d'origine en appliquant * une matrice de rotation inverse */ bx = (int) (cos(angle_radian) * (i-mx) + sin(angle_radian) * (j-my)) + mx; by = (int) (-sin(angle_radian) * (i-mx) + cos(angle_radian) * (j-my)) + my; /* on vérifie que l'on ne sort pas des bords*/ if (bx>=0 && bx< origine->w && by>=0 && by< origine->h) { couleur = SDL_LirePixel(origine, bx, by); SDL_EcrirePixel(destination, i, j, couleur); } } return destination; }
[Edit] il faut noter que l'on parcourt la surface de destination et non la surface d'origine pour forcer chaque pixel de destination a avoir une couleur à peu près correct (à peu près comme une rotation en informatique est dans la plupart des cas non bijective). Alors que si l'on parcourait les pixels de la surface d'origine, déterminait les positions de sa position, il pourrait y avoir des trous noirs dans la surface de destination.
[Edit] Voici la version qui ne déborde pas sur les bords et qui ajuste la taille de la surface de destination :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 /*effectue une rotation centrale, alloue automatiquement la mémoire*/ SDL_Surface* SDL_RotationCentralN(SDL_Surface* origine, float angle) { SDL_Surface* destination; int i; int j; Uint32 couleur; int mx, my, mxdest, mydest; int bx, by; float angle_radian; float tcos; float tsin; double largeurdest; double hauteurdest; /* détermine la valeur en radian de l'angle*/ angle_radian = -angle * M_PI / 180.0; /*pour éviter pleins d'appel, on stocke les valeurs*/ tcos = cos(angle_radian); tsin = sin(angle_radian); /*calcul de la taille de l'image de destination*/ largeurdest= ceil(origine->w * fabs(tcos) + origine->h * fabs(tsin)), hauteurdest= ceil( origine->w * fabs(tsin) + origine->h * fabs(tcos)), /* * alloue la mémoire à l'espace de destination, attention, * la surface est de même taille */ destination = SDL_CreateRGBSurface(SDL_HWSURFACE, largeurdest, hauteurdest, origine->format->BitsPerPixel, origine->format->Rmask, origine->format->Gmask, origine->format->Bmask, origine->format->Amask); /*on vérifie que la mémoire a été allouée*/ if(destination==NULL) return NULL; /*calcul du centre des images*/ mxdest = destination->w/2.; mydest = destination->h/2.; mx = origine->w/2.; my = origine->h/2.; for(j=0;j<destination->h;j++) for(i=0;i<destination->w;i++) { /* on détermine la valeur de pixel qui correspond le mieux pour la position * i,j de la surface de destination */ /* on détermine la meilleure position sur la surface d'origine en appliquant * une matrice de rotation inverse */ bx = (ceil (tcos * (i-mxdest) + tsin * (j-mydest) + mx)); by = (ceil (-tsin * (i-mxdest) + tcos * (j-mydest) + my)); /* on vérifie que l'on ne sort pas des bords*/ if (bx>=0 && bx< origine->w && by>=0 && by< origine->h) { couleur = SDL_LirePixel(origine, bx, by); SDL_EcrirePixel(destination, i, j, couleur); } } return destination; }
Partager