 
     
    
     
     
     
    
     
    
     
    
     
     
    
     
     
    
     
     
    
     
     
    
     
     
    
     
     
    
Le source: LancerDeRayonsFonctions.h
    /* Auteur: Nicolas JANEY                   */
      /* nicolas.janey@univ-fcomte.fr            */
      /* Avril 2004                              */
      /* Fonction de calcul de lancer de rayons  */
      
      #ifndef LANCERDERAYONSFONCTIONS
      #define LANCERDERAYONSFONCTIONS
      
      #include "ModuleMatriceVecteurDouble.h"
      
      enum {
        cube,
        sphere };
      
      struct couleur {
        float r;
        float v;
        float b;
        float a; };
      
      struct materiel {
        struct couleur *diffuse ;
        struct couleur *ambient ;
        int r;
        struct couleur *specular ;
        struct couleur *emission ;
        int t;
        struct couleur *transparence ;
        float shininess ;
        double indice ;
        int damier ;
        float carreau ; };
      
      struct rayon {
        vecteur o ;
        vecteur d ; };
      
      struct objet {
        int type ;
        double tx,ty,tz ;
        double a,ax,ay,az ;
        double rx,ry,rz ;
        struct materiel *m ;
        matrice mp ;
        matrice mpp ;
        matrice mpi ;
        vecteur ori ;
        vecteur dir ;
        vecteur p ;
        vecteur norm ;
        rayon rt ;
        int vrt ;
        rayon rr ; };
      
      struct lumiere {
        vecteur pos ;
        float e;
        struct couleur *coul ; };
        
      struct scene {
        int nobj ;
        struct objet *obj ;
        int nlum ;
        struct lumiere *lum ;
        double vang ;
        double cmin ;
        double cmax ;
        int tx ;
        int ty ; };
      
      extern double sensibilite;
      extern float fact;
      
      unsigned char *initialisationsCalculImageLancerDeRayon(scene *sc,int width2,int height2);
      void initialisationsCalculLancerDeRayon(scene *sc);
      void calculImageLancerDeRayon(scene *sc,int j,int w,int h,unsigned char *im);
      
      #endif
    
  
Le source: LancerDeRayonsFonctions.cpp
    /* Auteur: Nicolas JANEY                   */
      /* nicolas.janey@univ-fcomte.fr            */
      /* Avril 2004                              */
      /* Fonction de calcul de lancer de rayons  */
      
      #include <stdio.h>
      #include <stdlib.h>
      #include <math.h>
      
      #include "LancerDeRayonsFonctions.h"
      
      #define DMIN 100000.0
      #define EPSILON 0.0001
      
      double sensibilite = 15.0;
      float fact = 2.0F;
      static int prof = 15;
      
      void matricePlacement(objet *o,matrice m) {
        toScale(m,o->rx,o->ry,o->rz);
        matrice r;
        toRotation(r,o->a,o->ax,o->ay,o->az);
        matrice t;
        toTranslation(t,o->tx,o->ty,o->tz);
        produitMatriceMatrice(r,m,m);
        produitMatriceMatrice(t,m,m);
      }
      
      void matricePlacementInterm(objet *o,matrice m) {
        toRotation(m,o->a,o->ax,o->ay,o->az);
        matrice t;
        toTranslation(t,o->tx,o->ty,o->tz);
        produitMatriceMatrice(t,m,m);
      }
      
      void inverseMatricePlacement(objet *o,matrice m) {
        matrice s;
        toScale(s,1.0/o->rx,1.0/o->ry,1.0/o->rz);
        matrice r;
        toRotation(r,-o->a,o->ax,o->ay,o->az);
        toTranslation(m,-o->tx,-o->ty,-o->tz);
        produitMatriceMatrice(r,m,m);
        produitMatriceMatrice(s,m,m);
      }
      
      double intersectionCube(scene *s,objet *o,rayon *r) {
        o->ori[0] = r->o[0];
        o->ori[1] = r->o[1];
        o->ori[2] = r->o[2];
        o->ori[3] = 1.0;
        produitMatriceVecteur(o->mpi,o->ori,o->ori);
        o->dir[0] = r->d[0];
        o->dir[1] = r->d[1];
        o->dir[2] = r->d[2];
        o->dir[3] = 0.0;
        produitMatriceVecteur(o->mpi,o->dir,o->dir);
        int inter = 0;
        int cpt = 0;
        double dis = DMIN;
        { double d = (0.5-o->ori[2])/o->dir[2];
          double x = o->ori[0] + d*o->dir[0];
          double y = o->ori[1] + d*o->dir[1];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( y >= -0.5 ) && ( y <= 0.5 ) ) {
            inter += 1;
            if ( d > EPSILON ) {
              o->norm[0] = o->norm[1] = o->norm[3] = 0.0;
              o->norm[2] = 1.0;
              dis = d;
              cpt++; } } }
        { double d = (-0.5-o->ori[2])/o->dir[2];
          double x = o->ori[0] + d*o->dir[0];
          double y = o->ori[1] + d*o->dir[1];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( y >= -0.5 ) && ( y <= 0.5 ) ) {
            inter += 1;
            if ( ( d > EPSILON ) && ( d < dis ) ) {
              o->norm[0] = o->norm[1] = o->norm[3] = 0.0;
              o->norm[2] = -1.0;
              dis = d;
              cpt++; } } }
        if ( inter == 2 ) {
          if ( cpt == 0 )
            return(DMIN);
            else
            return(dis); }
        { double d = (-0.5-o->ori[1])/o->dir[1];
          double x = o->ori[0] + d*o->dir[0];
          double z = o->ori[2] + d*o->dir[2];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) ) {
            inter += 1;
            if ( ( d > EPSILON ) && ( d < dis ) ) {
              o->norm[0] = o->norm[2] = o->norm[3] = 0.0;
              o->norm[1] = -1.0;
              dis = d;
              cpt++; } } }
        if ( inter == 2 ) {
          if ( cpt == 0 )
            return(DMIN);
            else
            return(dis); }
        { double d = (0.5-o->ori[1])/o->dir[1];
          double x = o->ori[0] + d*o->dir[0];
          double z = o->ori[2] + d*o->dir[2];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) ) {
            inter += 1;
            if ( ( d > EPSILON ) && ( d < dis ) ) {
              o->norm[0] = o->norm[2] = o->norm[3] = 0.0;
              o->norm[1] = 1.0;
              dis = d;
              cpt++; } } }
        if ( inter == 2 ) {
          if ( cpt == 0 )
            return(DMIN);
            else
            return(dis); }
        { double d = (-0.5-o->ori[0])/o->dir[0];
          double y = o->ori[1] + d*o->dir[1];
          double z = o->ori[2] + d*o->dir[2];
          if ( ( y >= -0.5 ) && ( y <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) ) {
            inter += 1;
            if ( ( d > EPSILON ) && ( d < dis ) ) {
              o->norm[1] = o->norm[2] = o->norm[3] = 0.0;
              o->norm[0] = -1.0;
              dis = d;
              cpt++; } } }
        if ( inter == 2 ) {
          if ( cpt == 0 )
            return(DMIN);
            else
            return(dis); }
        { double d = (0.5-o->ori[0])/o->dir[0];
          double y = o->ori[1] + d*o->dir[1];
          double z = o->ori[2] + d*o->dir[2];
          if ( ( y >= -0.5 ) && ( y <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) ) {
            inter += 1;
            if ( ( d > EPSILON ) && ( d < dis ) ) {
              o->norm[1] = o->norm[2] = o->norm[3] = 0.0;
              o->norm[0] = 1.0;
              dis = d;
              cpt++; } } }
        if ( inter == 2 )
          if ( cpt == 0 )
            return(DMIN);
            else
            return(dis);
        return(DMIN);
      }
      
      double intersectionSphere(scene *s,objet *o,rayon *r) {
        o->ori[0] = r->o[0];
        o->ori[1] = r->o[1];
        o->ori[2] = r->o[2];
        o->ori[3] = 1.0;
        produitMatriceVecteur(o->mpi,o->ori,o->ori);
        o->dir[0] = r->d[0];
        o->dir[1] = r->d[1];
        o->dir[2] = r->d[2];
        o->dir[3] = 0.0;
        produitMatriceVecteur(o->mpi,o->dir,o->dir);
        double a = o->dir[0]*o->dir[0]+o->dir[1]*o->dir[1]+o->dir[2]*o->dir[2];
        double b = 2*(o->dir[0]*o->ori[0]+o->dir[1]*o->ori[1]+o->dir[2]*o->ori[2]);
        double c = o->ori[0]*o->ori[0]+o->ori[1]*o->ori[1]+o->ori[2]*o->ori[2] - 1.0;
        double delta = b*b - 4*a*c;
        if ( delta == 0.0 ) {
          double d = -b/2/a;
          if ( d > EPSILON ) {
            o->norm[0] = (o->dir[0]*d + o->ori[0])*o->ry*o->rz;
            o->norm[1] = (o->dir[1]*d + o->ori[1])*o->rx*o->rz;
            o->norm[2] = (o->dir[2]*d + o->ori[2])*o->rx*o->ry;
            o->norm[3] = 0.0;
            return(d); }
          else
          return(DMIN); }
        if ( delta > 0.0 ) {
          double d1 = (-b-sqrt(delta))/2/a;
          if ( d1 > EPSILON ) {
            o->norm[0] = (o->dir[0]*d1 + o->ori[0])*o->ry*o->rz;
            o->norm[1] = (o->dir[1]*d1 + o->ori[1])*o->rx*o->rz;
            o->norm[2] = (o->dir[2]*d1 + o->ori[2])*o->rx*o->ry;
            o->norm[3] = 0.0;
            return(d1); }
            else {
            double d2 = (-b+sqrt(delta))/2/a;
            if ( d2 > EPSILON ) {
              o->norm[0] = (o->dir[0]*d2 + o->ori[0])*o->ry*o->rz;
              o->norm[1] = (o->dir[1]*d2 + o->ori[1])*o->rx*o->rz;
              o->norm[2] = (o->dir[2]*d2 + o->ori[2])*o->rx*o->ry;
              o->norm[3] = 0.0;
              return(d2); } } }
        return(DMIN);
      }
      
      int testIntersectionCube(scene *s,objet *o,rayon *r) {
        vecteur ori;
        vecteur dir;
        ori[0] = r->o[0];
        ori[1] = r->o[1];
        ori[2] = r->o[2];
        ori[3] = 1.0;
        produitMatriceVecteur(o->mpi,ori,ori);
        dir[0] = r->d[0];
        dir[1] = r->d[1];
        dir[2] = r->d[2];
        dir[3] = 0.0;
        produitMatriceVecteur(o->mpi,dir,dir);
        { double d = (0.5-ori[2])/dir[2];
          double x = ori[0] + d*dir[0];
          double y = ori[1] + d*dir[1];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( y >= -0.5 ) && ( y <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        { double d = (-0.5-ori[2])/dir[2];
          double x = ori[0] + d*dir[0];
          double y = ori[1] + d*dir[1];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( y >= -0.5 ) && ( y <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        { double d = (-0.5-ori[1])/dir[1];
          double x = ori[0] + d*dir[0];
          double z = ori[2] + d*dir[2];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        { double d = (0.5-ori[1])/dir[1];
          double x = ori[0] + d*dir[0];
          double z = ori[2] + d*dir[2];
          if ( ( x >= -0.5 ) && ( x <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        { double d = (-0.5-ori[0])/dir[0];
          double y = ori[1] + d*dir[1];
          double z = ori[2] + d*dir[2];
          if ( ( y >= -0.5 ) && ( y <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        { double d = (0.5-ori[0])/dir[0];
          double y = ori[1] + d*dir[1];
          double z = ori[2] + d*dir[2];
          if ( ( y >= -0.5 ) && ( y <= 0.5 ) && ( z >= -0.5 ) && ( z <= 0.5 ) && ( d > EPSILON ) ) {
            return(1); } }
        return(0);
      }
      
      int testIntersectionSphere(scene *s,objet *o,rayon *r) {
        vecteur ori;
        vecteur dir;
        ori[0] = r->o[0];
        ori[1] = r->o[1];
        ori[2] = r->o[2];
        ori[3] = 1.0;
        produitMatriceVecteur(o->mpi,ori,ori);
        dir[0] = r->d[0];
        dir[1] = r->d[1];
        dir[2] = r->d[2];
        dir[3] = 0.0;
        produitMatriceVecteur(o->mpi,dir,dir);
        double a = dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2];
        double b = 2*(dir[0]*ori[0]+dir[1]*ori[1]+dir[2]*ori[2]);
        double c = ori[0]*ori[0]+ori[1]*ori[1]+ori[2]*ori[2] - 1.0;
        double delta = b*b - 4*a*c;
        if ( delta == 0.0 ) {
          double d = -b/2/a;
          if ( d > EPSILON ) {
            return(1); } }
        if ( delta > 0.0 ) {
          double d1 = (-b-sqrt(delta))/2/a;
          if ( d1 > EPSILON ) {
            return(1); }
            else {
            double d2 = (-b+sqrt(delta))/2/a;
            if ( d2 > EPSILON ) {
              return(1); } } }
        return(0);
      }
      
      int rayonTransmis(objet *obj,rayon *r,int interieur) {
        double indice = ( interieur ) ? obj->m->indice : 1.0/obj->m->indice;
        vecteur i = { -r->d[0],-r->d[1],-r->d[2],0.0 } ;
        vecteur norm = { obj->norm[0],obj->norm[1],obj->norm[2],0.0 } ;
        if ( interieur ) {
          norm[0] = -norm[0];
          norm[1] = -norm[1];
          norm[2] = -norm[2]; }
        double scal = produitScalaire(norm,i);
        double n2 = indice*indice;
        double val = 1.0F-n2*(1.0F-scal*scal);
        if ( val < 0.0F )
          return(0);
          else {
          val = indice*scal-sqrt(val);
          obj->rt.d[0] = val*norm[0]-indice*i[0];
          obj->rt.d[1] = val*norm[1]-indice*i[1];
          obj->rt.d[2] = val*norm[2]-indice*i[2];
          obj->rt.d[3] = 0.0;
          obj->rt.o[0] = obj->p[0];
          obj->rt.o[1] = obj->p[1];
          obj->rt.o[2] = obj->p[2];
          obj->rt.o[3] = 1.0;
          return(1); }
      }
      
      void rayonReflechi(objet *obj,rayon *r) {
        vecteur i = { -r->d[0],-r->d[1],-r->d[2],0.0 } ;
        double scal = produitScalaire(i,obj->norm);
        obj->rr.d[0] = 2*obj->norm[0]*scal-i[0];
        obj->rr.d[1] = 2*obj->norm[1]*scal-i[1];
        obj->rr.d[2] = 2*obj->norm[2]*scal-i[2];
        obj->rr.d[3] = 0.0;
        obj->rr.o[0] = obj->p[0];
        obj->rr.o[1] = obj->p[1];
        obj->rr.o[2] = obj->p[2];
        obj->rr.o[3] = 1.0;
      }
      
      void calculCaracteristiquesIntersection(objet *obj,double dmin,struct rayon *r,int interieur) {
        obj->p[0] = obj->ori[0] + dmin*obj->dir[0];
        obj->p[1] = obj->ori[1] + dmin*obj->dir[1];
        obj->p[2] = obj->ori[2] + dmin*obj->dir[2];
        obj->p[3] = 1.0;
        produitMatriceVecteur(obj->mp,obj->p,obj->p);
        produitMatriceVecteur(obj->mpp,obj->norm,obj->norm);
        normalise(obj->norm);
        if ( ( obj->m->r ) && ( !interieur ) )
          rayonReflechi(obj,r);
        if ( obj->m->t ) {
          obj->vrt = rayonTransmis(obj,r,interieur); }
          else
          obj->vrt = 0;
      }
      
      void diffusion(objet *obj,lumiere *lum,couleur *cd) {
        double dist = distance(lum->pos,obj->p);
        vecteur i;
        calculVecteurNorme(obj->p,lum->pos,i) ;
        double fact = produitScalaire(i,obj->norm);
        if ( fact > 0 ) {
          fact = fact/dist/dist*sensibilite;
          cd->r =(float) (fact*lum->coul->r*lum->e);
          cd->v =(float) (fact*lum->coul->v*lum->e);
          cd->b =(float) (fact*lum->coul->b*lum->e); }
          else {
          cd->r = cd->v = cd->b = 0.0F; }
      }
      
      int testRayonOmbre(scene *sc,objet *obj,lumiere *lum) {
        rayon r;
        calculVecteur(obj->p,lum->pos,r.d) ;
        r.o[0] = obj->p[0];
        r.o[1] = obj->p[1];
        r.o[2] = obj->p[2];
        r.o[3] = 1.0;
        r.d[3] = 0.0;
        for ( int i = 0 ; i < sc->nobj ; i++ ) {
          switch ( sc->obj[i].type ) {
            case cube      : if ( testIntersectionCube(sc,&sc->obj[i],&r) ) {
                               return(1); }
                             break;
            case sphere    : if ( testIntersectionSphere(sc,&sc->obj[i],&r) ) {
                               return(1); }
                             break; } }
        return(0);
      }
      
      void lancerDeRayons(scene *sc,rayon *r,couleur *c,int prof,int interieur) {
        double dmin = DMIN;
        int obj = -1;
        c->r = c->v = c->b = 0.0F;
        for ( int i = 0 ; i < sc->nobj ; i++ ) {
          double d;
          switch ( sc->obj[i].type ) {
            case cube      : d = intersectionCube(sc,&sc->obj[i],r);
                             break;
            case sphere    : d = intersectionSphere(sc,&sc->obj[i],r);
                             break; }
          if ( ( d > EPSILON ) && ( d < dmin ) ) {
            dmin = d;
            obj = i; } }
         if ( obj != -1 ) {
           calculCaracteristiquesIntersection(&sc->obj[obj],dmin,r,interieur);
           objet aux = sc->obj[obj];
           for ( int l = 0 ; l < sc->nlum ; l++ ) {
             if ( !testRayonOmbre(sc,&sc->obj[obj],&sc->lum[l]) ) {
               couleur cd;
               diffusion(&sc->obj[obj],&sc->lum[l],&cd);
               c->r += cd.r*sc->obj[obj].m->diffuse->r;
               c->v += cd.v*sc->obj[obj].m->diffuse->v;
               c->b += cd.b*sc->obj[obj].m->diffuse->b;
               sc->obj[obj] = aux; } }
           if ( prof > 0 ) {
             if ( sc->obj[obj].vrt ) {
               couleur ct;
               lancerDeRayons(sc,&sc->obj[obj].rt,&ct,prof-1,!interieur);
               c->r += ct.r*sc->obj[obj].m->transparence->r;
               c->v += ct.v*sc->obj[obj].m->transparence->v;
               c->b += ct.b*sc->obj[obj].m->transparence->b;
               sc->obj[obj] = aux; }
             if ( ( sc->obj[obj].m->r ) && ( !interieur ) ) {
               couleur cr;
               lancerDeRayons(sc,&sc->obj[obj].rr,&cr,prof-1,0);
               if ( sc->obj[obj].vrt ) {
                 c->r += cr.r*sc->obj[obj].m->specular->r;
                 c->v += cr.v*sc->obj[obj].m->specular->v;
                 c->b += cr.b*sc->obj[obj].m->specular->b; }
                 else {
                 c->r += cr.r*(sc->obj[obj].m->specular->r+sc->obj[obj].m->transparence->r);
                 c->v += cr.v*(sc->obj[obj].m->specular->v+sc->obj[obj].m->transparence->v);
                 c->b += cr.b*(sc->obj[obj].m->specular->b+sc->obj[obj].m->transparence->b); } } } }
      }
      
      void initialisationsCalculLancerDeRayon(scene *sc) {
        for ( int o = 0 ; o < sc->nobj ; o++ ) {
          inverseMatricePlacement(&sc->obj[o],sc->obj[o].mpi);
          matricePlacementInterm(&sc->obj[o],sc->obj[o].mpp);
          matricePlacement(&sc->obj[o],sc->obj[o].mp); }
      }
      
      unsigned char *initialisationsCalculImageLancerDeRayon(scene *sc,int width2,int height2) {
        initialisationsCalculLancerDeRayon(sc);
        int w = width2;
        int h = height2;
        int t = w*h*3 ;
        return((unsigned char *) calloc(t,sizeof(unsigned char)));
      }
      
      void calculImageLancerDeRayon(scene *sc,int j,int w,int h,unsigned char *im) {
        double d = tan(sc->vang/360.0F*3.14159F)*sc->cmin/h*2.0F;
        for ( int i = 0 ; i < w ; i++ ) {
          int p = i*3;
          rayon r;
          r.o[0] = 0.0F;
          r.o[1] = 0.0F;
          r.o[2] = 0.0F;
          r.o[3] = 1.0F;
          r.d[0] = (i-w/2)*d+d/2.0F;
          r.d[1] = (j-h/2)*d+d/2.0F;
          r.d[2] = -sc->cmin;
          r.d[3] = 1.0F;
          normalise(r.d);
          couleur c;
          lancerDeRayons(sc,&r,&c,prof,0);
          if ( c.r > 1.0F )
            c.r = 1.0F;
          if ( c.v > 1.0F )
            c.v = 1.0F;
          if ( c.b > 1.0F )
            c.b = 1.0F;
          im[p] =(unsigned char) (c.r*255.0F);
          im[p+1] =(unsigned char) (c.v*255.0F);
          im[p+2] =(unsigned char) (c.b*255.0F); }
      }
    
  
    /* Auteur: Nicolas JANEY                    */
      /* nicolas.janey@univ-fcomte.fr             */
      /* Avril 2004                               */
      /* Comparaison Z-Buffer - 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 "ModuleMenus.h"
      #include "ModuleFont.h"
      #include "ModuleMatriceVecteurDouble.h"
      #include "ModuleManipulateur.h"
      
      #include "LancerDeRayonsFonctions.h"
      
      static int width ;
      static int height ;
      static int width2 ;
      static int height2 ;
      static int f1;
      static int f2;
      static float indice = 1.0F;
      materiel c0 = { (couleur *) couleurRouge(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurBlanc(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c1 = { (couleur *) couleurVert(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurBlanc(),
                      3.0F,1.333F,
                      0,0.0F };
      materiel c2 = { (couleur *) couleurBlanc(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      3.0F,1.33F,
                      0,0.0F };
      materiel c3 = { (couleur *) couleurBleu(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurGrisMoyen(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c41 = { (couleur *) couleurBlanc(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.0F,
                       0,0.0F };
      materiel c42 = { (couleur *) couleurRouge(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.0F,
                       0,0.0F };
      materiel c43 = { (couleur *) couleurVert(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.0F,
                       0,0.0F };
      materiel c44 = { (couleur *) couleurBleu(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.0F,
                       0,0.0F };
      materiel c45 = { (couleur *) couleurMagenta(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.0F,
                       0,0.0F };
      materiel c5 = { (couleur *) newCouleur(couleurGris(0.15F,0.5F)),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       (couleur *) couleurNoir(),
                       1,(couleur *) couleurBlanc(),
                       3.0F,indice,
                       0,0.0F };
      materiel c6 = { (couleur *) newCouleur(couleurGris(0.15F,0.5F)),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurNoir(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurBlanc(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c7 = { (couleur *) couleurNoir(),
                      (couleur *) couleurNoir(),
                      1,(couleur *) couleurBlanc(),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurNoir(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c8 = { (couleur *) couleurJaune(),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurGrisClair(),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurNoir(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c9 = { (couleur *) couleurCyan(),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurGrisClair(),
                      (couleur *) couleurNoir(),
                      0,(couleur *) couleurNoir(),
                      3.0F,1.5F,
                      0,0.0F };
      materiel c10 = { (couleur *) couleurRouge(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurGrisClair(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.5F,
                       0,0.0F };
      materiel c11 = { (couleur *) couleurVert(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurGrisClair(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.5F,
                       0,0.0F };
      materiel c12 = { (couleur *) couleurBlanc(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurGrisClair(),
                       (couleur *) couleurNoir(),
                       0,(couleur *) couleurNoir(),
                       3.0F,1.5F,
                       0,0.0F };
      
      lumiere lums1[2] = { { { 0.0F,2.0F,-10.0F,1.0F },1.0F,(couleur *) couleurBlanc() },
                          { { 0.0F,-2.0F,-12.0F,1.0F },1.0F,(couleur *) couleurBlanc() } };
      lumiere lums2[2] = { { { 6.0F,0.0F,-5.0F,1.0F },1.0F,(couleur *) couleurBlanc() },
                           { { -3.0F,0.0F,-8.0F,1.0F },1.0F,(couleur *) couleurBlanc() } };
      lumiere lums3[2] = { { { 6.0F,0.0F,-7.5F,1.0F },2.0F,(couleur *) couleurJaune() },
                           { { -6.0F,0.0F,-7.5F,1.0F },2.0F,(couleur *) couleurBlanc() } };
      lumiere lums6[2] = { { { 2.0F,1.0F,-6.0F,1.0F },2.5F,(couleur *) couleurBlanc() },
                           { { -2.0F,-1.0F,-6.0F,1.0F },2.5F,(couleur *) couleurBlanc() } };
      objet objs1[4] = { { cube,2.0F,2.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.6F,1.2F,0.9F,&c0 },
                         { cube,-2.0F,2.0F,-15.0F,60.0F,1.0F,1.0F,0.0F,2.4F,1.8F,1.2F,&c1 },
                         { sphere,-2.0F,-2.0F,-15.0F,25.0F,-1.0F,1.0F,1.0F,0.9F,1.2F,1.4F,&c2 },
                         { sphere,2.0F,-2.0F,-15.0F,60.0F,-1.0F,-1.0F,1.0F,0.6F,2.1F,1.9F,&c3 } };
      objet objs2[2] = { { sphere,0.0F,0.0F,-15.0F,0.0F,0.0F,0.0F,1.0F,2.0F,3.0F,4.0F,&c2 },
                         { sphere,1.0F,0.0F,-10.0F,0.0F,0.0F,0.0F,1.0F,0.4F,0.4F,0.4F,&c3 } };
      objet objs3[26] = { { cube,3.0F,3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,3.0F,1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,3.0F,0.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,3.0F,-1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,3.0F,-3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,1.5F,3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,1.5F,1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,1.5F,0.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,1.5F,-1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,1.5F,-3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,0.0F,3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,0.0F,1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,0.0F,0.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,0.0F,-1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,0.0F,-3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,-1.5F,3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,-1.5F,1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,-1.5F,0.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,-1.5F,-1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,-1.5F,-3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,-3.0F,3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,-3.0F,1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,-3.0F,0.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,-3.0F,-1.5F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,-3.0F,-3.0F,-15.0F,35.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { sphere,0.0F,0.0F,-9.0F,0.0F,0.0F,0.0F,1.0F,2.0F,2.0F,2.0F,&c5 } };
      objet objs4[26] = { { cube,3.0F,3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,3.0F,1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,3.0F,0.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,3.0F,-1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,3.0F,-3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,1.5F,3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,1.5F,1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,1.5F,0.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,1.5F,-1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,1.5F,-3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,0.0F,3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,0.0F,1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,0.0F,0.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,0.0F,-1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,0.0F,-3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,-1.5F,3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,-1.5F,1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,-1.5F,0.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,-1.5F,-1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,-1.5F,-3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,-3.0F,3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c41 },
                          { cube,-3.0F,1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c42 },
                          { cube,-3.0F,0.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c43 },
                          { cube,-3.0F,-1.5F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c44 },
                          { cube,-3.0F,-3.0F,-15.0F,45.0F,1.0F,1.0F,1.0F,1.0F,0.8F,0.6F,&c45 },
                          { cube,0.0F,0.0F,-8.0F,40.0F,0.1F,1.0F,0.1F,3.0F,3.0F,0.7F,&c6 } };
      objet objs5[6] = { { cube,0.0F,0.0F,-14.5F,0.0F,1.0F,1.0F,1.0F,4.5F,4.5F,0.2F,&c12 },
                         { cube,0.0F,2.5F,-12.0F,0.0F,1.0F,1.0F,1.0F,4.5F,0.2F,4.5F,&c11 },
                         { cube,0.0F,-2.5F,-12.0F,0.0F,1.0F,1.0F,1.0F,4.5F,0.2F,4.5F,&c10 },
                         { cube,2.5F,0.0F,-12.0F,0.0F,1.0F,1.0F,1.0F,0.2F,4.5F,4.5F,&c9 },
                         { cube,-2.5F,0.0F,-12.0F,0.0F,1.0F,1.0F,1.0F,0.2F,4.5F,4.5F,&c8 },
                         { sphere,0.0F,0.0F,-12.0F,0.0F,0.0F,0.0F,1.0F,1.75F,1.75F,1.75F,&c7 } };
      scene sc1 = { 4,objs1,2,lums1,30.0F,5.0F,40.0F,160,160 };
      scene sc2 = { 2,objs2,2,lums2,30.0F,5.0F,40.0F,160,160 };
      scene sc3 = { 26,objs3,2,lums3,30.0F,5.0F,40.0F,210,210 };
      scene sc4 = { 26,objs4,2,lums3,30.0F,5.0F,40.0F,240,240 };
      scene sc5 = { 6,objs5,2,lums6,35.0F,5.0F,40.0F,210,210 };
      scene *scenes[6] = { &sc1,&sc2,&sc3,&sc4,&sc5,&sc5 };
      static int sce = 2;
      static int nsce = 6;
      static GLubyte *im = NULL ;
      
      void displayZBuffer(scene *sc) {
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(sc->vang,(double) width/height,sc->cmin,sc->cmax);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glPushMatrix();
        glEnable(GL_LIGHTING);
        glEnable(GL_CULL_FACE);
        int i;
        for ( i = 0 ; i < sc->nlum ; i++ ) {
          int l = GL_LIGHT0+i;
          glEnable(l);
          float p[4] = { (float) sc->lum[i].pos[0],(float) sc->lum[i].pos[1],(float) sc->lum[i].pos[2],(float) sc->lum[i].pos[3] };
          glLightfv(l,GL_POSITION,p);
          float d[4] = { (float) sc->lum[i].coul->r*sensibilite*fact,(float) sc->lum[i].coul->v*sensibilite*fact,(float) sc->lum[i].coul->b*sensibilite*fact,(float) sc->lum[i].coul->a };
          glLightfv(l,GL_DIFFUSE,d);
          glLightfv(l,GL_SPECULAR,d);
          glLightfv(l,GL_AMBIENT,couleurNoir());
          glLightf(l,GL_CONSTANT_ATTENUATION,0.0F);
          glLightf(l,GL_QUADRATIC_ATTENUATION,1.0F); }   
        for ( ; i < 8 ; i++ ) {
          int l = GL_LIGHT0+i;
          glEnable(l); }
        for ( i = 0 ; i < sc->nobj ; i++ ) {
          glPushMatrix();
          glTranslated(sc->obj[i].tx,sc->obj[i].ty,sc->obj[i].tz);
          manipulateurSouris();
          manipulateurClavier();
          glRotated(sc->obj[i].a,sc->obj[i].ax,sc->obj[i].ay,sc->obj[i].az);
          glScaled(sc->obj[i].rx,sc->obj[i].ry,sc->obj[i].rz);
          glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(float *) sc->obj[i].m->diffuse);
          glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(float *) sc->obj[i].m->ambient);
          glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(float *) sc->obj[i].m->specular);
          glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,(float *) sc->obj[i].m->emission);
          glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,(float *) &sc->obj[i].m->shininess);
          switch(sc->obj[i].type) {
            case cube     : glutSolidCube(1.0);
                            break;
            case sphere   : glutSolidSphere(1.0,180,180);
                            break; }
          glPopMatrix(); }
        glDisable(GL_LIGHTING);
        glDisable(GL_CULL_FACE);
        glPopMatrix();
        glFlush();
        glutSwapBuffers();
      }
      
      void display(void) {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(scenes[sce]->vang,(double) width/height,scenes[sce]->cmin,scenes[sce]->cmax);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        displayZBuffer(scenes[sce]);
        glFlush();
        glutSwapBuffers();
        glutSwapBuffers();
      }
      
      void myinit (void) {
        glClearColor(0.0F,0.0F,0.0F,0.0F);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_ALPHA_TEST);
        glEnable(GL_BLEND);
        glPixelStorei(GL_UNPACK_ALIGNMENT,1); 
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
      }
      
      void reshape(int w, int h) {
        glViewport(0,0,w,h);
        width = w;
        height = h;
      }
      
      void ajustementTailleFenetre() {
        if ( ( scenes[sce]->tx != width ) || ( scenes[sce]->ty != height ) )
          glutReshapeWindow(scenes[sce]->tx,scenes[sce]->ty);
          else
          glutPostRedisplay();
      }
      
      static int j = 0;
      static int anim = 0;
      
      void reAnime(void) {
        j = 0;
        anim = 0; }
      
      void idle(void) {
        int w = width2;
        int h = height2;
        glutSetWindow(f1);
        ajustementTailleFenetre();
        glutSetWindow(f2);
        ajustementTailleFenetre();
        if ( j == 0 )
          im = initialisationsCalculImageLancerDeRayon(scenes[sce],width2,height2);
        calculImageLancerDeRayon(scenes[sce],j,w,h,&im[(j*w)*3]);
        j++;
        if ( j == h ) {
          glutIdleFunc(NULL);
          anim = 0;
          j = 0; }
          else
          glutPostRedisplay();
      }
      
      void key2(unsigned char key,int x,int y) {
        switch (key) {
          case 0x0D : anim = 1;
                      glutIdleFunc(idle);
                      break;
          case ' '  : printf("Indice = ");
                      scanf("%f",&indice);
                      if ( indice < 0.01F )
                        indice = 0.01F ;
                      if ( sce == 2 )
                        c5.indice = indice;
                      reAnime();
                      glutIdleFunc(idle);
                      break ;
          case 43   : indice += 0.01F;
                      if ( sce == 2 )
                        c5.indice = indice;
                      reAnime();
                      glutIdleFunc(idle);
                      break;
          case 45   : indice -= 0.01F;
                      if ( indice < 1.0F )
                        indice = 1.0F;
                      if ( sce == 2 )
                        c5.indice = indice;
                      reAnime();
                      glutIdleFunc(idle);
                      break;
          case 's'  :
          case 'S'  : sce = (sce+1) % nsce;
                      if ( sce == 2 )
                        c5.indice = indice;
                      if ( sce == 4 )
                        c7.r = c8.r = c9.r = c10.r = c11.r = 0;
                      if ( sce == 5 )
                        c7.r = c8.r = c9.r = c10.r = c11.r = 1;
                      reAnime();
                      glutIdleFunc(idle);
                      break ;
          case 0x1B : exit(0) ;
                      break; }
      }
      
      void key(unsigned char ky,int x,int y) {
        if ( keyManipulateur(ky,x,y) )
          glutPostRedisplay();
          else
          key2(ky,x,y);
      }
      
      void displayLancerDeRayon(scene *sc) {
        glPushMatrix() ;
        int w = width2;
        int h = height2;
        if ( im == NULL ) {
          int t = w*h*3 ;
          im =(GLubyte *) calloc(t,sizeof(GLubyte)); }
        glRasterPos2f(0.0F,0.0F) ;
        glDrawPixels(w,h,GL_RGB,GL_UNSIGNED_BYTE,im) ;
        glPopMatrix() ;
      }
      
      void display2(void) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        displayLancerDeRayon(scenes[sce]);
        if ( sce == 2 ) {
          setAlignement(CENTER);
          placeFontCursor(width2/2,10.0,0.1F);
          simpleBitmapOutput(1,REGULAR8x13,"INDICE : %6.4f",indice) ; }
        glFlush();
        glutSwapBuffers();
      }
      
      void reshape2(int w,int h) {
        glutIdleFunc(idle);
        glViewport(0,0,w,h);
        width2 = w;
        height2 = h;
        int ww = w;
        int hh = h;
        int t = ww*hh*3 ;
        im =(GLubyte *) calloc(t,sizeof(GLubyte));
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0,w,0,h,-1.0,1.0); 
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
      }
      
      int main(int argc,char **argv) {
        glutInit(&argc,argv);
        glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
        { glutInitWindowSize(320,180); 
          glutInitWindowPosition(20,20); 
          f1 = glutCreateWindow("Mini lancer de rayons: Z-Buffer et Gouraud"); 
          myinit(); 
          ajustementTailleFenetre();
          creationMenuBasique();
          glutKeyboardFunc(key);
          glutReshapeFunc(reshape);
          glutDisplayFunc(display);
          glutSpecialFunc(specialBasique);
          glutMotionFunc(motionBasique);
          glutMouseFunc(sourisBasique); }
        { glutInitWindowPosition(30,300); 
          glutInitWindowSize(320,180); 
          f2 = glutCreateWindow("Mini lancer de rayons: Lancer de rayons"); 
          myinit(); 
          ajustementTailleFenetre();
          creationMenuBasique();
          glutIdleFunc(idle);
          glutKeyboardFunc(key2);
          glutReshapeFunc(reshape2);
          glutDisplayFunc(display2); }
        glutMainLoop();
        return(0);
      }