/* Este programa demonstra as funcionalidades * de iluminacao suportadas pelo OpenGL. * Duas fontes luminosas, 0 (vermelha) e 1 (azul), sao * indicadas na imagem por dois pontos azul e vermelho, * respectivamente. * * Dois objetos geométricos são iluminados por estas duas * fontes: tetraedro e cubo. * * x,X: +/- 5.0; * y,Y: +/- 5.0; * z,Z: +/- 5.0; * d : toggle difuso; * e : toggle especular; * a : toggle ambiente; * f : toggle fontes móveis; * 0 : toggle light 0 (vermelha); * 1 : toggle light 1 (azul); * r : reset; * * (Ting, 19/09/06) */ #include #include #include #include #include /* Fonte Luminosa */ /* posicao da fonte */ GLfloat light_position[4]; /* intensidade ambiente (Ia) */ GLfloat light_ambient[4]; /* intensidade lambertiana/difusa/incoerente (Id) */ GLfloat light_diffuse[4]; /* intensidade especular (Is) */ GLfloat light_specular[4]; /* direcao da fonte spot (d) */ GLfloat spot_direction[3]; /* expoente de decaimento da intensidade (c) */ GLfloat spot_exponent; /* angulo de abrangencia da fonte spot (gamma) */ GLfloat spot_cutoff; /* coeficiente do termo constante do fator de atenuacao (c_1) */ GLfloat fat_constant; /* coeficiente do termo linear do fator de atenuacao (c_2) */ GLfloat fat_linear; /* coeficiente do termo quadratico do fator de atenuacao (c_3) */ GLfloat fat_quadratic; GLfloat lmodel_ambient[4]={0.2,0.2,0.2,1.0}; /* Material do Objeto */ GLfloat mat_ambient[4]; /* Ka*/ GLfloat mat_diffuse[4]; /* Kd */ GLfloat mat_specular[4]; /* Ks */ GLfloat mat_shininess; /* n */ GLfloat mat_emission[4]; GLenum rotateObjectLight = GL_TRUE; /* rotate light and object simultaneously */ GLenum especular=GL_TRUE, difuso=GL_TRUE, ambiente=GL_TRUE; GLenum light0=GL_TRUE, light1=GL_TRUE; GLfloat dX = 0.0, dY = 0.0, dZ = 0.0; GLfloat rotX = 0.0, rotY = 0.0, rotZ = 0.0; GLfloat c = 1.73205080756887729, length; GLdouble w; void DrawTetrahedron () { GLdouble l; GLdouble v1[3], v2[3], cp[3], norm, x, y, z; /* Desenhar um tetraedron inscrito numa esfera de raio . Observe que cada vértice tem 3 normais definidos */ /* Face 1 */ v1[0] = -2. * length; v1[1] = -2. * length; v1[2] = 0.0; v2[0] = 2. * length; v2[1] = 0.0; v2[2] = -2. * length; /* calculo da normal normalizada da face */ cp[0] = v1[1]*v2[2] - v2[1]*v1[2]; cp[1] = v1[2]*v2[0] - v2[2]*v1[0]; cp[2] = v1[0]*v2[1] - v2[0]*v1[1]; norm = sqrt(cp[0]*cp[0] + cp[1]*cp[1] + cp[2]*cp[2]); cp[0] /= norm; cp[1] /= norm; cp[2] /= norm; /* especificar a geometria da face: sequencia de vertices, associando a todos eles a normal da face */ glBegin (GL_TRIANGLES); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, -length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, -length, -length); glEnd(); /* Face 2 */ v1[0] = 2. * length; v1[1] = 0.0; v1[2] = -2. * length; v2[0] = 0.0; v2[1] = -2. * length; v2[2] = -2. * length; /* calculo da normal normalizada da face */ cp[0] = v1[1]*v2[2] - v2[1]*v1[2]; cp[1] = v1[2]*v2[0] - v2[2]*v1[0]; cp[2] = v1[0]*v2[1] - v2[0]*v1[1]; norm = sqrt(cp[0]*cp[0] + cp[1]*cp[1] + cp[2]*cp[2]); cp[0] /= norm; cp[1] /= norm; cp[2] /= norm; /* especificar a geometria da face: sequencia de vertices, associando a todos eles a normal da face */ glBegin (GL_TRIANGLES); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, length, -length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, -length, -length); glEnd(); /* Face 3 */ v1[0] = 2. * length; v1[1] = 2. * length; v1[2] = 0.0; v2[0] = -2. * length; v2[1] = 0.0; v2[2] = -2. * length; /* calculo da normal normalizada da face */ cp[0] = v1[1]*v2[2] - v2[1]*v1[2]; cp[1] = v1[2]*v2[0] - v2[2]*v1[0]; cp[2] = v1[0]*v2[1] - v2[0]*v1[1]; norm = sqrt(cp[0]*cp[0] + cp[1]*cp[1] + cp[2]*cp[2]); cp[0] /= norm; cp[1] /= norm; cp[2] /= norm; /* especificar a geometria da face: sequencia de vertices, associando a todos eles a normal da face */ glBegin (GL_TRIANGLES); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, -length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, length, -length); glEnd(); /* Face 4 */ v1[0] = -2. * length; v1[1] = 0.0; v1[2] = 2. * length; v2[0] = 0.0; v2[1] = 2. * length; v2[2] = -2. * length; /* calculo da normal normalizada da face */ cp[0] = v1[1]*v2[2] - v2[1]*v1[2]; cp[1] = v1[2]*v2[0] - v2[2]*v1[0]; cp[2] = v1[0]*v2[1] - v2[0]*v1[1]; norm = sqrt(cp[0]*cp[0] + cp[1]*cp[1] + cp[2]*cp[2]); cp[0] /= norm; cp[1] /= norm; cp[2] /= norm; /* especificar a geometria da face: sequencia de vertices, associando a todos eles a normal da face */ glBegin (GL_TRIANGLES); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (length, -length, -length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, -length, length); glNormal3f(cp[0],cp[1],cp[2]); glVertex3f (-length, length, -length); glEnd (); } void DrawCube () { /* definir as normais e os vértices das 6 faces */ static GLdouble n[6][3] = { {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} }; static GLint faces[6][4] = { { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 }, { 4, 5, 1, 0 }, { 6, 2, 1, 5 }, { 3, 7, 4, 0 } }; GLdouble v[8][3]; GLint i; /* Desenhar um cubo de lado <2*w> centrado na origem. Novamente, observe que em cada vértice há 3 normais definidos. */ v[0][0] = v[1][0] = v[2][0] = v[3][0] = -w; v[4][0] = v[5][0] = v[6][0] = v[7][0] = w; v[0][1] = v[1][1] = v[4][1] = v[5][1] = -w; v[2][1] = v[3][1] = v[6][1] = v[7][1] = w; v[0][2] = v[3][2] = v[4][2] = v[7][2] = -w; v[1][2] = v[2][2] = v[5][2] = v[6][2] = w; for (i = 0; i < 6; i++) { glBegin(GL_POLYGON); glNormal3dv(&n[i][0]); glVertex3dv(&v[faces[i][0]][0]); glNormal3dv(&n[i][0]); glVertex3dv(&v[faces[i][1]][0]); glNormal3dv(&n[i][0]); glVertex3dv(&v[faces[i][2]][0]); glNormal3dv(&n[i][0]); glVertex3dv(&v[faces[i][3]][0]); glEnd(); } } /* Initialize material property, light source, lighting model, * and depth buffer. */ void init(void) { /* Setar o modo de tonalizacao em Gouraud */ glShadeModel(GL_SMOOTH); /* Habilitar a iluminacao */ glEnable(GL_LIGHTING); /* setar o modo de renderizacao das faces. Ha tres alternativas: GL_POINT (somente vertices), GL_LINE (somente linhas) e GL_FILL (faces preenchidas) */ glPolygonMode(GL_FRONT, GL_FILL); /* setar a convencao de orientacao. Ha duas alternativas: GL_CCW (anti-horario) e GL_CW (horario) */ glFrontFace (GL_CCW); /* Habilitar face culling */ glEnable (GL_CULL_FACE); /* definir as faces a serem discardadas. Ha tres alternativas: GL_FRONT, GL_BACK e GL_FRONT_AND_BACK */ glCullFace (GL_BACK); /* setar uma luz de ambiente */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); /* setar o modo como a componente especular é calculada */ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); /* setar o modo como a componente especular é integrada à intensidade */ glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); /* setar os lados para os quais deve se aplicar o modelo de iluminacao */ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); c /= sqrt(3 * c * c); } void Light0 (void) { /****************** Fonte 0 (Vermelha) *****************/ light_position[0] = -w-1.0; light_position[1] = -w-1.0; light_position[2] = -w-1.0; light_position[3] = 1.0; light_ambient[0] = 1.0; light_ambient[1] = 0.2; light_ambient[2] = 0.2; light_ambient[3] = 1.0; light_diffuse[0] = 1.0; light_diffuse[1] = 0.2; light_diffuse[2] = 0.2; light_diffuse[3] = 1.0; light_specular[0] = 1.0; light_specular[1] = 1.0; light_specular[2] = 1.0; light_specular[3] = 1.0; spot_direction[0] = 1./sqrt(3.); spot_direction[1] = 1./sqrt(3.); spot_direction[2] = 1./sqrt(3.); spot_exponent = 5.0; /* default: 0.0 */ spot_cutoff = 45.0; /* angulo entre 0 a 90 */ fat_constant = 1.0; /* default: 1.0 */ fat_linear = 0.0; /* default: 0.0 */ fat_quadratic = 0.0; /* deafult: 0.0 */ /* Definir a posicao da luz */ glLightfv (GL_LIGHT0, GL_POSITION, light_position); /* Definir as intensidades ambiente, difusa e especular */ glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular); /* Caso for fonte spot, definir a direcao, o expoente de decaimento e angulo */ glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, spot_exponent); glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, spot_cutoff); /* Definir o fator de atenuacao da intensidade da fonte */ glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, fat_constant); glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION, fat_linear); glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, fat_quadratic); glDisable(GL_LIGHTING); /* desabilitar o modelo de iluminacao para colorir o ponto com a "cor" especificada */ /* desenhar a posicao da fonte */ glColor3f(1.0, 0.0, 0.0); glPointSize(4.0); glBegin(GL_POINTS); glVertex3fv(light_position); glEnd(); glPointSize(1.0); /* desenhar a direcao do feixe */ glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex3fv(light_position); glVertex3f(light_position[0]+spot_direction[0],light_position[1]+spot_direction[1], light_position[2]+spot_direction[2]); glEnd(); glEnable(GL_LIGHTING); /* reabilitar o modelo de iluminacao */ } void Light1 (void) { /****************** Fonte 1 (Azul) ******************/ light_position[0] = length+1.0; light_position[1] = length+1.0; light_position[2] = length+1.0; light_position[3] = 1.0; light_ambient[0] = 0.2; light_ambient[1] = 0.2; light_ambient[2] = 1.0; light_ambient[3] = 1.0; light_diffuse[0] = 0.2; light_diffuse[1] = 0.2; light_diffuse[2] = 1.0; light_diffuse[3] = 1.0; light_specular[0] = 1.0; light_specular[1] = 1.0; light_specular[2] = 1.0; light_specular[3] = 1.0; spot_direction[0] = -1.0/sqrt(3.); spot_direction[1] = -1.0/sqrt(3.); spot_direction[2] = -1.0/sqrt(3.); spot_exponent = 0.0; spot_cutoff = 60.0; fat_constant = 1.0; fat_linear = 0.0; fat_quadratic = 0.0; /* Definir a posicao da luz */ glLightfv (GL_LIGHT1, GL_POSITION, light_position); /* Definir as intensidades ambiente, difusa e especular */ glLightfv (GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT1, GL_SPECULAR, light_specular); /* Caso for fonte spot, definir a direcao, o expoente de decaimento e angulo */ glLightfv (GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction); glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, spot_exponent); glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, spot_cutoff); /* Definir o fator de atenuacao da intensidade da fonte */ glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, fat_constant); glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, fat_linear); glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, fat_quadratic); glDisable(GL_LIGHTING); /* desabilitar o modelo de iluminacao para colorir o ponto com a "cor" especificada */ /* Desenhar a posicao da fonte */ glColor3f(0.0, 0.0, 1.0); glPointSize(4.0); glBegin(GL_POINTS); glVertex3fv(light_position); glEnd(); glPointSize(1.0); /* Desenhar a direcao do feixe */ glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex3fv(light_position); glVertex3f(light_position[0]+spot_direction[0], light_position[1]+spot_direction[1], light_position[2]+spot_direction[2]); glEnd(); glEnable(GL_LIGHTING); /* reabilitar o modelo de iluminacao */ } void MaterialCube() { mat_emission[0] = 0.0; mat_emission[1] = 0.0; mat_emission[2] = 0.0; mat_emission[3] = 1.0; if (especular) { mat_specular[0] = 1.0; mat_specular[1] = 1.0; mat_specular[2] = 1.0; mat_specular[3] = 1.0; mat_shininess = 50.0; } else { mat_specular[0] = mat_specular[1] = mat_specular[2] = mat_specular[3] = 0.0; } if (ambiente) { mat_ambient[0] = 0.2; mat_ambient[1] = 0.2; mat_ambient[2] = 0.2; mat_ambient[3] = 1.0; } else { mat_ambient[0] = mat_ambient[1] = mat_ambient[2] = mat_ambient[3] = 0.0; } if (difuso) { mat_diffuse[0] = 0.8; mat_diffuse[1] = 0.8; mat_diffuse[2] = 0.8; mat_diffuse[3] = 1.0; } else { mat_diffuse[0] = mat_diffuse[1] = mat_diffuse[2] = mat_diffuse[3] = 0.0; } glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular); glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess); glMaterialfv (GL_FRONT, GL_EMISSION, mat_emission); } void MaterialPiramide() { mat_emission[0] = 0.0; mat_emission[1] = 0.0; mat_emission[2] = 0.0; mat_emission[3] = 1.0; if (especular) { mat_specular[0] = 1.0; mat_specular[1] = 1.0; mat_specular[2] = 1.0; mat_specular[3] = 1.0; mat_shininess = 10.0; } else { mat_specular[0] = mat_specular[1] = mat_specular[2] = mat_specular[3] = 0.0; } if (ambiente) { mat_ambient[0] = 0.0; mat_ambient[1] = 0.2; mat_ambient[2] = 0.2; mat_ambient[3] = 1.0; } else { mat_ambient[0] = mat_ambient[1] = mat_ambient[2] = mat_ambient[3] = 0.0; } if (difuso) { mat_diffuse[0] = 0.0; mat_diffuse[1] = 0.8; mat_diffuse[2] = 0.8; mat_diffuse[3] = 1.0; } else { mat_diffuse[0] = mat_diffuse[1] = mat_diffuse[2] = mat_diffuse[3] = 0.0; } glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular); glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess); glMaterialfv (GL_FRONT, GL_EMISSION, mat_emission); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef (0.0, 0.0, -15.0); /* Desenhar a piramide */ length = c * 3.0; /* Habilitar as fontes */ if (light0) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0); if (light1) glEnable(GL_LIGHT1); else glDisable (GL_LIGHT1); if (! rotateObjectLight) Light1(); glPushMatrix(); glTranslatef (3.0, 0.0, 0.0); glRotatef(rotX, 1.0, 0.0, 0.0); glRotatef(rotY, 0.0, 1.0, 0.0); glRotatef(rotZ, 0.0, 0.0, 1.0); if (rotateObjectLight) Light1(); /* Definir o material da piramide */ MaterialPiramide(); DrawTetrahedron(); glPopMatrix(); /* Desenhar o cubo solido iluminado pela fonte <0> */ w = 3.0/2.; if (! rotateObjectLight) Light0(); glPushMatrix(); glTranslatef (-3.0, 0.0, 0.0); glRotatef(rotX, 1.0, 0.0, 0.0); glRotatef(rotY, 0.0, 1.0, 0.0); glRotatef(rotZ, 0.0, 0.0, 1.0); if (rotateObjectLight) Light0(); /* Definir o material do cubo */ MaterialCube(); DrawCube(); glPopMatrix(); glFlush(); } void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (-7.0, 7.0, -7.0, 7.0, 0.0, 30.0); glMatrixMode(GL_MODELVIEW); } /* ARGSUSED1 */ void keyboard(unsigned char key, int x, int y) { switch (key) { /* Finalizar quando a tecla e' apertada */ case 27: exit(0); break; /* Incremento de 5 no angulo de rotacao em torno de x */ case 'x': rotX += 5.0; break; /* Incremento de 5 no angulo de rotacao em torno de y */ case 'y': rotY += 5.0; break; /* Incremento de 5 no angulo de rotacao em torno de z */ case 'z': rotZ += 5.0; break; /* Decremento de 5 no angulo de rotacao em torno de x */ case 'X': rotX -= 5.0; break; /* Decremento de 5 no angulo de rotacao em torno de y */ case 'Y': rotY -= 5.0; break; /* Decremento de 5 no angulo de rotacao em torno de z */ case 'Z': rotZ -= 5.0; break; case 'd': if (difuso) difuso = GL_FALSE; else difuso = GL_TRUE; break; case 'e': if (especular) especular = GL_FALSE; else especular = GL_TRUE; break; case 'a': if (ambiente) ambiente = GL_FALSE; else ambiente = GL_TRUE; break; case 'f': if (rotateObjectLight) rotateObjectLight = GL_FALSE; else rotateObjectLight = GL_TRUE; break; case '0': if (light0) light0 = GL_FALSE; else light0 = GL_TRUE; break; case '1': if (light1) light1 = GL_FALSE; else light1 = GL_TRUE; break; case 'r': dX = dY = dZ = 0.0; rotX = rotY = rotZ = 0.0; ambiente = difuso = especular = GL_TRUE; rotateObjectLight = GL_TRUE; break; } /* Forcar a atualizacao da area de desenho */ glutPostRedisplay(); } /* Main Loop * Open window with initial window size, title bar, * RGBA display mode, and handle input events. */ int main(int argc, char** argv) { /* Inicializacao da biblioteca do glut */ glutInit(&argc, argv); /* Setar o modo de imageamento */ glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* Definir as dimensoes da janela */ glutInitWindowSize (800, 500); /* Definir a posicao da janela */ glutInitWindowPosition (100, 100); /* Criar a janela com os parametros setados */ glutCreateWindow (argv[0]); /* Inicializar os atributos graficos */ init (); /* Definir os tratadores de eventos */ glutDisplayFunc(display); /* quando a area de desenho e' modificada. */ glutReshapeFunc(myReshape); /* quando as dimensoes da janela sao alteradas. */ glutKeyboardFunc(keyboard); /* quando uma tecla eh acionada */ /* Fica num laco de espera pelos eventos */ glutMainLoop(); return 0; }