Correction
examen de TD 2000-2001

WB01624_.gif (281 octets) RETOUR

Mercredi 30 Mai 2001 - 1h30

Horizontale.gif (2348 octets)

Exercice 1: OpenGL

Question a)

La spécification d'une normale est obligatoire car un éclairage est demandé à la question c).

void facette(void) {
  glBegin(GL_QUADS);
  glNormal3f(0.0F,0.0F,1.0F);
  glVertex2f(0.0F,0.0F);
  glVertex2f(1.0F,0.0F);
  glVertex2f(1.0F,1.0F);
  glVertex2f(0.0F,1.0F);
  glEnd();
}
Question b)
void scene(int n) {
  glPushMatrix();
  float dp =(float) -n/2;
  for ( int i = 0 ; i < n ; i++ )
    for ( int j = 0 ; j < n ; j++ ) {
      glPushMatrix();
      glTranslatef(dp+i,dp+j,0.0F);
      facette();
      glPopMatrix(); }
  glPopMatrix();
}
Question c)
void display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  GLfloat spot_diffuse[] = { 1.0F,0.0F,0.0F,1.0F };
  GLfloat spot_specular[] = { 1.0F,0.0F,0.0F,1.0F };
  GLfloat spot_position[] = { 0.0F,0.0F,100.0F,1.0F };
  GLfloat spot_direction[] = { 0.0F,0.0F,-1.0F };
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glPushMatrix();
  glLightfv(GL_LIGHT0,GL_DIFFUSE,spot_diffuse);
  glLightfv(GL_LIGHT0,GL_SPECULAR,spot_specular);
  glLightfv(GL_LIGHT0,GL_POSITION,spot_position);
  glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spot_direction);
  glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,5.0F);
  scene(45);
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}
Fichier source complet: Ex1ExamTD20002001.cpp
Modules utilitaires: Modules.zip

Exercice 2

La rotation à réaliser peut être obtenue par la réalisation successive de 7 transformations géométriques:

  • Une translation T pour déplacer l'axe D de manière qu'il coupe l'origine du repère. Les matrices de rotation canonique utilisées ne modélisent que des rotations autour d'axes passant par l'origine, donc l'axe doit passer par O. La valeur de la translation n'influe pas si le passage par O est vérifier. On pourra prendre (-2, -1, -3) ou (-4, -2, 1) qui ramène à l'origine les points de définition de l'axe, ou toute autre valeur de translation vérifiant (-2+f*2, -1+f*1, -3+f*-4).

  • Une rotation R1 dans le sens direct autour de l'axe Oy pour ramener l'axe D dans le plan yOz. L'angle ay de cette rotation vérifie tan(ay) = 1/2 -> 26,565° ou 0,4636 radian.

  • Une rotation R2 dans le sens rétrograde (valeur négative) autour de l'axe Ox pour ramener l'axe D sur l'axe Oz. La valeur absolue de l'angle ax de cette rotation vérifie sin(ax) = 1/sqrt(21) ->12,604° ou 0,22 radian.

  • Une R rotation d'angle 60° autour de l'axe Oz.

  • La rotation R2-1 permettant de commencer le replacement de l'axe D en sa position initiale.

  • La rotation R1-1.

  • La translation T-1.

On a donc la matrice de transformation M résultante:

M = T-1.R1-1.R2-1.R.R2.R1.T

Fichier source complet: Ex2ExamTD20002001.cpp
Modules utilitaires: Modules.zip

Exercice 3

Question a)

struct coord3D {
  float x;
  float y;
  float z; } ;

struct facette {
  int ns;
  coord3D *s; } ;

Une structure coord3D pour stocker la position d'un sommet dans l'espace. On aurait aussi pu travailler en coordonnées homogènes et donc avoir une quatrième coordonnée utilisable.

Une structure facette composée d'un entier représentant le nombre de sommets du polygone et d'un tableau pour stocker les positions de ces sommets.

Autre solution: Utiliser une liste chaînée de sommets.

Question b)

Une méthode simple pour tester la planarité d'un polygone de plus de trois sommets (un polygone à trois ou moins de trois sommets est forcément plan) consiste à utiliser les trois premiers sommets pour calculer la normale à la facette triangulaire qu'ils forment, puis à tester au moyen d'un produit scalaire l'orthogonalité de cette normale avec chacun des cotés du polygone (moins les deux premiers qui sont forcément orthogonaux). Si (sitôt que) une valeur différente de 0 (-> non orthogonalité) est trouvée, on peut conclure à la non planarité.

Une méthode plus complexe consiste à utiliser les trois premiers sommets du polygone pour calculer l'équation du plan incluant la facette triangulaire qu'ils forment (ax+by+cz+d = 0), puis ensuite vérifier que tous les autres sommets sont bien dans ce plan. Inconvénient de cette méthode: Trouver a,b,c et d nécessite la résolution d'un système d'équations.

Question c)

struct direc3D {
  float x;
  float y;
  float z; } ;
/* -------------------------------------------------- */
/* Calcul du produit scalaire entre deux vecteurs     */
/* -------------------------------------------------- */
float produitScalaire(direc3D *v1,direc3D *v2) {
  return(v1->x*v2->x+v1->y*v2->y+v1->z*v2->z);
}
/* -------------------------------------------------- */
/* Calcul du produit vectoriel entre deux vecteurs    */
/* -------------------------------------------------- */
void produitVectoriel(direc3D *v1,direc3D *v2,direc3D *v) {
  v->x = v1->y*v2->z-v2->y*v1->z;
  v->y = v1->z*v2->x-v2->z*v1->x;
  v->z = v1->x*v2->y-v2->x*v1->y;
}
/* -------------------------------------------------- */
/* Calcul du vecteur entre deux sommets               */
/* -------------------------------------------------- */
void vecteur(coord3D *p1,coord3D *p2,direc3D *v) {
  v->x = p2->x - p1->x;
  v->y = p2->y - p1->y;
  v->z = p2->z - p1->z;
}
/* -------------------------------------------------- */
/* Test d'egalite a 0 a epsilon pres                  */
/* -------------------------------------------------- */
int egalZero(float v) {
  return(fabs(v) < 0.00001);
}
/* -------------------------------------------------- */
/* Fonction de test de planarite d'une facette        */
/* -------------------------------------------------- */
int testPlanarite(facette *f) {
  if ( f->ns <= 3 )
    return(1);
  direc3D v1;
  direc3D v2;
  direc3D n;
  vecteur(&f->s[1],&f->s[2],&v1);
  vecteur(&f->s[2],&f->s[3],&v2);
  produitVectoriel(&v1,&v2,&n);
  for ( int i = 2 ; i < f->ns-1 ; i++ ) {
    direc3D v;
    vecteur(&f->s[i],&f->s[i+1],&v);
    float scal = produitScalaire(&n,&v);
    if ( !egalZero(scal) )
      return(0); }
  return(1);
}
Fichier source complet: Ex3ExamTD20002001.cpp
Modules utilitaires: Modules.zip

Horizontale.gif (2348 octets)

Remarques, erreurs
nicolas.janey@univ-fcomte.fr