TD2 : positionnement automatique de la caméra pour viser l'objet
Introduction
Maintenant que nous avons réussi à visualiser un cube en
3d, il est peut-être temps de changer d'objet !
Dans le sous-répertoire OBJECTS de l'archive que vous avez récupéré
dans le TD1 se trouvent de nombreux autres objets, bien plus intéressants
que le cube à pan coupé du TD1.
 |
galleon.obj
|
 |
intercept.obj
|
 |
teapot.obj
|
 |
tennis.obj
|
Comment visualiser tous ces objets ?
Ils ont tous une taille différente, pourtant on aimerait bien les
voir du mieux possible, c'est-à-dire centrés au milieu de
la fenêtre graphique, et occupant au mieux cette fenêtre.
Lorsque je visualise la théière, il est propable que ses
dimensions sont de l'odre de la dizaine de centimètres. Lorsque
je regarde l'interceptor de la guerre des étoile, sa taille est
probablement en dizaine ou en centaine de mètres.
Comment faire pour placer la caméra automatiquement en face
de l'objet et à la bonne distance ?
-
Pour centrer l'objet il faut que son repère local soit situé
en son centre. En son centre ou en son centre de gravité ? A
vous de voir, je conseille le centre de gravité, car lorsque nous
ferons tourner l'objet ou lorsque nous tournerons autours de lui pour l'examiner
sous tous les angles, le point fixe le plus naturel à l'oeil est
bien le centre de gravité.
-
Il faut placer la caméra à la bonne distance. Pour
calculer cette distance, il faudra tenir compte du plus grand côté
de l'objet (hauteur, largeur, profondeur), de la taille de la fenêtre
et des angles de vision de la caméra.
Travail à effectuer
-
Dans le fichier object.c, écrire une fonction CenterObjectPoints(Object
* obj) qui calcule le centre de gravité des points de l'objet,
puis qui les déplace de manière à ce que le centre
du repère se trouve en son centre de gravité. On travaille
dans le repère local de l'objet, bien entendu. Cette fonction est
appelée dès que la lecture du fichier décrivant l'objet
est terminée, donc à la fin de ReadObject()
-
Pour placer la caméra automatiquement, nous allons avoir besoin
de connaître la boîte englobante de l'objet. Vous devrez calculer
cette boîte englobante, pourquoi pas dans la fonction CenterObjectPoints
? Vous créérez pour cela un nouveau type BBox dans
le fichier object.h.
typedef struct BBoxStruct {
VERTEX Vertex[8]; /* 8 sommets */
Quad QuadList[6]; /* 6 faces rectangulaires */
double hauteur, largeur, profondeur;
double plusGrandCote;
} BBox;
typedef struct QuadStruct {
int PtVertex[4]; /* 4 indices de sommets dans le tableau des VERTEX de la BBox */
COORD3D N; /* normale en cette face, servira plus tard pour dessiner la BBox */
} Quad;
typedef struct ObjectStruct {
...
BBox boundingBox;
...
}
Pour placer la caméra vous n'aurez pas besoin de tous les champs,
mais ils vous seront utiles plus rard lorsque vous voudrez dessiner la
BoundingBox de l'objet, ou tester si un objet est dans le champs de vision,
juste en regardant les sommets de la BBox.
Vous écrirez dans objetc.c une fonction PlacerCamera(Camera
* camera, Object *obj) qui place la caméra en face de l'objet.
Pour cela, commencer par initialiser les matrices de positionnement de
la caméra à l'identité. Puis vous translaterez la
caméra de tx, ty et tz mètres de manière à
voir l'objet.
Rappelez-vous le cours : on prendra tx = Ox, la position
en X du centre du repère de l'objet (dernière colonne de
la matrice de positonnement de l'objet, première ligne), ty
= Oy, et tz = Oz + D. Seule cette distance D est réellement
à calculer en fonction du plus grand côté de l'objet
et des angles de visiond e la caméra.
Vous appelerez cette fonction depuis main.c, sitôt que l'objet
et la caméra ont été lus sur disque. Je vous conseille
également de modifier le fichier graphics.c pour appeler
cette fonction de centrage de la caméra lors de l'appui sur une
touche du clavier (touche 'c' par exemple)