/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Octobre 2004 */ /* Evaluation de la luniere diffusee */ /* sur une surface eclairee par une */ /* lumiere ponctuelle */ #include #include #include #include #include #include #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); }