L'exécutable

Plus l'observateur se voit proche de l'intérieur du cone de réflexion spéculaire, plus celle-ci est importante. Dans le cone, la réflexion est d'autant plus importante que l'observateur se rapproche de l'axe.

Le source : ReflexionSpeculaire.cpp

/* Auteur: Nicolas JANEY                    */
/* nicolas.janey@univ-fcomte.fr             */
/* Juin 2001                                */
/* Illustration de la reflexion speculaire  */

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

static vecteur pl = { -0.4F,1.4F,1.1F,1.0F } ;
static vecteur pi = { 0.4F,0.0F,0.6F } ;
static vecteur n ;
static vecteur l ;
static vecteur r ;
static float scal;
static float fact = 2.0F;
static int f1 ;
static int f2 ;
static float degres ;
static float shininess = 40.0F;

void myinit(void) {
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_NORMALIZE) ;
  glDepthFunc(GL_LESS);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
  glLightfv(GL_LIGHT0,GL_AMBIENT,couleurNoir());
  glLightfv(GL_LIGHT0,GL_SPECULAR,couleurNoir());
  glLightfv(GL_LIGHT1,GL_AMBIENT,couleurNoir());
  glLightfv(GL_LIGHT1,GL_SPECULAR,couleurJaune());
  glLightfv(GL_LIGHT2,GL_SPECULAR,couleurNoir());
  glLightfv(GL_LIGHT2,GL_AMBIENT,couleurNoir());
  float l2[4] = { 0.0F,1.0F,0.0F,0.0F };
  glLightfv(GL_LIGHT2,GL_POSITION,l2);
}

void axes() {
  glPushMatrix() ;
  glColor4fv(couleurJaune()) ;
  glBegin(GL_LINES) ;
  glVertex3f(0.0F,0.0F,0.0F) ;
  glVertex3f(0.25F,0.0F,0.0F) ;
  glEnd() ;
  placeFontCursor(0.3F,0.05F,0.05F);
  simpleBitmapOutput(1,1,"x");
  glColor4fv(couleurCyan()) ;
  glBegin(GL_LINES) ;
  glVertex3f(0.0F,0.0F,0.0F) ;
  glVertex3f(0.0F,0.25F,0.0F) ;
  glEnd() ;
  placeFontCursor(0.05F,0.3F,0.05F);
  simpleBitmapOutput(1,1,"y");
  glColor4fv(couleurMagenta()) ;
  glBegin(GL_LINES) ;
  glVertex3f(0.0F,0.0F,0.0F) ;
  glVertex3f(0.0F,0.0F,0.25F) ;
  glEnd() ;
  placeFontCursor(0.05F,0.05F,0.3F);
  simpleBitmapOutput(1,1,"z");
  glPopMatrix() ;
}

void solidHemisphere(double r,int n1,int n2) {
  vecteur **p =(vecteur **) calloc(n1,sizeof(vecteur *));
  int i;
  for ( i = 0 ; i < n1 ; i++ )
    p[i] =(vecteur *) calloc(n2,sizeof(vecteur));
  for ( i = 0 ; i < n1 ; i++ ) {
    double a1 = i * 3.14159 / 2.0 / (n1-1);
    double csa1 = cos(a1);
    double sna1 = sin(a1);
    for ( int j = 0 ; j < n2 ; j++ ) {
      double a2 = j * 3.14159 * 2.0 / (n2-1);
      double csa2 = cos(a2);
      double sna2 = sin(a2);
      p[i][j][0] = csa2*csa1;
      p[i][j][2] = sna2*csa1;
      p[i][j][1] = sna1; } }
  glBegin(GL_QUADS);
  for ( i = 0 ; i < n1-1 ; i++ ) {
    for ( int j = 0 ; j < n2 ; j++ ) {
      glNormal3f(p[i+1][j][0],p[i+1][j][1],p[i+1][j][2]);
      glVertex3f(r*p[i+1][j][0],r*p[i+1][j][1],r*p[i+1][j][2]);
      glNormal3f(p[i+1][(j+1)%n2][0],p[i+1][(j+1)%n2][1],p[i+1][(j+1)%n2][2]);
      glVertex3f(r*p[i+1][(j+1)%n2][0],r*p[i+1][(j+1)%n2][1],r*p[i+1][(j+1)%n2][2]);
      glNormal3f(p[i][(j+1)%n2][0],p[i][(j+1)%n2][1],p[i][(j+1)%n2][2]);
      glVertex3f(r*p[i][(j+1)%n2][0],r*p[i][(j+1)%n2][1],r*p[i][(j+1)%n2][2]);
      glNormal3f(p[i][j][0],p[i][j][1],p[i][j][2]);
      glVertex3f(r*p[i][j][0],r*p[i][j][1],r*p[i][j][2]); } } 
  glEnd();
  for ( i = 0 ; i < n1 ; i++ )
    free(p[i]);
  free(p);
}

void solidBaseHemisphere(double r,int n2) {
  vecteur *p =(vecteur *) calloc(n2,sizeof(vecteur));
  int j;
  for ( j = 0 ; j < n2 ; j++ ) {
    double a2 = j * 3.14159 * 2.0 / (n2-1);
    double csa2 = cos(a2);
    double sna2 = sin(a2);
    p[j][0] = r*csa2;
    p[j][2] = r*sna2;
    p[j][1] = 0.0F; }
  glBegin(GL_POLYGON);
  glNormal3f(0.0F,-1.0F,0.0F);
  for ( j = 0 ; j < n2 ; j++ ) {
    glVertex3f(p[j][0],p[j][1],p[j][2]); }
  glEnd();
  free(p);
}

static int estEgal(float a,float b) {
  return(fabs(a-b) < 0.00001) ;
}

void coneOriente(float dx,float dy,float dz,float cr,float cl) {
  glPushMatrix();
  double d = pow((double) (dx*dx+dy*dy+dz*dz),0.5);
  glPushMatrix();
  dx /= d; 
  dy /= d; 
  dz /= d;
  if ( estEgal(dz,-1.0F) )
    glRotatef(180.0F,1.0F,0.0F,0.0F);
    else
    if ( !estEgal(dz,1.0F) ) {
      double a = acos(dz) * 180 / 3.14159;
      glRotatef(a,-dy,dx,0); }
  glPushMatrix();
  glutSolidCone(cl,cr,36,20);
  glPopMatrix();
  glPopMatrix();
  glPopMatrix();
}

void display(void) {
  glClearColor(0.7F,0.7F,0.6F,0.0F);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  manipulateurSouris();
  manipulateurClavier();
  glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc());
  glLightfv(GL_LIGHT1,GL_DIFFUSE,couleurNoir());
  glLightfv(GL_LIGHT2,GL_DIFFUSE,couleurBlanc());
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glEnable(GL_LIGHT2);
  glTranslatef(0.0F,-0.65F,0.0F);
  float lreel[4] = { pl[0],pl[1],pl[2],1.0F };
  glLightfv(GL_LIGHT1,GL_POSITION,lreel);
  { glPushMatrix();
    glTranslatef(-0.4F,0.8F,-1.4F);
    axes();
    glPopMatrix(); }
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,shininess);
  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,couleurNoir());
  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,couleurNoir());
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurJaune());
  { glPushMatrix();
    glTranslatef(pl[0],pl[1],pl[2]);
    glutSolidSphere(0.06F,20,20);
    glPopMatrix(); }
  pi[1] = sqrt(1.0F-pi[0]*pi[0]-pi[2]*pi[2]);
  n[0] = pi[0]; 
  n[1] = pi[1]; 
  n[2] = pi[2];
  normalise(n); 
  l[0] = pl[0]-pi[0]; 
  l[1] = pl[1]-pi[1]; 
  l[2] = pl[2]-pi[2]; 
  normalise(l);
  scal = produitScalaire(l,n);
  if ( scal > 0.0F ) {
    degres = atan2(1.0F/shininess*50,fact)*180.0F/3.14159F;
    r[0] = 2.0F*n[0]*scal-l[0];
    r[1] = 2.0F*n[1]*scal-l[1];
    r[2] = 2.0F*n[2]*scal-l[2]; }
  vecteur axe = { r[2],0.0F,-r[0] };
  vecteur rd = { r[0],r[1],r[2] };
  matrice m;
  toRotation(m,degres,axe[0],axe[1],axe[2]);
  produitMatriceVecteur(m,rd,rd);
  glDisable(GL_LIGHTING);
  glColor3fv(couleurVert());
  vecteur pint;
  positionIntermediaire(rd,r,n,0.75F,pint);
  traceAngle(rd,r,n,20,0.75F,1);
  glEnable(GL_LIGHTING);
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurBleu());
  { glPushMatrix();
    glDisable(GL_LIGHTING);
    glTranslatef(pi[0],pi[1],pi[2]);
    glColor3fv(couleurVert());
    glBegin(GL_LINES);
    glVertex3f(0.0F,0.0F,0.0F);
    glVertex3f(rd[0]*2,rd[1]*2,rd[2]*2);
    glEnd();
    glEnable(GL_LIGHTING);
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurBleu());
    glutSolidSphere(0.04F,20,20);
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurJaune());
    flecheEnVolume(pl[0]-pi[0],pl[1]-pi[1],pl[2]-pi[2],0.03F,0.1F,0.01F);
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurRouge());
    flecheEnVolume(l[0],l[1],l[2],0.03F,0.1F,0.012F);
    if ( scal > 0.0F ) {
      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurVert());
      flecheEnVolume(r[0],r[1],r[2],0.03F,0.1F,0.012F); }
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurMagenta());
    flecheEnVolume(pi[0],pi[1],pi[2],0.03F,0.1F,0.01F);
    glPopMatrix(); }
  glDisable(GL_CULL_FACE);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurNoir());
  glLightfv(GL_LIGHT1,GL_DIFFUSE,couleurBlanc());
  glDisable(GL_LIGHT2);
  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,couleurJaune());
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurRougeFonce());
  solidHemisphere(1.0,120,120);
  solidBaseHemisphere(1.0,120);
  glDisable(GL_CULL_FACE);
  glEnable(GL_LIGHT2);
  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,couleurNoir());
  glLightfv(GL_LIGHT1,GL_DIFFUSE,couleurNoir());
  glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc());
  glDisable(GL_LIGHTING);
  glColor3fv(couleurVert());
  placeFontCursor(pint[0],pint[1],pint[2]) ;
  deplacementCursor(10,0,0) ;
  simpleBitmapOutput(1,SYMBOL,"q") ; 
  deplacementCursor(20,0,0) ;
  simpleBitmapOutput(1,REGULAR8x13," = %6.2f",degres) ;
  glColor3fv(couleurJaune());
  placeFontCursor(pl[0],pl[1],pl[2]) ;
  setAlignement(CENTER);
  deplacementCursor(0,-40,0) ;
  simpleBitmapOutput(1,REGULAR8x13,"LUMIERE") ; 
  deplacementCursor(0,-20,0) ;
  simpleBitmapOutput(1,REGULAR8x13,"PONCTUELLE") ; 
  glColor3fv(couleurMagenta());
  placeFontCursor(2*pi[0],2*pi[1],2*pi[2]) ;
  deplacementCursor(15,5,0) ;
  simpleBitmapOutput(1,REGULAR8x13,"N") ; 
  deplacementCursor(15,0,0) ;
  simpleBitmapOutput(1,DESSIN,"TF") ;
  glColor3fv(couleurRouge());
  placeFontCursor(pi[0]+l[0],pi[1]+l[1],pi[2]+l[2]) ;
  deplacementCursor(5,-15,0) ;
  simpleBitmapOutput(1,REGULAR8x13,"L") ; 
  deplacementCursor(5,-20,0) ;
  simpleBitmapOutput(1,DESSIN,"TF") ;
  glColor3fv(couleurVert());
  placeFontCursor(pi[0]+r[0],pi[1]+r[1],pi[2]+r[2]) ;
  deplacementCursor(5,-15,0) ;
  simpleBitmapOutput(1,REGULAR8x13,"R") ; 
  deplacementCursor(5,-20,0) ;
  simpleBitmapOutput(1,DESSIN,"TF") ;
  setAlignement(LEFT);
  glEnable(GL_LIGHTING);
  if ( scal > 0.0F ) {
    glPushMatrix();
    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurVert(0.5F));
    glTranslatef(pi[0]+fact*r[0],pi[1]+fact*r[1],pi[2]+fact*r[2]);
    coneOriente(-r[0]*fact,-r[1]*fact,-r[2]*fact,fact,1.0F/shininess*50);
    glPopMatrix(); }
  glDisable(GL_LIGHTING);
  glPopMatrix();
  glFlush();
  glutPostWindowRedisplay(f2);
  glutSwapBuffers();
}

void key2(unsigned char key,int x,int y) {
  switch ( key ) {
    case 45   : shininess *= 1.02F;
                glutPostWindowRedisplay(f1);
                break
    case 43   : shininess /= 1.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'a'  : pl[0] += 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'A'  : pl[0] -= 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'q'  : pl[1] += 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'Q'  : pl[1] -= 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'w'  : pl[2] += 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case 'W'  : pl[2] -= 0.02F;
                glutPostWindowRedisplay(f1);
                break
    case '4'  : { float px = pi[0] - 0.02F;
                  if ( px*px+pi[2]*pi[2] < 1.0F )
                    pi[0] = px ; 
                  glutPostWindowRedisplay(f1); }
                break
    case '6'  : { float px = pi[0] + 0.02F;
                  if ( px*px+pi[2]*pi[2] < 1.0F )
                    pi[0] = px ;
                  glutPostWindowRedisplay(f1); }
                break
    case '2'  : { float pz = pi[2] - 0.02F;
                  if ( pz*pz+pi[0]*pi[0] < 1.0F )
                    pi[2] = pz ;
                  glutPostWindowRedisplay(f1); }
                break
    case '8'  : { float pz = pi[2] + 0.02F;
                  if ( pz*pz+pi[0]*pi[0] < 1.0F )
                    pi[2] = pz ;
                  glutPostWindowRedisplay(f1); }
                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);
}

void display2(void) {
  glClearColor(0.0F,0.0F,0.0F,1.0F) ;
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  float pos = 1.0F;
  glColor4fv(couleurJaune());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"LUMIERE      :  %6.3f %6.3f %6.3f",pl[0],pl[1],pl[2]) ;
  pos += 1.0F;
  glColor4fv(couleurBleu());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"INTERSECTION :  %6.3f %6.3f %6.3f",pi[0],pi[1],pi[2]) ;
  pos += 1.0F;
  glColor4fv(couleurMagenta());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"NORMALE      :  %6.3f %6.3f %6.3f",n[0],n[1],n[2]) ;
  pos += 1.0F;
  glColor4fv(couleurRouge());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"L            :  %6.3f %6.3f %6.3f",l[0],l[1],l[2]) ;
  pos += 1.0F;
  glColor4fv(couleurVert());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"REFLEXION    :  %6.3f %6.3f %6.3f",r[0],r[1],r[2]) ;
  pos += 1.0F;
  glColor4fv(couleurVert());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"THETA        : %7.3f",degres) ;
  pos += 1.0F;
  glColor4fv(couleurVert());
  placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
  simpleBitmapOutput(1,REGULAR8x13,"SHININESS    : %7.3f",shininess) ;
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

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();
}

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
  glutInitWindowPosition(10,10);
  glutInitWindowSize(400,270);
  f1 = glutCreateWindow("La reflexion speculaire");
  myinit();
  creationMenuBasique();
  setParametresOrthoBasique(-1.1F,1.1F,-1.1F,1.1F,-50.0,50.0);
  setManipulateurDistance(1.0F);
  setManipulateurClavierAngle(15.0F,-50.0F,0.0F) ;
  glutReshapeFunc(reshapeOrthoBasique);
  glutKeyboardFunc(key);
  glutSpecialFunc(specialBasique);
  glutMotionFunc(motionBasique);
  glutMouseFunc(sourisBasique);
  glutDisplayFunc(display);
  glutInitWindowSize(370,150);
  glutInitWindowPosition(60,360);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  f2 = glutCreateWindow("Valeurs");
  creationMenuBasique();
  glutDisplayFunc(display2);
  glutReshapeFunc(reshape2);
  glutKeyboardFunc(key2);
  glutSpecialFunc(special);
  glutMainLoop();
  return(0);
}

/* ************************************************** */

Les modules utilitaires : Modules.zip

RETOUR