/* Calcul de diffusion Lambertienne */ /* sous l'éclairage de lumieres directionnelles */ /* et ponctuelles */ /* */ /* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2012 */ #include #include #include #include #include #include #include "Couleur.h" #include "Energie.h" #include "LumierePonctuelle.h" #include "LumiereDirectionnelle.h" #include "Position3D.h" #include "Direction3D.h" #include "Rotation3D.h" /* Variables et constantes globales */ static const float blanc[] = { 1.0F,1.0F,1.0F,1.0F }; static const float noir[] = { 0.0F,0.0F,0.0F,1.0F }; static float rx = 0.0F; static float ry = 0.0F; static float rz = 0.0F; static double dist = 5.0; static int l = 1; static bool attenuationLp = false; static bool onLp = true; static bool onLd = true; static double iLp = 1.2; static double iLd = 1.5; static float cLp[] = { 1.0F,0.5F,1.0F,1.0F }; static float cLd[] = { 1.0F,1.0F,0.5F,1.0F }; static float couleur[] = { 0.3F,0.6F,0.9F,1.0F }; static Couleur *c; static LumierePonctuelle *lp; static LumiereDirectionnelle *ld; static int w1; static int w2; static void postRedisplay(void) { glutPostWindowRedisplay(w1); glutPostWindowRedisplay(w2); } /* Fonction d'affectation de leurs valeurs */ /* aux lumieres */ static void ajusteMaterielEtLumiere(void) { c->r = couleur[0]; c->v = couleur[1]; c->b = couleur[2]; TransformationGeometrique3D *m = new TransformationGeometrique3D(); Rotation3D *rtx = new Rotation3D(rx,1.0,0.0,0.0); Rotation3D *rty = new Rotation3D(ry,0.0,1.0,0.0); Rotation3D *rtz = new Rotation3D(rz,0.0,0.0,1.0); m->compose(rtz); m->compose(rty); m->compose(rtx); delete(rtx); delete(rty); delete(rtz); if ( l ) { ld->on = onLd; ld->c->r = cLd[0]; ld->c->v = cLd[1]; ld->c->b = cLd[2]; ld->intensite = iLd; Direction3D *d = new Direction3D(dist,dist,dist); m->transforme(d); ld->d->c[0] = d->c[0]; ld->d->c[1] = d->c[1]; ld->d->c[2] = d->c[2]; ld->d->c[3] = d->c[3]; delete(d); } else { lp->on = onLp; lp->c->r = cLp[0]; lp->c->v = cLp[1]; lp->c->b = cLp[2]; lp->intensite = iLp; Position3D *p = new Position3D(-dist,dist,dist); m->transforme(p); lp->p->c[0] = p->c[0]; lp->p->c[1] = p->c[1]; lp->p->c[2] = p->c[2]; lp->p->c[3] = p->c[3]; lp->attenuation = attenuationLp; delete(p); } delete(m); printf("Coefficients diffusion du materiel: "); c->print(); printf("\n"); if ( l ) { printf("Ld: "); ld->print(); printf("\n"); } else { printf("Lp: "); lp->print(); printf("\n"); } } /* Fonction executee lors de la frappe */ /* d'une touche du clavier */ static void diminueCoefficient(float *c) { *c -= 0.01F; if ( *c < 0.0F ) *c = 0.0F; } static void augmenteCoefficient(float *c) { *c += 0.01F; if ( *c > 1.0F ) *c = 1.0F; } static void keyboard(unsigned char key,int x,int y) { switch ( key ) { case 0x20 : l = (l+1)%2; ajusteMaterielEtLumiere(); postRedisplay(); break; case 'o' : if ( l ) { onLd = !onLd; } else { onLp = !onLp; } ajusteMaterielEtLumiere(); postRedisplay(); break; case 'a' : attenuationLp = !attenuationLp; ajusteMaterielEtLumiere(); postRedisplay(); break; case 'D' : dist += 0.01; ajusteMaterielEtLumiere(); postRedisplay(); break; case 'd' : dist -= 0.01; ajusteMaterielEtLumiere(); postRedisplay(); break; case 'i' : if ( l ) { iLd -= 0.01; if ( iLd < 0.0 ) iLd = 0.0; } else { iLp -= 0.01; if ( iLp < 0.0 ) iLp = 0.0; } ajusteMaterielEtLumiere(); postRedisplay(); break; case 'I' : if ( l ) { iLd += 0.01; } else { iLp += 0.01; } ajusteMaterielEtLumiere(); postRedisplay(); break; case 'j' : if ( l ) { iLd -= 0.1; if ( iLd < 0.0 ) iLd = 0.0; } else { iLp -= 0.1; if ( iLp < 0.0 ) iLp = 0.0; } ajusteMaterielEtLumiere(); postRedisplay(); break; case 'J' : if ( l ) { iLd += 0.1; } else { iLp += 0.1; } ajusteMaterielEtLumiere(); postRedisplay(); break; case 0x1B : exit(0); break; } } /* Fonction executee lors de l'appui */ /* d'une touche de curseur ou d'une touche */ /* page up ou page down */ static void gestionDiminution(int modifier,float *c,float *cLd,float *cLp,float *a) { switch ( glutGetModifiers() ) { case GLUT_ACTIVE_CTRL : diminueCoefficient(c); break; case GLUT_ACTIVE_SHIFT : if ( l ) diminueCoefficient(cLd); else diminueCoefficient(cLp); break; default : (*a)++; break; } } static void gestionAugmentation(int modifier,float *c,float *cLd,float *cLp,float *a) { switch ( glutGetModifiers() ) { case GLUT_ACTIVE_CTRL : augmenteCoefficient(c); break; case GLUT_ACTIVE_SHIFT : if ( l ) augmenteCoefficient(cLd); else augmenteCoefficient(cLp); break; default : (*a)--; break; } } static void special(int key,int x,int y) { switch(key) { case GLUT_KEY_UP : gestionAugmentation(glutGetModifiers(),&couleur[0],&cLd[0],&cLp[0],&rx); ajusteMaterielEtLumiere(); postRedisplay(); break; case GLUT_KEY_DOWN : gestionDiminution(glutGetModifiers(),&couleur[0],&cLd[0],&cLp[0],&rx); ajusteMaterielEtLumiere(); postRedisplay(); break; case GLUT_KEY_LEFT : gestionAugmentation(glutGetModifiers(),&couleur[1],&cLd[1],&cLp[1],&ry); ajusteMaterielEtLumiere(); postRedisplay(); break; case GLUT_KEY_RIGHT : gestionDiminution(glutGetModifiers(),&couleur[1],&cLd[1],&cLp[1],&ry); ajusteMaterielEtLumiere(); postRedisplay(); break; case GLUT_KEY_PAGE_UP : gestionAugmentation(glutGetModifiers(),&couleur[2],&cLd[2],&cLp[2],&rz); ajusteMaterielEtLumiere(); postRedisplay(); break; case GLUT_KEY_PAGE_DOWN : gestionDiminution(glutGetModifiers(),&couleur[2],&cLd[2],&cLp[2],&rz); ajusteMaterielEtLumiere(); postRedisplay(); break; } } /* Fonction d'initialisation des parametres */ /* OpenGL ne changeant pas au cours de la vie */ /* du programme */ static void init1(void) { glEnable(GL_LIGHTING); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_AUTO_NORMAL); // glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); } static void init2(void) { glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); // glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); } #ifndef M_PI #define M_PI 3.14159F #endif void solidSphere(double r,int nl,int ns,Couleur *couleur,Lumiere *lumiere) { Energie *e = new Energie(); Position3D *p = new Position3D(); Direction3D *n = new Direction3D(); for ( int i = 0 ; i < ns ; i++ ) { float a1 = -M_PI/2.0F + i*M_PI/ns ; float a2 = a1 + M_PI/ns ; 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 <= nl ; j++ ) { float a = j*2*M_PI/nl; float x1 = cs1*sin(a); float y1 = cs1*cos(a); float x2 = cs2*sin(a); float y2 = cs2*cos(a); p->c[0] = r*x1; p->c[1] = r*y1; p->c[2] = r*sn1; n->c[0] = x1; n->c[1] = y1; n->c[2] = sn1; lumiere->energieDiffusee(e,p,n,couleur); glColor3f(e->r,e->v,e->b); glVertex3d(p->c[0],p->c[1],p->c[2]); p->c[0] = r*x2; p->c[1] = r*y2; p->c[2] = r*sn2; n->c[0] = x2; n->c[1] = y2; n->c[2] = sn2; lumiere->energieDiffusee(e,p,n,couleur); glColor3f(e->r,e->v,e->b); glVertex3d(p->c[0],p->c[1],p->c[2]); } glEnd(); } delete(n); delete(p); delete(e); } static void scene2(void) { glPushMatrix(); if ( l ) { solidSphere(4.0,24,24,c,ld); } else { solidSphere(4.0,24,24,c,lp); } glPopMatrix(); } static void clean(void) { delete(c); delete(ld); delete(lp); } /* Scene dessinee */ static void scene1(void) { const GLfloat mat_shininess[] = { 50.0 }; float ldif[4]; float lpos[4]; if ( l ) { if ( ld->on ) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0); ldif[0] = ld->intensite*ld->c->r; ldif[1] = ld->intensite*ld->c->v; ldif[2] = ld->intensite*ld->c->b; ldif[3] = 1.0F; for ( int i = 0 ; i < 4 ; i++ ) lpos[i] = ld->d->c[i]; } else { if ( lp->on ) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0); ldif[0] = lp->intensite*lp->c->r; ldif[1] = lp->intensite*lp->c->v; ldif[2] = lp->intensite*lp->c->b; ldif[3] = 1.0F; for ( int i = 0 ; i < 4 ; i++ ) lpos[i] = lp->p->c[i]; } glLightfv(GL_LIGHT0,GL_DIFFUSE,ldif); glLightfv(GL_LIGHT0,GL_POSITION,lpos); if ( attenuationLp ) { glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,1.0F); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,0.0F); } else { glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0F); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0F); } glMaterialfv(GL_FRONT,GL_DIFFUSE,couleur); glMaterialfv(GL_FRONT,GL_SPECULAR,noir); glMaterialfv(GL_FRONT,GL_AMBIENT,noir); glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); glPushMatrix(); glutSolidSphere(4.0,24,24); glPopMatrix(); } /* Fonction executee lors d'un rafraichissement */ /* de la fenetre de dessin */ static void display1(void) { glClearColor(0.5F,0.5F,0.5F,1.0F); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); scene1(); glPopMatrix(); glFlush(); glutSwapBuffers(); int error = glGetError(); if ( error != GL_NO_ERROR ) printf("Erreur OpenGL: %d\n",error); } /* Fonction executee lors d'un rafraichissement */ /* de la fenetre de dessin */ static void display2(void) { glClearColor(0.5F,0.5F,0.5F,1.0F); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); scene2(); glPopMatrix(); glFlush(); glutSwapBuffers(); int error = glGetError(); if ( error != GL_NO_ERROR ) printf("Erreur OpenGL: %d\n",error); } /* Fonction executee lors d'un changement */ /* de la taille de la fenetre OpenGL */ /* -> Ajustement de la camera de visualisation */ static void reshape(int x,int y) { glViewport(0,0,x,y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if ( x > y ) glOrtho(-6.0*(double) x/y,6.0*(double) x/y,-6.0,6.0,-6.0,6.0); else glOrtho(-6.0,6.0,-6.0*(double) y/x,6.0*(double) y/x,-6.0,6.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Fonction principale */ void select(int selection) { switch (selection) { case 0 : case 1 : l = selection; ajusteMaterielEtLumiere(); postRedisplay(); break; case -1 : exit(0); break; } glutPostRedisplay(); } static void makeMenu(void) { int menu = glutCreateMenu(select); glutAddMenuEntry("Lumiere ponctuelle",0); glutAddMenuEntry("Lumiere directionnelle",1); glutAddMenuEntry("Quitter",-1); glutAttachMenu(GLUT_RIGHT_BUTTON); } int main(int argc,char **argv) { atexit(clean); c = new Couleur(); lp = new LumierePonctuelle(); ld = new LumiereDirectionnelle(); ajusteMaterielEtLumiere(); glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(300,300); glutInitWindowPosition(50,50); w1 = glutCreateWindow("Eclairages OpenGL"); makeMenu(); init1(); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutReshapeFunc(reshape); glutDisplayFunc(display1); glutInitWindowSize(300,300); glutInitWindowPosition(50,400); w2 = glutCreateWindow("Eclairages \"maison\""); makeMenu(); init2(); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutReshapeFunc(reshape); glutDisplayFunc(display2); glutMainLoop(); return(0); }