IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

[SOURCE] [SDL] Comment programmer une rotation


Sujet :

Contribuez

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut [SOURCE] [SDL] Comment programmer une rotation
    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.

    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;
    }
    Si vous avez des suggestions, n'hésitez pas !


    [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;
    }

  2. #2
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Très intéressants, cela me rappelle mes cours d'algébre (d'isomorphisme...), mais j'ai 3 remarques :

    1) Quels sont les performances par rapport à l'utilisation de rotozoomSurface ?

    2) Pourquoi faire une décomposition pour 3 bytes et pas 2 ou 4 ? Cela me semble particulier, non ?

    3) Pourquoi garder la même taille ? Si on fait 4 fois des rotations de 90 degrés, on ne perd pas les bords ?

    Jc

  3. #3
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par fearyourself
    Très intéressants, cela me rappelle mes cours d'algébre (d'isomorphisme...), mais j'ai 3 remarques :

    1) Quels sont les performances par rapport à l'utilisation de rotozoomSurface ?
    Je n'ai pas testé, mais apparement, la fonction rotozoom a acceleré par la carte graphique, il faudrait réaliser des tests (jvais le faire)

    2) Pourquoi faire une décomposition pour 3 bytes et pas 2 ou 4 ? Cela me semble particulier, non ?
    Si tu parles de LirePixel et EcrirePixel, ce sont les fonctions que l'on peut recuperer à droite à gauche, et je ne sais pas en quoi l'endianness du système change qqch.

    3) Pourquoi garder la même taille ? Si on fait 4 fois des rotations de 90 degrés, on ne perd pas les bords ?
    Effectivement, on perd les bords, mais j'avais la flemme de faire le calcul, je vais essayer de le faire. De plus, classiquement, on coupe les bords comme ça (on peut le constater avec des logiciels de traitement d'image)

  4. #4
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Alors j'ai testé les différences de performances sur mon ordi entre la bibliothèque gfx (qui est acceleré par la carte graphique) et la fonction que j'ai proposé.

    100 rotations d'une image de 800*600 :
    - gxf : 10 sec
    - ma fonction : 1 min...
    Néanmoins, cela reste interessant de voir le code d'une rotation et ça évite d'ajouter une bibliothèque en plus (enfin, si elle est performante... )

    Sinon, je ferais une autre version qui ne rogne pas les bords, j'avais réalisé les calculs pour cela l'an dernier, mais ils sont sur un serveur qui est en arrêt jusqu'au 20 25, et n'ayant pas envie de perdre du temps là dessus, je ferai la mise à jour dans ces eaux là.

  5. #5
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    J'ai apparement retrouvé de tête les calculs, mais ce n'est pas vraiment optimisé (par exemple pour les calculs de la taille de la surface de destination).

    J'ai donc ajouté au code une autre fonction qui créait une surface de destination plus grande et qui ne déborde pas.

  6. #6
    Membre Expert
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Par défaut
    Je me suis un peu essayé à l'optimisation. Pour le côté pédagogique et lisible ça ne va plus être ça mais ça tourne mieux.

    Je n'en ai pas besoin chez moi alors je ne l'ai pas mis mais utiliser "SDL_LockSurface" peut-être nécessaire pour accéder directement aux pixels.

    J'ai commencé par modifier la fonction pour prendre la surface de destination en entrée afin de ne pas la créer à chaque frame et j'ai aussi supprimé les calculs de taille maximale. Dans une optique jeu/temps réel couper l'image n'est pas un problème (pour du dessin ça pourrait être différent) car on ne cumule pas les rotations (ce qui aurait comme défaut de cumuler les approximations et de vite corrompre l'image). Typiquement on incrémente l'angle et on refait la rotation à partir de l'original à chaque frame (de toute façon on a rien à y gagner pour les performances).
    Par contre il faudrait (mais là j'ai eu la flemme pour ce soir) permettre de placer l'image après la rotation à des coordonnées données (ce devrait être simple, juste un décalage à mettre). De plus, dans l'optique de placer un sprite à un endroit de l'écran, il faudrait ne boucler que sur la zone (limitée) de l'écran qu'occupe le sprite ce qui limitera beaucoup les calculs.

    Bref sur une image qui trainait en 800x600 j'ai obtenu # 20 fps.

    Les fonction d'accès aux pixels semblaient un bon angle d'attaque donc je m'en suis passé. Mon image étant en 8 bits j'ai fait avec (mais cela m'oblige a avoir le même format de pixels entre source et destination... ce qui semble de toute façon souhaitable pour les performances). Je suppose qu'en 32 bits cela irait aussi vite avec un processeur 32 bits, à moins que la bande passante mémoire ne suive pas. Cela m'a surtout permis d'utiliser un pointeur sur les pixels de destination pour passer d'un pixel à un autre avec une simple incrémentation du pointeur. Résultat 28 fps.

    Comme entre deux pixels on incrémente juste i et/ou j on peut incrémenter les coordonnées dans l'image d'origine d'une valeur fixe ce qui suprime beaucoup d'opérations sur les flottants, à commencer par les multiplications. 36fps.

    Pour voir j'ai passé les boucles à "for(j=destination->h; j>0; --j)" ce qui m'a donnée environ 0.5fps. Pas terrible mais bon.

    Ultime détail, l'ajout de "-O3 -march=athlon64" aux options de compilation pour optimiser au maximum et là... presque 70fps ! Ce qui me fait penser qu'il faudrait que je retente avec les fonctions d'accès aux pixels qui n'étaient peut-être pas en inline à l'origine, et elles n'étaient peut-être donc pas si coûteuses que ça.

    Pour faire mieux il faudrait passer à des calculs sur des entiers. En remplaçant les conversions flottants vers entiers (pour se faire une idée du coût de la conversion) par une mise à 0 je passe de 70 à 115 fps
    Sinon commencer pour chaque ligne directement à un pixel qui tombe dans l'image d'origine mais ça risque de casser les boucles.

    Je pense qu'un petit bout d'assembleur pas bien compliqué pour les boucles elles mêmes pourrait bien aider (en tout cas si l'asm sert c'est là ou nul part). Je serait curieux de voir combien on y gagnerait.


    Sinon c'est vrai qu'il faudrait un rien pour en faire un rotozoom. Là il est un peut tard mais ce serait plus classe et pas plus lent.

    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
     
    void SDL_RotationCentralN(SDL_Surface* origine, SDL_Surface* destination, float angle_radian) {
       Uint8* p;                 // pointeur sur le pixel à remplir
       int i;
       int j;
       int midx, midy;           // coordonees du milieu de l'ecran
       int intx, inty;           // valeurs entieres pour atteindre le pixel lui-même
       float x, y;               // valeurs de travail
       float ligne_x, ligne_y;   // valeurs au debut des lignes
       float dxi, dyi, dxj, dyj; // increments des x et y suivant i et j (compteurs des x et y)
       float tcos;
       float tsin;
     
       /*pour éviter pleins d'appel, on stocke les valeurs*/
       tcos = cos(angle_radian);
       tsin = sin(angle_radian);
     
       /* pour simplifier les notations*/
       midx = origine->w/2;
       midy = origine->h/2;
     
       p = (Uint8*)destination->pixels;
       ligne_x = -tcos * midx - tsin * midy + midx;
       ligne_y =  tsin * midx - tcos * midy + midy;
       dxi =  tcos;
       dxj =  tsin;
       dyi = -tsin;
       dyj =  tcos;
     
       /* 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
        */
       for(j=destination->h; j>0; --j) {
          x = ligne_x;
          y = ligne_y;
          for(i=destination->w; i>0; --i) {
             intx = (int) x;
             inty = (int) y;
     
             /* on vérifie que l'on ne sort pas des bords*/
             if (intx>=0 && intx < origine->w && inty>=0 && inty < origine->h)
                // On va cherche la couleur du pixel
                *p = * ((Uint8*)origine->pixels + inty * origine->pitch + intx);
     
             ++p;     // pixel suivant
             x += dxi;
             y += dyi;
          }
          ligne_x += dxj;
          ligne_y += dyj;
       }
    }

  7. #7
    Invité de passage
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2024
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2024
    Messages : 1
    Par défaut Merci Millie
    Merci Millie, je vois que tu as publie ce code en 2006 mais 20 ans plus tard il est quand meme plus simple et efficace que celui que j'ai bidouille pendant 1h avec ChatGPT.

    Citation Envoyé par millie Voir le message

    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
     
    /*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; 
        }  
     
    }

    [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;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 03/05/2006, 15h33
  2. Comment programmer une mise à jour ?
    Par qnop dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 15/03/2006, 16h33
  3. Comment faire une rotation de metafile (l'angle de 90° me suffit) ?
    Par Tardiff Jean-François dans le forum Langage
    Réponses: 4
    Dernier message: 28/01/2005, 08h58
  4. comment programmer une progressbar
    Par Choucas dans le forum Paradox
    Réponses: 3
    Dernier message: 13/11/2002, 11h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo