Le source : TD-DiffusionLumierePonctuelle.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Fevrier 2002 */
/* 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 ; } Position ;
typedef struct Direction {
float dx ;
float dy ;
float dz ; } Direction ;
typedef struct Couleur {
float r ;
float v ;
float b ;
float a ; } Couleur ;
typedef struct Energie {
float er ;
float ev ;
float eb ; } Energie ;
typedef struct LumierePonctuelle {
Position p;
Couleur c;
float e; } LumierePonctuelle ;
typedef struct Materiau {
Couleur kd; } Materiau ;
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;
float produitScalaire(Direction *v1,Direction *v2) {
return(v1->dx*v2->dx+v1->dy*v2->dy+v1->dz*v2->dz);
}
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;
}
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 lumiereDiffusee(Position *p,Direction *n,Materiau *m,LumierePonctuelle *lp,Energie *e) {
Direction d;
vecteur(p,&lp->p,&d);
float l = longueur(&d);
normalize(&d);
float scal = produitScalaire(&d,n);
if ( scal < 0.0F )
scal = 0.0F;
e->er = lp->e*lp->c.r*m->kd.r*scal/l/l;
e->ev = lp->e*lp->c.v*m->kd.v*scal/l/l;
e->eb = lp->e*lp->c.b*m->kd.b*scal/l/l;
}
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 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;
}
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);
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);
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 '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);
}