L'exécutable

Le source : TP-DiffusionLumierePonctuelle.cpp

/* Auteur: Nicolas JANEY              */
/* nicolas.janey@univ-fcomte.fr       */
/* Octobre 2004                       */
/* Evaluation de la luniere diffusee  */
/* sur une surface eclairee par une   */
/* lumiere ponctuelle                 */

#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 "ModuleFleche.h"
#include "ModuleFont.h"
#include "ModuleManipulateur.h"
#include "ModuleMenus.h"
#include "ModuleReshape.h"

#ifndef M_PI
#define M_PI 3.14159
#endif

typedef struct Position {
  float x ;
  float y ;
  float z ;
  float t ; } Position ;

typedef struct Direction {
  float dx ;
  float dy ;
  float dz ;
  float t ; } Direction ;

typedef struct Couleur {
  float r ;
  float v ;
  float b ;
  float a ; } Couleur ;

typedef struct LumierePonctuelle {
  Position p;
  Couleur c;
  float e; } LumierePonctuelle ;

typedef struct Materiau {
  Couleur kd; } Materiau ;

typedef struct Energie {
  float er ;
  float ev ;
  float eb ; } Energie ;

static int f1;
static int f2;
static LumierePonctuelle lp = { { -0.6F,-0.8F,0.8F },
                                { 1.0F,1.0F,0.0F,1.0F },
                                1.0F } ;
static Materiau m = { { 1.0F,0.0F,1.0F,1.0F } } ;
static Direction n = { 0.0F,0.0F,1.0F };
static Position p = { 0.0F,0.0F,0.0F };
static Energie e = { 0.0F,0.0F,0.0F };
static Couleur c = { 0.0F,0.0F,0.0F,0.8F };
static int carac = 0;
static int cf = 0;
static int obj = 1;
static int disc = 50;
static int solid = 50;

float produitScalaire(Direction *v1,Direction *v2) {
  return(v1->dx*v2->dx+v1->dy*v2->dy+v1->dz*v2->dz);
}

void produitVectoriel(Direction *v1,Direction *v2,Direction *v) {
  v->dx = v1->dy*v2->dz-v2->dy*v1->dz;
  v->dy = v1->dz*v2->dx-v2->dz*v1->dx;
  v->dz = v1->dx*v2->dy-v2->dx*v1->dy;
  v->t = 0.0F;
}

void vecteur(Position *p1,Position *p2,Direction *d) {
  d->dx = p2->x - p1->x;
  d->dy = p2->y - p1->y;
  d->dz = p2->z - p1->z;
  d->t = 0.0F;
}

float longueur(Direction *v) {
  return(sqrt(v->dx*v->dx+v->dy*v->dy+v->dz*v->dz));
}

void normalize(Direction *v) {
  float d = longueur(v);
  if ( d != 0 ) {
    v->dx /= d;
    v->dy /= d;
    v->dz /= d; }
}

void energieRecue(Position *p,LumierePonctuelle *lp,Energie *e) {
  Direction d;
  vecteur(p,&lp->p,&d);
  float l = longueur(&d);
  float facteur = lp->e/(l*l);
  e->er = facteur*lp->c.r;
  e->ev = facteur*lp->c.v;
  e->eb = facteur*lp->c.b;
}

void lumiereDiffusee(Position *p,Direction *n,Materiau *m,LumierePonctuelle *lp,Energie *e) {
  Direction d;
  vecteur(p,&lp->p,&d);
  normalize(&d);
  float scal = produitScalaire(&d,n);
  if ( scal < 0.0F )
    e->er = e->ev = e->eb = 0.0F;
    else {
    energieRecue(p,lp,e);
    e->er *= m->kd.r*scal;
    e->ev *= m->kd.v*scal;
    e->eb *= m->kd.b*scal; }
}

void couleurEnergie(Energie *e,Couleur *c) {
  c->r = e->er;
  if ( c->r > 1.0F )
    c->r = 1.0F;
  c->v = e->ev;
  if ( c->v > 1.0F )
    c->v = 1.0F;
  c->b = e->eb;
  if ( c->b > 1.0F )
    c->b = 1.0F;
}

void myinit(void) {
  GLfloat light_position0[] = { 1.0F,0.0F,1.0F,0.0F };
  GLfloat light_position1[] = { -1.0F,0.0F,1.0F,0.0F };
  glLightfv(GL_LIGHT0,GL_AMBIENT,couleurNoir());
  glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc());
  glLightfv(GL_LIGHT1,GL_DIFFUSE,couleurBlanc());
  glLightfv(GL_LIGHT0,GL_SPECULAR,couleurNoir());
  glLightfv(GL_LIGHT0,GL_POSITION,light_position0);
  glLightfv(GL_LIGHT1,GL_POSITION,light_position1);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_NORMALIZE);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}

void dessineFacette(Position *p1,Position *p2,Position *p4,int disc) {
  float dx1 = (p2->x-p1->x)/disc;
  float dy1 = (p2->y-p1->y)/disc;
  float dz1 = (p2->z-p1->z)/disc;
  float dx2 = (p4->x-p1->x)/disc;
  float dy2 = (p4->y-p1->y)/disc;
  float dz2 = (p4->z-p1->z)/disc;
  glBegin(GL_QUADS);
  for ( int i = 0 ; i < disc ; i++ )
    for ( int j = 0 ; j < disc ; j++ ) {
      Energie e;
      Couleur c = { 0.0F,0.0F,0.0F,0.8F};
      Position pp1 = { p1->x+i*dx1+j*dx2,p1->y+i*dy1+j*dy2,p1->z+i*dz1+j*dz2};
      Position pp2 = { pp1.x+dx1,pp1.y+dy1,pp1.z+dz1 };
      Position pp3 = { pp1.x+dx1+dx2,pp1.y+dy1+dy2,pp1.z+dz1+dz2 };
      Position pp4 = { pp1.x+dx2,pp1.y+dy2,pp1.z+dz2 };
      lumiereDiffusee(&pp1,&n,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &pp1);
      lumiereDiffusee(&pp2,&n,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &pp2);
      lumiereDiffusee(&pp3,&n,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &pp3);
      lumiereDiffusee(&pp4,&n,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &pp4); }
  glEnd();
}

void dessineFacetteOrthogonale(Position *p,Direction *n) {
  Direction v1 = { -n->dy,n->dx,0.0F };
  if ( ( v1.dx == 0.0F ) && ( v1.dy == 0.0F ) )
    v1.dx = n->dz;
  normalize(&v1);
  Direction v2;
  produitVectoriel(n,&v1,&v2);
  Position p1 = { p->x+v1.dx+v2.dx,p->y+v1.dy+v2.dy,p->z+v1.dz+v2.dz };
  Position p2 = { p->x-v1.dx+v2.dx,p->y-v1.dy+v2.dy,p->z-v1.dz+v2.dz };
  Position p4 = { p->x+v1.dx-v2.dx,p->y+v1.dy-v2.dy,p->z+v1.dz-v2.dz };
  dessineFacette(&p1,&p2,&p4,disc);
}

void displayFacette(void) {
  lumiereDiffusee(&p,&n,&m,&lp,&e);
  couleurEnergie(&e,&c);
  if ( cf )
    glClearColor(0.5F,0.5F,0.5F,1.0F);
    else
    glClearColor(0.0F,0.0F,0.0F,0.0F);
  glPolygonMode(GL_FRONT,( solid ) ? GL_FILL : GL_LINE);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix() ;
  manipulateurSouris();
  manipulateurClavier();
  glEnable(GL_LIGHTING);
  glMaterialfv(GL_FRONT,GL_DIFFUSE,(float *) &lp.c);
  Direction l = { lp.p.x,lp.p.y,lp.p.z };
  normalize(&l);
  glPushMatrix();
  glTranslatef(0.0F,0.0F,0.0F);
  flecheEnVolume(l.dx,l.dy,l.dz,0.035F,0.15F,0.007F);
  glPopMatrix();
  glPushMatrix();
  glTranslatef(lp.p.x,lp.p.y,lp.p.z);
  glutSolidSphere(0.1,36,36);
  glPopMatrix();
  glMaterialfv(GL_FRONT,GL_DIFFUSE,(float *) &m.kd);
  glPushMatrix();
  glTranslatef(0.0F,0.0F,0.0F);
  flecheEnVolume(n.dx,n.dy,n.dz,0.035F,0.15F,0.007F);
  glPopMatrix();
  glDisable(GL_LIGHTING);
  glPushMatrix();
  glTranslatef(p.x,p.y,p.z);
  dessineFacetteOrthogonale(&p,&n);
  glPopMatrix();
  glPopMatrix() ;
  glFlush();
  glutSwapBuffers() ;
  glutPostWindowRedisplay(f2);
}

void solidSphere(float r,float nn,float nm) {
  for ( int i = 0 ; i < nn ; i++ ) {
    float a1 = -M_PI/2.0F + i*M_PI/nn ;
    float a2 = a1 + M_PI/nn ;
    float cs1 = cos(a1);
    float cs2 = cos(a2);
    float sn1 = sin(a1);
    float sn2 = sin(a2);
    glBegin(GL_QUAD_STRIP);
    for ( int j = 0 ; j <= nm ; j++ ) {
      float a = j*2*M_PI/nm;
      float sn = sin(a);
      float cs = cos(a);
      float x1 = cs1*cs;
      float y1 = cs1*sn;
      float x2 = cs2*cs;
      float y2 = cs2*sn;
      Position p1 = { r*x1,r*y1,r*sn1 };
      Direction n1 = { x1,y1,sn1 };
      lumiereDiffusee(&p1,&n1,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &p1);
      Position p2 = { r*x2,r*y2,r*sn2 };
      Direction n2 = { x2,y2,sn2 };
      lumiereDiffusee(&p2,&n2,&m,&lp,&e);
      couleurEnergie(&e,&c);
      glColor4fv((float *) &c);
      glVertex3fv((float *) &p2); }
    glEnd(); }
}

void displaySphere(void) {
  if ( cf )
    glClearColor(0.5F,0.5F,0.5F,1.0F);
    else
    glClearColor(0.0F,0.0F,0.0F,1.0F);
  glPolygonMode(GL_FRONT,( solid ) ? GL_FILL : GL_LINE);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix() ;
  manipulateurSouris();
  manipulateurClavier();
  glEnable(GL_LIGHTING);
  glMaterialfv(GL_FRONT,GL_DIFFUSE,(float *) &lp.c);
  Direction l = { lp.p.x,lp.p.y,lp.p.z };
  normalize(&l);
  glPushMatrix();
  glTranslatef(0.0F,0.0F,0.0F);
  flecheEnVolume(l.dx,l.dy,l.dz,0.035F,0.15F,0.007F);
  glPopMatrix();
  glPushMatrix();
  glTranslatef(lp.p.x,lp.p.y,lp.p.z);
  glutSolidSphere(0.1,36,36);
  glPopMatrix();
  glDisable(GL_LIGHTING);
  solidSphere(0.65,disc*2,disc);
  glPopMatrix() ;
  glFlush();
  glutSwapBuffers() ;
  glutPostWindowRedisplay(f2);
}

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

void incrementComposante(float *c) {
  *c += 0.01F;
  if ( *c > 1.0F )
    *c = 1.0F;
}                

void decrementComposante(float *c) {
  *c -= 0.01F;
  if ( *c < 0.0F )
    *c = 0.0F;
}                

void special(int key,int x,int y) {
  if ( specialManipulateur(key,x,y) ) {
    glutPostWindowRedisplay(f1); }
}

void reshape2(int w,int h) {
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0,w,-h,0,-1.0,1.0); 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void displayFacette2() {
  if ( cf )
    glClearColor(0.5F,0.5F,0.5F,1.0F);
    else
    glClearColor(0.0F,0.0F,0.0F,1.0F);
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  float pos = 1.0F;
  glColor4fv(couleurBlanc());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"Position lumiere   : %6.3f %6.3f %6.3f",lp.p.x,lp.p.y,lp.p.z) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv((float *) &lp.c);
  simpleBitmapOutput(1,REGULAR8x13,"Couleur lumiere    : %6.3f %6.3f %6.3f",lp.c.r,lp.c.v,lp.c.b) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv(couleurBlanc());
  simpleBitmapOutput(1,REGULAR8x13,"Intensite lumiere  : %6.3f",lp.e) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv((float *) &m.kd);
  simpleBitmapOutput(1,REGULAR8x13,"Diffusion materiau : %6.3f %6.3f %6.3f",m.kd.r,m.kd.v,m.kd.b) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv(couleurBlanc());
  simpleBitmapOutput(1,REGULAR8x13,"Normale            : %6.3f %6.3f %6.3f",n.dx,n.dy,n.dz) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"Position           : %6.3f %6.3f %6.3f",p.x,p.y,p.z) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"Energie diffusee   : %6.3f %6.3f %6.3f",e.er,e.ev,e.eb) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv((float *) &e);
  simpleBitmapOutput(1,REGULAR8x13,"Couleur obtenue    : %6.3f %6.3f %6.3f",c.r,c.v,c.b) ;
  glPopMatrix();
  glutSwapBuffers();
}

void displaySphere2() {
  if ( cf )
    glClearColor(0.5F,0.5F,0.5F,1.0F);
    else
    glClearColor(0.0F,0.0F,0.0F,1.0F);
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  float pos = 1.0F;
  glColor4fv(couleurBlanc());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"Position lumiere   : %6.3f %6.3f %6.3f",lp.p.x,lp.p.y,lp.p.z) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv((float *) &lp.c);
  simpleBitmapOutput(1,REGULAR8x13,"Couleur lumiere    : %6.3f %6.3f %6.3f",lp.c.r,lp.c.v,lp.c.b) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv(couleurBlanc());
  simpleBitmapOutput(1,REGULAR8x13,"Intensite lumiere  : %6.3f",lp.e) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv((float *) &m.kd);
  simpleBitmapOutput(1,REGULAR8x13,"Diffusion materiau : %6.3f %6.3f %6.3f",m.kd.r,m.kd.v,m.kd.b) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  glColor4fv(couleurBlanc());
  simpleBitmapOutput(1,REGULAR8x13,"Normale            : %6.3f %6.3f %6.3f",n.dx,n.dy,n.dz) ;
  pos += 1.0F;
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"Position           : %6.3f %6.3f %6.3f",p.x,p.y,p.z) ;
  glPopMatrix();
  glutSwapBuffers();
}

void key2(unsigned char key,int x,int y) {
  switch ( key ) {
    case 0x0D : obj = !obj;
                glutSetWindow(f1);
                glutDisplayFunc((obj) ? displayFacette : displaySphere);
                glutSetWindow(f2);
                glutDisplayFunc((obj) ? displayFacette2 : displaySphere2);
                postRedisplay();
                break;
    case 'm'  :
    case 'M'  : solid = !solid ;
                postRedisplay();
                break;
    case 'c'  :
    case 'C'  : cf = !cf ;
                postRedisplay();
                break;
    case '1'  : lp.p.x -= 0.01;
                postRedisplay();
                break;
    case '3'  : lp.p.x += 0.01;
                postRedisplay();
                break;
    case '4'  : lp.p.y -= 0.01;
                postRedisplay();
                break;
    case '6'  : lp.p.y += 0.01;
                postRedisplay();
                break;
    case '7'  : lp.p.z -= 0.01;
                postRedisplay();
                break;
    case '9'  : lp.p.z += 0.01;
                postRedisplay();
                break;
    case ' '  : carac = !carac;
                break;
    case 'r'  : incrementComposante((carac) ? &m.kd.r : &lp.c.r);
                postRedisplay();
                break;
    case 'R'  : decrementComposante((carac) ? &m.kd.r : &lp.c.r);
                postRedisplay();
                break;
    case 'v'  : incrementComposante((carac) ? &m.kd.v : &lp.c.v);
                postRedisplay();
                break;
    case 'V'  : decrementComposante((carac) ? &m.kd.v : &lp.c.v);
                postRedisplay();
                break;
    case 'b'  : incrementComposante((carac) ? &m.kd.b : &lp.c.b);
                postRedisplay();
                break;
    case 'B'  : decrementComposante((carac) ? &m.kd.b : &lp.c.b);
                postRedisplay();
                break;
    case 'd'  : disc++;
                postRedisplay();
                break;
    case 'D'  : disc--;
                if ( disc < 2 )
                  disc = 2;
                postRedisplay();
                break;
    case 43   : lp.e *= 1.1F;
                postRedisplay();
                break;
    case 45   : lp.e /= 1.1F;
                postRedisplay();
                break;
    case 0x1B : exit(0);
                break; }
}

void key(unsigned char key,int x,int y) {
  if ( keyManipulateur(key,x,y) )
    glutPostWindowRedisplay(f1);
    else
    key2(key,x,y);
}

int main(int argc,char **argv) {
  lumiereDiffusee(&p,&n,&m,&lp,&e);
  couleurEnergie(&e,&c);
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowPosition(50,50); 
  glutInitWindowSize(420,240); 
  f1 = glutCreateWindow("Diffusion vis a vis d'une lumiere ponctuelle");
  myinit(); 
  creationMenuBasique();
  setParametresOrthoBasique(-1.0,1.0,-1.0,1.0,-50.0,50.0);
  setManipulateurDistance(1.0F);
  setManipulateurClavierAngle(-50.0F,0.0F,-20.0F);
  glutReshapeFunc(reshapeOrthoBasique);
  glutKeyboardFunc(key);
  glutSpecialFunc(specialBasique);
  glutDisplayFunc(displayFacette);
  glutMotionFunc(motionBasique);
  glutMouseFunc(sourisBasique);
  glutInitWindowSize(430,170);
  glutInitWindowPosition(60,340);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  f2 = glutCreateWindow("Valeurs");
  creationMenuBasique();
  glutDisplayFunc(displayFacette2);
  glutReshapeFunc(reshape2);
  glutKeyboardFunc(key);
  glutSpecialFunc(special);
  glutMainLoop();
  return(0);
}

Les modules utilitaires : Modules.zip

RETOUR