require("../global.php"); entete(); ?>
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 :
x' = x*cos(az) - y*sin(az) |
y' = x*sin(az) + y*cos(az) |
z' = z |
y' = y*cos(ax) - z*sin(ax) |
z' = y*sin(ax) + z*cos(ax) |
x' = x |
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:
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 :
Et le tour est joué !
/* 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.
PiedDePage(); ?>