Eclairage en blanc d'un objet avec réflexion diffuse dans le rouge et réflexion spéculaire dans le blanc
Lumières ponctuelles |
Lumières directionnelles |
Spots |
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Octobre 2008 */
/* Typologie des lumieres */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "ModuleManipulateur.h"
#include "ModuleMenus.h"
#include "ModuleReshape.h"
#ifndef M_PI
#define M_PI 3.14159
#endif
static int disc = 200;
static int fill = 1;
static int type = 0;
static GLfloat l_pos[] = { 0.0,0.0,6.0,1.0 };
static GLfloat l_dir[] = { 0.0,0.0,1.0,0.0 };
static int attenuation = 0;
static float ouverture = 30.0F;
static float spotDir[] = { 0.0F,0.0F,-1.0F };
static float shininess = 100.0F;
static int obj = 0;
static int mode = 0;
static const GLfloat blanc[] = { 1.0,1.0,1.0,1.0 };
static const GLfloat rouge[] = { 1.0,0.0,0.0,1.0 };
static const GLfloat noir[] = { 0.0,0.0,0.0,1.0 };
static const GLfloat gris[] = { 0.7,0.7,0.7,1.0 };
typedef struct Position {
float x ;
float y ;
float z ; } Position ;
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;
glNormal3f(0.0F,0.0F,1.0F);
glBegin(GL_QUADS);
for ( int i = 0 ; i < disc ; i++ )
for ( int j = 0 ; j < disc ; j++ ) {
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 };
glVertex3fv((float *) &pp1);
glVertex3fv((float *) &pp2);
glVertex3fv((float *) &pp3);
glVertex3fv((float *) &pp4); }
glEnd();
}
void displayLumierePonctuelle(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK,(fill) ? GL_FILL : GL_LINE);
manipulateurSouris();
manipulateurClavier();
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,shininess);
switch ( mode ) {
case 0 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 1 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 2 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break;
case 3 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break; }
glRotatef(-50.0F,1.0F,0.0F,0.0F);
glLightfv(GL_LIGHT0,GL_POSITION,l_pos);
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,180.0F);
switch ( attenuation ) {
case 0 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0F);
break;
case 1 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0F);
break;
case 2 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,1.0F);
break; }
Position p1 = { -8.0F,-8.0F,0.0F } ;
Position p2 = { 8.0F,-8.0F,0.0F } ;
Position p3 = { -8.0F, 8.0F,0.0F } ;
glEnable(GL_LIGHTING);
switch ( obj ) {
case 0 :
dessineFacette(&p1,&p2,&p3,disc);
break;
case 1 :
glutSolidTorus(2.0F,6.0F,disc,disc);
break; }
glTranslatef(l_pos[0],l_pos[1],l_pos[2]);
glColor4fv(blanc);
glDisable(GL_LIGHTING);
glutSolidSphere(0.3F,36,36);
glPopMatrix();
glFlush();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Erreur : %d\n",error);
}
void displayLumiereDirectionnelle(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK,(fill) ? GL_FILL : GL_LINE);
manipulateurSouris();
manipulateurClavier();
glRotatef(-50.0F,1.0F,0.0F,0.0F);
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,shininess);
switch ( mode ) {
case 0 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 1 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 2 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break;
case 3 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break; }
glLightfv(GL_LIGHT0,GL_POSITION,l_dir);
Position p1 = { -8.0F,-8.0F,0.0F } ;
Position p2 = { 8.0F,-8.0F,0.0F } ;
Position p3 = { -8.0F, 8.0F,0.0F } ;
glEnable(GL_LIGHTING);
switch ( obj ) {
case 0 :
dessineFacette(&p1,&p2,&p3,disc);
break;
case 1 :
glutSolidTorus(2.0F,6.0F,disc,disc);
break; }
glTranslatef(0.0F,0.0F,7.0F);
glColor4fv(blanc);
glDisable(GL_LIGHTING);
glutSolidSphere(0.2F,36,36);
glBegin(GL_LINES);
glVertex3f(0.0F,0.0F,0.0F);
glVertex3f(-5.0F*l_dir[0],-5.0F*l_dir[1],-5.0F*l_dir[2]);
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Erreur : %d\n",error);
}
static void dessineCone(float *dir,float ouverture,int n) {
if ( dir[2] != -1.0F ) {
if ( dir[2] == 1.0F )
glRotatef(180.0F,1.0F,0.0F,0.0F);
else {
float angle =(float) (acos(-dir[2])*180.0/3.14159);
glRotatef(-angle,-dir[1],dir[0],0.0F); } }
ouverture = ouverture/180.0*M_PI;
float dx =(float) (4.0*sin(ouverture));
float dz =(float) (-4.0*cos(ouverture));
for ( int i = 0 ; i < n ; i++ ) {
glPushMatrix();
float angle = i*360.0F/n;
glRotatef(angle,0.0F,0.0F,1.0F);
glBegin(GL_LINES);
glVertex3f(0.0F,0.0F,0.0F);
glVertex3f(dx,0.0F,dz);
glEnd();
glPopMatrix(); }
}
void displayLumiereSpot(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK,(fill) ? GL_FILL : GL_LINE);
manipulateurSouris();
manipulateurClavier();
glRotatef(-50.0F,1.0F,0.0F,0.0F);
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,shininess);
switch ( mode ) {
case 0 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 1 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
break;
case 2 :
glLightfv(GL_LIGHT0,GL_SPECULAR,blanc);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break;
case 3 :
glLightfv(GL_LIGHT0,GL_SPECULAR,noir);
glLightfv(GL_LIGHT0,GL_DIFFUSE,noir);
break; }
glLightfv(GL_LIGHT0,GL_POSITION,l_pos);
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,ouverture);
glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);
switch ( attenuation ) {
case 0 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0F);
break;
case 1 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0F);
break;
case 2 :
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0F);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,1.0F);
break; }
Position p1 = { -8.0F,-8.0F,0.0F } ;
Position p2 = { 8.0F,-8.0F,0.0F } ;
Position p3 = { -8.0F, 8.0F,0.0F } ;
glEnable(GL_LIGHTING);
switch ( obj ) {
case 0 :
dessineFacette(&p1,&p2,&p3,disc);
break;
case 1 :
glutSolidTorus(2.0F,6.0F,disc,disc);
break; }
glTranslatef(l_pos[0],l_pos[1],l_pos[2]);
glColor4fv(blanc);
glDisable(GL_LIGHTING);
glutSolidSphere(0.3F,36,36);
glBegin(GL_LINES);
glVertex3f(0.0F,0.0F,0.0F);
glVertex3f(5.0F*spotDir[0],5.0F*spotDir[1],5.0F*spotDir[2]);
glEnd();
glColor4fv(gris);
dessineCone(spotDir,ouverture,9);
glPopMatrix();
glFlush();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Erreur : %d\n",error);
}
void myinit (void) {
glClearColor(0.75,0.75,0.95,1.0) ;
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,rouge);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,blanc);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
}
static void rotateX(float *v,float ax) {
ax = ax/180.0F*M_PI;
float cs =(float) cos(ax);
float sn =(float) sin(ax);
float m[3][3] = { { 1.0F,0.0F,0.0F },
{ 0.0F, cs, -sn },
{ 0.0F, sn, cs } };
float nv[3];
for ( int i = 0 ; i < 3 ; i++ ) {
nv[i] = 0.0F;
for ( int j = 0 ; j < 3 ; j++ )
nv[i] += m[i][j]*v[j]; }
for ( int i = 0 ; i < 3 ; i++ )
v[i] = nv[i];
}
static void rotateY(float *v,float ay) {
ay = ay/180.0F*M_PI;
float cs =(float) cos(ay);
float sn =(float) sin(ay);
float m[3][3] = { { cs,0.0F, sn },
{ 0.0F,1.0F,0.0F },
{ -sn,0.0F, cs } };
float nv[3];
for ( int i = 0 ; i < 3 ; i++ ) {
nv[i] = 0.0F;
for ( int j = 0 ; j < 3 ; j++ )
nv[i] += m[i][j]*v[j]; }
for ( int i = 0 ; i < 3 ; i++ )
v[i] = nv[i];
}
static void rotateZ(float *v,float az) {
az = az/180.0F*M_PI;
float cs =(float) cos(az);
float sn =(float) sin(az);
float m[3][3] = { { cs, -sn,0.0F },
{ sn, cs,0.0F },
{ 0.0F,0.0F,1.0F } };
float nv[3];
for ( int i = 0 ; i < 3 ; i++ ) {
nv[i] = 0.0F;
for ( int j = 0 ; j < 3 ; j++ )
nv[i] += m[i][j]*v[j]; }
for ( int i = 0 ; i < 3 ; i++ )
v[i] = nv[i];
}
void key(unsigned char key,int x,int y) {
switch ( key ) {
case 'm' :
case 'M' :
mode = (mode+1)%4;
glutPostRedisplay();
break;
case 'a' :
case 'A' :
obj = (obj+1)%2;
glutPostRedisplay();
break;
case 'o' :
if ( type == 2 ) {
ouverture -= 0.2F;
if ( ouverture < 0.0F )
ouverture = 0.0F;
else
glutPostRedisplay(); }
break;
case 'O' :
if ( type == 2 ) {
ouverture += 0.2F;
if ( ouverture > 90.0F )
ouverture = 90.0F;
else
glutPostRedisplay(); }
break;
case '1' :
switch ( type ) {
case 1 :
rotateX(l_dir,1.0F);
glutPostRedisplay();
break;
case 2 :
rotateX(spotDir,1.0F);
glutPostRedisplay();
break; }
break;
case '4' :
switch ( type ) {
case 1 :
rotateX(l_dir,-1.0F);
glutPostRedisplay();
break;
case 2 :
rotateX(spotDir,-1.0F);
glutPostRedisplay();
break; }
break;
case '2' :
switch ( type ) {
case 1 :
rotateY(l_dir,1.0F);
glutPostRedisplay();
break;
case 2 :
rotateY(spotDir,1.0F);
glutPostRedisplay();
break; }
break;
case '5' :
switch ( type ) {
case 1 :
rotateY(l_dir,-1.0F);
glutPostRedisplay();
break;
case 2 :
rotateY(spotDir,-1.0F);
glutPostRedisplay();
break; }
case '3' :
switch ( type ) {
case 1 :
rotateZ(l_dir,1.0F);
glutPostRedisplay();
break;
case 2 :
rotateZ(spotDir,1.0F);
glutPostRedisplay();
break; }
break;
case '6' :
switch ( type ) {
case 1 :
rotateZ(l_dir,-1.0F);
glutPostRedisplay();
break;
case 2 :
rotateZ(spotDir,-1.0F);
glutPostRedisplay();
break; }
break;
case 'x' :
switch ( type ) {
case 0 :
case 2 :
l_pos[0] -= 0.1F;
glutPostRedisplay();
break; }
break;
case 'X' :
switch ( type ) {
case 0 :
case 2 :
l_pos[0] += 0.1F;
glutPostRedisplay();
break; }
break;
case 'y' :
switch ( type ) {
case 0 :
case 2 :
l_pos[1] -= 0.1F;
glutPostRedisplay();
break; }
break;
case 'Y' :
switch ( type ) {
case 0 :
case 2 :
l_pos[1] += 0.1F;
glutPostRedisplay();
break; }
break;
case 'z' :
switch ( type ) {
case 0 :
case 2 :
l_pos[2] -= 0.1F;
glutPostRedisplay();
break; }
break;
case 'Z' :
switch ( type ) {
case 0 :
case 2 :
l_pos[2] += 0.1F;
glutPostRedisplay();
break; }
break;
case 0x0D :
type =(type+1)%3;
switch ( type ) {
case 0 :
glutDisplayFunc(displayLumierePonctuelle);
glutPostRedisplay();
break;
case 1 :
glutDisplayFunc(displayLumiereDirectionnelle);
glutPostRedisplay();
break;
case 2 :
glutDisplayFunc(displayLumiereSpot);
glutPostRedisplay();
break; }
break;
case ' ' :
if ( ( type == 0 ) || ( type == 2 ) ) {
attenuation = (attenuation+1)%3;
glutPostRedisplay(); }
break;
case 'F' :
case 'f' :
fill = !fill;
glutPostRedisplay();
break;
case 's' :
shininess += 1.0F;
if ( shininess > 128.0F )
shininess = 128.0F;
glutPostRedisplay();
break;
case 'S' :
shininess -= 1.0F;
if ( shininess < 0.0F )
shininess = 0.0F;
glutPostRedisplay();
break;
case 43 :
disc++;
glutPostRedisplay();
break;
case 45 :
disc--;
if ( disc < 3 )
disc = 3;
glutPostRedisplay();
break;
case 0x1B :
exit(0); }
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(220,200);
glutInitWindowPosition(50,50);
glutCreateWindow("Typologie des lumières");
myinit();
creationMenuBasique();
setParametresPerspectiveBasique(35.0F,1.5F,1.0F,30.0F,0.0F,0.0F,-20.0F);
setManipulateurDistance(20.0F);
glutReshapeFunc(reshapePerspectiveBasique);
glutKeyboardFunc(key);
glutSpecialFunc(specialBasique);
glutMotionFunc(motionBasique);
glutMouseFunc(sourisBasique);
glutIdleFunc(idleBasique);
glutDisplayFunc(displayLumierePonctuelle);
glutMainLoop();
return(0);
}