/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Avril 2001 */ /* Calculs sur l'energie diffusee */ /* par une surface plane triangulaire */ #include #include #include #include #include #include "ModuleCouleurs.h" #include "ModuleManipulateur.h" #include "ModuleReshape.h" #include "ModuleFont.h" #include "ModuleFleche.h" #include "ModuleMenus.h" typedef struct coord_3D { float x ; float y ; float z ; } coord_3D ; typedef struct couleur { float r ; float v ; float b ; } couleur ; typedef struct pointLight { coord_3D pos ; couleur coul ; float energie ; } pointLight ; typedef struct dir_3D { float dx ; float dy ; float dz ; } dir_3D ; typedef struct dirLight { dir_3D dir ; couleur coul ; float energie ; } dirLight ; typedef struct materiau { couleur diffusion ; /* couleur reflexion ; */ /* couleur transmission ; */ /* couleur emission ; */ } materiau ; typedef struct facette { struct coord_3D pa ; struct coord_3D pb ; struct coord_3D pc ; } facette ; typedef struct energie { float er ; float ev ; float eb ; } energie ; enum { MATERIEL = 0, LUMIERE }; static int question = 0; static int t = 3; static float sensibilite = 1.0F; static int modif = MATERIEL; static pointLight pl = { {-1.0F,2.0F,2.0F}, {1.0F,0.5F,0.3F}, 2.5F } ; static dirLight dl = { {0.5F,-0.5F,-1.0F}, {1.0F,0.5F,0.5F}, 2.5F } ; static materiau m = { {0.5F,0.5F,1.0F}, /* {0.0F,0.0F,0.0F}, */ /* {0.0F,0.0F,0.0F}, */ /* {0.0F,0.0F,0.0F} */ } ; static facette f = { {-1.2F,-1.5F,-0.5F}, { 1.1F,-0.1F, 1.4F}, { -0.2F, 1.1F, 0.4F} }; float distance(coord_3D *p1, coord_3D *p2) { double x = p1->x - p2->x ; double y = p1->y - p2->y ; double z = p1->z - p2->z ; double d2 = x*x + y*y + z*z ; return((float) pow(d2,0.5)) ; } void calculVecteurNorme(coord_3D *pi, coord_3D *pf, dir_3D *n) { double x = pf->x - pi->x ; double y = pf->y - pi->y ; double z = pf->z - pi->z ; double d2 = distance(pi,pf) ; n->dx =(float) (x / d2) ; n->dy =(float) (y / d2) ; n->dz =(float) (z / d2) ; } void normalise(dir_3D *n) { float d2 = n->dx*n->dx + n->dy*n->dy + n->dz*n->dz ; d2 =(float) pow((double) d2,0.5) ; n->dx /= d2 ; n->dy /= d2 ; n->dz /= d2 ; } void calculVecteur(coord_3D *pi, coord_3D *pf, dir_3D *n) { n->dx = pf->x - pi->x ; n->dy = pf->y - pi->y ; n->dz = pf->z - pi->z ; } float produitScalaire(dir_3D *d1, dir_3D *d2) { return(d1->dx*d2->dx + d1->dy*d2->dy + d1->dz*d2->dz) ; } void produitVectoriel(dir_3D *v1,dir_3D *v2,dir_3D *n) { n->dx = v1->dy*v2->dz - v1->dz*v2->dy; n->dy = v1->dz*v2->dx - v1->dx*v2->dz; n->dz = v1->dx*v2->dy - v1->dy*v2->dx; } void calculNormaleFacette(facette *f,dir_3D *n) { dir_3D v1; dir_3D v2; calculVecteur(&f->pa,&f->pb,&v1) ; calculVecteur(&f->pa,&f->pc,&v2) ; produitVectoriel(&v1,&v2,n); normalise(n); } void calculEnergieRecueAvecAttenuation(coord_3D *p, pointLight *l, energie *e) { float d = distance(p,&l->pos) ; float atten = 5.0F / d / d ; e->er = atten * l->energie * l->coul.r ; e->ev = atten * l->energie * l->coul.v ; e->eb = atten * l->energie * l->coul.b ; } void calculEnergieRecueSansAttenuation(coord_3D *p, pointLight *l, energie *e) { e->er = l->energie * l->coul.r ; e->ev = l->energie * l->coul.v ; e->eb = l->energie * l->coul.b ; } void calculEnergieRecue(coord_3D *p, dirLight *l, energie *e) { e->er = l->energie * l->coul.r ; e->ev = l->energie * l->coul.v ; e->eb = l->energie * l->coul.b ; } void calculEnergieDiffusee(coord_3D *p, facette *f, materiau *m, pointLight *l, energie *e, int atten) { energie recu ; switch (atten) { case 0 : calculEnergieRecueSansAttenuation(p,l,&recu) ; break; case 1 : calculEnergieRecueAvecAttenuation(p,l,&recu) ; break; } dir_3D li ; calculVecteurNorme(&l->pos,p,&li) ; dir_3D n ; calculNormaleFacette(f,&n); float scal = -produitScalaire(&li,&n) ; if ( scal < 0.0F ) scal = 0.0F ; e->er = recu.er * scal * m->diffusion.r ; e->ev = recu.ev * scal * m->diffusion.v ; e->eb = recu.eb * scal * m->diffusion.b ; } void calculEnergieDiffusee(facette *f, materiau *m, dirLight *l, energie *e) { dir_3D n ; calculNormaleFacette(f,&n); energie recu ; calculEnergieRecue(&f->pa,l,&recu) ; float scal = -produitScalaire(&l->dir,&n) ; if ( scal < 0.0F ) scal = 0.0F ; e->er = recu.er * scal * m->diffusion.r ; e->ev = recu.ev * scal * m->diffusion.v ; e->eb = recu.eb * scal * m->diffusion.b ; } void milieu(coord_3D *p1,coord_3D *p2,coord_3D *p) { p->x = (p1->x+p2->x)/2.0F; p->y = (p1->y+p2->y)/2.0F; p->z = (p1->z+p2->z)/2.0F; } void traceFacetteSousDirectionnalLight(facette *f, materiau *m, dirLight *l) { energie ed ; calculEnergieDiffusee(f,m,l,&ed) ; glColor4f(ed.er*sensibilite, ed.ev*sensibilite, ed.eb*sensibilite, 1.0F); glBegin(GL_POLYGON); glVertex3f(f->pa.x,f->pa.y,f->pa.z); glVertex3f(f->pb.x,f->pb.y,f->pb.z); glVertex3f(f->pc.x,f->pc.y,f->pc.z); glEnd(); } void traceFacetteSousPointLight(facette *f, int t, materiau *m, pointLight *l, int atten) { if ( t == 0 ) { energie eda; energie edb; energie edc; calculEnergieDiffusee(&f->pa,f,m,l,&eda,atten) ; calculEnergieDiffusee(&f->pb,f,m,l,&edb,atten) ; calculEnergieDiffusee(&f->pc,f,m,l,&edc,atten) ; glBegin(GL_POLYGON); glColor4f(eda.er*sensibilite, eda.ev*sensibilite, eda.eb*sensibilite, 1.0F); glVertex3f(f->pa.x,f->pa.y,f->pa.z); glColor4f(edb.er*sensibilite, edb.ev*sensibilite, edb.eb*sensibilite, 1.0F); glVertex3f(f->pb.x,f->pb.y,f->pb.z); glColor4f(edc.er*sensibilite, edc.ev*sensibilite, edc.eb*sensibilite, 1.0F); glVertex3f(f->pc.x,f->pc.y,f->pc.z); glEnd(); } else { coord_3D pab; coord_3D pac; coord_3D pbc; milieu(&f->pa,&f->pb,&pab); milieu(&f->pa,&f->pc,&pac); milieu(&f->pb,&f->pc,&pbc); facette ff; ff.pa = f->pa; ff.pb = pab; ff.pc = pac; traceFacetteSousPointLight(&ff,t-1,m,l,atten); ff.pb = f->pb; ff.pa = pab; ff.pc = pbc; traceFacetteSousPointLight(&ff,t-1,m,l,atten); ff.pc = f->pc; ff.pa = pac; ff.pb = pbc; traceFacetteSousPointLight(&ff,t-1,m,l,atten); ff.pc = pab; ff.pb = pac; ff.pa = pbc; traceFacetteSousPointLight(&ff,t-1,m,l,atten); } } void centre(facette *f,coord_3D *p) { p->x =(f->pa.x+f->pb.x+f->pc.x)/3.0F; p->y =(f->pa.y+f->pb.y+f->pc.y)/3.0F; p->z =(f->pa.z+f->pb.z+f->pc.z)/3.0F; } void questionLumiereDirectionnelle() { coord_3D pcentre; centre(&f,&pcentre); glPushMatrix(); manipulateurSouris(); manipulateurClavier(); glEnable(GL_DEPTH_TEST); glColor4fv(couleurBlanc()); traceFacetteSousDirectionnalLight(&f,&m,&dl); dir_3D nm ; calculNormaleFacette(&f,&nm); glPushMatrix(); glColor4fv(couleurRouge()); glTranslatef(pcentre.x,pcentre.y,pcentre.z); flecheEnVolume(nm.dx,nm.dy,nm.dz,0.05F,0.2F,0.015F) ; glPopMatrix(); glPushMatrix(); glTranslatef(-1.0F,1.0F,1.0F); glColor3f(pl.coul.r,pl.coul.v,pl.coul.b); flecheEnVolume(dl.dir.dx,dl.dir.dy,dl.dir.dz,0.05F,0.2F,0.015F) ; glPopMatrix(); glPopMatrix(); energie e ; energie ed ; glDisable(GL_DEPTH_TEST); float xmin = getXmin(); float ymax = getYmax(); float tpix = getTaillePixel(); setAntialiased(1); setBold(1); setEcartementCaracteres(15.0F); glColor4fv(couleurRouge()); strokeOutput(xmin,-ymax+70*tpix,0.65F,"Dir light"); strokeOutput(xmin,-ymax+50*tpix,0.65F,"Couleur emise : %f %f %f\n",pl.coul.r,pl.coul.v,pl.coul.b); strokeOutput(xmin,-ymax+30*tpix,0.65F,"Energie emise : %f\n",pl.energie); strokeOutput(xmin,-ymax+10*tpix,0.65F,"Direction : %f %f %f\n",pl.pos.x,pl.pos.y,pl.pos.z); strokeOutput(xmin,ymax-16*tpix,0.65F,"Materiau : %f %f %f\n",m.diffusion.r,m.diffusion.v,m.diffusion.b) ; calculEnergieRecue(&pcentre,&dl,&e) ; strokeOutput(xmin,ymax-36*tpix,0.65F,"Energie recue : %f %f %f\n",e.er,e.ev,e.eb) ; calculEnergieDiffusee(&f,&m,&dl,&ed) ; strokeOutput(xmin,ymax-56*tpix,0.65F,"Energie diffusee : %f %f %f\n",ed.er,ed.ev,ed.eb) ; setAntialiased(0); setBold(0); setEcartementCaracteres(0.0F); } void questionLumierePonctuelle() { coord_3D pcentre; centre(&f,&pcentre); energie e ; energie ed ; glPushMatrix(); manipulateurSouris(); manipulateurClavier(); glEnable(GL_DEPTH_TEST); traceFacetteSousPointLight(&f,t,&m,&pl,0); glPushMatrix(); glTranslatef(pl.pos.x,pl.pos.y,pl.pos.z); glColor3f(pl.coul.r,pl.coul.v,pl.coul.b); glutSolidSphere(0.05F,20,20); glPopMatrix(); dir_3D nm ; calculNormaleFacette(&f,&nm); glPushMatrix(); glColor4fv(couleurRouge()); glTranslatef(pcentre.x,pcentre.y,pcentre.z); flecheEnVolume(nm.dx,nm.dy,nm.dz,0.05F,0.2F,0.015F) ; glPopMatrix(); glPopMatrix(); glDisable(GL_DEPTH_TEST); float xmin = getXmin(); float ymax = getYmax(); float tpix = getTaillePixel(); setAntialiased(1); setBold(1); setEcartementCaracteres(15.0F); glColor4fv(couleurBlanc()); strokeOutput(xmin,-ymax+70*tpix,0.65F,"Point light"); strokeOutput(xmin,-ymax+50*tpix,0.65F,"Couleur emise : %f %f %f\n",pl.coul.r,pl.coul.v,pl.coul.b); strokeOutput(xmin,-ymax+30*tpix,0.65F,"Energie emise : %f\n",pl.energie); strokeOutput(xmin,-ymax+10*tpix,0.65F,"Position : %f %f %f\n",pl.pos.x,pl.pos.y,pl.pos.z); strokeOutput(xmin,ymax-16*tpix,0.65F,"Materiau : %f %f %f\n",m.diffusion.r,m.diffusion.v,m.diffusion.b) ; calculEnergieRecueSansAttenuation(&pcentre,&pl,&e) ; strokeOutput(xmin,ymax-36*tpix,0.65F,"Energie recue : %f %f %f\n",e.er,e.ev,e.eb) ; calculEnergieDiffusee(&pcentre,&f,&m,&pl,&ed,0) ; strokeOutput(xmin,ymax-56*tpix,0.65F,"Energie diffusee : %f %f %f\n",ed.er,ed.ev,ed.eb) ; setAntialiased(0); setBold(0); setEcartementCaracteres(0.0F); } void questionLumierePonctuelleAttenuation() { coord_3D pcentre; centre(&f,&pcentre); energie e ; energie ed ; glPushMatrix(); manipulateurSouris(); manipulateurClavier(); glEnable(GL_DEPTH_TEST); glColor4fv(couleurBlanc()); traceFacetteSousPointLight(&f,t,&m,&pl,1); glPushMatrix(); glTranslatef(pl.pos.x,pl.pos.y,pl.pos.z); glColor3f(pl.coul.r,pl.coul.v,pl.coul.b); glutSolidSphere(0.05F,20,20); glPopMatrix(); dir_3D nm ; calculNormaleFacette(&f,&nm); glPushMatrix(); glColor4fv(couleurRouge()); glTranslatef(pcentre.x,pcentre.y,pcentre.z); flecheEnVolume(nm.dx,nm.dy,nm.dz,0.05F,0.2F,0.015F) ; glPopMatrix(); glPopMatrix(); glDisable(GL_DEPTH_TEST); float xmin = getXmin(); float ymax = getYmax(); float tpix = getTaillePixel(); setAntialiased(1); setBold(1); setEcartementCaracteres(15.0F); glColor4fv(couleurBlanc()); strokeOutput(xmin,-ymax+70*tpix,0.65F,"Point light"); strokeOutput(xmin,-ymax+50*tpix,0.65F,"Couleur emise : %f %f %f\n",pl.coul.r,pl.coul.v,pl.coul.b); strokeOutput(xmin,-ymax+30*tpix,0.65F,"Energie emise : %f\n",pl.energie); strokeOutput(xmin,-ymax+10*tpix,0.65F,"Position : %f %f %f\n",pl.pos.x,pl.pos.y,pl.pos.z); strokeOutput(xmin,ymax-16*tpix,0.65F,"Materiau : %f %f %f\n",m.diffusion.r,m.diffusion.v,m.diffusion.b) ; calculEnergieRecueAvecAttenuation(&pcentre,&pl,&e) ; strokeOutput(xmin,ymax-36*tpix,0.65F,"Energie recue : %f %f %f\n",e.er,e.ev,e.eb) ; calculEnergieDiffusee(&pcentre,&f,&m,&pl,&ed,1) ; strokeOutput(xmin,ymax-56*tpix,0.65F,"Energie diffusee : %f %f %f\n",ed.er,ed.ev,ed.eb) ; setAntialiased(0); setBold(0); setEcartementCaracteres(0.0F); } void display() { glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glPushMatrix(); switch ( question ) { case 0 : questionLumierePonctuelle(); break; case 1 : questionLumierePonctuelleAttenuation(); break; case 2 : questionLumiereDirectionnelle(); break;} glPopMatrix(); glutSwapBuffers(); } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else switch ( key ) { case '1' : if ( question == 2 ) dl.dir.dx -= 0.05F; else pl.pos.x -= 0.05F; break; case '7' : if ( question == 2 ) dl.dir.dx += 0.05F; else pl.pos.x += 0.05F; break; case '2' : if ( question == 2 ) dl.dir.dy -= 0.05F; else pl.pos.y -= 0.05F; break; case '8' : if ( question == 2 ) dl.dir.dy += 0.05F; else pl.pos.y += 0.05F; break; case '3' : if ( question == 2 ) dl.dir.dz -= 0.05F; else pl.pos.z -= 0.05F; break; case '9' : if ( question == 2 ) dl.dir.dz += 0.05F; else pl.pos.z += 0.05F; break; case 's' : sensibilite /= 1.02F; break; case 'S' : sensibilite *= 1.02F; break; case 'e' : if ( question == 2 ) dl.energie /= 1.02F; else pl.energie /= 1.02F; break; case 'E' : if ( question == 2 ) dl.energie *= 1.02F; else pl.energie *= 1.02F; break; case 'R' : switch ( modif ) { case MATERIEL : m.diffusion.r += 0.01F; if ( m.diffusion.r > 1.0F ) m.diffusion.r = 1.0F ; break; case LUMIERE : pl.coul.r += 0.01F; if ( pl.coul.r > 1.0F ) pl.coul.r = 1.0F ; break; } break; case 'r' : switch ( modif ) { case MATERIEL : m.diffusion.r -= 0.01F; if ( m.diffusion.r < 0.0F ) m.diffusion.r = 0.0F ; break; case LUMIERE : pl.coul.r -= 0.01F; if ( pl.coul.r < 0.0F ) pl.coul.r = 0.0F ; break; } break; case 'V' : switch ( modif ) { case MATERIEL : m.diffusion.v += 0.01F; if ( m.diffusion.v > 1.0F ) m.diffusion.v = 1.0F ; break; case LUMIERE : pl.coul.v += 0.01F; if ( pl.coul.v > 1.0F ) pl.coul.v = 1.0F ; break; } break; case 'v' : switch ( modif ) { case MATERIEL : m.diffusion.v -= 0.01F; if ( m.diffusion.v < 0.0F ) m.diffusion.v = 0.0F ; break; case LUMIERE : pl.coul.v -= 0.01F; if ( pl.coul.v < 0.0F ) pl.coul.v = 0.0F ; break; } break; case 'B' : switch ( modif ) { case MATERIEL : m.diffusion.b += 0.01F; if ( m.diffusion.b > 1.0F ) m.diffusion.b = 1.0F ; break; case LUMIERE : pl.coul.b += 0.01F; if ( pl.coul.b > 1.0F ) pl.coul.b = 1.0F ; break; } break; case 'b' : switch ( modif ) { case MATERIEL : m.diffusion.b -= 0.01F; if ( m.diffusion.b < 0.0F ) m.diffusion.b = 0.0F ; break; case LUMIERE : pl.coul.b -= 0.01F; if ( pl.coul.b < 0.0F ) pl.coul.b = 0.0F ; break; } break; case 'd' : t--; if ( t < 0 ) t = 0 ; break; case 'D' : t++; if ( t > 6 ) t = 6; break; case 32 : modif = (modif+1)%2; break; case 0x0D : question = (question+1)%3; break; } glutPostRedisplay(); } void special(int k,int x,int y) { if ( specialManipulateur(k,x,y) ) glutPostRedisplay(); else switch (k) { case GLUT_KEY_F1 : modif = MATERIEL ; glutPostRedisplay(); break; case GLUT_KEY_F2 : modif = LUMIERE ; glutPostRedisplay(); break; } } void myInit() { glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glShadeModel(GL_SMOOTH); } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitWindowSize(400,400); glutInitWindowPosition(50,50); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutCreateWindow("Calcul diffusions"); myInit(); creationMenuBasique(); setParametresOrthoBasique(-6.0,6.0,-6.0,6.0,-500.0,500.0); setManipulateurDistance(1.0F); glutReshapeFunc(reshapeOrthoBasique); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutKeyboardFunc(key); glutSpecialFunc(special); glutDisplayFunc(display); glutMainLoop(); return(0); }