2008-09-20 11 views
13

J'ai un objet 3D que je souhaite pouvoir faire pivoter en 3D. Le plus simple est de traduire directement le mouvement de la souris X et Y en rotation autour des axes Y et X, mais s'il y a une rotation le long des deux axes, la rotation du modèle devient très contre-intuitif (p. axe, votre mouvement le long de l'autre axe est inversé). Je pourrais simplement faire la méthode ci-dessus, mais au lieu de stocker la quantité à faire tourner autour des deux axes, je pourrais stocker la matrice de rotation complète et juste de plus tourner sur les mêmes axes pour chaque glisser de la souris, mais je suis préoccupé que cela aurait rapidement des problèmes de précision.Meilleure façon de traduire le mouvement de déplacement de la souris en rotation 3D d'un objet

Répondre

4

Créez une matrice d'accumulateurs et initialisez-la avec l'identité.

Chaque cadre, applique cela à votre état de matrice modelview/world avant de dessiner l'objet. Lors du mouvement de la souris, construire une matrice de rotation autour de l'axe X avec un peu de sensibilité_constant * delta_x. Construire une autre matrice de rotation autour de l'axe Y pour l'autre composant. Multipliez-en un, puis l'autre sur l'accumulateur.

L'accumulateur change lorsque vous déplacez la souris. Lors du dessin, il orientera l'objet comme prévu.

Aussi, la personne qui parle de quaternions a raison; cela semblera bon seulement pour de petits changements incrémentiels. Si vous le faites glisser rapidement en diagonale, il ne tournera pas comme prévu.

+0

Je surestime l'effet de Imprécision virgule flottante. Le simple fait d'accumuler les rotations fonctionne bien. Je vais regarder dans quaternions, mais comme je ne fais que tourner autour de 2 axes, tout va bien. –

3

Vous pouvez faire face à la perte de précision en renormalisant votre matrice de rotation de sorte que chacune des 3 lignes soit à nouveau perpendiculaire. Vous pouvez également régénérer la matrice de rotation que vous êtes sur le point de modifier en fonction des informations existantes sur l'objet, ce qui élimine le besoin de renormalisation.

Vous pouvez également utiliser quaternions, qui est une alternative aux angles d'Euler pour traiter les rotations.

J'ai appris beaucoup de ceci dans mes premiers jours de this faq, qui traite de ce problème (bien que pour une autre application) dans Euler's are Evil.

6

Il est probablement plus intuitif de faire pivoter l'objet autour de l'axe perpendiculairement à la direction de traînée actuelle, soit de manière incrémentielle à chaque mouvement de la souris, soit par rapport à la position de départ de la traînée. Les deux options donnent des interactions utilisateur légèrement différentes, chacune ayant ses avantages et ses inconvénients.

Il existe une méthode relatively straightforward pour convertir un angle et un vecteur 3D représentant l'axe en rotation dans une matrice de rotation.

Vous avez raison de dire que la mise à jour d'une matrice de rotation brute par des rotations incrémentielles fera que la matrice ne sera plus une matrice de rotation pure. C'est parce qu'une matrice de rotation 3x3 a trois fois plus de données que nécessaire pour représenter une rotation.

Une méthode plus compacte pour représenter les rotations est avec Euler Angles, ayant un vecteur minimal de 3 valeurs. Vous pouvez prendre la rotation actuelle en tant que vecteur d'angle d'Euler, la convertir en matrice, appliquer la rotation (incrémentielle ou non) et convertir la matrice en un vecteur d'angle d'Euler. Cette dernière étape éliminerait naturellement tout composant non-rotationnel à votre matrice, de sorte que vous vous retrouveriez avec une matrice rotationnelle pure pour l'état suivant.

Les angles d'Euler sont conceptuellement agréables, mais il faut beaucoup de travail pour effectuer les conversions.

Un choix plus pratique est Quaternions (also), qui sont des vecteurs à quatre éléments. Les quatre éléments spécifient la rotation et l'échelle uniforme, et il arrive que si vous entrez et normalisez le vecteur à la longueur de l'unité, vous obtiendrez un facteur d'échelle de 1,0. Il se trouve qu'une valeur de l'axe d'angle peut également être converti en une valeur quaternionique très facilement par

q.x = sin(0.5*angle) * axis.x; 
q.y = sin(0.5*angle) * axis.y; 
q.z = sin(0.5*angle) * axis.z; 
q.w = cos(0.5*angle); 

Vous pouvez alors prendre le produit quaternion (qui utilise seulement simple multiplication et l'addition) du quaternion de rotation actuelle et incrémentale rotation quaternion pour obtenir un nouveau quaternion qui représente l'exécution des deux rotations. À ce stade, vous pouvez normaliser la longueur pour assurer une rotation pure, mais sinon continuer itérativement combinant les rotations.

La conversion du quaternion en une matrice de rotation est très simple (utilise uniquement la multiplication et l'ajout) lorsque vous souhaitez afficher le modèle dans son état de rotation en utilisant des API graphiques traditionnelles.

5

Dans mon cours de Computer Graphics, nous avons reçu le code suivant qui nous a permis de ne pas réinventer la roue.

trackball.h

trackball.c

Questions connexes