Rotation/fr
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Rotations
Le type LSL rotation est utilisé pour représenter une orientation en 3D (nous nous efforçons d'écrire le nom des types en gras). Une orientation, ou angle en 3D, est représentée par un objet mathématique appelé un quaternion. Considérons les quaternions comme un ensemble de 4 nombres, dont trois représentent la direction à laquelle l'objet fait face et la quatrième son pivotage vers la droite ou vers la gauche autour de cette direction. Le principal intérêt d'utiliser les quaternions est qu'ils ne sont pas sujets à la perte de degré de liberté (gimbal lock). Pour le fonctionnement interne complexe des mathématiques des quaternions, voir quaternion. Pour une liste de fonctions ou d'évènements liés aux rotations, voir résumé des rotations. Il y a aussi des informations sur la façon de faire tourner des textures sur la page consacrée aux textures.
Autres représentations
Une autre façon de représenter une rotation est d'utiliser 3 nombres, <X, Y, Z>, qui représentent de combien (en radians) l'objet tourne autour de trois axes. C'est par exemple utilisé dans la fenêtre de modification et est généralement facilement visualisé par les gens. Notez que ces trois nombres sont de type vector et non de type rotation, bien que cela puisse représenter la même information. On appelle cela les rotations d'Euler.
Une troisième façon de faire est d'utiliser trois vecteurs, qui vont indiquer vers où sont orientés l'avant, le dessus et le coté gauche. En réalité, il n'y a besoin que de deux de ces vecteurs, le troisième découlant des deux premiers.
Il y a de bonne raisons de préférer la version à quatre nombres, la rotation, bien qu'elle soit plus compliquée à s'approprier pour des débutants. Il existe des fonctions qui permettent de convertir facilement d'une représentation à une autre.
La règle de la main droite
Dans LSL, toutes les rotations sont effectuées suivant la règle de la main droite. Avec votre main droite, pointez l'index vers la direction de l'axe X positif, le majeur à angle droit de l'index pointera alors en direction de l'axe Y positif, et le pouce, à angle droit des deux autres, pointera vers l'axe Z positif. Lorsque vous modifiez un objet, les trois flèches de couleur pointent vers le coté positif de chacun des axes (X rouge, Y vert, Z bleu).
Gardez votre main en position, c'est utile pour autre chose : trouver de quel côté est l'axe positif. Fermez le poing et sortez le pouce en direction du coté positif de l'axe qui vous intéresse. Vos autres doigts sont repliés dans le sens des axes positifs. Les rotations autour des axes X, Y et Z sont géréralement appelées roulis, tangage et lacet, en particulier lorsqu'il est question de véhicules.
Dans le monde ou localement
Il est important de différencier les rotations relatives au monde et la rotation relative à l'objet lui-même. Dans la fenetre de modifications, vous pouvez passer de l'une à l'autre. Dans un script, il faut convertir l'une en l'autre pour obtenir le comportement souhaité.
Pour obtenir la rotation d'une prim non liée depuis un script, utiliser :
rotation maRot | = llGetRot(); | // charge la rotation par rapport au monde dans maRot |
Rotations combinées
Pour combiner des rotations, on utilise les opérateurs multiplier et diviser. Ne pas utiliser les opérateurs addition ou soustraction, qui ne donneront pas le résultat attendu. L'opération multiplier s'applique à la rotation dans le sens direct, l'opération diviser effectue une rotation en sens inverse. Il est également possible d'obtenir une rotation inverse directement, en calculant l'opposé du composant S avec le signe - : X.s = -X.s.
À l'inverse d'autres types comme float, l'ordre dans lequel les opérations sont effectuées est important. non commutative. La raison en est simple : l'ordre dans lequel on effectue des rotations est importante dans le monde réel. Par exemple, si vous avez une flèche avec quatre plumes, au départ à la rotation <0, 0, 0> avec sa queue comme origine, elle sera alignée sur l'axe X avec sa pointe dans la direction X positive, ses plumes seront alignées sur les axes Z et Y et les axes de la fleche seront alignés sur les axes dans le monde. Nous allons la faire tourner de 45 degrés autour de l'axe X et de 30 degrés autour de l'axe Y, mais en changeant l'ordre.
D'abord, après une rotation de 45° autour de l'axe X, la flèche sera toujours alignée le long de l'axe X et n'aura pas bougé, elle aura simplement pivoté autour de son axe, donc les plumes seront à 45° des axes. Ensuite, la faire tourner de 30° autour de l'axe Y la fera pointer de 30° vers le bas (par rapport à l'axe X - souvenez vous que la règle de la main droite fait qu'une rotation positive va vers le bas). La flèche finit par être pointée de 30° vers le bas, sur le même plan vertical qu'au départ, mais en ayant pivoté sur elle même, ce qui fait que les plumes ne sont plus alignées vers le haut et le bas.
Si on effectue les modifications dans l'autre ordre, en commençant par une rotation de 30° sur l'axe Y, la flèche va pencher vers le bas par rapport au plan XY. Notez qu'elle n'est plus alignée par rapport à son axe X : donc, son axe X et celui du monde ne sont plus alignés l'un par rapport à l' autre. Une rotation de 45° autour de l'axe X la fera pivoter autour de sa queue, la pointe tournera de 45° vers le haut et la droite en suivant un cône de 30° dont l'axe est aligné avec l'axe positif dans le monde.
Le résultat est clairement différent de celui de la premiere rotation, alors que seul l'ordre dans lequel les rotations ont été effectuées a changé.
Pour effectuer une rotation constante, vous devez définir une valeur rotation, ce qui se fait en créant un vector avec comme composants les angles X, Y, Z en radians (cela s'appelle un angle d'Euler), puis en le convertissant en rotation avec la fonction llEuler2Rot. Vous pouvez aussi créer directement une rotation native : la partie réelle est le cosinus de la motié de l'angle de rotation et la partie vectorielle l'axe normalisé de rotation multiplié par le sinus de la moitié de l'angle de rotation. Pour passer d'une rotation à un vecteur angle d'Euler, utilisez llRot2Euler.
NOTE: les angles dans LSL sont en radians, pas en degrés, mais vous pouvez facilement les convertir avec les constantes prédéfinies RAD_TO_DEG et DEG_TO_RAD. Pour une rotation de 30 degrés autour de l'axe X par exemple :
rotation rot30X | = llEuler2Rot(<30, 0,0> * DEG_TO_RAD); | // convertit les degrés en radians, puis convertit ce vecteur en une rotation, rot30x |
vector vec30X | = llRot2Euler(rot30X ); | // retransforme la rotation en un vecteur (avec les valeurs en radians) |
Rotations locales ou globales
Les rotations locales sont effectuées autour des axes de l'objet lui-même, dans les directions avant/arriere, droite/gauche et bas/haut, quelle que soit l'orientation de l'objet dans le monde qui l'entoure. Les rotations globales sont effectuées autour des axes du monde, Nord/Sud, Est/Ouest, plus haut/plus bas. Vous pouvez voir la différence en faisant tourner une prim, puis en la modifiant et en changeant les réglages d'axes entre local et global : regardez comment les flèches de couleur changent.
Dans LSL, la différence entre une rotation locale ou globale réside dans l'ordre dans selon lequel les rotations seront évaluées dans l'instruction.
Ce script effectue une rotation locale en plaçant la rotation constante de 30° à gauche de la rotation de l'objet. C'est comme la première opération effectuée dans l'exemple précédent, cela fait pivoter la flèche autour de son axe longitudinal.
rotation rotLocale = | rot30X * maRot; | // effectue une rotation locale en multipliant une rotation constante par une rotation dans le monde. |
Pour effectuer une rotation globale, utiliser les mêmes valeurs rotation, mais dans l'ordre opposé. Cela correspond à la seconde rotation du second exemple, avec la flèche qui pivote vers le haut et la droite autour de l'axe X du monde.
rotation rotGlobale | = maRot * rot30X; | // effectue une rotation globale en multipliant une rotation dans le monde par une rotation constante. |
Une autre façon de voir les rotations combinées
Regardez cette différence entre locale et globale en considérant que les rotations sont effectuées dans l'ordre de traitement, ce qui veut dire de gauche à droite sauf pour les expressions entre parenthèses.
Dans le cas du rotLocale, ce qui se passe est qu'en partant de <0, 0, 0>, la rot30X est effectuée en premier et fait tourner la prim autour de l'axe X du monde. Dans la mesure où la prim n'a pas encore bougé, les axes local et global sont identiques, donc le résultat est de faire tourner la prim autour de son propre axe local X. Ensuite, la deuxième rotation maRot est exécutée, ce qui fait pivoter la prim vers sa position d'origine, mais en intégrant la rotation X précédente. Le résultat est que la prim tourne sur place autour de son propre axe X, ce qui est une rotation locale.
Dans le cas du globalRot, toujours en partant de <0, 0, 0>, l'objet pivote d'abord vers sa position d'origine, mais les axes de l'objet et du monde ne sont plus alignés. Donc la deuxième rotation rot30x fait exactement la meme chose que dans le cas local, c'est a dire qu'elle tourne l'objet de 30° autour de l'axe X du monde, mais la conséquence est que l'objet pivote suivant un cône aligné sur l'axe X du monde, puisque les axes X du monde et de l'objet ne sont plus alignés dans ce cas. Le résultat est que la prim tourne de 30° autour de l'axe X du monde, ce qui est une rotation globale.
La division de rotations a pour effet d'effectuer la rotation dans le sens opposé : multiplier une rotation par 330 degrés revient au même que diviser par une rotation de 30 degrés.
Utilisation des rotations
On peut accéder à chacune des composantes d'une rotation R au moyen de R.x, R.y, R.z et R.s (pas R.w). la partie scalaire R.s est le cosinus de la moitié de l'angle de rotation. La partie vectorielle (R.x, R.y, R.z) est le produit du vecteur unitaire dirigeant l'axe de rotation par le sinus de la moitié de l'angle de rotation. On peut obtenir une rotation inverse en utilisant des nombres opposés pour x, y et z (ou en utilisant une valeur s opposée). De plus, vous pouvez aussi utiliser une rotation en tant que container pour des valeurs float, chaque rotation en contenant quatre, une liste composée de rotations étant plus efficace qu'une list composée de floats, mais cela implique de les déballer au préalable.
rotation rot30X | = llEuler2Rot(<30, 0,0> * DEG_TO_RAD ); | // Crée une rotation constante |
rotation rotCopiee | = rot30X; | // Simplement la copier dans rotCopiee, cela copie les 4 composantes float |
float X | = rotCopiee.x; | // Extrait chacune des composantes d'une rotation |
float Y | = rotCopiee.y; | |
float Z | = rotCopiee.z; | |
float S | = rotCopiee.s; | |
rotation uneAutreCopie | = <X, Y, Z, S>; | // Crée une nouvelle rotation à partir des composantes |
Il existe une constante prédéfinie pour la rotation nulle ZERO_ROTATION qui peut être utilisée directement. Si vous avez besoin d'inverser une rotation R, divisez ZERO_ROTATION par R. Rappel de ce qui est ci-dessus, cela fonctionne en effectuant d'abord une rotation à la position zéro, puis (parce que c'est une division) en tournant dans le sens inverse de la rotation d'origine, ce qui revient donc à une rotation inversée.
rotation rot330X | = <-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s>; | // Inverse une rotation - NOTE la composante s n'est pas négative |
rotation uneAutre330X | = ZERO_ROTATION / rot30X; | // Inverse la rotation avec une division, même résultat que rot330X |
rotation encoreUneAutre330X | = <rot30X.x, rot30X.y, rot30X.z, -rot30X.s>; | // pas exactement la même chose, mais revient au même. |
Prims uniques ou racine / prims liées et attachements
Ceci est important pour des objets tels que les portes sur un véhicule : le mouvement de la porte doit s'effectuer par rapport au véhicule, quelle que soit la façon dont celui-ci est tourné. S'il est possible de le faire avec des rotations globales, cela ne tardera pas à être pénible. Une prim peut faire partie de 3 systèmes de coordonnées : tout seul, partie d'un ensemble lié ou partie d'un attachement. Quand la prim est seule, c'est-à-dire qu'elle ne fait pas partie d'un ensemble lié, elle se comporte comme une prim racine; quand elle fait partie d'un attachement, elle se comporte différemment, et de façon moins cohérente.
Fonction | Isolée ou racine | Membre d'un ensemble lié | Attachement | Membre d'un ensemble lié attaché |
---|---|---|---|---|
llGetRot llGetPrimitiveParams |
rotation globale de la prim | rotation globale de la prim | rotation globale de l'avatar | rotation globale de l'avatar multipliée par la rotation globale de la prim (Inutile) |
llGetLocalRot | rotation globale de la prim | rotation de la prim relative au prim racine | rotation de l'attachement relative au point d'attachement | rotation de la prim relative à la prim racine de l'attachement |
llGetGlobalRotation | rotation globale de la prim | rotation globale de la prim racine | rotation globale de l'avatar | rotation globale de l'avatar |
llSetRot(*) llSetPrimitiveParams(*) |
change la rotation globale | compliqué, voir llSetRot | change la rotation relative à l'avatar | change la rotation en la rotation globale de la racine multipliée par la nouvelle rotation |
llSetLocalRot(*) | change la rotation globale | change la rotation de la prim par rapport à la prim racine | change la rotation globale par rapport à l'avatar | change la rotation de la prim par rapport à la prim racine de l'attachement |
llTargetOmega† | fait tourner l'ensemble lié autour du centre de la prim | fait tourner la prim autour de son centre | fait tourner l'ensemble lié autour du centre de l'attachement | fait tourner la prim autour de son centre |
* | Les objets physiques qui ne sont pas des fils dans un ensemble lié ne répondront pas aux changements de rotations |
† | Pour les objets non physiques, llTargetOmega est exécuté du côté du client, ce qui donne une méthode à faible lag pour obtenir des rotations fluides et continues |
Rotation de vecteurs
Dans LSL, faire pivoter un vecteur est très utile quand vous voulez faire bouger un objet suivant un arc de cercle, mais que le centre de la rotation n'est pas le centre de l'objet.
Ca peut sembler très compliqué, mais c'est beaucoup plus simple qu'il n'y paraît. Rappelez vous de la partie ci dessus sur la rotation de flèche, et remplacez la flèche par un vecteur dont l'origine est la queue de la flèche et dont les composants X, Y, and Z indiquent la position de la pointe de la flèche. Faire tourner la flèche autour de sa queue fait bouger sa pointe suivant un arc dont le centre est la queue de la flèche. De la même façon, faire tourner un vecteur qui représente un décalage par rapport au centre de la prim la fait pivoter suivant le même arc. L'objet pivote autour d'une position qui est décalée par rapport au centre de la prim par le vector.
rotation rot30X | = llEuler2Rot(<30, 0,0> * DEG_TO_RAD ); | // crée une rotation constante, 30 degrés autour de l'axe X |
vector decalage | = <0, 1, 0>; | // décale d'un mètre dans la direction Y positive |
vector decalageTourne | = decalage * rot30X; | // fait tourner le vecteur décalage pour obtenir le mouvement donné par la rotation |
vector nouvellePos | = llGetPos() + decalageTourne; | // déplace la position de la prim en fonction du décalage tourné |
Nota Bene: Ceci est un mouvement, donc prenez garde aux problèmes qui se posent lorsqu'un objet est bougé hors du monde, sous le sol, de plus de 10 mètres, etc...
Constantes
ZERO_ROTATION
ZERO_ROTATION = <0.0, 0.0, 0.0, 1.0>;
Une constante de rotation correspondant à un angle d'Euler de <0.0, 0.0, 0.0>.
DEG_TO_RAD
DEG_TO_RAD = 0.01745329238f;
Une constante float qui donne l'angle en radians quand on multiplie l'angle en degrés par elle.
RAD_TO_DEG
RAD_TO_DEG = 57.29578f;
Une constante float qui donne l'angle en degrés quand on multiplie l'angle en radians par elle.