
    
    
    
/* Auteur: Nicolas JANEY               */
    /* nicolas.janey@univ-fcomte.fr        */
    /* Avril 2001                          */
    /* Illustration du trace d'un segment  */
    /* de voxels pour une utilisation      */
    /* en lancer de rayons                 */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include <GL/glut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    
    #include "ModuleCouleurs.h"
    #include "ModuleManipulateur.h"
    #include "ModuleMenus.h"
    #include "ModuleReshape.h"
    
    static int aff = 0 ;
    static int lim = 0 ;
    
    void myinit(void) {
      GLfloat light_position0[] = { 1.0F,1.0F,1.0F,0.0F };
      glLightfv(GL_LIGHT0,GL_AMBIENT,couleurNoir());
      glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc());
      glLightfv(GL_LIGHT0,GL_SPECULAR,couleurBlanc());
      glLightfv(GL_LIGHT0,GL_POSITION,light_position0);
      glEnable(GL_LIGHT0);
      glEnable(GL_AUTO_NORMAL);
      glEnable(GL_DEPTH_TEST);
      glDepthFunc(GL_LESS);
      glEnable(GL_CULL_FACE);
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_AUTO_NORMAL);
      glEnable(GL_NORMALIZE);
    }
    
    void voxel1(int x,int y,int z) {
      glColor4fv(couleurBlanc(0.5F)) ;
      glBegin(GL_LINES) ;
      glVertex3i(x,y,z) ;
      glVertex3i(x+1,y,z) ;
      glVertex3i(x,y+1,z) ;
      glVertex3i(x+1,y+1,z) ;
      glVertex3i(x,y,z+1) ;
      glVertex3i(x+1,y,z+1) ;
      glVertex3i(x,y+1,z+1) ;
      glVertex3i(x+1,y+1,z+1) ;
      glVertex3i(x,y,z) ;
      glVertex3i(x,y+1,z) ;
      glVertex3i(x+1,y,z) ;
      glVertex3i(x+1,y+1,z) ;
      glVertex3i(x,y,z+1) ;
      glVertex3i(x,y+1,z+1) ;
      glVertex3i(x+1,y,z+1) ;
      glVertex3i(x+1,y+1,z+1) ;
      glVertex3i(x,y,z) ;
      glVertex3i(x,y,z+1) ;
      glVertex3i(x+1,y,z) ;
      glVertex3i(x+1,y,z+1) ;
      glVertex3i(x,y+1,z) ;
      glVertex3i(x,y+1,z+1) ;
      glVertex3i(x+1,y+1,z) ;
      glVertex3i(x+1,y+1,z+1) ;
      glEnd() ;
    }
    
    void voxel2(int x,int y,int z) {
      glPushMatrix() ;
      glTranslatef(x+0.5F,y+0.5F,z+0.5F) ;
      glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurRouge(0.5F)) ;
      glutSolidCube(1.0) ;
      glPopMatrix() ;
    }
    
    void ligneVoxels1(int xi,int yi,int zi,int xf,int yf,int zf) {
      int dx,dy,dz,i,xinc,yinc,zinc,c1,c2,x,y,z ;
      x = xi ;
      y = yi ;
      z = zi ;
      dx = xf - xi ;
      dy = yf - yi ;
      dz = zf - zi ;
      xinc = ( dx > 0 ) ? 1 : -1 ;
      yinc = ( dy > 0 ) ? 1 : -1 ;
      zinc = ( dz > 0 ) ? 1 : -1 ;
      dx = abs(dx) ;
      dy = abs(dy) ;
      dz = abs(dz) ;
      voxel1(x,y,z) ;
      if ( ( dx > dy ) && ( dx > dz ) ) {
        c1 = c2 = dx / 2 ;
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          c1 += dy ;
          int n = 0 ;
          if (c1 >= dx) {
            c1 -= dx ;
            n++ ;
            y += yinc ; }
          c2 += dz ;
          if (c2 >= dx) {
            c2 -= dx ;
            n++ ;
            z += zinc ; }
          voxel1(x,y,z) ; } }
        else
        if ( ( dy > dx ) && ( dy > dz ) ) {
          c1 = c2 = dy / 2 ;
          for ( i = 1 ; i <= dy ; i++ ) {
            y += yinc ;
            c1 += dx ;
            if ( c1 >= dy ) {
              c1 -= dy ;
              x += xinc ; }
            c2 += dz ;
            if ( c2 >= dy ) {
              c2 -= dy ;
              z += zinc ; }
            voxel1(x,y,z) ; } }
          else {
          c1 = c2 = dz / 2 ;
          for ( i = 1 ; i <= dz ; i++ ) {
            z += zinc ;
            c1 += dy ;
            if ( c1 >= dz ) {
              c1 -= dz ;
              y += yinc ; }
            c2 += dx ;
            if ( c2 >= dz ) {
              c2 -= dz ;
              x += xinc ; }
            voxel1(x,y,z) ; } }
    }
    
    void ligneVoxels2(int xi,int yi,int zi,int xf,int yf,int zf) {
      int dx,dy,dz,i,xinc,yinc,zinc,c1,c2,x,y,z ;
      x = xi ;
      y = yi ;
      z = zi ;
      dx = xf - xi ;
      dy = yf - yi ;
      dz = zf - zi ;
      xinc = ( dx > 0 ) ? 1 : -1 ;
      yinc = ( dy > 0 ) ? 1 : -1 ;
      zinc = ( dz > 0 ) ? 1 : -1 ;
      dx = abs(dx) ;
      dy = abs(dy) ;
      dz = abs(dz) ;
      voxel2(x,y,z) ;
      if ( ( dx > dy ) && ( dx > dz ) ) {
        c1 = c2 = dx / 2 ;
        for ( i = 1 ; i <= dx ; i++ ) {
          x += xinc ;
          c1 += dy ;
          int n = 0 ;
          if (c1 >= dx) {
            c1 -= dx ;
            n++ ;
            y += yinc ; }
          c2 += dz ;
          if (c2 >= dx) {
            c2 -= dx ;
            n++ ;
            z += zinc ; }
          voxel2(x,y,z) ; } }
        else
        if ( ( dy > dx ) && ( dy > dz ) ) {
          c1 = c2 = dy / 2 ;
          for ( i = 1 ; i <= dy ; i++ ) {
            y += yinc ;
            c1 += dx ;
            if ( c1 >= dy ) {
              c1 -= dy ;
              x += xinc ; }
            c2 += dz ;
            if ( c2 >= dy ) {
              c2 -= dy ;
              z += zinc ; }
            voxel2(x,y,z) ; } }
          else {
          c1 = c2 = dz / 2 ;
          for ( i = 1 ; i <= dz ; i++ ) {
            z += zinc ;
            c1 += dy ;
            if ( c1 >= dz ) {
              c1 -= dz ;
              y += yinc ; }
            c2 += dx ;
            if ( c2 >= dz ) {
              c2 -= dz ;
              x += xinc ; }
            voxel2(x,y,z) ; } }
    }
    
    void parcoursVoxels1(int xi,int yi,int zi,int xf,int yf,int zf,int lim) {
      int x = xi ;
      int y = yi ;
      int z = zi ;
      voxel1(x,y,z) ;
      float px =(float) x ;
      float py =(float) y ;
      float pz =(float) z ;
      float dx =(float) xf-xi ;
      float dy =(float) yf-yi ;
      float dz =(float) zf-zi ;
      int cp = 0 ;
      while ( ( ( x != xf ) || ( y != yf ) || ( z != zf ) ) && ( cp != lim ) ) {
        cp++ ;
        float max = 10e+10F ;
        int cas ;
        float dd = ( x-0.5F-px)/dx ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 1 ; 
          max = dd ; }
        dd = ( x+0.5F-px)/dx ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 2 ;
          max = dd ; }
        dd = ( y-0.5F-py)/dy ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 3 ;
          max = dd ; }
        dd = ( y+0.5F-py)/dy ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 4 ;
          max = dd ; }
        dd = ( z-0.5F-pz)/dz ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 5 ;
          max = dd ; }
        dd = ( z+0.5F-pz)/dz ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 6 ;
          max = dd ; }
        px += max*dx ;
        py += max*dy ;
        pz += max*dz ;
        switch(cas) {
          case 1 : x-- ;
                   break ;
          case 2 : x++ ;
                   break ;
          case 3 : y-- ;
                   break ;
          case 4 : y++ ;
                   break ;
          case 5 : z-- ;
                   break ;
          case 6 : z++ ;
                   break ; }
        voxel1(x,y,z) ; } 
    }
    
    void parcoursVoxels2(int xi,int yi,int zi,int xf,int yf,int zf,int lim) {
      int x = xi ;
      int y = yi ;
      int z = zi ;
      voxel2(x,y,z) ;
      float px =(float) x ;
      float py =(float) y ;
      float pz =(float) z ;
      float dx =(float) xf-xi ;
      float dy =(float) yf-yi ;
      float dz =(float) zf-zi ;
      int cp = 0 ;
      while ( ( ( x != xf ) || ( y != yf ) || ( z != zf ) ) && ( cp != lim ) ) {
        cp++ ;
        float max = 10e+10F ;
        int cas ;
        float dd = ( x-0.5F-px)/dx ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 1 ; 
          max = dd ; }
        dd = ( x+0.5F-px)/dx ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 2 ;
          max = dd ; }
        dd = ( y-0.5F-py)/dy ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 3 ;
          max = dd ; }
        dd = ( y+0.5F-py)/dy ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 4 ;
          max = dd ; }
        dd = ( z-0.5F-pz)/dz ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 5 ;
          max = dd ; }
        dd = ( z+0.5F-pz)/dz ;
        if ( ( dd > 0.0F ) && ( dd <= max ) ) {
          cas = 6 ;
          max = dd ; }
        px += max*dx ;
        py += max*dy ;
        pz += max*dz ;
        switch(cas) {
          case 1 : x-- ;
                   break ;
          case 2 : x++ ;
                   break ;
          case 3 : y-- ;
                   break ;
          case 4 : y++ ;
                   break ;
          case 5 : z-- ;
                   break ;
          case 6 : z++ ;
                   break ; }
        voxel2(x,y,z) ; } 
    }
    
    void display(void) {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glPushMatrix() ;
      manipulateurSouris();
      manipulateurClavier();
      glLineWidth(4.0) ;
      glColor4fv(couleurBleu()) ;
      glBegin(GL_LINES) ;
      glVertex3f(-8.5,-1.5,-2.5) ;
      glVertex3f(8.5,3.5,5.5) ;
      glEnd() ;
      glLineWidth(1.0) ;
      switch ( aff ) {
        case 1 : ligneVoxels1(-9,-2,-3,8,3,5);
                 glEnable(GL_LIGHTING);
                 ligneVoxels2(-9,-2,-3,8,3,5);
                 glDisable(GL_LIGHTING);
                 break ;
        case 2 : parcoursVoxels1(-9,-2,-3,8,3,5,1000);
                 glEnable(GL_LIGHTING);
                 parcoursVoxels2(-9,-2,-3,8,3,5,1000);
                 glDisable(GL_LIGHTING);
                 break ;
        case 3 : parcoursVoxels1(-9,-2,-3,8,3,5,lim);
                 glEnable(GL_LIGHTING);
                 parcoursVoxels2(-9,-2,-3,8,3,5,lim);
                 glDisable(GL_LIGHTING);
                 break ; }
      glPopMatrix() ;
      glFlush();
      glutSwapBuffers();
    }
    
    void key(unsigned char key,int x,int y) {
      if ( keyManipulateur(key,x,y) )
        glutPostRedisplay();
        else
        switch ( key ) {
          case 0x0D : lim = 0 ;
                      aff = (aff+1)%4 ;
                      glutPostRedisplay();
                      break;
          case 32   : lim = (lim+1)%40 ;
                      glutPostRedisplay();
                      break; }
    }
    
    int main(int argc,char **argv) {
      glutInit(&argc,argv);
      glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
      glutInitWindowSize(400,220); 
      glutInitWindowPosition(50,50); 
      glutCreateWindow("Une ligne de voxels"); 
      myinit(); 
      creationMenuBasique();
      setParametresOrthoBasique(-6.0,6.0,-6.0,6.0,-500.0,500.0);
      setManipulateurDistance(1.0F);
      glutReshapeFunc(reshapeOrthoBasique);
      glutKeyboardFunc(key);
      glutSpecialFunc(specialBasique);
      glutMotionFunc(motionBasique);
      glutMouseFunc(sourisBasique);
      glutDisplayFunc(display);
      glutMainLoop();
      return(0);
    }