
    2 facettes à afficher
    au moyen dun Z-Buffer
     
    
Pixélisation de chacune de ces facettes
     
    
    Calcul daltitude pour chacun des pixels
    de chacune des deux facettes
     
    
    Affichage des pixels visibles
    par comparaison des altitudes
    (deux affichages possibles suivant
    l'ordre de parcours des facettes)
/* Auteur: Nicolas JANEY         */
    /* nicolas.janey@univ-fcomte.fr  */
    /* Mars 2002                     */
    /* Illustration du Z-Buffer      */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <GL/glut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    
    #include "ModuleCouleurs.h"
    #include "ModuleMenus.h"
    #include "ModuleFont.h"
    #include "ModuleFleche.h"
    #include "ModuleReshape.h"
    
    static int mode = 0 ;
    static float f11[3] = {-5.0F,6.0F,-3.0F};
    static float f12[3] = {6.0F,4.0F,4.0F};
    static float f13[3] = {-2.0F,-6.0F,6.0F};
    static float f21[3] = {0.0F,3.0F,5.0F};
    static float f22[3] = {3.0F,-6.0F,-1.0F};
    static float f23[3] = {-5.0F,-4.0F,3.0F};
    
    int arrondi(int z) {
      if ( z > 0 )
        z = (z+499)/1000;
        else
        z = (z-499)/1000;
      return(z);
    }
    
    void pixel(float *coul,int x,int y,int z) {
      glColor4fv(coul) ;
      z = arrondi(z) ;
      glBegin(GL_QUADS) ;
      glVertex3f(x-15.5,y-15.5,z) ;
      glVertex3f(x-14.5,y-15.5,z) ;
      glVertex3f(x-14.5,y-14.5,z) ;
      glVertex3f(x-15.5,y-14.5,z) ;
      glEnd() ;
      glColor4fv(couleurGrisFonce()) ;
      placeFontCursor(x-15,y-15,z+1) ;
      deplacementCursor(0,-3,0) ;
      simpleBitmapOutput(0,REGULAR6x10,"%d",z) ;
    }
    
    void ligneDiscrete(float *coul,int y,int x1,int z1,int x2,int z2) {
      if ( x2 != -100 ) {
        int i,cumul ;
        int x = x1 ;
        int z = z1 ;
        int dx = x2 - x1 ;
        int dz = z2 - z1 ;
        int xinc = ( dx > 0 ) ? 1 : -1 ;
        int zinc = ( dz > 0 ) ? 1 : -1 ;
        dx = abs(dx) ;
        dz = abs(dz) ;
        pixel(coul,x,y,z) ;
        cumul = dz / 2 ;
        while ( cumul > dx ) {
          cumul -= dx ;
          z += zinc ; }
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          cumul += dz ;
          while ( cumul > dx ) {
            cumul -= dx ;
            z += zinc ; }
          pixel(coul,x,y,z) ; } }
    }
    
    void ligne(int xi,int yi,int zi,int xf,int yf,int zf,int *px,int *pz) {
      int i,cumul,cumulz ;
      int x = xi ;
      int y = yi ;
      int z = zi ;
      int dx = xf - xi ;
      int dy = yf - yi ;
      int dz = zf - zi ;
      int xinc = ( dx > 0 ) ? 1 : -1 ;
      int yinc = ( dy > 0 ) ? 1 : -1 ;
      int zinc = ( dz > 0 ) ? 1 : -1 ;
      dx = abs(dx) ;
      dy = abs(dy) ;
      dz = abs(dz) ;
      px[y] = x ;
      pz[y] = z ;
      if ( dx > dy ) {
        cumul = dx / 2 ;
        cumulz = dx / 2 ;
        while (cumulz >= dx) {
          cumulz -= dx ;
          z += zinc ; }
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          cumul += dy ;
          cumulz += dz ;
          if (cumul >= dx) {
            cumul -= dx ;
            y += yinc ; }
          while (cumulz >= dx) {
            cumulz -= dx ;
            z += zinc ; }
          px[y] = x ; 
          pz[y] = z ; } }
        else {
        cumul = dy / 2 ;
        cumulz = dx / 2 ;
        while ( cumulz >= dy ) {
          cumulz -= dy ;
          z += zinc ; }
        for ( i = 1 ; i <= dy ; i++ ) {
          y += yinc ;
          cumul += dx ;
          cumulz += dz ;
          if ( cumul >= dy ) {
            cumul -= dy ;
            x += xinc ; }
          while ( cumulz >= dy ) {
            cumulz -= dy ;
            z += zinc ; }
          px[y] = x ;
          pz[y] = z ; } }
    }
    
    void facetteDiscrete(float *coul,float *p1,float *p2,float *p3) {
      glPushMatrix() ;
      int px1[30] ;
      int px2[30] ;
      int px3[30] ;
      int pz1[30] ;
      int pz2[30] ;
      int pz3[30] ;
      int i;
      for ( i = 0 ; i < 30 ; i++ ) {
        px1[i] = px2[i] = px3[i] = -100 ;
        pz1[i] = pz2[i] = pz3[i] = 0 ; }
      ligne((int) (p1[0]+15),(int) (p1[1]+15),(int) (p1[2]),(int) (p2[0]+15),(int) (p2[1]+15),(int) (p2[2]),px1,pz1) ;
      ligne((int) (p1[0]+15),(int) (p1[1]+15),(int) (p1[2]),(int) (p3[0]+15),(int) (p3[1]+15),(int) (p3[2]),px2,pz2) ;
      ligne((int) (p2[0]+15),(int) (p2[1]+15),(int) (p2[2]),(int) (p3[0]+15),(int) (p3[1]+15),(int) (p3[2]),px3,pz3) ;
      int x1[30] ;
      int x2[30] ;
      int z1[30] ;
      int z2[30] ;
      for ( i = 0 ; i < 30 ; i++ ) {
        x1[i] = x2[i] = -100 ;
        z1[i] = z2[i] = 0 ; }
      for ( i = 0 ; i < 30 ; i++ ) {
        if ( px1[i] > x1[i] ) {
          x1[i] = px1[i] ;
          z1[i] = pz1[i] ; }
        if ( px2[i] > x1[i] ) {
          x1[i] = px2[i] ;
          z1[i] = pz2[i] ; }
        if ( px3[i] > x1[i] ) {
          x1[i] = px3[i] ; 
          z1[i] = pz3[i] ; } }
      for ( i = 0 ; i < 30 ; i++ )
        x2[i] = x1[i] ;
      for ( i = 0 ; i < 30 ; i++ ) {
        if ( ( px1[i] <= x2[i] ) && ( px1[i] != -100 ) ) {
          x2[i] = px1[i] ;
          z2[i] = pz1[i] ; }
        if ( ( px2[i] <= x2[i] ) && ( px2[i] != -100 ) ) {
          x2[i] = px2[i] ;
          z2[i] = pz2[i] ; }
        if ( ( px3[i] <= x2[i] ) && ( px3[i] != -100 ) ) {
          x2[i] = px3[i] ;
          z2[i] = pz3[i] ; } }
      for ( int y = 0 ; y < 30 ; y++ )
        ligneDiscrete(coul,y,x2[y],z2[y],x1[y],z1[y]) ;
      glPopMatrix() ;
    }
    
    void dessineQuadrillage(void) {
      float i;
      glColor4fv(couleurGrisMoyen()) ;
      glBegin(GL_LINES);
      for ( i = -7.5 ; i < 8.5 ; i++ ) {
        glVertex3d(-7.5,i,-10.0);
        glVertex3d(7.5,i,-10.0); }
      for ( i = -7.5 ; i < 8.5 ; i++ ) {
        glVertex3d(i,-7.5,-10.0);
        glVertex3d(i,7.5,-10.0); }
      glEnd() ;
      glPushMatrix();
      glTranslatef(-7.0F,0.0F,-10.0F);
      flecheEnVolume(14.25F,0.0F,0.0F,0.4F,1.25F,0.12F);
      glPopMatrix();
      glPushMatrix();
      glTranslatef(0.0F,-7.0F,-10.0F);
      flecheEnVolume(0.0F,14.25F,0.0F,0.4F,1.25F,0.12F);
      glPopMatrix();
    }
    
    void objetDiscret1() {
      f11[2] *= 1000.0F;
      f12[2] *= 1000.0F;
      f13[2] *= 1000.0F;
      facetteDiscrete(couleurRose(0.7F),f11,f12,f13);
      f11[2] /= 1000.0F;
      f12[2] /= 1000.0F;
      f13[2] /= 1000.0F;
      glColor4fv(couleurBleu()) ;
      placeFontCursor(f11[0],f11[1],f11[2]) ;
      deplacementCursor(10,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f11[0],(int) f11[1],(int) f11[2]) ;
      placeFontCursor(f12[0],f12[1],f12[2]) ;
      deplacementCursor(-7,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f12[0],(int) f12[1],(int) f12[2]) ;
      placeFontCursor(f13[0],f13[1],f13[2]) ;
      deplacementCursor(-15,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f13[0],(int) f13[1],(int) f13[2]) ;
    }
    
    void objetDiscret2() {
      glColor4fv(couleurVert(0.7F)) ;
      f21[2] *= 1000.0F;
      f22[2] *= 1000.0F;
      f23[2] *= 1000.0F;
      facetteDiscrete(couleurVert(0.7F),f21,f22,f23);
      f21[2] /= 1000.0F;
      f22[2] /= 1000.0F;
      f23[2] /= 1000.0F;
      glColor4fv(couleurBleu()) ;
      placeFontCursor(f21[0],f21[1],f21[2]) ;
      deplacementCursor(0,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f21[0],(int) f21[1],(int) f21[2]) ;
      placeFontCursor(f22[0],f22[1],f22[2]) ;
      deplacementCursor(10,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f22[0],(int) f22[1],(int) f22[2]) ;
      placeFontCursor(f23[0],f23[1],f23[2]) ;
      deplacementCursor(4,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f23[0],(int) f23[1],(int) f23[2]) ;
    }
    
    void objet1() {
      glColor4fv(couleurRose(0.7F)) ;
      glBegin(GL_TRIANGLES) ;
      glVertex3fv(f11) ;
      glVertex3fv(f12) ;
      glVertex3fv(f13) ;
      glEnd() ;
      glColor4fv(couleurBleu()) ;
      placeFontCursor(f11[0],f11[1],f11[2]) ;
      deplacementCursor(10,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f11[0],(int) f11[1],(int) f11[2]) ;
      placeFontCursor(f12[0],f12[1],f12[2]) ;
      deplacementCursor(-7,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f12[0],(int) f12[1],(int) f12[2]) ;
      placeFontCursor(f13[0],f13[1],f13[2]) ;
      deplacementCursor(-15,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f13[0],(int) f13[1],(int) f13[2]) ;
    }
    
    void objet2() {
      glColor4fv(couleurVert(0.7F)) ;
      glBegin(GL_TRIANGLES) ;
      glVertex3fv(f21) ;
      glVertex3fv(f22) ;
      glVertex3fv(f23) ;
      glEnd() ;
      glColor4fv(couleurBleu()) ;
      placeFontCursor(f21[0],f21[1],f21[2]) ;
      deplacementCursor(0,-16,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f21[0],(int) f21[1],(int) f21[2]) ;
      placeFontCursor(f22[0],f22[1],f22[2]) ;
      deplacementCursor(10,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f22[0],(int) f22[1],(int) f22[2]) ;
      placeFontCursor(f23[0],f23[1],f23[2]) ;
      deplacementCursor(4,14,0) ;
      simpleBitmapOutput(0,REGULAR8x13,"(%d,%d,%d)",(int) f23[0],(int) f23[1],(int) f23[2]) ;
    }
    
    void pixel2(float *coul,int x,int y,int z) {
      glColor4fv(coul) ;
      glBegin(GL_QUADS) ;
      glVertex3f(x-15.5,y-15.5,z) ;
      glVertex3f(x-14.5,y-15.5,z) ;
      glVertex3f(x-14.5,y-14.5,z) ;
      glVertex3f(x-15.5,y-14.5,z) ;
      glEnd() ;
      glColor4fv(couleurGrisFonce()) ;
      placeFontCursor(x-15,y-15,z+1) ;
      deplacementCursor(0,-3,0) ;
      simpleBitmapOutput(0,REGULAR6x10,"%d",z) ;
    }
    
    void pixel(int coul,int x,int y,int z,int **bt,int **ht) {
      z = arrondi(z) ;
      if ( z > ht[y][x] ) {
        ht[y][x] = z;
        bt[y][x] = coul; }
    }
    
    void ligneDiscrete(int coul,int y,int x1,int z1,int x2,int z2,int **bt,int **ht) {
      if ( x2 != -100 ) {
        int i,cumul ;
        int x = x1 ;
        int z = z1 ;
        int dx = x2 - x1 ;
        int dz = z2 - z1 ;
        int xinc = ( dx > 0 ) ? 1 : -1 ;
        int zinc = ( dz > 0 ) ? 1 : -1 ;
        dx = abs(dx) ;
        dz = abs(dz) ;
        pixel(coul,x,y,z,bt,ht) ;
        cumul = dz / 2 ;
        while ( cumul > dx ) {
          cumul -= dx ;
          z += zinc ; }
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          cumul += dz ;
          while ( cumul > dx ) {
            cumul -= dx ;
            z += zinc ; }
          pixel(coul,x,y,z,bt,ht) ; } }
    }
    
    void facetteDiscrete(int coul,float *p1,float *p2,float *p3,int **bt,int **ht) {
      int px1[30] ;
      int px2[30] ;
      int px3[30] ;
      int pz1[30] ;
      int pz2[30] ;
      int pz3[30] ;
      int i;
      for ( i = 0 ; i < 30 ; i++ ) {
        px1[i] = px2[i] = px3[i] = -100 ;
        pz1[i] = pz2[i] = pz3[i] = 0 ; }
      ligne((int) (p1[0]+15),(int) (p1[1]+15),(int) (p1[2]),(int) (p2[0]+15),(int) (p2[1]+15),(int) (p2[2]),px1,pz1) ;
      ligne((int) (p1[0]+15),(int) (p1[1]+15),(int) (p1[2]),(int) (p3[0]+15),(int) (p3[1]+15),(int) (p3[2]),px2,pz2) ;
      ligne((int) (p2[0]+15),(int) (p2[1]+15),(int) (p2[2]),(int) (p3[0]+15),(int) (p3[1]+15),(int) (p3[2]),px3,pz3) ;
      int x1[30] ;
      int x2[30] ;
      int z1[30] ;
      int z2[30] ;
      for ( i = 0 ; i < 30 ; i++ ) {
        x1[i] = x2[i] = -100 ;
        z1[i] = z2[i] = 0 ; }
      for ( i = 0 ; i < 30 ; i++ ) {
        if ( px1[i] > x1[i] ) {
          x1[i] = px1[i] ;
          z1[i] = pz1[i] ; }
        if ( px2[i] > x1[i] ) {
          x1[i] = px2[i] ;
          z1[i] = pz2[i] ; }
        if ( px3[i] > x1[i] ) {
          x1[i] = px3[i] ; 
          z1[i] = pz3[i] ; } }
      for ( i = 0 ; i < 30 ; i++ )
        x2[i] = x1[i] ;
      for ( i = 0 ; i < 30 ; i++ ) {
        if ( ( px1[i] <= x2[i] ) && ( px1[i] != -100 ) ) {
          x2[i] = px1[i] ;
          z2[i] = pz1[i] ; }
        if ( ( px2[i] <= x2[i] ) && ( px2[i] != -100 ) ) {
          x2[i] = px2[i] ;
          z2[i] = pz2[i] ; }
        if ( ( px3[i] <= x2[i] ) && ( px3[i] != -100 ) ) {
          x2[i] = px3[i] ;
          z2[i] = pz3[i] ; } }
      for ( int y = 0 ; y < 30 ; y++ )
        ligneDiscrete(coul,y,x2[y],z2[y],x1[y],z1[y],bt,ht) ;
    }
    
    void objetDiscret2puis1(void) {
      int i;
      int **cl =(int **) calloc(30,sizeof(int *));
      int **ht =(int **) calloc(30,sizeof(int *));
      for ( i = 0 ; i < 30 ; i++ ) {
        cl[i] =(int *) calloc(30,sizeof(int));
        ht[i] =(int *) calloc(30,sizeof(int));
        for ( int j = 0 ; j < 30 ; j++ )
          ht[i][j] = -10000000; }
      f11[2] *= 1000.0F;
      f12[2] *= 1000.0F;
      f13[2] *= 1000.0F;
      f21[2] *= 1000.0F;
      f22[2] *= 1000.0F;
      f23[2] *= 1000.0F;
      facetteDiscrete(1,f11,f12,f13,cl,ht);
      facetteDiscrete(2,f21,f22,f23,cl,ht);
      f11[2] /= 1000.0F;
      f12[2] /= 1000.0F;
      f13[2] /= 1000.0F;
      f21[2] /= 1000.0F;
      f22[2] /= 1000.0F;
      f23[2] /= 1000.0F;
      for ( i = 0 ; i < 30 ; i++ ) {
        for ( int j = 0 ; j < 30 ; j++ ) {
          if ( ht[i][j] != -10000000.0 ) {
            float *c;
            switch ( cl[i][j] ) {
              case 1 : c = couleurRose(0.75F);
                       break;
              case 2 : c = couleurVert(0.75F);
                       break; }
            pixel2(c,j,i,ht[i][j]) ; } } }
      for ( i = 0 ; i < 30 ; i++ ) {
        free(cl[i]);
        free(ht[i]); }
      free(cl);
      free(ht);
    }
    
    void objetDiscret1puis2(void) {
      int i;
      int **cl =(int **) calloc(30,sizeof(int *));
      int **ht =(int **) calloc(30,sizeof(int *));
      for ( i = 0 ; i < 30 ; i++ ) {
        cl[i] =(int *) calloc(30,sizeof(int));
        ht[i] =(int *) calloc(30,sizeof(int));
        for ( int j = 0 ; j < 30 ; j++ )
          ht[i][j] = -10000000; }
      f11[2] *= 1000.0F;
      f12[2] *= 1000.0F;
      f13[2] *= 1000.0F;
      f21[2] *= 1000.0F;
      f22[2] *= 1000.0F;
      f23[2] *= 1000.0F;
      facetteDiscrete(2,f21,f22,f23,cl,ht);
      facetteDiscrete(1,f11,f12,f13,cl,ht);
      f11[2] /= 1000.0F;
      f12[2] /= 1000.0F;
      f13[2] /= 1000.0F;
      f21[2] /= 1000.0F;
      f22[2] /= 1000.0F;
      f23[2] /= 1000.0F;
      for ( i = 0 ; i < 30 ; i++ ) {
        for ( int j = 0 ; j < 30 ; j++ ) {
          if ( ht[i][j] != -10000000.0 ) {
            float *c;
            switch ( cl[i][j] ) {
              case 1 : c = couleurRose(0.75F);
                       break;
              case 2 : c = couleurVert(0.75F);
                       break; }
            pixel2(c,j,i,ht[i][j]) ; } } }
      for ( i = 0 ; i < 30 ; i++ ) {
        free(cl[i]);
        free(ht[i]); }
      free(cl);
      free(ht);
    }
    
    void display(void) {
      glClearColor(1.0,1.0,1.0,1.0);
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
      glPushMatrix();
      dessineQuadrillage();
      switch ( mode) {
        case 0 : objet2() ;
                 objet1() ;
                 break;
        case 1 : objet1() ;
                 break;
        case 2 : objetDiscret1() ;
                 break;
        case 3 : objet2() ;
                 break;
        case 4 : objetDiscret2() ;
                 break;
        case 5 : objetDiscret2puis1() ;
                 break;
        case 6 : objetDiscret1puis2() ;
                 break; }
      glPopMatrix();
      glFlush();
      glutSwapBuffers();
    }
    
    void myinit(void) {
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_DEPTH_TEST) ;
      setAlignement(CENTER);
      glShadeModel(GL_SMOOTH);
      glEnable(GL_AUTO_NORMAL);
      glEnable(GL_NORMALIZE);
    }
    
    void key(unsigned char key,int x,int y) {
      switch ( key ) {
        case 0x1B : exit(0);
                    break;
        case ' '  : mode = (mode+1)%7;
                    glutPostRedisplay();
                    break; }
    }
    
    int main(int argc,char **argv) {
      glutInit(&argc,argv);
      glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
      glutInitWindowSize(240,240); 
      glutInitWindowPosition(50,50); 
      glutCreateWindow("ZBuffer"); 
      myinit(); 
      creationMenuBasique();
      setParametresOrthoBasique(-8.0,8.0,-8.0,8.0,-50.0,50.0);
      glutReshapeFunc(reshapeOrthoBasique);
      glutKeyboardFunc(key);
      glutDisplayFunc(display);
      glutMainLoop();
      return(0);
    }