Correction
examen de TD 1999-2000

WB01624_.gif (281 octets) RETOUR

Mercredi 5 Avril 2000 - 1h25

Horizontale.gif (2348 octets)

Exercice 1: OpenGL

Le cube est constitué d'un ensemble de 6 facettes carrées. Pour permettre à OpenGL de gérer les ombrages, il faut définir les normales aux facettes. Pour permettre à OpenGL d'effectuer un placage de texture, il faut définir la position de chaque sommet de chaque facette au sein de la bitmap qui tient lieu de texture.

/* -------------------------------------------------- */
/* Dessin d'un cube de cote cote, avec gestion des    */
/* ombrages et d'une texture                          */
/* -------------------------------------------------- */
void myAuxSolidCube(double cote) {
  // sommets du cube
  static GLfloat vdata[8][3] = {
    { 0.5, 0.5,-0.5},{ 0.5,-0.5,-0.5},
    {-0.5,-0.5,-0.5},{-0.5, 0.5,-0.5},
    { 0.5, 0.5, 0.5},{ 0.5,-0.5, 0.5},
    {-0.5,-0.5, 0.5},{-0.5, 0.5, 0.5}} ;
  // indexes des sommets des facettes
  static GLint t[6][4] = {
    {0,1,2,3},
    {7,6,5,4},
    {5,6,2,1},
    {0,3,7,4},
    {6,7,3,2},
    {4,5,1,0}} ;
  // normales aux facettes
  static GLfloat ndata[6][3] = {
    { 0.0, 0.0,-1.0},
    { 0.0, 0.0, 1.0},
    { 0.0,-1.0, 0.0},
    { 0.0, 1.0, 0.0},
    {-1.0, 0.0, 0.0},
    { 1.0, 0.0, 0.0}} ;
  // empilement de la transformation courante
  glPushMatrix();
  // mise a l'echelle d'un facteur cote
  glScaled(cote,cote,cote) ;
  // dessin de chaque facette
  for ( int i = 0 ; i < 6 ; i++ ) {
    // facette a quatre sommets
    glBegin(GL_QUADS) ;
    // definition de la normale a la facette (ombrage)
    glNormal3fv(&ndata[i][0]);
    // definitions successives des quatre sommets et
    // de leurs positions dans la texture
    glTexCoord2f(0.0F,0.0F) ;
    glVertex3fv(&vdata[t[i][0]][0]);
    glTexCoord2f(1.0F,0.0F) ;
    glVertex3fv(&vdata[t[i][1]][0]);
    glTexCoord2f(1.0F,1.0F) ;
    glVertex3fv(&vdata[t[i][2]][0]);
    glTexCoord2f(0.0F,1.0F) ;
    glVertex3fv(&vdata[t[i][3]][0]);
    glEnd() ; }
  // depilement de la transformation courante
  glPopMatrix();
}
/* -------------------------------------------------- */

Fichier C++ complet : Exo1.cpp

Exercice 2: OpenGL

Pas de difficulté particulière.

/* ************************************************** */

static int anim = 0 ;
static int image = 0 ;

/* ************************************************** */

/* -------------------------------------------------- */
/* Fonction d'initialisation.                         */
/*  - Une lumiere blanche                             */
/*  - Matiere diffusante rouge                        */
/*  - Activation de l'elimination des parties cachees */
/* -------------------------------------------------- */
void myinit(void) {
  GLfloat light_ambient[] = { 0.0F,0.0F,0.0F,1.0F };
  GLfloat light_diffuse[] = { 1.0F,1.0F,1.0F,1.0F };
  GLfloat light_specular[] = { 1.0F,1.0F,1.0F,1.0F };
  GLfloat light_position[] = { 1.0F,1.0F,1.0F,0.0F };
  glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
  glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
  glLightfv(GL_LIGHT0,GL_POSITION,light_position);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  GLfloat rouge[] = { 1.0F,0.0F,0.0F,0.0F };
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,rouge);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
}
/* -------------------------------------------------- */
/* Dessin d'une image.                                */
/* - Effacement de la fenetre.                        */
/* - Empilement de la transformation courante.        */
/* - Translation selon l'axe y de valeur fonction     */
/*   du numero de l'image.                            */
/* - Dessin de la sphere.                             */
/* - Flush de l'image.                                */
/* - Depilement de la transformation courante.        */
/* -------------------------------------------------- */
void CALLBACK display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  if ( image < 100 )
    glTranslatef(0.0F,10.0F-image*image/1000,0.0F) ;
    else
    glTranslatef(0.0F,10.0F-(200-image)*(200-image)/1000,0.0F) ;
  auxSolidSphere(1.0) ;
  glPopMatrix();
  glFlush();
  auxSwapBuffers();
}
/* -------------------------------------------------- */
/* Gestion de l'animation.                            */
/* Si une animation est en cours :                    */
/*   - Le numero de l'image est incremente.           */
/*   - Si le numero de l'image devient superieur      */
/*     a 200, il redevient egal a 0 et l'animation    */
/*     est desactivee.                                */
/*   - Le dessin d'une image est demande.             */
/* -------------------------------------------------- */
void CALLBACK idle(void) {
  if ( anim ) {
    image++ ;
    if ( image > 200 ) {
      image = 0 ;
      anim = 0 ; }
    display() ; }
}
/* -------------------------------------------------- */
/* Activation/Desactivation de l'animation.           */
/* -------------------------------------------------- */
void CALLBACK keyA(void) {
  anim = !anim ;
}

/* ************************************************** */

Fichier C++ complet : Exo2.cpp

Exercice 3: Infographie classique

Question a

La solution proposée consiste à dessiner le segment de n pixels d'épaisseur comme n segments adjacents décalés par rapport au segment défini par les deux sommets. Le décalage est horizontal ou vertical suivant l'orientation du segment générateur:
- horizontal pour un segment de coefficient directeur de valeur absolue superieure à 1 (plus vertical qu'horizontal),
- vertical pour un segment de coefficient directeur de valeur absolue inférieure à 1 (plus vertical qu'horizontal).
Les n segments seront équitablement répartis autour de la position génératrice.

/* -------------------------------------------------- */
/* Fonction de dessin d'une suite horizontale ou      */
/* verticale de n pixels autour d'une position        */
/* de reference (x,y) avec la couleur c.              */
/* dx et dy definissent les dimensions en x et en y   */
/* permettant de choisir entre horizontal (dy>dx)     */
/* et vertical (sinon).                               */
/* -------------------------------------------------- */
void pixelAvecEpaisseur(int x,int y,float *c,int n,
                        int dx,int dy) {
  if ( dx > dy )
    for ( int i = y-n/2 ; i < y-n/2+n ; i++ )
      pixel(x,i,c) ;
    else
    for ( int i = x-n/2 ; i < x-n/2+n ; i++ )
      pixel(i,y,c) ;
}
/* -------------------------------------------------- */
/* Dessin d'un segment tirete (p1,p2) de couleur c,   */
/* n pixels allumes suivis de m pixels non modifies : */
/* Algorithme de Bresenham avec fonction de dessin    */
/* d'un pixel modifie de maniere a dessiner plusieurs */
/* pixels autour (horizontalement ou verticalement    */
/* en fonction de l'orientation du segment)           */
/* de la position de reference                        */
/* -------------------------------------------------- */
void ligneAvecEpaisseur(float *c,int *p1,int *p2,int n) {
  int dx,dy,i,xinc,yinc,cumul,x,y ;
  x = p1[0] ;
  y = p1[1] ;
  dx = p2[0] - p1[0] ;
  dy = p2[1] - p1[1] ;
  xinc = ( dx > 0 ) ? 1 : -1 ;
  yinc = ( dy > 0 ) ? 1 : -1 ;
  dx = abs(dx) ;
  dy = abs(dy) ;
  pixelAvecEpaisseur(x,y,c,n,dx,dy) ;
  if ( dx > dy ) {
    cumul = dx / 2 ;
    for ( i = 1 ; i <= dx ; i++ ) {
      x += xinc ;
      cumul += dy ;
      if (cumul >= dx) {
        cumul -= dx ;
        y += yinc ; }
      pixelAvecEpaisseur(x,y,c,n,dx,dy) ; } }
    else {
    cumul = dy / 2 ;
    for ( i = 1 ; i <= dy ; i++ ) {
      y += yinc ;
      cumul += dx ;
      if ( cumul >= dy ) {
        cumul -= dy ;
        x += xinc ; }
      pixelAvecEpaisseur(x,y,c,n,dx,dy) ; } }
}
/* -------------------------------------------------- */

Question b

La solution proposée consiste à tracer un segment normal si ce n'est que m pixels sur n+m pixels seront ignorés (les pixels n, n+1, n+2, ..., n+m-1). Cette discrimination est effectuée au moment où chaque pixel sera tracé.

/* -------------------------------------------------- */
/* Fonction de dessin d'un pixel de couleur c         */
/* en position (x,y) si le numero p du pixel est tel  */
/* que p modulo (n+m) est inferieur strictement a n.  */
/* -> n pixels traces consecutivement puis m places   */
/*    libres et ainsi de suite.                       */
/* -------------------------------------------------- */
void pixelTirete(int x,int y,float *c,int n,int m,int p) {
  if ( p%(n+m) < n )
    pixel(x,y,c) ;
}
/* -------------------------------------------------- */
/* Dessin d'un segment tirete (p1,p2) de couleur c,   */
/* n pixels allumes suivis de m pixels non modifies : */
/* Algorithme de Bresenham avec fonction de dessin    */
/* d'un pixel modifie de maniere a tester le numero   */
/* du pixel pour dessiner ou non.                     */
/* -------------------------------------------------- */
void ligneTirete(float *c,int *p1,int *p2,int n,int m) {
  int dx,dy,i,xinc,yinc,cumul,x,y ;
  x = p1[0] ;
  y = p1[1] ;
  dx = p2[0] - p1[0] ;
  dy = p2[1] - p1[1] ;
  xinc = ( dx > 0 ) ? 1 : -1 ;
  yinc = ( dy > 0 ) ? 1 : -1 ;
  dx = abs(dx) ;
  dy = abs(dy) ;
  pixelTirete(x,y,c,n,m,0) ;
  if ( dx > dy ) {
    cumul = dx / 2 ;
    for ( i = 1 ; i <= dx ; i++ ) {
      x += xinc ;
      cumul += dy ;
      if (cumul >= dx) {
        cumul -= dx ;
        y += yinc ; }
      pixelTirete(x,y,c,n,m,i) ; } }
    else {
    cumul = dy / 2 ;
    for ( i = 1 ; i <= dy ; i++ ) {
      y += yinc ;
      cumul += dx ;
      if ( cumul >= dy ) {
        cumul -= dy ;
        x += xinc ; }
      pixelTirete(x,y,c,n,m,i) ; } }
}
/* -------------------------------------------------- */

Fichier C++ complet : Exo3.cpp
(deux variantes de la fonction de la question a)

Horizontale.gif (2348 octets)

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