Computação Gráfica I

Trabalho Prático

Exercícios



3. Modelagem usando malhas

Pra começar...

O objetivo deste exercício é introduzir o uso das bibliotecas OpenGL and GLUT para modelar e visualizar malhas de polígonos.
Baixem aqui o exemplo, criem seu próprio projeto no DevC++ e adicionem os arquivos.
No arquivo mesh.h é dada uma classe Mesh para ser usada na representação de uma malha poligonal, ou mais especificamente, uma malha de triângulos - e outras estruturas úteis. Malhas de triângulos são amplamente usadas na definição de formas 3D. Começaremos usando esta classe hoje e adicionaremos a ela novas funcionalidade ao longo do semestre.

struct Color
{
  float r,g,b;
};

struct Vertex
{
  float x,y,z;
};

struct Triangle
{
  unsigned int vert[3];
};


class Mesh
{
public:
  Mesh();
  virtual ~Mesh();

  void initVerts(int nbrVerts);
  void initTris(int nbrTris);

  Vertex   *verts;
  int       nbrVerts;
  Color    *colors;
  Triangle *tris;
  int       nbrTris;

};

 

Pra aquecer...

O arquivo mesh.cpp implementa a classe Mesh, e o arquivo main.cpp define um programa aplicativo para desenhar malhas com OpenGL. Vocês encontrarão nesse aplicativo: a função main do C++, alguns callbacks da GLUT (init, reshape, display) e duas funções drawMesh diferentes. As duas funções fornecem o mesmo resultado visual, mas com performances bastante diferentes. Tais funções são chamadas na função display para desenhar, primeiro, o triângulo da aula anterior agora com cores. Descomentem alternadamente as chamadas para drawMeshBoringAndSlow e drawMeshCoolAndFast para testar possíveis diferenças e ver como o triângulo e o tetraedro são mostrados; tentem entender como são implementados. Depois, descomentem glRotatef para rotacionar os objetos sendo visualizados.



Agora vamos botar a mão na massa!

De forma análoga aos exemplos do triângulo e tetraedro dados, criem uma malha para desenhar um cubo. Definam vertices e índices de triângulos da mesma maneira como foi feito para as outras primitivas  (ver init).
Finalmente, façam múltiplas chamadas para as funções drawMesh alternando chamadas para as transformações da OpenGL (glTranslatef, glRotatef, glScalef ) entre elas. Criem várias cópias das suas primitivas com diferentes tamanhos, posições e orientações.

Fonte:

#include <GL/glut.h>
#include "mesh.h"


Mesh triangle;
Mesh tetra;
Mesh cube; // This one you define yourself

void drawMeshBoringAndSlow(Mesh& m)
{
  glBegin(GL_TRIANGLES);
  for (int i=0;i<m.nbrTris;i++)
  {
    for (int v=0;v<3;v++)
    {
      glColor3f(m.colors[m.tris[i].vert[v]].r,
                m.colors[m.tris[i].vert[v]].g,
                m.colors[m.tris[i].vert[v]].b);
     
      glVertex3f(m.verts[m.tris[i].vert[v]].x,
                m.verts[m.tris[i].vert[v]].y,
                m.verts[m.tris[i].vert[v]].z);
    }
  }
  glEnd();
}

void drawMeshCoolAndFast(Mesh& m)
{
  glVertexPointer(3,GL_FLOAT,0,m.verts);
  glColorPointer (3,GL_FLOAT,0,m.colors);
  glDrawElements (GL_TRIANGLES,m.nbrTris*3,GL_UNSIGNED_INT,m.tris);
}

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Clear the colour and depth buffer

  glLoadIdentity(); // Clear matrix stack

  static float a=0;
  a+=0.5;

  glTranslatef(0,0,-3);
  //glRotatef(a,0,1,1); // Uncomment for rotation
  drawMeshBoringAndSlow(triangle);
  // Uncomment the following lines to try other geometries
  //drawMeshCoolAndFast(triangle);
  //drawMeshBoringAndSlow(tetra);
  //drawMeshCoolAndFast(tetra);

  glFlush(); // Makes sure that we output the model to the graphics card
  glutSwapBuffers();
  glutPostRedisplay();
}

// Called when a key is pressed
void key(unsigned char k, int x, int y)
{
  if( k == 'q' ) exit(0);
}

void reshape(int width,int height)
{
  glViewport(0,0,width,height); // Reset The Current Viewport

  glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
  glLoadIdentity(); // Reset The Projection Matrix

  // Calculate The Aspect Ratio Of The Window
  gluPerspective(45.0f,(float)640/(float)480,0.1f,1000.0f);
  // Always keeps the same aspect as a 640 wide and 480 high window

  glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
  glLoadIdentity(); // Reset The Modelview Matrix
}

void init()
{
  glClearColor(0.2,0,0.5,0);
  glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST); // Enables Depth Testing
  glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading

  // NEW to initialize the vertex array drawing
  // used by glDrawElements,glVertexPointer and glColorPointer
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_COLOR_ARRAY);

  // Initialization of triangle
  triangle.initVerts(3);
  triangle.initTris(1);
  triangle.verts[0].x=0;triangle.verts[0].y=0;triangle.verts[0].z=0;
  triangle.verts[1].x=1;triangle.verts[1].y=0;triangle.verts[1].z=0;
  triangle.verts[2].x=0;triangle.verts[2].y=1;triangle.verts[2].z=0;
  triangle.colors[0].r=1;triangle.colors[0].g=0;triangle.colors[0].b=0;
  triangle.colors[1].r=0;triangle.colors[1].g=1;triangle.colors[1].b=0;
  triangle.colors[2].r=0;triangle.colors[2].g=0;triangle.colors[2].b=1;

  triangle.tris[0].vert[0]=0;
  triangle.tris[0].vert[1]=1;
  triangle.tris[0].vert[2]=2;

  // Intialization of tetrahedron
  tetra.initVerts(4);
  tetra.initTris(4);
  tetra.verts[0].x=-0.5;tetra.verts[0].y=-0.5;tetra.verts[0].z=-0.5;
  tetra.verts[1].x=0.5;tetra.verts[1].y=-0.5;tetra.verts[1].z=-0.5;
  tetra.verts[2].x=0;tetra.verts[2].y=-0.5;tetra.verts[2].z=0.5;
  tetra.verts[3].x=0;tetra.verts[3].y=0.5;tetra.verts[3].z=0;

  tetra.colors[0].r=1;tetra.colors[0].g=0;tetra.colors[0].b=0;
  tetra.colors[1].r=0;tetra.colors[1].g=1;tetra.colors[1].b=0;
  tetra.colors[2].r=0;tetra.colors[2].g=0;tetra.colors[2].b=1;
  tetra.colors[3].r=1;tetra.colors[3].g=1;tetra.colors[3].b=1;

  tetra.tris[0].vert[0]=0;
  tetra.tris[0].vert[1]=2;
  tetra.tris[0].vert[2]=1;

  tetra.tris[1].vert[0]=0;
  tetra.tris[1].vert[1]=3;
  tetra.tris[1].vert[2]=2;

  tetra.tris[2].vert[0]=0;
  tetra.tris[2].vert[1]=1;
  tetra.tris[2].vert[2]=3;

  tetra.tris[3].vert[0]=1;
  tetra.tris[3].vert[1]=2;
  tetra.tris[3].vert[2]=3;

}

int main(int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE); // We want rgb display functionality
  glutInitWindowSize(640,480); // Set the window dimensions
  glutInitWindowPosition(0,0); // Set the window starting point
  glutCreateWindow("El Triangulo del Futuro Numero Dos"); // Set the caption and launch the window

  init();

  // Last things before rendering starts
  glutDisplayFunc(display); // This will be called every frame
  glutReshapeFunc(reshape); // Reshape the window when something changes
  glutKeyboardFunc(key); // Callback for input

  glutMainLoop(); // Starts the main program

  // We will not reach this point unless exit(0) is called (see function keyCB)

  return 0;
}