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);
}
/* ************************************************** */