Après tant de lecture sur les transformations, il est temps d'implémenter une trackball pour mon application. Je comprends que je dois créer un vecteur de l'origine à l'endroit où la souris est cliquée, puis un autre de l'origine à l'endroit où la souris est relâchée.
Ma question est la suivante: dois-je convertir les cordons de pixels (x, y) en cordes du monde ou dois-je tout faire dans l'espace image (étant donné que l'espace image est la projection 2D de la scène mesurée en pixels)?
ÉDITER
La réponse de Richie Sams est très bonne. Cependant, je pense que je suis en train de suivre une approche légèrement différente, veuillez me corriger si je me trompe ou si je me méprends sur quelque chose.
Dans ma demande , j'ai une SimplePerspectiveCamera
classe qui reçoit position
de la caméra, le position of the target
nous regardons, le up
vecteur, les fovy
, aspectRatio
, near
et far
distances.
Avec celles-ci, je construis mes matrices de vue et de projection. Maintenant, si je veux faire un zoom avant / arrière, je mets à jour le champ de vision et mets à jour ma matrice de projection. Si je veux faire un panoramique, je déplace la position de la caméra et regarde par le delta produit par la souris.
Enfin, pour les rotations, je peux utiliser la transformation angle-axe ou les quaternions. Pour cela, j'enregistre les pixels-coords où la souris a été enfoncée, puis lorsque la souris se déplace, j'enregistre également les pixels-coords.
Pour chaque paire de coords je peux calculer la valeur Z compte tenu de la formule pour une sphère, à savoir, sqrt (1-x ^ 2-y ^ 2), puis calculer des vecteurs qui vont de l' target
au PointMousePressed
et à partir target
de PointMouseMoved
, faire produit vectoriel pour obtenir l'axe de rotation et utiliser n'importe quelle méthode pour calculer la nouvelle position de la caméra.
Cependant, mon plus grand doute est que les valeurs (x, y, z) sont données en pixels-coords, et lors du calcul des vecteurs que j'utilise, target
ce qui est un point en monde-coords. Ce mélange de système de coordonnées n'affecte-t-il pas le résultat de la rotation que j'essaie de faire?
z
valeur d'une sphère de rayonr
, mais je ne sais pas si cette sphère vit dans l'espace-monde ou l'espace-image et quelles sont les implications. Je réfléchis peut-être trop au problème.Réponses:
En supposant que vous voulez dire une caméra qui tourne en fonction du mouvement de la souris:
Une façon de l'implémenter est de garder une trace de la position de la caméra et de sa rotation dans l'espace. Les coordonnées sphériques sont pratiques pour cela, car vous pouvez représenter directement les angles.
La caméra est située à P qui est défini par m_theta, m_phi et m_radius. Nous pouvons tourner et nous déplacer librement où nous voulons en modifiant ces trois valeurs. Cependant, nous regardons et tournons toujours autour de m_target. m_target est l'origine locale de la sphère. Cependant, nous sommes libres de déplacer cette origine où nous voulons dans l'espace mondial.
Il existe trois fonctions principales de l'appareil photo:
Dans leurs formes les plus simples, Rotate () et Zoom () sont triviaux. Il suffit de modifier respectivement m_theta, m_phi et m_radius:
Le panoramique est un peu plus compliqué. Un panoramique de la caméra est défini comme le déplacement de la caméra vers la gauche / droite et / ou vers le haut / bas par rapport à la vue de caméra actuelle. La façon la plus simple de le faire est de convertir notre vue de caméra actuelle des coordonnées sphériques en coordonnées cartésiennes. Cela nous donnera des vecteurs ascendants et droits .
Donc, tout d'abord, nous convertissons notre système de coordonnées sphériques en cartésien pour obtenir notre vecteur de look . Ensuite, nous faisons le produit vectoriel croisé avec le vecteur monde vers le haut , afin d'obtenir un bon vecteur. Il s'agit d'un vecteur qui pointe directement à droite de la vue de la caméra. Enfin, nous faisons un autre vecteur produit croisé pour obtenir la caméra jusqu'à vecteur.
Pour terminer le panoramique, nous déplaçons m_target le long des vecteurs haut et droit .
Une question que vous pourriez vous poser est la suivante: pourquoi convertir entre cartésien et sphérique tout le temps (vous devrez également convertir pour créer la matrice de vue).
Bonne question. Moi aussi, j'ai eu cette question et j'ai essayé d'utiliser exclusivement la carte cartésienne. Vous vous retrouvez avec des problèmes de rotation. Étant donné que les opérations en virgule flottante ne sont pas exactement précises, plusieurs rotations finissent par accumuler des erreurs, qui correspondaient à la caméra lentement et roulaient accidentellement.
Donc, à la fin, je suis resté avec des coordonnées sphériques. Afin de contrer les calculs supplémentaires, j'ai fini par mettre en cache la matrice de vue et à la calculer uniquement lorsque la caméra se déplace.
La dernière étape consiste à utiliser cette classe Camera. Appelez simplement la fonction membre appropriée dans les fonctions MouseDown / Up / Scroll de votre application:
Les variables de facteur m_camera * ne sont que des facteurs d'échelle qui changent la vitesse de rotation / panoramique / défilement de votre appareil photo
Le code que j'ai ci-dessus est une version pseudo-code simplifiée du système de caméra que j'ai fait pour un projet parallèle : camera.h et camera.cpp . La caméra essaie d'imiter le système de caméra Maya. Le code est gratuit et open source, alors n'hésitez pas à l'utiliser dans votre propre projet.
la source
Dans le cas où vous souhaitez jeter un œil à une solution prête, j'ai un port de THREE.JS TrackBall contrôlés en C ++ et C #
la source