/* Un mini programme de ray-tracing             */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Mars 2014                                    */

#if defined(WIN32) || defined(WIN64)
  #define _CRTDBG_MAP_ALLOC
  #if defined(_DEBUG)
    #define _AFXDLL
    #include <afx.h>
  #endif
#endif
#include <stdlib.h>
#if defined(WIN32) || defined(WIN64)
  #include <crtdbg.h>
#endif

#include <stdio.h>
#include <math.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "Image.h"

#include "Couleur.h"
#include "Materiel.h"

#include "Sphere.h"
#include "Scene.h"

#include "RayonLumineux.h"

#include "LumierePonctuelle.h"
#include "LumiereDirectionnelle.h"

#include "Dir3D.h"
#include "Pos3D.h"
#include "Rt3D.h"
#include "Tr3D.h"
#include "TG3D.h"

/* Variables globales de stockage des handles   */
/* des deux fenetres                            */

static int f1;
static int f2;

/* Variables globales de gestion                */
/* de l'interactivite clavier et souris         */

static int clic = 0;
static int mx;
static int my;
static float rx = 0.0F;
static float ry = 0.0F;
static float csc = 200.0F;

/* Variables globales                           */

static int lignesTraitees = 0;
static long nbRayons;
static long nbRayonsOmbre;
static int sc = 0;
static int mode = 1;

/* Definition d'un tableau de 2 scenes          */

static Scene *scn[3] = { NULL,NULL,NULL };

/* Variables globales de gestion du ray-tracing */

static int niveauRecursivite = 10;
static int resolutionX = 480;
static int resolutionY = 300;
static double sensibilite = 100.0;

/* Variables globales de stockage de l'image calculee */

static Image *ima = NULL ;

/* Fonction de nettoyage memoire                */

void clean(void) {
  if ( ima ) {
    delete(ima);
    ima = NULL; }
  if ( scn[0] ) {
    delete(scn[0]);
    scn[0] = NULL; }
  if ( scn[1] ) {
    delete(scn[1]);
    scn[1] = NULL; }
  if ( scn[2] ) {
    delete(scn[2]);
    scn[2] = NULL; }
}

/* Fonction d'affichage d'une eventuelle        */
/* erreur OpenGL                                */

static void checkError(int line) {
  GLenum err = glGetError();
  if (err) {
    printf("GL Error %s (0x%x) at line %d\n",
           gluErrorString(err), (int) err, line); }
}

/* Fonction display GLUT d'affichage            */
/* de la bitmap resultat du ray-tracing         */

void display(void) { 
  glClear(GL_COLOR_BUFFER_BIT); 
  glPushMatrix();
  glClearColor(0.0,0.0,0.0,1.0); 
  glPixelStorei(GL_UNPACK_ALIGNMENT,1); 
  glPixelStorei(GL_PACK_ALIGNMENT,1); 
  ima->affichage();
  glPopMatrix();
  glFlush(); 
  checkError(__LINE__);
  glutSwapBuffers();
} 

void orienteScene(Scene *scene) {
  Tr3D tr1(0.0,0.0,csc);
  Rt3D rtx(rx,1.0,0.0,0.0);
  Rt3D rty(ry,0.0,1.0,0.0);
  Tr3D tr2(0.0,0.0,-csc);
  TG3D m0(&rty,&tr1);
  TG3D m1(&rtx,&m0);
  TG3D m(&tr2,&m1);
  int i;
  for ( i = 0 ; i < scene->nbObjets ; i++ )
    scene->objets[i]->centre->transformation(&m);
  for ( i = 0 ; i < scene->nbLumieres ; i++ )
    scene->lumieres[i]->transforme(&m);
}

/* Fonction de calcul en ray-tracing            */
/* d'une ligne de pixels de l'image             */
/* Chaque rayon primaire est dirige en -z       */
/* -> projection parallele orthographique       */

void traiteLigne(int ligne,Image *img) {
  for ( int i = 0 ; i < img->tx ; i++ ) {
    RayonLumineux *rl = new RayonLumineux();
    rl->origine->x = (i-img->tx/2.0)/(img->tx/480.0);
    rl->origine->y = (ligne-img->ty/2.0)/(img->tx/480.0);
    rl->origine->z = 2000.0;
    rl->direction->x = 0.0;
    rl->direction->y = 0.0;
    rl->direction->z = -1.0;
    Energie energieRecue;
    Scene *nsc = new Scene(scn[sc]);
    orienteScene(nsc);
    nsc->rayTracing(&energieRecue,rl,niveauRecursivite,1.0,1,&nbRayons,&nbRayonsOmbre);
    img->affecteEnergieSurPixel(&energieRecue,sensibilite,i,ligne);
    delete(nsc);
    delete(rl); }
}

/* Fonction idle                                */
/* Calcul de 20 lignes de pixels en ray-tracing */
/* Arret quand l'image est entierement calculee */

void idle(void) {
  for ( int i = 0 ; i < 20 ; i++ ) {
    traiteLigne(lignesTraitees,ima);
    lignesTraitees++;
    if ( lignesTraitees == resolutionY ) {
      glutIdleFunc(NULL);
      printf("%3d : %10d %10d : %10d\n",niveauRecursivite,nbRayons,nbRayonsOmbre,nbRayons+nbRayonsOmbre);
      glutPostWindowRedisplay(f1);
      return; } }
  glutPostWindowRedisplay(f1);
}

/* Fonction executee lors de la frappe          */
/* d'une touche alphanumerique du clavier       */

void key(unsigned char key,int x,int y) {
  switch ( key ) {
    case 43 :
      niveauRecursivite++;
      lignesTraitees = 0;
      delete(ima);
      ima = new Image(resolutionX,resolutionY);
      nbRayons = 0;
      nbRayonsOmbre = 0;
      glutIdleFunc(idle);
      break;
    case 45 :
      niveauRecursivite--;
      if ( niveauRecursivite < 1 )
        niveauRecursivite = 1;
      lignesTraitees = 0;
      delete(ima);
      ima = new Image(resolutionX,resolutionY);
      nbRayons = 0;
      nbRayonsOmbre = 0;
      glutIdleFunc(idle);
      break;
    case 0x20 :
      sc = (sc+1)%3;
      csc = (sc == 1) ? 150.0F : 200.0F;
      glutIdleFunc(NULL);
      glutPostWindowRedisplay(f2);
      break;
    case 0x0D :
      lignesTraitees = 0;
      delete(ima);
      ima = new Image(resolutionX,resolutionY);
      nbRayons = 0;
      nbRayonsOmbre = 0;
      glutIdleFunc(idle);
      break;
    case 0x1B :
      clean();
      exit(0);
      break; }
}

/* Fonction reshape de l'affichage ray-tracing  */

void reshape(int w,int h) {
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0,w,0,h,-1.0,1.0); 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  resolutionX = w;
  resolutionY = h;
  delete(ima);
  ima = new Image(resolutionX,resolutionY);
  glutIdleFunc(NULL);
  glutSetWindow(f2);
  glutReshapeWindow(w,h);
}

/* Fonction reshape de l'affichage OpenGL       */

void reshapeOpenGL(int w,int h) {
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-240.0,240.0,
          -240.0*(double) h/w,240.0*(double) h/w,
          -5000.0,5000.0); 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction display GLUT d'affichage OpenGL     */
/* de la scene                                  */

void displayOpenGL(void) {
  glClearColor(0.0F,0.0F,0.0F,1.0F);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
  glEnable(GL_LIGHTING);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_CULL_FACE);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  float noir[4] = { 0.0F,0.0F,0.0F,0.0F };
  glPushMatrix();
  glTranslatef(0.0F,0.0F,-csc);
  glRotatef(rx,1.0F,0.0F,0.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  glTranslatef(0.0F,0.0F,csc);
  int lum = GL_LIGHT0;
  int i;
  for ( i = 0 ; i < 8 ; i++ ) {
    glDisable(lum);
    lum++; }
  lum = GL_LIGHT0;
  for ( i = 0 ; i < scn[sc]->nbLumieres ; i++ ) {
    Lumiere *l = scn[sc]->lumieres[i];
    float fact = l->intensite * sensibilite / 255.0;
    glEnable(lum);
    l->modeliseOpenGL(lum);
    glLightf(lum,GL_CONSTANT_ATTENUATION,1.0F);
    glLightf(lum,GL_LINEAR_ATTENUATION,1.0F);
    glLightf(lum,GL_QUADRATIC_ATTENUATION,1.0F);
    float dif[4] = { (float) l->c->r * fact,
                     (float) l->c->v * fact,
                     (float) l->c->b * fact,
                     1.0F };
    glLightfv(lum,GL_SPECULAR,noir);
    glLightfv(lum,GL_DIFFUSE,dif);
    lum++; }
  for ( i = 0 ; i < scn[sc]->nbObjets ; i++ ) {
    Objet *o = scn[sc]->objets[i];
    float alpha =(o->materiel->kt->r+
                  o->materiel->kt->v+
                  o->materiel->kt->b)/3.0F;
    glPushMatrix();
    glTranslatef(o->centre->x,o->centre->y,o->centre->z);
    float dif[4] = { (float) o->materiel->kd->r,
                     (float) o->materiel->kd->v,
                     (float) o->materiel->kd->b,
                     1.0F-alpha };
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif);
    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,noir);
    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,noir);
    o->modeliseOpenGL();
    glPopMatrix(); }
  glPopMatrix();
  glFlush(); 
  checkError(__LINE__);
  glutSwapBuffers();
} 

/* Fonction executee lors d'un clic de souris   */
/* dans la fenetre                              */

void mouse(int bouton,int etat,int x,int y) {
  if ( bouton == GLUT_LEFT_BUTTON ) {
    if ( etat == GLUT_DOWN ) {
      clic = 1;
      mx = x;
      my = y; }
    if ( etat == GLUT_UP ) {
      clic = 0; } }
}

/* Fonction executee lors d'un deplacement      */
/* de la souris sur la fenetre                  */
/* avec un bouton appuye                        */

void motion(int x,int y) {
  if ( clic ) {
    ry += (x-mx);
    rx += (y-my);
    mx = x;
    my = y;
    glutPostWindowRedisplay(f2); }
}

/* Fonction Pricipale                           */

int main(int argc,char **argv) {

#if defined(WIN32) || defined(WIN64)
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  //_crtBreakAlloc = 472;
#endif

  atexit(clean);

  { Scene *scene0 = new Scene();
    scn[0] = scene0;
    { Pos3D *pos = new Pos3D(-90.0,90.0,-600.0);
      Couleur *kd = new Couleur(1.0,0.0,0.0);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.0);
      Sphere *sp = new Sphere(pos,40.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(90.0,-90.0,-600.0);
      Couleur *kd = new Couleur(0.0,1.0,0.0);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.0);
      Sphere *sp = new Sphere(pos,40.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(-90.0,-90.0,-600.0);
      Couleur *kd = new Couleur(0.0,0.0,1.0);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.0);
      Sphere *sp = new Sphere(pos,40.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(90.0,90.0,-600.0);
      Couleur *kd = new Couleur(1.0,1.0,1.0);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.0);
      Sphere *sp = new Sphere(pos,40.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(0.0,0.0,-610.0);
      Couleur *kd = new Couleur(1.0,1.0,0.0);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.0);
      Sphere *sp = new Sphere(pos,40.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(0.0,0.0,-200.0);
      Couleur *kd = new Couleur(0.25,0.25,0.25);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.75,0.75,0.75);
      Materiel *m = new Materiel(kd,kr,kt,1.5);
      Sphere *sp = new Sphere(pos,120.0,m);
      scene0->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Dir3D *dir = new Dir3D(0.0,0.707,-0.707);
      Couleur *coul = new Couleur(0.8,0.0,0.8);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,1.5,coul);
      scene0->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Dir3D *dir = new Dir3D(-0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.8,0.0,0.8);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,1.5,coul);
      scene0->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Dir3D *dir = new Dir3D(0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.0,0.9,0.9);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,3.0,coul);
      scene0->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Pos3D *pos = new Pos3D(80.0,20.0,0.0);
      Couleur *coul = new Couleur(0.9,0.9,0.0);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,15000.0,coul);
      scene0->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); }
    { Pos3D *pos = new Pos3D(-80.0,-20.0,0.0);
      Couleur *coul = new Couleur(0.8,0.8,0.8);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,28000.0,coul);
      scene0->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); } }
  { Scene *scene1 = new Scene();
    scn[1] = scene1;
    { Pos3D *pos = new Pos3D(160.0,50.0,-200.0);
      Couleur *kd = new Couleur(0.8,0.8,0.8);
      Couleur *kr = new Couleur(0.1,0.1,0.1);
      Couleur *kt = new Couleur(0.1,0.1,0.1);
      Materiel *m = new Materiel(kd,kr,kt,1.3);
      Sphere *sp = new Sphere(pos,90.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(130.0,115.0,-100.0);
      Couleur *kd = new Couleur(0.3,0.3,0.8);
      Couleur *kr = new Couleur(0.6,0.6,0.1);
      Couleur *kt = new Couleur(0.1,0.1,0.1);
      Materiel *m = new Materiel(kd,kr,kt,1.3);
      Sphere *sp = new Sphere(pos,20.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(10.0,-10.0,-150.0);
      Couleur *kd = new Couleur(0.1,0.2,0.4);
      Couleur *kr = new Couleur(0.9,0.8,0.6);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.5);
      Sphere *sp = new Sphere(pos,70.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(-150.0,-60.0,-150.0);
      Couleur *kd = new Couleur(0.5,0.4,0.3);
      Couleur *kr = new Couleur(0.1,0.1,0.1);
      Couleur *kt = new Couleur(0.4,0.5,0.6);
      Materiel *m = new Materiel(kd,kr,kt,1.4);
      Sphere *sp = new Sphere(pos,60.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(-110.0,-80.0,-30.0);
      Couleur *kd = new Couleur(0.4,0.3,0.2);
      Couleur *kr = new Couleur(0.3,0.2,0.4);
      Couleur *kt = new Couleur(0.2,0.4,0.3);
      Materiel *m = new Materiel(kd,kr,kt,1.2);
      Sphere *sp = new Sphere(pos,30.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(50.0,20.0,-30.0);
      Couleur *kd = new Couleur(0.2,0.3,0.0);
      Couleur *kr = new Couleur(0.8,0.6,0.7);
      Couleur *kt = new Couleur(0.0,0.1,0.3);
      Materiel *m = new Materiel(kd,kr,kt,1.2);
      Sphere *sp = new Sphere(pos,10.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(-90.0,90.0,-70.0);
      Couleur *kd = new Couleur(1.0,0.5,0.5);
      Couleur *kr = new Couleur(0.0,0.5,0.5);
      Couleur *kt = new Couleur(0.0,0.0,0.0);
      Materiel *m = new Materiel(kd,kr,kt,1.2);
      Sphere *sp = new Sphere(pos,50.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Pos3D *pos = new Pos3D(0.0,65.0,-45.0);
      Couleur *kd = new Couleur(0.25,0.25,0.25);
      Couleur *kr = new Couleur(0.0,0.0,0.0);
      Couleur *kt = new Couleur(0.75,0.75,0.75);
      Materiel *m = new Materiel(kd,kr,kt,1.45);
      Sphere *sp = new Sphere(pos,44.0,m);
      scene1->add(sp);
      delete(pos);
      delete(kd);
      delete(kr);
      delete(kt);
      delete(m);
      delete(sp); }
    { Dir3D *dir = new Dir3D(-0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.8,0.0,0.8);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,1.5,coul);
      scene1->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Dir3D *dir = new Dir3D(0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.0,0.9,0.9);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,3.0,coul);
      scene1->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Pos3D *pos = new Pos3D(80.0,20.0,0.0);
      Couleur *coul = new Couleur(0.9,0.9,0.0);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,15000.0,coul);
      scene1->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); }
    { Pos3D *pos = new Pos3D(-80.0,-20.0,0.0);
      Couleur *coul = new Couleur(0.8,0.8,0.8);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,28000.0,coul);
      scene1->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); } }
  { Scene *scene = new Scene();
    scn[2] = scene;
    { for ( double x = -100.0 ; x < 105.0 ; x += 100.0 ) {
        for ( double y = -100.0 ; y <105.0 ; y += 100.0 ) {
          for ( double z = -100.0 ; z <105.0 ; z += 100.0 ) {
            Pos3D *pos = new Pos3D(x,y,z-200.0);
            switch (rand()%5) {
              case 0 :
              case 1 :
              case 2 :
                { Couleur *kd = new Couleur(( rand()%3 != 0 ) ? 1.0 : 0.0,
                                            ( rand()%3 != 0 ) ? 1.0 : 0.0,
                                            ( rand()%3 != 0 ) ? 1.0 : 0.0);
                  Couleur *kr = new Couleur(0.1,0.1,0.1);
                  Couleur *kt = new Couleur(0.1,0.1,0.1);
                  Materiel *m = new Materiel(kd,kr,kt,1.5);
                  Sphere *sp = new Sphere(pos,30.0,m);
                  scene->add(sp);
                  delete(kd);
                  delete(kr);
                  delete(kt);
                  delete(m);
                  delete(sp); }
                break;
              case 3 :
                { Couleur *kd = new Couleur(0.1,0.1,0.1);
                  Couleur *kr = new Couleur(1.0,1.0,1.0);
                  Couleur *kt = new Couleur(0.1,0.1,0.1);
                  Materiel *m = new Materiel(kd,kr,kt,1.5);
                  Sphere *sp = new Sphere(pos,30.0,m);
                  scene->add(sp);
                  delete(kd);
                  delete(kr);
                  delete(kt);
                  delete(m);
                  delete(sp); }
                break;
              case 4 :
                { Couleur *kd = new Couleur(0.1,0.1,0.1);
                  Couleur *kr = new Couleur(0.1,0.1,0.1);
                  Couleur *kt = new Couleur(1.0,1.0,1.0);
                  Materiel *m = new Materiel(kd,kr,kt,1.5);
                  Sphere *sp = new Sphere(pos,30.0,m);
                  scene->add(sp);
                  delete(kd);
                  delete(kr);
                  delete(kt);
                  delete(m);
                  delete(sp); }
                break; }
            delete(pos); } } } }
    { Dir3D *dir = new Dir3D(-0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.8,0.8,0.8);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,1.5,coul);
      scene->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Dir3D *dir = new Dir3D(0.57735,0.57735,0.57735);
      Couleur *coul = new Couleur(0.9,0.9,0.9);
      LumiereDirectionnelle *ld = new LumiereDirectionnelle(dir,3.0,coul);
      scene->add(ld);
      delete(ld);
      delete(dir);
      delete(coul); }
    { Pos3D *pos = new Pos3D(80.0,20.0,0.0);
      Couleur *coul = new Couleur(0.9,0.9,0.9);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,15000.0,coul);
      scene->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); }
    { Pos3D *pos = new Pos3D(-80.0,-20.0,0.0);
      Couleur *coul = new Couleur(0.8,0.8,0.8);
      LumierePonctuelle *lp = new LumierePonctuelle(pos,28000.0,coul);
      scene->add(lp);
      delete(lp);
      delete(pos);
      delete(coul); } }
  ima = new Image(resolutionX,resolutionY);
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  glutInitWindowSize(resolutionX,resolutionY); 
  glutInitWindowPosition(30,30); 
  f1 = glutCreateWindow("Mini Ray-Tracing"); 
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutDisplayFunc(display);
  glutInitWindowPosition(530,30); 
  f2 = glutCreateWindow("OpenGL");
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutKeyboardFunc(key);
  glutReshapeFunc(reshapeOpenGL);
  glutDisplayFunc(displayOpenGL);
  glutMainLoop();
  return(0);
}
