TD 3 : zoom, translation et rotation

Introduction

Dans ce TD, qui va certainement durer deux séances, nous vous demandons d'implémenter les interactions suivantes :
 

Translation de l'objet (ou de la caméra)

On souhaite, lorsque on déplace la souris en maintenant le bouton du milieu appuyé, que l'objet se déplace à l'écran.

Pour obtenir un déplacement apparent de l'objet de droite à gauche lorsqu'on déplace la souris ddans le même sens on a le choix : soit déplacer l'objet de droite à gauche par rapport à la caméra, soit déplacer la caméra de gauche à droite. Vous pourrez donc choisir de déplacer soit l'objet, soit la caméra.

La seule difficulté consiste à calculer en mètres les valeurs de translations tx et ty. Puisque l'objet ne s'éloigne pas de la caméra mais se déplace dans un plan fronto-parallèle, la valeur de translation en Z est nulle.

Je vous ai proposé en cours de calculer les valeurs de translations en tenant compte de la taille apparente de l'objet dans l'écran. Si on suppose l'objet centré au milieu de l'écran, on peut se dire : "si je dépace la souris horizontalement de gauche à droite sur toute la largeur de l'écran, je veux que l'objet se déplace de trois fois sa taille vers la droite. On a donc :
 

Pixels
Mètres
ResX/2
3 fois le plus grand côté de la Bounding Box
n pixels
?
Si la souris se déplace de n pixels, on obtient donc un déplacement en mètres en X de (n * 3)/(ResX/2).

La valeur 3 a été choisie arbitrairement, mais on pourrait l'adapter dynamiquement en fonction du plus grand côté du rectangle contenant l'objet dans l'écran (une fois projeté), ou encore pouvoir spécifier sa valeur à l'aide d'un ascenseur dans l'interface graphique de votre application.

On utilise un raisonnement similaire pour calculer le déplacement en Y.

Implémentation :

Tout se passe dans la fonction mainloop() du fichier graphics.c. Je vous conseille de créer une variable mode_deplacement qui pourra prendre les valeurs TRANSLATION, ROTATION, ZOOM (définir ces macros avec des #define), et de mettre un switch dans les différentes parties de mainloop :
 

case ButtonPress :
    switch(evt.xbutton.button) {
        old_x = evt.xbutton.x;
        old_y = evt.xbutton.y;
        case Button1 :
            mode_deplacement = ROTATION;
            break;
        case Button2:
            mode_deplacement = TRANSLATION;
            break;
        case Button3 :
            mode_deplacement = ZOOM;
            break;
    }
    break;
case ButtonRelease :
    mode_deplacement = AUCUN;
    break;
case MotionNotify :
    switch(mode_deplacement) {
        new_x = evt.xmotion.x;
        new_y = evt.xmotion.y;
        /* déplacement en pixels */
        dx = new_x - old_x;
        dy = new_y - old_y;
        case TRANSLATION:
            tx = ......;
            ty = ......;
            TranslateObject(tx, ty, 0);
            UpdateLocalToCamera(...);
            draw_object(...);
            ...
            break;
        case ROTATION:
            ...
            break;
        case ZOOM:
            ...
            break;
        }
        old_x = new_x;
        old_y = new_y;
....

Zoom

Ici aussi on peut soit rapprocher la caméra, soit éloigner l'objet.

On effectuera une translation uniquement selon l'axe des Z : tx = ty = 0. Pour calculer la valeur de tz, on utilisera un raisonnement similaire à celui dont on s'est servi pour calculer les valeurs de translation : si ma souris se déplace du haut vers le bas, je rapproche l'objet de 3 fois sa taille, etc....
 

Boule Virtuelle

Vous écrirez plusieurs fonctions : Vous complèterez ensuite la fonction mainloop() de graphics.c. En déplaçant la souris avec le bouton 1 enfoncé, vous calculerez pour chaque position successive de la souris les vecteurs OA et OB, puis les matrices M et M_INV. N'oubliez pas que pour que l'objet tourne sur place, il faut au préalable l'avoir translaté à l'origine.