Created
August 14, 2013 19:21
-
-
Save ynurmahomed/6234561 to your computer and use it in GitHub Desktop.
Programa openGL que desenha um diamante
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <GL/glut.h> | |
#include <math.h> | |
#include <stdio.h> | |
#define WINDOW_WIDTH 1080 | |
#define WINDOW_HEIGHT 520 | |
GLfloat angle, fAspect; | |
// Angulo de rotação da camera | |
GLdouble alfa = 0.02; | |
GLdouble eyeX = 0.0; | |
GLdouble eyeY = 80.0; | |
GLdouble eyeZ = 200.0; | |
GLdouble upY = 1; | |
// Retorna um vetor unitário | |
GLfloat* normaliza (GLfloat x, GLfloat y, GLfloat z) { | |
GLfloat *v = (GLfloat*) malloc(3 * sizeof(GLfloat)); | |
float comp = sqrt((x * x) + (y * y) + (z * z)); | |
v[0] = x / comp; | |
v[1] = y / comp; | |
v[2] = z / comp; | |
return v; | |
} | |
GLfloat* determinante (GLfloat* v1, GLfloat *v2) { | |
GLfloat *v1xv2 = (GLfloat*) malloc(sizeof(GLfloat)); | |
v1xv2[0] = v1[1] * v2[2] - v1[2] * v2[1]; | |
v1xv2[1] = -(v1[0] * v2[2] - v1[2] * v2[0]); | |
v1xv2[2] = v1[0] * v2[1] - v1[2] * v2[0]; | |
return v1xv2; | |
} | |
void Desenha (void) { | |
GLfloat TOPO = 40.0, PI = 3.14159, x1, x2, x3, x4, z1, z2, z3, z4, y1, y2, y3, y4, teta1, teta2; | |
GLfloat r1 = 40, r2 = r1 + 10; | |
GLfloat *v1, *v2, *d; | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glColor4f(0.1f, 0.1f, 0.4f, 0.7f); | |
// Desenha o octógono do topo | |
glBegin(GL_TRIANGLE_FAN); | |
glNormal3f(0.0, 1.0, 0.0); // Normal da face | |
for (int i = 0; i < 8; ++i) { | |
teta1 = i * 2.0 * PI / 8.0; // radianos | |
x1 = r1 * cos(teta1); | |
z1 = r1 * sin(teta1); | |
glVertex3f(x1, TOPO, z1); | |
} | |
glEnd(); | |
// Desenha a segunda secção | |
// teta2 é o angulo em radianos do circulo de baixo dos triangle_strip | |
// teta1 é o angulo em radianos do cirvulo de cima dos triagle_strip | |
glBegin(GL_TRIANGLE_STRIP); | |
// A cada iteração são desenhados 4 pontos, formando 2 triangulos | |
// 9 iterações para tapar o vazio criado na primeira | |
for (int i = 0; i < 9; ++i) { | |
teta2 = (2 * i) * 2.0 * PI / 16.0; // radianos | |
x1 = r2 * cos(teta2); | |
y1 = TOPO - 10; | |
z1 = r2 * sin(teta2); | |
teta1 = i * 2.0 * PI / 8.0; // radianos | |
x2 = r1 * cos(teta1); | |
y2 = TOPO; | |
z2 = r1 * sin(teta1); | |
teta2 = (2 * i + 1) * 2.0 * PI / 16.0; // radianos | |
x3 = r2 * cos(teta2); | |
y3 = TOPO - 10; | |
z3 = r2 * sin(teta2); | |
teta1 = (i + 1) * 2.0 * PI / 8.0; // radianos | |
x4 = r1 * cos(teta1); | |
y4 = TOPO; | |
z4 = r1 * sin(teta1); | |
glVertex3f(x1, y1, z1); | |
// Determina a normal do primeiro triangulo | |
v1 = normaliza(x2 - x1, y2 - y1, z2 - z1); | |
v2 = normaliza(x3 - x1, y3 - y1, z3 - z1); | |
d = determinante(v1, v2); | |
glNormal3fv(d); | |
glVertex3f(x2, y2, z2); | |
glVertex3f(x3, y3, z3); | |
// Determina a normal do segundo triangulo | |
v1 = normaliza(x3 - x2, y3 - y2, z3 - z2); | |
v2 = normaliza(x4 - x2, y4 - y2, z4 - z2); | |
d = determinante(v1, v2); | |
glNormal3fv(d); | |
glVertex3f(x4, y4, z4); | |
} | |
glEnd(); | |
// Desenha a segunda secção | |
glBegin(GL_TRIANGLES); | |
x1 = 0.0; y1 = TOPO - 80; z1 = 0.0; | |
glNormal3f(0.0, -1.0, 0.0); | |
for (int i = 0; i < 17; i += 1) { | |
teta2 = i * 2.0 * PI / 16.0; | |
x2 = r2 * cos(teta2); | |
y2 = TOPO - 10; | |
z2 = r2 * sin(teta2); | |
teta2 = (i + 1) * 2.0 * PI / 16.0; | |
x3 = r2 * cos(teta2); | |
y3 = TOPO - 10; | |
z3 = r2 * sin(teta2); | |
v1 = normaliza(x2 - x1, y2 - y1, z2 - z1); | |
v2 = normaliza(x3 - x1, y3 - y1, z3 - z1); | |
glNormal3fv(determinante(v1, v2)); | |
glVertex3f(x1, y1, z1); | |
glVertex3f(x2, y2, z2); | |
glVertex3f(x3, y3, z3); | |
} | |
glEnd(); | |
free(d); | |
free(v1); | |
free(v2); | |
glutSwapBuffers(); | |
} | |
// Inicializa parâmetros de rendering | |
void Inicializa (void) { | |
GLfloat luzAmbiente[4]={0.7, 0.7, 0.7, 1.0}; | |
GLfloat luzDifusa[4]={1.0,1.0,0.7,1.0}; // "cor" | |
GLfloat luzEspecular[4]={1.0, 0.0, 0.0, 1.0};// "brilho" | |
GLfloat posicaoLuz[4]={0.0, -40.0, 0.0, 1.0}; | |
// Capacidade de brilho do material | |
GLfloat especularidade[4]={1.0,1.0,1.0,1.0}; | |
GLint especMaterial = 1; | |
// Especifica que a cor de fundo da janela será preta | |
glClearColor(0.02f, 0.0f, 0.0f, 1.0f); | |
// Habilita o modelo de colorização de Gouraud | |
glShadeModel(GL_SMOOTH); | |
// Define a refletância do material | |
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR, especularidade); | |
// Define a concentração do brilho | |
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,especMaterial); | |
// Ativa o uso da luz ambiente | |
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente); | |
// Define os parâmetros da luz de número 0 | |
glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente); | |
glLightfv(GL_LIGHT0, GL_DIFFUSE, luzDifusa ); | |
glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular ); | |
glLightfv(GL_LIGHT0, GL_POSITION, posicaoLuz ); | |
// Spot | |
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0); | |
GLfloat spot_direction[] = { 0.0, 1.0, 0.0 }; | |
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); | |
// Habilita a definição da cor do material a partir da cor | |
// corrente | |
glEnable(GL_COLOR_MATERIAL); | |
//Habilita o uso de iluminação | |
glEnable(GL_LIGHTING); | |
// Habilita a luz de número 0 | |
glEnable(GL_LIGHT0); | |
// Habilita o depth-buffering | |
glEnable(GL_DEPTH_TEST); | |
angle=45; | |
// para transparencia | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
} | |
// Função usada para especificar o volume de visualização | |
void EspecificaParametrosVisualizacao(void) { | |
// Especifica sistema de coordenadas de projeção | |
glMatrixMode(GL_PROJECTION); | |
// Inicializa sistema de coordenadas de projeção | |
glLoadIdentity(); | |
// Especifica a projeção perspectiva | |
gluPerspective(angle,fAspect,0.4,500); | |
// Especifica sistema de coordenadas do modelo | |
glMatrixMode(GL_MODELVIEW); | |
// Inicializa sistema de coordenadas do modelo | |
glLoadIdentity(); | |
// Especifica posição do observador e do alvo | |
gluLookAt(eyeX, eyeY, eyeZ, 0,0,0, 0,upY,0); | |
} | |
// Função callback chamada quando o tamanho da janela é alterado | |
void AlteraTamanhoJanela(GLsizei w, GLsizei h) { | |
// Para previnir uma divisão por zero | |
if ( h == 0 ) h = 1; | |
// Especifica o tamanho da viewport | |
glViewport(0, 0, w, h); | |
// Calcula a correção de aspecto | |
fAspect = (GLfloat)w/(GLfloat)h; | |
EspecificaParametrosVisualizacao(); | |
} | |
// Função callback chamada para gerenciar eventos do mouse | |
void GerenciaMouse(int button, int state, int x, int y) { | |
if (button == GLUT_LEFT_BUTTON) | |
if (state == GLUT_DOWN) { // Zoom-in | |
if (angle >= 10) angle -= 5; | |
} | |
if (button == GLUT_RIGHT_BUTTON) | |
if (state == GLUT_DOWN) { // Zoom-out | |
if (angle <= 130) angle += 5; | |
} | |
EspecificaParametrosVisualizacao(); | |
glutPostRedisplay(); | |
} | |
void GerenciaTeclado (int key, int x, int y) { | |
switch (key) { | |
// rotação da camera sobre o eixoY no sentido anti-horário | |
case GLUT_KEY_RIGHT: | |
eyeX = eyeZ * sin(alfa) + eyeX * cos(alfa); | |
// eyeY = eyeY :) | |
eyeZ = eyeZ * cos(alfa) - eyeX * sin(alfa); | |
EspecificaParametrosVisualizacao(); | |
break; | |
// rotação da camera sobre o eixoY no sentido horário | |
case GLUT_KEY_LEFT: | |
eyeX = eyeZ * sin(-alfa) + eyeX * cos(-alfa); | |
eyeZ = eyeZ * cos(-alfa) - eyeX * sin(-alfa); | |
EspecificaParametrosVisualizacao(); | |
break; | |
// rotação da camera sobre o eixoX no sentido horário | |
case GLUT_KEY_UP: | |
eyeY = eyeY * cos(-alfa) - eyeZ * sin(-alfa); | |
eyeZ = eyeY * sin(-alfa) + eyeZ * cos(-alfa); | |
if ((int)eyeZ < 0) | |
upY = -1; | |
else | |
upY = 1; | |
EspecificaParametrosVisualizacao(); | |
break; | |
// rotação da camera sobre o eixoX no sentido anti-horário | |
case GLUT_KEY_DOWN: | |
eyeY = eyeY * cos(alfa) - eyeZ * sin(alfa); | |
eyeZ = eyeY * sin(alfa) + eyeZ * cos(alfa); | |
if ((int)eyeZ < 0) | |
upY = -1; | |
else | |
upY = 1; | |
EspecificaParametrosVisualizacao(); | |
break; | |
} | |
glutPostRedisplay(); | |
} | |
// Programa Principal | |
int main(int argc, char *argv[]) { | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); | |
glutInitWindowSize(WINDOW_WIDTH,WINDOW_HEIGHT); | |
glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-WINDOW_WIDTH)/2,(glutGet(GLUT_SCREEN_HEIGHT)-WINDOW_HEIGHT)/2); | |
glutCreateWindow("Visualizacao 3D"); | |
glutDisplayFunc(Desenha); | |
glutReshapeFunc(AlteraTamanhoJanela); | |
glutMouseFunc(GerenciaMouse); | |
glutSpecialFunc(GerenciaTeclado); | |
Inicializa(); | |
glutMainLoop(); | |
} | |
// gcc -Wall diamante.c -std=c99 -o diamante -lm -lGLU -lGL -lglut |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment