M2 - Images
TP 1 - Transformations
Partie 1 : échauffement en 2D
On souhaite afficher un "mini" système
solaire composé du soleil et de la terre. La terre est
placée autour du soleil en fonction du jour de
l'année et son orientation dépend de l'heure de la
journée (entre 0 et 24h).
Dans un premier temps, on se contentera d'un
affichage statique. De même, afin de simplifier la mise en route,
on supposera que le soleil est au centre de l'univers ... c'est
à dire aux coordonnées (0, 0) dans un plan 2D.
Q1: Comment décrire la position et l'orientation de la terre par rapport au soleil ?
Q2: Comment composer les différentes
transformations nécessaires ? Quel type de vecteur permet de le
faire facilement ?
Q3: Ecrivez une fonction qui affiche la terre
dont la position et l'orientation sont passées en
paramètres :
void terre_afficher(float jour, float heure);
Vous pouvez vous aider de sdlkit pour
réaliser l'affichage et effectuer les différents calculs
(manipulations de vecteurs, de matrices, etc.). La documentation est en
annexe. L'utilisation directe d'openGL est
prévue pour un des prochains TP. Vous êtes bien sur libre
de l'utiliser, si vous le souhaitez.
Q4: Animez votre système solaire et
vérifiez que la terre peut bien s'orienter indépendament
de sa position autour du soleil.
Vous pouvez modifier la fonction keyboard afin de rendre l'affichage interactif (cf. Annexe).
Partie 2 : il manque un D ?? (ou 2)
On souhaite maintenant choisir le point de vue
permettant d'observer la "scène". Le "Système solaire"
peut être représenté en 3D par le plan XZ.
Q1: Comment définir une caméra ?
Q2: Comment la positionner dans la scène ?
Q3: Comment représenter simplement ces
différentes transformations (et calculer la position des points
de la scène sur l'écran) ?
Q4: Y-a-t-il d'autres problèmes ??
Q5: Modifiez votre programme afin de pouvoir
observer le système solaire depuis n'importe quel point de vue.
Question subsidiaire : qu'est ce qu'une caméra (réellement) ?
Q6: Comment déplacer interactivement la
caméra afin d'observer la scène ? Existe-t-il plusieurs
solutions ? Pourquoi ?
Question subsidiaire : identifiez dans votre
programme les différentes étapes du pipeline graphique
...
Annexe : sdlkit
Installation de sdlkit (seul)
Téléchargez sdlkit
créez un répertoire et dézippez l'archive dedans
cd <répertoire>
tar -zxvf sdlkit_latest.tar.gz
make
make install
si vous souhaitez installer les exemples :
créez un répertoire tests dans le répertoire sdlkit et dézippez l'archive dedans
cd tests
tar -zxvf sdlkit_tests_latest.tar.gz
make
Affichage avec sdlkit + sdlkit_2d + exemple
exemple de programme utilisant sdlkit pour afficher un point, une droite, un triangle (en 2D) :
téléchargez le programme d'exemple + sdlkit + les fonctions d'affichage
#include "sdlkit.h"
#include "sdlkit_2d.h"
/* fonctions d'affichage 2D utilisees dans la fonction display */
/* fonction a modifier */
void display(void)
{
/* obligatoire : preparation de l'affichage */
display_begin();
/* exemple d'affichages ... */
color_display(255, 0, 0); // choisir une couleur (rouge)
/* afficher un point (en rouge) */
point_display(100, 100);
/* changer la couleur des affichages suivants (en jaune) */
color_display(255, 255, 0);
/* tracer une ligne (en jaune) */
line_display(100, 100, 200, 200);
/* tracer un triangle (en vert) */
color_display(0, 200, 0);
triangle_display(200, 150, 400, 250, 300, 350);
/* obligatoire : realise l'affichage */
display_end();
}
int main(void)
{
/* creation de la fenetre d'affichage de 600 par 600 */
sdlkit_init(600, 600);
/* tant que la fenetre existe */
while(!sdlkit_stop())
{
/* traiter les evenements souris / clavier ...*/
sdlkit_events();
keyboard();
sdlkit_anime();
/* affichage : fonction a modifier */
display();
}
/* c'est fini ! */
sdlkit_quit();
return 0;
}
Si vous souhaitez manipuler votre animation au clavier, il suffit de modifer la fonction keyboard :
void keyboard(void)
{
SDLMod mod;
unsigned char *keys;
mod= SDL_GetModState();
keys= sdlkit_get_keys();
if(keys[SDLK_q] || keys[SDLK_ESCAPE])
/* permet de quitter le programme en appuyant sur ESC */
sdlkit_send_stop();
/* il suffit de tester une touche et d'agir en consequence */
if(keys[SDLK_LEFT])
/* aller a gauche ! */
}
La liste des symboles correspondants aux touches du clavier sont dans le SDL Programming Guide. L'état des touches "mortes" (shift, alt, ctrl, etc.) est donné par SDL_GetModState().
Calculs avec sdlkit
Les fonctions de manipulation de vecteurs se trouvent dans vec.h et celles travaillant sur les matrices dans mat44.h.
Opérations sur les vecteurs :
Il y a plusieurs types de vecteurs : 2D, 3D et 4D.
Chaque groupe de fonctions est prefixé par la taille des
vecteurs manipulés, vec2 pour les vecteurs 2D, vec3 pour les
vecteurs 3D, etc. Les vecteurs sont représentés par des
tableaux de float, vous pouvez utiliser les types
prédéfinis VEC2, VEC3 et VEC (pour 4D).
Les fonctions prefixées par vecX_* existent pour les différentes tailles de vecteurs.
Création :
- void vecX_init(float *v, float x, float y [, float z [, float w]]); // création d'un vecteur dont les composantes sont connues.
- void vecX_zero(float *v); // création d'un vecteur null
- vecX_copy(float *dst, const float *v); // création d'un vecteur par copie d'un autre vecteur.
Addition :
- void vecX_add(float *dst, const float *v1, const float *v2);
- void vecX_sub(float *dst, const float *v1, const float *v2);
- void vecX_neg(float *dst, const float *v); // vecteur opposé
Produit :
- void vecX_mul(float *dst, const float *v1, const float *v2); // produit composante par composante
- void vecX_const_mul(float *dst, float k, const float *v); // produit par un scalaire k
- vecX_dot(const float *u, const float *v); // produit scalaire
- vecX_cross(const float *u, const float *v); // produit vectoriel
Autres :
- float vecX_length(const float *v); // longueur du vecteur
- void vecX_norm(float *dst, const float *v); // normalisation d'un vecteur
Opérations sur les matrices homogènes :
Seules les matrices homogènes 4x4 sont
définies. Elles sont représentées par un tableau
de 16 float.
Création :
- void mat44_identity(float *a); // crée une matrice identité
- void mat44_zero(float *a); // crée une matrice nulle
Addition :
- void mat44_add(float *a, const float *b, const float *c); // A= B + C
- void mat44_sub(float *a, const float *b, const float *c); // A= B - C
Produit :
- void mat44_mul(float *a, const float *b, const float *c); // A= B * C
- void mat44_const_mul(float *a, float k, const float *b); // A= k * B
- void mat44_compose(float *a, const float *b); // A= A * B
Produit par un vecteur :
- void mat44_mul_vec(float *v, const float *a, const float *u); // v= A * u
- void mat44_compose_vec(const float *a, float *u); // u= A * u
Autres :
- int mat44_inverse(float *A, const float *B); // A= B-1
- void mat44_print(const float *a);
Transformation géométriques (construit une matrice A représentant une transformation) :
- void mat44_scale(float *a, float x, float y, float z); // homothétie
- void mat44_translate(float *a, float x, float y, float z); // translation par le vecteur (x, y, z)T
- void mat44_rotate(float *a, float angle, float x, float y, float z); // rotation de angle degrés autour de l'axe (x, y, z)T
- void mat44_lookat(float *a, const float *eye, const float *center, const float *up); // positionne la caméra
- void mat44_frustum(float *a, float left, float right, float bottom, float top, float near, float far); // definit le volume projetté / observé par la caméra
- void mat44_perspective(float *a, float fovy, float aspect, float near, float far); // définit une projection perspective
Les explications sur les différentes transformations sont dans le "openGL Programming Guide" / Chapitre 4. Les matrices construites par ces fonctions sont au format openGL, il est possible de les charger directement avec glLoadMatrixf().