L'exécutable

CoordonneesHomogenes.h - CoordonneesHomogenes.cpp - Position3D.h - Position3D.cpp

ModuleAffichageChaineDeCarateres.h - ModuleAffichageChaineDeCarateres.cpp

Le source : Direction3D.h

/* Mathematiques de l'informatique graphique    */
/* Direction en 3D                              */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2011                                */

#ifndef ____DIRECTION3D____
#define ____DIRECTION3D____

class Position3D;

#include "CoordonneesHomogenes.h"

class Direction3D : public CoordonneesHomogenes {

  public :

    /* Constructeurs                                */
    Direction3D(void);
    Direction3D(double x,double y,double z);
    Direction3D(Direction3D *c);
    Direction3D(Position3D *p1,Position3D *p2);

    /* Destructeur                                  */
    ~Direction3D(void);

    /* Methode de calcul de la norme                */
    double norme(void);

    /* Methode de normalisation                     */
    double normalisation(void);

    /* Methode de calcul du produit scalaire        */
    /* de deux directions                           */
    double produitScalaire(Direction3D *d);

    /* Methode de calcul du produit vectoriel       */
    /* de deux directions                           */
    void produitVectoriel(Direction3D *d1,Direction3D *d2);

    /* Methode de calcul du produit vectoriel       */
    /* de deux directions                           */
    Direction3D *produitVectoriel(Direction3D *d);

    /* Methode de calcul de la direction            */
    /* du rayon reflechi au niveau d'une interface  */
    bool reflechi(Direction3D *i,Direction3D *n);

    /* Methode de calcul de la direction            */
    /* du rayon transmis au niveau d'une interface  */
    bool transmis(Direction3D *i,Direction3D *n,double rp);
};

#endif

Le source : Direction3D.cpp

/* Mathematiques de l'informatique graphique    */
/* Direction en 3D                              */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Octobre 2011                                 */

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

#include "CoordonneesHomogenes.h"
#include "Direction3D.h"
#include "Position3D.h"

/* Constructeurs                                */

Direction3D::Direction3D(void):CoordonneesHomogenes(0.0,0.0,0.0,0.0) {
}

Direction3D::Direction3D(double x,double y,double z):CoordonneesHomogenes(x,y,z,0.0) {
}

Direction3D::Direction3D(Direction3D *p):CoordonneesHomogenes(p) {
}

Direction3D::Direction3D(Position3D *p1,Position3D *p2):CoordonneesHomogenes() {
  c[0] = p2->c[0]-p1->c[0];
  c[1] = p2->c[1]-p1->c[1];
  c[2] = p2->c[2]-p1->c[2];
  c[3] = 0.0;
}

/* Destructeur                                  */

Direction3D::~Direction3D(void) {
}

/* Methode de calcul de la norme                */

double Direction3D::norme(void) {
  return(sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]));
}

/* Methode de normalisation                     */

double Direction3D::normalisation(void) {
  double d = norme();
  if ( d != 0.0 ) {
    c[0] /= d;
    c[1] /= d;
    c[2] /= d; }
  return(d);
}

/* Methode de calcul du produit scalaire        */
/* de deux directions                           */

double Direction3D::produitScalaire(Direction3D *d) {
  return(c[0]*d->c[0]+c[1]*d->c[1]+c[2]*d->c[2]);
}

/* Methode de calcul du produit vectoriel       */
/* de deux directions                           */

void Direction3D::produitVectoriel(Direction3D *d1,Direction3D *d2) {
  double x = d1->c[1]*d2->c[2] - d1->c[2]*d2->c[1];
  double y = d1->c[2]*d2->c[0] - d1->c[0]*d2->c[2];
  double z = d1->c[0]*d2->c[1] - d1->c[1]*d2->c[0];
  c[0] = x;
  c[1] = y;
  c[2] = z;
  c[3] = 0.0;
}

/* Methode de calcul du produit vectoriel       */
/* de deux directions                           */

Direction3D *Direction3D::produitVectoriel(Direction3D *d) {
  return(new Direction3D(c[1]*d->c[2] - c[2]*d->c[1],
                         c[2]*d->c[0] - c[0]*d->c[2],
                         c[0]*d->c[1] - c[1]*d->c[0]));
}

bool Direction3D::reflechi(Direction3D *i,Direction3D *n) {
  double ps = i->produitScalaire(n);
  if ( ps < 0.0 )
    return(false);
  c[0] = 2.0*ps*n->c[0]-i->c[0];
  c[1] = 2.0*ps*n->c[1]-i->c[1];
  c[2] = 2.0*ps*n->c[2]-i->c[2];
  c[3] = 0.0;
  return(true);
}

bool Direction3D::transmis(Direction3D *i,Direction3D *n,double rp) {
  double ps = i->produitScalaire(n);
  double fact = 1.0-rp*rp*(1.0-ps*ps);
  if ( fact < 0.0 )
    return(false);
  fact = rp*ps-sqrt(fact);
  c[0] = fact*n->c[0]-rp*i->c[0];
  c[1] = fact*n->c[1]-rp*i->c[1];
  c[2] = fact*n->c[2]-rp*i->c[2];
  c[3] = 0.0;
  return(true);
}

Le source : Sphere.h

/* Mathematiques de l'informatique graphique    */
/* Sphere                                       */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2011                                */

#ifndef ____SPHERE____
#define ____SPHERE____

class Position3D;
class Rayon;

class Sphere {

  public :
    Position3D *centre;
    double rayon;

  public :

    /* Constructeurs                                */
    Sphere(void);
    Sphere(double cx,double cy,double cz,double rayon);
    Sphere(Position3D *c,double rayon);

    /* Destructeur                                  */
    ~Sphere(void);

    /* Methode de test de l'intersection            */
    /* entre une sphere et un rayon                 */
    bool intersection(Rayon *r);

    /* Methode de test de l'intersection            */
    /* entre une sphere et un rayon                 */
    /* t rendu a la distance a l'intersection       */
    bool intersection(Rayon *r,double *t);
};

#endif

Le source : Sphere.cpp

/* Mathematiques de l'informatique graphique    */
/* Sphere                                       */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2011                                */

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

#include "Sphere.h"
#include "Position3D.h"
#include "Direction3D.h"
#include "Rayon.h"

Sphere::Sphere(void) {
  centre = new Position3D();
  rayon = 1.0;
}

Sphere::Sphere(double cx,double cy,double cz,double rayon) {
  centre = new Position3D(cx,cy,cz);
  this->rayon = rayon;
}

Sphere::Sphere(Position3D *c,double rayon) {
  centre = new Position3D(c);
  this->rayon = rayon;
}

Sphere::~Sphere(void) {
  delete(centre);
}

bool Sphere::intersection(Rayon *r) {
  double dpx = centre->c[0]-r->pos->c[0];
  double dpy = centre->c[1]-r->pos->c[1];
  double dpz = centre->c[2]-r->pos->c[2];
  double a = r->dir->c[0]*r->dir->c[0]+
             r->dir->c[1]*r->dir->c[1]+
             r->dir->c[2]*r->dir->c[2];
  double b = -2.0*(r->dir->c[0]*dpx+
                   r->dir->c[1]*dpy+
                   r->dir->c[2]*dpz);
  double c = dpx*dpx+dpy*dpy+dpz*dpz-rayon*rayon;
  double delta = b*b-4.0*a*c;
  if ( delta < 0.0 )
    return(false);
  if ( delta == 0.0 ) {
    double t = -b/(2.0*a);
    return(t > 0.0); }
  double t1 = (-b-sqrt(delta))/(2.0*a);
  if ( t1 > 0.0 )
    return(true);
  double t2 = (-b+sqrt(delta))/(2.0*a);
  return(t2 > 0.0);
}

bool Sphere::intersection(Rayon *r,double *tt) {
  double dpx = centre->c[0]-r->pos->c[0];
  double dpy = centre->c[1]-r->pos->c[1];
  double dpz = centre->c[2]-r->pos->c[2];
  double a = r->dir->c[0]*r->dir->c[0]+
             r->dir->c[1]*r->dir->c[1]+
             r->dir->c[2]*r->dir->c[2];
  double b = -2.0*(r->dir->c[0]*dpx+
                   r->dir->c[1]*dpy+
                   r->dir->c[2]*dpz);
  double c = dpx*dpx+dpy*dpy+dpz*dpz-rayon*rayon;
  double delta = b*b-4.0*a*c;
  if ( delta < 0.0 )
    return(false);
  if ( delta == 0.0 ) {
    double t = -b/(2.0*a);
    if ( t > 0.0 ) {
      *tt = t;
      return(true); }
      else
      return(false); }
  double t1 = (-b-sqrt(delta))/(2.0*a);
  double t2 = (-b+sqrt(delta))/(2.0*a);
  double min = ( t1 < t2 ) ? t1 : t2;
  double max = ( t1 > t2 ) ? t1 : t2;
  if ( ( t1 <= 0.0 ) && ( t2 <= 0.0 ) )
    return(false);
  if ( t1 <= 0.0 )
    *tt = t2;
    else
    *tt = t1;
  return(true);
}

Le source : Rayon.h

/* Mathematiques de l'informatique graphique    */
/* Rayon lumineux                               */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2011                                */

#ifndef ____RAYON____
#define ____RAYON____

class Position3D;
class Direction3D;
class Sphere;

class Rayon {

  public :
    Position3D *pos;
    Direction3D *dir;

  public :

    /* Constructeurs                                */
    Rayon(void);
    Rayon(double px,double py,double pz,
          double dx,double dy,double dz);
    Rayon(Position3D *c,Direction3D *d);

    /* Destructeur                                  */
    ~Rayon(void);

    /* Methode de test de l'intersection            */
    /* entre un rayon et une sphere                 */
    bool intersection(Sphere *s);
};

#endif

Le source : Rayon.cpp

/* Mathematiques de l'informatique graphique    */
/* Rayon lumineux                               */
/*                                              */
/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2011                                */

#include "Rayon.h"
#include "Position3D.h"
#include "Direction3D.h"
#include "Sphere.h"

Rayon::Rayon(void) {
  pos = new Position3D();
  dir = new Direction3D();
}

Rayon::Rayon(double px,double py,double pz,
             double dx,double dy,double dz){
  pos = new Position3D(px,py,pz);
  dir = new Direction3D(dx,dy,dz);
}

Rayon::Rayon(Position3D *c,Direction3D *d) {
  pos = new Position3D(c);
  dir = new Direction3D(d);
}

Rayon::~Rayon(void) {
  delete(pos);
  delete(dir);
}

bool Rayon::intersection(Sphere *s) {
  return(s->intersection(this));
}

Le source : MathematiquesLancerDeRayons.cpp

/* Implantation mathematique             */
/* d'operations utilisees                */
/* en lancer de rayons                   */
/*                                       */
/* Auteur: Nicolas JANEY                 */
/* nicolas.janey@univ-fcomte.fr          */
/* Novembre 2011                         */

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

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

#include "ModuleAffichageChaineDeCarateres.h"

#include "Position3D.h"
#include "Direction3D.h"
#include "Sphere.h"
#include "Rayon.h"

/* Variables et constantes globales             */
/* pour les angles et les couleurs utilises     */

static int f1;
static int aff = 1;

static float rx = -20.0F;
static float ry = 0.0F;
static float rz = 0.0F;
static float px = -0.1F;
static float py = 0.1F;
static float pz = 0.2F;
static float rp = 1.0F;

static void postRedisplay(void) {
  glutPostWindowRedisplay(f1);
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre (1)               */

void reshape(int w,int h) {
  glViewport(0,0,w,h); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-1.0F,1.0,(float) -h/w,(float) h/w,-50.0,50.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin (1)                  */

static void drawDirection(Direction3D *d) {
  glBegin(GL_LINES);
  glVertex3f(0.0F,0.0F,0.0F);
  glVertex3d(d->c[0],d->c[1],d->c[2]);
  glEnd();
}

void displayReflexionEtTransmission() {
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  glRotatef(rz,0.0F,0.0F,1.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  glRotatef(rx,1.0F,0.0F,0.0F);
  glLineWidth(2.0F);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  Direction3D *n = new Direction3D(0.3,0.6,sqrt(1.0-0.6*0.6-0.3*0.3));
  Direction3D *i = new Direction3D(-0.3,0.7,sqrt(1.0-0.7*0.7-0.3*0.3));
  Direction3D *a1 = new Direction3D();
  a1->produitVectoriel(n,i);
  Direction3D *a2 = new Direction3D();
  a2->produitVectoriel(n,a1);
  Direction3D *r = new Direction3D();
  bool rr;
  if ( rr = r->reflechi(i,n) ) {
    glColor4f(1.0F,0.0F,0.0F,1.0F);
    drawDirection(r); }
  Direction3D *t = new Direction3D();
  bool rt;
  if ( rt = t->transmis(i,n,rp) ) {
    glColor4f(0.0F,1.0F,0.0F,1.0F);
    drawDirection(t); }
  glColor4f(1.0F,1.0F,0.0,1.0F);
  drawDirection(i);
  glColor4f(1.0F,0.0F,1.0F,1.0F);
  drawDirection(n);
  glColor4f(0.5F,0.5F,0.5F,0.5F);
  glBegin(GL_QUADS);
  glVertex3f(a1->c[0]*2.0F,a1->c[1]*2.0F,a1->c[2]*2.0F);
  glVertex3f(a2->c[0]*2.0F,a2->c[1]*2.0F,a2->c[2]*2.0F);
  glVertex3f(-a1->c[0]*2.0F,-a1->c[1]*2.0F,-a1->c[2]*2.0F);
  glVertex3f(-a2->c[0]*2.0F,-a2->c[1]*2.0F,-a2->c[2]*2.0F);
  glEnd();
  drawString(10,20,"I : %6.3lf %6.3lf %6.3lf",i->c[0],i->c[1],i->c[2]);
  drawString(10,40,"N : %6.3lf %6.3lf %6.3lf",n->c[0],n->c[1],n->c[2]);
  drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-50,"Rapport ni/nt : %7.4lf",rp);
  if ( rr )
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,
               "R : %6.3lf %6.3lf %6.3lf",r->c[0],r->c[1],r->c[2]);
    else
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,"R : inexistant");
  if ( rt )
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,
               "T : %6.3lf %6.3lf %6.3lf",t->c[0],t->c[1],t->c[2]);
    else
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,"T : inexistant");
  delete(t);
  delete(r);
  delete(i);
  delete(n);
  delete(a1);
  delete(a2);
  glPopMatrix();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

void drawPoint(double ix,double iy,double iz) {
  glDisable(GL_DEPTH_TEST);
  glPushMatrix();
  glPointSize(5.0F);
  glColor4f(0.0F,1.0F,0.0,1.0F);
  glBegin(GL_POINTS);
  glVertex3d(ix,iy,iz);
  glEnd();
  glPopMatrix();
  glEnable(GL_DEPTH_TEST);
}

void drawSphere(Sphere *s) {
  glPushMatrix();
  glTranslated(s->centre->c[0],s->centre->c[1],s->centre->c[2]);
  glutSolidSphere(s->rayon,72,72);
  glPopMatrix();
}

void drawRayon(Rayon *r) {
  glLineWidth(2.0F);
  glPointSize(5.0F);
  glColor4f(1.0F,0.0F,0.0,1.0F);
  glPushMatrix();
  glTranslated(r->pos->c[0],r->pos->c[1],r->pos->c[2]);
  glBegin(GL_POINTS);
  glVertex3d(0.0,0.0,0.0);
  glEnd();
  glBegin(GL_LINES);
  glVertex3d(0.0,0.0,0.0);
  glVertex3dv((double *) r->dir);
  glEnd();
  glPopMatrix();
}

void displayIntersection() {
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  const GLfloat light0_position[] = { 1.0,1.0,1.0,0.0 };
  const GLfloat light1_position[] = { -1.0,1.0,1.0,0.0 };
  glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
  glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
  glRotatef(rz,0.0F,0.0F,1.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  glRotatef(rx,1.0F,0.0F,0.0F);
  Rayon *r = new Rayon(px,py,pz,0.5,0.6,-sqrt(1.0-0.25-0.36));
  drawRayon(r);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  Sphere *s = new Sphere(0.2,0.1,-0.3,0.5);
  drawSphere(s);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  drawString(10,20,"Rp = %7.4lf %7.4lf %7.4lf",
             r->pos->c[0],r->pos->c[1],r->pos->c[2]);
  drawString(10,40,"Rd = %7.4lf %7.4lf %7.4lf",
             r->dir->c[0],r->dir->c[1],r->dir->c[2]);
  drawString(10,65,"Sp = %7.4lf %7.4lf %7.4lf",
             s->centre->c[0],s->centre->c[1],s->centre->c[2]);
  drawString(10,85,"Sr = %7.4lf",s->rayon);
  if ( s->intersection(r) ) {
    double t;
    s->intersection(r,&t);
    double ix = r->pos->c[0] + t*r->dir->c[0];
    double iy = r->pos->c[1] + t*r->dir->c[1];
    double iz = r->pos->c[2] + t*r->dir->c[2];
    drawPoint(ix,iy,iz);
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-50,"Intersection");
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,"t = %lf",t);
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,
               "pos = %7.4lf %7.4lf %7.4lf",ix,iy,iz); }
    else {
    drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,"Pas d'intersection"); }
  delete(r);
  delete(s);
  glPopMatrix();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

void myinit(void) {
  const GLfloat gris[] = { 0.8F,0.8F,0.8F,1.0F };
  const GLfloat blanc[] = { 1.0F,1.0F,1.0F,0.5F };
  const GLfloat mat_shininess[] = { 50.0 };
  glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
  glMaterialfv(GL_FRONT,GL_SPECULAR,blanc);
  glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,gris);
  glLightfv(GL_LIGHT1,GL_DIFFUSE,gris);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}

/* Fonction executee lors de la frappe          */
/* d'une touche special du clavier:             */
/* - touches de curseur                         */
/* - touches de fonction                        */
/* - ...                                        */

void special(int code,int x,int y) {
  switch ( code ) {
    case GLUT_KEY_UP :
      rx += 1.0F;
      postRedisplay(); 
      break;
    case GLUT_KEY_DOWN :
      rx -= 1.0F;
      postRedisplay(); 
      break;
    case GLUT_KEY_RIGHT :
      ry += 1.0F;
      postRedisplay(); 
      break;
    case GLUT_KEY_LEFT :
      ry -= 1.0F;
      postRedisplay(); 
      break;
    case GLUT_KEY_PAGE_UP :
      rz += 1.0F;
      postRedisplay(); 
      break;
    case GLUT_KEY_PAGE_DOWN :
      rz -= 1.0F;
      postRedisplay(); 
      break; }
}

/* Fonction executee lorsqu'aucun evenement     */
/* n'est en file d'attente                      */

void idle(void) {
  rx += 0.03355F;
  ry += 0.06117F;
  rz += 0.04174F;
  postRedisplay();
}

/* Fonction executee lors de l'appui            */
/* d'une touche alphanumerique du clavier       */

void keyboard(unsigned char key,int x,int y) {
  switch (key) {
    case 43 :
      rp *= 0.99F;
      postRedisplay(); 
      break;
    case 45 :
      rp /= 0.99F;
      postRedisplay(); 
      break;
    case 'x' :
      px -= 0.02F;
      postRedisplay(); 
      break;
    case 'X' :
      px += 0.02F;
      postRedisplay(); 
      break;
    case 'y' :
      py -= 0.02F;
      postRedisplay(); 
      break;
    case 'Y' :
      py += 0.02F;
      postRedisplay(); 
      break;
    case 'z' :
      pz -= 0.02F;
      postRedisplay(); 
      break;
    case 'Z' :
      px += 0.02F;
      postRedisplay(); 
      break;
    case 'r' :
      rx = 0.0F;
      ry = 0.0F;
      rz = 0.0F;
      postRedisplay();
      break;
    case 0x20 :
      aff = (aff+1)%2;
      if ( aff )
        glutDisplayFunc(displayReflexionEtTransmission);
        else
        glutDisplayFunc(displayIntersection);
      postRedisplay();
      break;
    case 0x0D :
      { static int anim = 0;
        anim = !anim;
        glutIdleFunc(( anim ) ? idle : NULL); }
      break;
    case 0x1B :
      exit(0);
      break; }
}

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitWindowSize(310,380);
  glutInitWindowPosition(50,50);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  f1 = glutCreateWindow("Mathematiques pour le ray tracing");
  myinit();
  glutDisplayFunc(displayReflexionEtTransmission);
  glutReshapeFunc(reshape);
  glutKeyboardFunc(keyboard);
  glutSpecialFunc(special);
  glutMainLoop();
  return(0);
}

RETOUR