Desenhos Tridimensionais

Slides:



Advertisements
Apresentações semelhantes
Sistemas de Interfaces com o Usuário e Glut/OpenGL
Advertisements

SLIDE 1 – Transformações - Translação
Funções para serem usadas no exercício de Lab
Listas Lineares Estrutura que permite representar um conjunto de dados de forma a preservar a relação de ordem linear. Uma lista linear é composta de nós,
Computação Gráfica Geometria de Transformações
OpenGL Clique para adicionar texto Soraia Musse 6/4/2011.
Recursividade Prof. Alex F. V. Machado
Algoritmos e Estrutura de Dados I
Introdução a OpenGL (parte final).
Claudio Esperança Paulo Roma Cavalcanti
Introdução à Computação Gráfica OpenGL Básico
Navegador de cenas com openGL e rastreamento de raios
Sistemas de Interfaces com o Usuário e OpenGL/Glut
OpenGL Alberto B. Raposo.
Como utilizar esta ferramenta para apresentações profissionais.
Funções para serem usadas no exercício de Lab nos dias (11/03/2010 e 17/03/10) Visualização 3D Incluir no FrameWork Básico (na página da disciplina), as.
Computação Gráfica Teórica
Callback de Teclado // registro void glutKeyboardFuc(Teclado);
Funções para serem usadas no exercício de Lab Hoje glRotatef(GLfloat angulo, GLfloat x, GLfloat y, GLfloat z) glTranslatef(GLfloat x, GLfloat y, GLfloat.
Iluminação Para programar um sistema de iluminação, dois passos principais devem ser considerados: c) Que tipo e posição de Iluminação se deseja b) Que.
Computação Gráfica: Rendering e Rasterização
Listas com Ponteiros Listas encadeadas Listas circulares.
Movimentos de Câmara – Modo Explorador
Listas Encadeadas.
Professor Reverton de Paula Faculdade Anhanguera de Indaiatuba
Simulação Massa-Mola para Tecidos
Fundamentos Corel Draw Aula I Prof. David Bianchini
Aula prática 8 Ponteiros Monitoria de Introdução à Programação
Aula prática 6 Vetores e Matrizes
Introdução à Computação Gráfica Projeções
Linguagem de Programação II Parte V
Linguagem de Programação II Parte IX
INTELIGÊNCIA ARTIFICIAL
Animações Independentes na Mesma Cena
Tarefa: Implementar o Demo na página da disciplina. Para trabalhar com iluminação em OpenGL, deve-se definir: 1)Vetores de iluminação : Ex: GLfloat luzAmbiente[4]={0.2,0.2,0.2,1.0};
Transformações Geométricas no Plano e no Espaço
TRANSFORMAÇÕES GEOMÉTRICAS
Computação Gráfica – Visibilidade
Linguagem e Ambiente Scratch
Computação Gráfica – Introdução ao OpenGL
Computação Gráfica Introdução ao OpenGL.
Introdução à Computação Gráfica OpenGL Básico
COMPUTAÇÃO GRÁFICA E INTERFACES
Introdução à Linguagem C
Computação Gráfica – Visibilidade Profa. Mercedes Gonzales Márquez.
Computação Gráfica – Animação
Computação Gráfica – Transformações Projetivas
Computação Gráfica – Introdução ao OpenGL
Realidade Virtual Aula 5
Visualização Tridimensional
Viewport.
Computação Gráfica – Animação
Teoria do crescimento - IV
Computação Gráfica – Visibilidade Profa. Mercedes Gonzales Márquez.
Realidade Virtual Aula 2 Remis Balaniuk. Enxergando grande, começando pequeno Quem começa a aprender RV normalmente sofre um primeiro impacto negativo.
Visualização Tridimensional. Quando se trabalha em três dimensões, o SRU (Sistema de Referência do Universo) passa a ser composto por três eixos ortogonais.
AULA 5 – CÁLCULO COM GEOMETRIA ANALÍTICA II Superfícies Quádricas
Introdução à Programação
Computação Gráfica – Visibilidade Profa. Mercedes Gonzales Márquez.
Vetores Normais.
Animação 2D. // Variáveis que guardam a translação que será aplicada // sobre a casinha GLfloat Tx; GLfloat Ty; // Variáveis que guardam os valores mínimos.
Algoritmo e Estrutura de Dados I Aulas 15 – Linguagem C Alocação Dinâmica de Memória Márcia Marra
4 Visualizações Principais (Viewports) Click com botão esquerdo do mouse ativa cada uma das Viewports.
Linguagem de Programação
1º e 2º ano XII Olimpíadas das Cores Emílio Miotti.
Tipo Abstrato de Dados (TAD) Estrutura de Dados Professor: Rodrigo Alves Sarmento Professor: André Cypriano.
Estrutura de Dados Prof. André Cypriano M. Costa
Alocação Dinâmica Dilvan Moreira. Objetivos  Entender o que são e como usar:  Gerenciamento de Memória  Alocação Dinâmica em C.
Superfícies de Bézier Visualização 3D
Transcrição da apresentação:

Desenhos Tridimensionais

Primitivas Gráficas em 3D A forma de representação de objetos 3D mais utilizada em computação gráfica consiste na especificação de uma malha de faces poligonais. Uma superfície discretizada por faces planas que podem ser triângulos (preferencialmente) ou quadrados com tabela de vértices e tabela de faces.

A utilização de primitivas gráficas em três e duas dimensões é praticamente igual. A principal diferença está na especificação dos vértices , pois em 3 dimensões deve-se atribuir um valor para a coordenada Z. Qualquer uma das primitivas gráficas podem ser utilizadas quando se está trabalhando em 3 dimensões.

Implementação de um objeto A primeira providência é definir algumas estruturas para armazenar vértices e faces. A estrutura de vértices é simplesmente uma coordenada 3D: // Define um vértice typedef struct { float x,y,z; // posição no espaço } VERT;

Já na estrutura de faces é preciso armazenar o total de vértices sendo utilizados por cada uma e um outro vetor, que contém os índices para cada vértice. (Triângulos e Quadriláteros) // Define uma face typedef struct { int total; // total de vértices int ind[4]; // índices para o vetor de vértices } FACE;

A última estrutura é para representar um objeto – aqui se guardam apontadores para o vetor de vértices, para o vetor de faces e também a quantidade de faces, uma vez que essa informação não existe em nenhum outro local: // Define um objeto 3D typedef struct { VERT *vertices; // aponta para os vértices FACE *faces; // aponta para as faces int total_faces; // total de faces no objeto } OBJ;

Vetor de vértice // Definição dos vértices VERT vertices[ ] = { { -1, 0, -1 }, // 0 canto inf esquerdo tras. { 1, 0, -1 }, // 1 canfo inf direito tras. { 1, 0, 1 }, // 2 canto inf direito diant. { -1, 0, 1 }, // 3 canto inf esquerdo diant. { 0, 2, 0 }, // 4 topo };

Vetor de Faces // Definição das faces FACE faces[] = { { 4, { 0,1,2,3 }}, // base { 3, { 0,1,4,-1 }}, // lado traseiro { 3, { 0,3,4,-1 }}, // lado esquerdo { 3, { 1,2,4,-1 }}, // lado direito { 3, { 3,2,4,-1 }} // lado dianteiro };

Definição do Objeto // Finalmente, define o objeto pirâmide OBJ piramide = { vertices, faces, 5 };

Por que fazer tudo isso?

Faces diretamente no código? - Separar o modelo 3D do código que desenha o mesmo; * Se trocar o modelo não será necessário modificar o código. Eficiência no armazenamento: se substituirmos as estruturas por um conjunto de chamadas de desenho, potencialmente vários vértices serão repetidamente informados.

Pirâmide: Cada vértice é compartilhado por pelo menos três faces. Isso também criaria um problema considerável no caso da necessidade de alterar o modelo: todas as ocorrências de cada vértice teriam que ser modificadas.

Função: Partindo dessas razões, escrevemos uma função que recebe um objeto genérico, indicado por sua estrutura devidamente preenchida, e traça o contorno de todas as suas faces (usando GL_LINE_LOOP):

// Desenha um objeto em wireframe void DesenhaObjetoWireframe(OBJ *objeto) { OBJ *obj = objeto; // Percorre todas as faces for(int f=0; f < obj->total_faces; ++f) glBegin(GL_LINE_LOOP); // Percorre todos os vértices da face for(int v=0; v < obj->faces[f].total; ++v) glVertex3f(obj->vertices[faces[f].ind[v]].x, obj->vertices[faces[f].ind[v]].y, obj->vertices[faces[f].ind[v]].z); } glEnd();

Para desenhar um objeto, basta agora chamar a função “DesenhaObjetoWireframe” e passar um apontador para o objeto desejado (se houver mais de um). Isso é feito na função callback de desenho:

// 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); // Desenha o objeto definido anteriormente: uma pirâmide DesenhaObjetoWireframe(&piramide); // Executa os comandos OpenGL glFlush(); }

Este exemplo também introduz um conceito muito importante: comandos de navegação, que serão incluidos em quase todos os demais códigos, como segue: - Movimento do mouse: botões esquerdo, direito e centro. - Teclas Home e End

A implementação desses comandos é realizada em funções diferentes: para rotacionar o objeto, utilizam-se duas variáveis – rotX e rotY - que são empregados na função que posiciona o observador (PosicionaObservador). Nessa mesma função também se empregam as variáveis obsX, obsY e obsZ, que informam a posição do objeto em relação ao observador.

// 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); }

Ângulo de Visão Já o ângulo de visão (variável angle) é empregada na função EspecificaParametrosDeVisualizacao:

// 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(); }

Callbacks de mouse // 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;

Durante o movimento em si, a GLUT chama a função GerenciaMovim, a qual recebe as coordenadas atualizadas do mouse. Primeiramente, determina-se qual botão foi pressionado: se foi o botão esquerdo, calculam-se as diferenças (em X e Y) entre a posição atual e a inicial (salva na função GerenciaMouse), e atualizamos as variáveis que controlam a rotação do objeto. A constante SENS_ROT, definida antes da função, permite especificar a sensibilidade do movimento: quanto maior o valor, mais o mouse terá que ser deslocado para afetar a rotação.

// Função callback para eventos de movimento do mouse #define SENS_ROT 5.0 #define SENS_OBS 15.0 #define SENS_TRANSL 30.0 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; }

No segundo trecho, trata-se o botão direito: nesse caso, basta calcular a diferença apenas em Y e atualizar a variável obsZ. É utilizada outra constante, SENS_OBS, também para definira sensibilidade do movimento:

// 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; }

Por fim, o último trecho considera o botão do meio: o processo é praticamente o mesmo do primeiro trecho, mas atualizam-se as variáveis que controlam a translação em X e Y: obsX e obsY. Porém, note que as diferenças são somadas em X, mas subtraídas em Y, de modo que se o mouse for deslocado para baixo, o objeto também será movido na mesma direção. A constante de sensibilidade empregada aqui é denominada SENS_TRANSL:

// 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();