Superfícies de Bézier Visualização 3D Estruturas de Dados Básica (Global) para Construção de uma Superfície Bézier 3D: // Pontos de controle da Bézier (Ver teoria da Sala de Aula) GLfloat pontos[4][4][3] = { {{0.0, 0.0, 0.0}, {0.3, 0.5, 0.0}, {0.7, 0.5, 0.0}, {1.0, 0.0, 0.0}}, {{0.0, 0.0, 0.3}, {0.3, 0.5, 0.3}, {0.7, 0.5, 0.3}, {1.0, 0.0, 0.3}}, {{0.0, 0.0, 0.7}, {0.3, 0.5, 0.7}, {0.7, 0.5, 0.7}, {1.0, 0.0, 0.7}}, {{0.0, 0.0, 1.0}, {0.3, 0.5, 1.0}, {0.7, 0.5, 1.0}, {1.0, 0.0, 1.0}} }; #define SENS_ROT #define SENS_OBS #define SENS_TRANSL 5.0 15.0 30.0 Superfícies de Bézier Para Construir a Superfície de Bézier são necessários principalmente: uma estrutura de Dados (slide anterior) e as funções a seguir: // Função para calcular a Superfície (Chamada de dentro da inicializa) // Define significado dos pontos de controle glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &pontos[0][0][0]); // Ativa geração de coordenadas glEnable(GL_MAP2_VERTEX_3); Superfícies de Bézier Explicação mais Detalhada // Função para calcular a superfície (Chamada de dentro da inicializa) // Define significado dos pontos de controle glMap2f(GL_MAP2_VERTEX_3,GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat *pontos); •GL_MAP2_VERTEX_3: significado dos pontos de controle. Outras opções podem ser: GL_MAP2_VERTEX_4, GL_MAP2_INDEX, GL_MAP2_COLOR_4, GL_MAP2_NORMAL, GL_MAP2_TEXTURE_COORD_1, GL_MAP2_TEXTURE_COORD_2, GL_MAP2_TEXTURE_COORD_3 e GL_MAP2_TEXTURE_COORD_4. • u1 e u2, v1 e v2 definem os intervalos para as variáveis de controle em duas dimensões. Superfícies de Bézzier Explicação mais Detalhada // Função para calcular a Bézier (Chamada de dentro da inicializa) // Define significado dos pontos de controle glMap2f(GL_MAP2_VERTEX_3,GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat *pontos); • Os valores ustride e vstride indicam quantos valores float existem entre cada elemento do vetor no sentido horizontal (ustride) e vertical (vstride) • Os parâmetros uorder e vorder devem conter a quantidade de elementos nos dois sentidos • *pontos é um ponteiro para a estrutura de dados onde são guardados os pontos de controle. Superfícies de Bézier Explicação mais Detalhada Finalmente, glEvalCoord2f(i,j) é a função que avalia os pontos de controle nas coordenadas definidas por glMap2f Parâmetros avaliados com o uso da função glEvalCoord2f Pontos de controle Relembrando da Teoria: Curva de Bézier de grau 3 1 3 3 1 B0 3 6 3 0 B 1 P(t ) t 3 t 2 t 1 3 3 0 0 B2 T 0 0 0 B3 1 MB GB P(t ) (1 t )3 B0 3t (1 t )2 B1 3t 2 (1 t ) B2 t 3 B3 Superfícies de Bézier // Função de Avaliação (Chamada de dentro das macros de desenho (glBegin/Ebd)) // Traça a superfície for(float j=0; j<=1.01; j+=delta) { glBegin(GL_LINE_STRIP); // desenha (avalia) uma dimensão for(float i=0; i<=1.01; i+=delta) glEvalCoord2f(i,j); glEnd(); glBegin(GL_LINE_STRIP); // desenha (avalia) a segunda dimenção for(float i=0; i<=1.01; i+=delta) glEvalCoord2f(j,i); glEnd(); } Superfícies de Bézier Sugestão de ClallBacks para serem usadas: // Registra a função callback para eventos de botões do mouse glutMouseFunc(GerenciaMouse); // Registra a função callback para eventos de movimento do mouse glutMotionFunc(GerenciaMovim); // Registra a função callback para tratamento das teclas normais glutKeyboardFunc (Teclado); // Registra a função callback para tratamento das teclas especiais glutSpecialFunc (TeclasEspeciais); Superfícies de Bézier // Função callback para eventos de botões do mouse void GerenciaMouse(int button, int state, int x, int y) { if (state==GLUT_DOWN) { // Salva os parâmetros atuais x_ini = x; y_ini = y; obsX_ini = obsX; obsY_ini = obsY; obsZ_ini = obsZ; rotX_ini = rotX; rotY_ini = rotY; bot = button; } else bot = -1; } Superfícies de Bézier // Função callback para eventos de movimento do mouse void GerenciaMovim(int x, int y) { // Botão esquerdo ? if(bot==GLUT_LEFT_BUTTON) { // Calcula diferenças int deltax = x_ini - x; int deltay = y_ini - y; // E modifica ângulos rotY = rotY_ini - deltax/SENS_ROT; rotX = rotX_ini - deltay/SENS_ROT; } Superfícies de Bézier // Função callback para eventos de movimento do mouse (Continuação) // Botão direito ? else if(bot==GLUT_RIGHT_BUTTON) { // Calcula diferença int deltaz = y_ini - y; // E modifica distância do observador obsZ = obsZ_ini + deltaz/SENS_OBS; } // Botão do meio ? else if(bot==GLUT_MIDDLE_BUTTON) { // Calcula diferenças int deltax = x_ini - x; int deltay = y_ini - y; // E modifica posições obsX = obsX_ini + deltax/SENS_TRANSL; obsY = obsY_ini - deltay/SENS_TRANSL; } PosicionaObservador(); glutPostRedisplay(); } Superfícies de Bézier // Função responsável por inicializar parâmetros e variáveis (Chamada na Função Principal) void Inicializa (void) { // Define significado dos pontos de controle (explicação acima) glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &pontos[0][0][0]); // Ativa geração de coordenadas glEnable(GL_MAP2_VERTEX_3); (explicação acima) // Define a cor de fundo da janela de visualização como branca glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Inicializa a variável que especifica o ângulo da projeção // perspectiva angle=60; // Inicializa as variáveis usadas para alterar a posição do // observador virtual rotX = 0; rotY = 0; obsX = obsY = 0; obsZ = 5; } Superfícies de Bézier // Função callback para tratar eventos de teclas especiais void TeclasEspeciais (int tecla, int x, int y) { switch (tecla) { case GLUT_KEY_HOME: if(angle>=10) angle -=5; break; case GLUT_KEY_END: if(angle<=150) angle +=5; break; } EspecificaParametrosVisualizacao(); glutPostRedisplay(); } Superfícies de Bézier // Função callback chamada para gerenciar eventos de teclas void Teclado (unsigned char key, int x, int y) { switch(key) { case '-': if(prec>2) prec--; break; case '+': prec++; break; case 27: exit(0); break; } glutPostRedisplay(); } Superfícies de Bézier // 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 as dimensões da viewport glViewport(0, 0, w, h); // Calcula a correção de aspecto fAspect = (GLfloat)w/(GLfloat)h; EspecificaParametrosVisualizacao(); } Superfícies de Bézier // 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(angulo,aspecto,zMin,zMax) gluPerspective(angle,fAspect,0.1,1200); PosicionaObservador(); } Superfícies de Bézier Explicação mais Detalhada // Especifica a projeção perspectiva(angulo,aspecto,zMin,zMax) GLvoid gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble nearClip, GLdouble farClip ) •Um Grande fovy é como olhar através de uma lente grande •Um pequeno fovy é como olhar através de um telescópio •O aspecto é a largura/altura do plano de projeção Superfícies de Bézier // Função usada para especificar a posição do observador virtual void PosicionaObservador(void) { // Especifica sistema de coordenadas do modelo glMatrixMode(GL_MODELVIEW); // Inicializa sistema de coordenadas do modelo glLoadIdentity(); // Posiciona e orienta o observador glTranslatef(-obsX,-obsY,-obsZ); glRotatef(rotX,1,0,0); glRotatef(rotY,0,1,0); } Superfícies de Bézier // Função callback de redesenho da janela de visualização void Desenha(void) { // Limpa a janela de visualização com a cor // de fundo definida previamente glClear(GL_COLOR_BUFFER_BIT); // Altera a cor do desenho para preto glColor3f(0.0f, 0.0f, 0.0f); // Calcula incremento de acordo com o total // de pontos intermediários float delta = 1.0/(float)prec; Superfícies de Bézier // Função callback de redesenho da janela de visualização (Continuação) // Traça a superfície for(float j=0; j<=1.01; j+=delta) { glBegin(GL_LINE_STRIP); for(float i=0; i<=1.01; i+=delta) glEvalCoord2f(i,j); glEnd(); glBegin(GL_LINE_STRIP); for(float i=0; i<=1.01; i+=delta) glEvalCoord2f(j,i); glEnd(); } Superfícies de Bézier // Função callback de redesenho da janela de visualização (Continuação) // Muda a cor para vermelho glColor3f(1.0f, 0.0f, 0.0f); // Define tamanho de um ponto glPointSize(5.0); // Desenha os pontos de controle glBegin(GL_POINTS); for(int i=0; i<4; ++i) for(int j=0; j<4; ++j) glVertex3fv(pontos[i][j]); glEnd(); // Executa os comandos OpenGL glFlush(); }