ROTATION AUTOUR DE (0,0,0)

 

Un peu de théorie

Pour commencer on va faire la rotation d'un point P en 2D, cela va nous donner les formules de base.

On a donc un point P de coordonnées (x,y). Une autre façon de le représenter est de considérer sa distance d à l'origine O et l'angle b entre PO et x'Ox.

Les vieux souvenirs de trigonométrie permettent de passer de la représentation polaire (d,b) à la représentation cartésienne (x,y) :

x = d*cos(b)
y = d*sin(b)

Dessin médiocre qui tente de représenter la chose :

                   ^
                   |
                   |                 P
      y = d.sin(b) *-------------- *
                   |           **  |
                   |        ***    |
                   |     ***       |
                   |   **          |
                   |*** ) b        |
           --------*---------------*------->
                 O |               x = d.cos(b)

On va donc faire subir à notre point P une rotation d'un angle a autour de O. La représentation polaire du point une fois tourné est :

P' = (d, a+b)

car sa distance à l'origine n'a pas changé, il a tourné comme sur un cercle de centre O et de rayon d et l'angle entre P'O et x'Ox a été augmenté de l'angle a.

La représentation cartésienne du point P' est (on reprend les mêmes formules) :

x' = d*cos(a+b)
y' = d*sin(a+b)

Comme on ne connait que x,y et pas d,b il faut s'en débarrasser dans le résultat. Pour cela on développe sin(a+b) et cos(a+b) :

sin(a+b) = sin(a)*cos(b) + sin(b)*cos(a)
cos(a+b) = cos(a)*cos(b) - sin(a)*sin(b)

Puis on remplace :

x' = d*cos(b) * cos(a) - d*sin(b) * sin(a)
y' = d*sin(b) * cos(a) + d*cos(b) * sin(a)

Et comme :

x = d*cos(b)
y = d*sin(b)

Ca nous donne le résultat attendu :

x' = x*cos(a) - y*sin(a)
y' = x*sin(a) + y*cos(a)

Bon, on sait faire tourner un point d'un angle donné autour de l'origine en 2D. Comment ça se passe en 3D ?

Et bien on ne fait plus tourner autour d'un point mais d'une droite. Commençons par les cas simples :

 

Rotation autour de l'axe z'Oz :

Dans ce cas, la composante z du point reste identique et les composantes x et y se calculent comme on vient de le faire en 2D donc:

x' = x*cos(az) - y*sin(az)
y' = x*sin(az) + y*cos(az)
z' = z

 

Rotation autour de l'axe x'Ox :

Dans ce cas, la composante x du point reste identique et les composantes y et z se calculent comme on vient de le faire en 2D en transposant :

y' = y*cos(ax) - z*sin(ax)
z' = y*sin(ax) + z*cos(ax)
x' = x

 

Rotation autour de l'axe y'Oy :

Dans ce cas, la composante y du point reste identique et les composantes x et z se calculent comme on vient de le faire en 2D en transposant :

x' = x*cos(ay) + z*sin(ay)
z' = -x*sin(ay) + z*cos(ay)
y' = y

Arrivé à ce stade, on peut continuer et en déduire les formules nécessaires pour tourner autour de n'importe-quelle droite. La rotation proprement dite n'est pas plus compliquée ensuite. Mais les demomakers s'arrêtent là. L'avantage est qu'il est plus facile (vraisemblablement) de gérer ainsi les mouvements simples d'objets. (A vrai dire je ne suis pas du tout convaincu par l'argument mais bon ...) De toutes façons nous verrons plus loin comment faire dans ce cas général.

Donc comment faire quand on en reste là ?

Et bien on défini un "centre de rotation" de l'objet. Pour un avion se sera le milieu des ailes par exemple. Puis on fait subir à l'objet 3 rotations à suivre:

  1. autour de la droite parallèle à x'Ox passant par ce "centre"
  2. autour de la droite parallèle à y'Oy passant par ce "centre"
  3. autour de la droite parallèle à z'Oz passant par ce "centre"

L'ordre de ces trois rotations est bien sûr capital et c'est celui que la plupart retiennent.

On a donc a spécifier à notre routine de rotation 3 angles et un "centre".

Mais on ne sait pas tourner autour d'une autre droite qu'un axe avec les formules données plus haut !

Qu'à cela ne tienne, on procède en 3 temps :

  1. on translate l'objet de telle sorte que son "centre de rotation" se retrouve à l'origine
  2. on effectue les 3 rotations autour des 3 axes
  3. on translate en sens inverse notre objet roté de manière à ce que son "centre de rotation" se retrouve à sa place initiale.

Et le tour est joué !

 

Un peu de pratique

Un code en C qui réalise la rotation "comme les demomakers" pourrait être :

    /* En entrée on a les 3 angles ax,ay,az, les coordonnées du centre
       Cx,Cy,Cz ainsi que le point à roter Px,Py,Pz.
       En sortie on a les coordonnées du point roté dans Rx,Ry,Rz.
    */

    /* Calcul des constantes */
    sinx = sin(ax);
    siny = sin(ay);
    sinz = sin(az);
    cosx = cos(ax);
    cosy = cos(ay);
    cosz = cos(az);

    /* 1ère translation pour amener le "centre" à l'origine */
    x = Px - Cx;
    y = Py - Cy;
    z = Pz - Cz;

    /* Rotation autour de l'axe x'Ox */
    t = y*cosx - z*sinx;
    z = y*sinx + z*cosx;
    y = t;
    /* Rotation autour de l'axe y'Oy */
    t = x*cosy + z*siny;
    z = z*cosy - x*siny;
    x = t;
    /* Rotation autour de l'axe z'Oz */
    t = x*cosz - y*sinz;
    y = x*sinz + y*cosz;
    x = t;

    /* Translation pour ramener le centre à sa place */
    Rx = x + Cx;
    Ry = y + Cy;
    Rz = z + Cz;
    

Celà fait 12 multiplications et 12 additions.

Il est facile de gagner 3 multiplications sans changer grand chose à notre routine. Il suffit pour cela d'utiliser une optimisation très courante en traitement du signal :

au lieu de faire :

x' = x*cos(a) - y*sin(a)
y' = x*sin(a) + y*cos(a)

qui prend 4 multiplications, on fait :

x' = cos(a)*(x+y) - y*(sin(a) + cos(a))
y' = x*(sin(a) - cos(a)) + cos(a)*(x+y)

Ce qui nous ramène à 3 muls/3 add au lieu de 4 muls/2 add.

Il existe une autre optimisation qui donne aussi 3 muls/3 add mais elle est vraisemblablement moins pratique (à voir ?). En tout cas, voici le petit bijou d'Oscar Buneman en 1973 :

t = x - y*tg(a/2)
y' = y + t*sin(a)
x' = t - y'*tg(a/2)

Résumons-nous : on sait faire la rotation des demomakers en 9 muls /15 add (si les 15 additions vous effraient, nous allons voir ci-après comment en gagner 3).

Ca ne demande aucun précalcul si ce n'est gérer des tables de sinus/cosinus (ou sinus/tangente pour l'optimisation d'O. Buneman).

Si on a pas besoin de faire les 3 rotations et que 2 ou une seule suffisent, c'est certainement la meilleure façon de procéder.

Mais si le problème est un peu plus complexe; par exemple modéliser la terre qui tourne sur elle-même et autour du soleil dans le même temps, il va nous falloir réaliser 2 fois cette rotation pour chaque point ?

Non bien sûr, mais il va nous falloir passer par le calcul matriciel pour composer les rotations.