Diferencia entre revisiones de «ManuelRomero/grafica/ej1»

De WikiEducator
Saltar a: navegación, buscar
(Rutinas de inicialización de OpenGL y GLUT)
Línea 1: Línea 1:
{{TEP}}
+
===Nuestro código===
{{:Usuario:ManuelRomero/grafica/nav}}
+
*Una vez inicializado el entorno vienen nuestra acciones
<br>
+
*El el programa principal son las siguientes invocaciones
 
+
<sourece lang=cpp>
===Practica 2===
+
  printInteraction();
;Enunciado
+
  ...
:Se trata de realizar de forma diferente el mismo dibujo
+
  setup();  
:Vamos a dibujar un disco o ''agujero'' de tres formas diferentes
+
  glutDisplayFunc(drawScene);  
:Obtenemos la misma imagen, pero de ''la forma real'' nos permite modificar facilmente su aspecto
+
glutReshapeFunc(resize);   
*Observamos el escenario
+
glutKeyboardFunc(keyInput);
[[Imagen:OpenGEPractica2.png]]
+
glutMainLoop();  
 
+
return 0;   
===Crear un nuevo proyecto===
+
*Creamos un nuevo proyecto según hemos visto en el capítulo anterior
+
Archivo ==> Nuevo ==> Proyecto
+
Seleccionamos  '''''Proyecto vacío'''''
+
*Ponemos nombre al proyecto
+
*Seleccionamos la opción ''crear directorio para la solución''
+
 
+
===Creamos el proyecto===
+
*Ahora creamos un nuevo archivo fuente para nuestro proyecto
+
*Para ello abrimos la venta '''''Explorador de soluciones'''''
+
*Esta ventana muestra la estructura de directorios creada para nuestra ''solución'' o proyecto
+
[[Imagen:VCPPNuevoArchivo3.png]]
+
*En él seleccionamos la carpeta de Archivo de código fuente y con el botón derecho creamos un nuevo fichero
+
[[Imagen:VCPPNuevoArchivo4.png]]
+
*Pegamos el fuente que se nos ha facilitado en la práctica.
+
<source lang=cpp>
+
///////////////////////////////////////////////////////////////////////////////////////////       
+
// circularAnnuluses.cpp
+
//
+
// This program draws three identical-looking circular annuluses in three different ways -
+
// see comments below.
+
//
+
// Interaction:
+
// Press the space bar to toggle between wirefrime and filled for the lower annulus.
+
//
+
// Sumanta Guha.
+
///////////////////////////////////////////////////////////////////////////////////////////
+
 
+
#include <cstdlib>
+
#include <cmath>
+
#include <iostream>
+
 
+
#ifdef __APPLE__
+
# include <GLUT/glut.h>
+
#else
+
#  include <GL/glut.h>
+
#endif
+
 
+
#define PI 3.14159265
+
#define N 40.0 // Number of vertices on the boundary of the disc.
+
 
+
using namespace std;
+
 
+
// Globals.
+
static int isWire = 0; // Is wireframe?
+
static long font = (long)GLUT_BITMAP_8_BY_13; // Font selection.
+
 
+
// Routine to draw a bitmap character string.
+
void writeBitmapString(void *font, char *string)
+
{  
+
  char *c;
+
 
+
  for (c = string; *c != '\0'; c++) glutBitmapCharacter(font, *c);
+
}
+
 
+
// Function to draw a disc with center at (X, Y, Z), radius R, parallel to the
+
// xy-plane.
+
void drawDisc(float R, float X, float Y, float Z)
+
{
+
  float t;
+
  int i;
+
 
+
  glBegin(GL_TRIANGLE_FAN);
+
      glVertex3f( X, Y, Z);
+
      for(i = 0; i <= N; ++i)
+
  {
+
        t = 2 * PI * i / N;
+
        glVertex3f(X + cos(t) * R, Y + sin(t) * R, Z);
+
  }
+
  glEnd();
+
}
+
 
+
// Drawing routine.
+
void drawScene(void)
+
{  
+
  float angle;
+
  int i;
+
 
+
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the buffers including
+
                                                      // the depth buffer.
+
 
+
  glPolygonMode(GL_FRONT, GL_FILL);
+
 
+
  // Upper left circular annulus: the white disc overwrites the red disc.
+
  glColor3f(1.0, 0.0, 0.0);
+
  drawDisc(20.0, 25.0, 75.0, 0.0);
+
  glColor3f(1.0, 1.0, 1.0);
+
  drawDisc(10.0, 25.0, 75.0, 0.0);
+
 
+
  // Upper right circular annulus: the white disc is in front of the red disc blocking it.
+
  glEnable(GL_DEPTH_TEST); // Enable depth testing.
+
  glColor3f(1.0, 0.0, 0.0);
+
  drawDisc(20.0, 75.0, 75.0, 0.0);
+
  glColor3f(1.0, 1.0, 1.0);
+
  drawDisc(10.0, 75.0, 75.0, 0.5); // Compare this z-value with that of the red disc.
+
  glDisable(GL_DEPTH_TEST); // Disable depth testing.
+
 
+
  // Lower circular annulus: with a true hole.
+
  if (isWire) glPolygonMode(GL_FRONT, GL_LINE);else glPolygonMode(GL_FRONT, GL_FILL);
+
  glColor3f(1.0, 0.0, 0.0);
+
  glBegin(GL_TRIANGLE_STRIP);
+
      for(i = 0; i <= N; ++i)
+
  {
+
        angle = 2 * PI * i / N;
+
        glVertex3f(50 + cos(angle) * 10.0, 30 + sin(angle) * 10.0, 0.0);
+
        glVertex3f(50 + cos(angle) * 20.0, 30 + sin(angle) * 20.0, 0.0);
+
  }
+
  glEnd();
+
 
+
  // Write labels.
+
  glColor3f(0.0, 0.0, 0.0);
+
  glRasterPos3f(15.0, 51.0, 0.0);
+
  writeBitmapString((void*)font, "Overwritten");
+
  glRasterPos3f(69.0, 51.0, 0.0);
+
  writeBitmapString((void*)font, "Floating");
+
  glRasterPos3f(38.0, 6.0, 0.0);
+
  writeBitmapString((void*)font, "The real deal!");
+
 
+
  glFlush();
+
}
+
 
+
// Initialization routine.
+
void setup(void)
+
{
+
  glClearColor(1.0, 1.0, 1.0, 0.0);
+
}
+
 
+
// OpenGL window reshape routine.
+
void resize(int w, int h)
+
{
+
  glViewport(0, 0, (GLsizei)w, (GLsizei)h);
+
  glMatrixMode(GL_PROJECTION);
+
  glLoadIdentity();
+
  glOrtho(0.0, 100.0, 0.0, 100.0, -1.0, 1.0);
+
  glMatrixMode(GL_MODELVIEW);
+
  glLoadIdentity();
+
}
+
 
+
// Keyboard input processing routine.
+
void keyInput(unsigned char key, int x, int y)
+
{
+
  switch(key)
+
  {
+
      case ' ':
+
        if (isWire == 0) isWire = 1;
+
        else isWire = 0;
+
        glutPostRedisplay();
+
        break;  
+
      case 27:
+
        exit(0);
+
        break;
+
      default:
+
        break;
+
  }
+
}
+
 
+
// Routine to output interaction instructions to the C++ window.
+
void printInteraction(void)
+
{
+
  cout << "Interaction:" << endl;
+
  cout << "Press the space bar to toggle between wirefrime and filled for the lower annulus." << endl;  
+
}
+
 
+
// Main routine.
+
int main(int argc, char **argv)
+
{
+
  printInteraction();
+
  glutInit(&argc, argv);
+
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); // Initialize the buffers
+
                                                            // including the depth buffer.
+
  glutInitWindowSize(500, 500);
+
  glutInitWindowPosition(100, 100);
+
  glutCreateWindow("circularAnnuluses.cpp");
+
  setup();
+
  glutDisplayFunc(drawScene);  
+
  glutReshapeFunc(resize);   
+
  glutKeyboardFunc(keyInput);
+
  glutMainLoop();  
+
 
+
  return 0;   
+
}
+
 
+
 
</source>
 
</source>
*
+
;void printInteraction(void)
 
+
===Explicación del fuente===
+
*A continuación se va a explicar el código que genera el escenario anterior
+
*Por ser esta práctica la primera se explicará de forma detallada
+
*de esta forma servirá para empezar a entender cómo usar OpenGL en programación
+
===Cabecera===
+
*definimos bibliotecas stardar de C++
+
<source lang=cpp>
+
#include <cstdlib>
+
#include <cmath>
+
#include <iostream>
+
</source>
+
*Se incluye la biblioteca para usar glut
+
*Todas las funciones que empiecen por '''''glut''''' serán de esta biblioteca
+
<source lang=cpp>
+
#ifdef __APPLE__
+
#  include <GLUT/glut.h>
+
#else
+
#  include <GL/glut.h>
+
#endif
+
</source>
+
*Constantes
+
#PI para operaciones matemáticas
+
#N el número de vértices para el límite de un disco
+
<source lang=cpp>
+
#define PI 3.14159265
+
#define N 40.0 // Number of vertices on the boundary of the disc.
+
</source>
+
*Se define un namespace para el proyecto
+
<source lang=cpp>
+
using namespace std;
+
</source>
+
 
+
*Variables globales que son estáticas y por lo tanto inicializadas
+
<source lang=cpp>
+
// Globals.
+
static int isWire = 0; // Is wireframe?
+
static long font = (long)GLUT_BITMAP_8_BY_13; // Font selection.
+
</source>
+
 
+
===Programa principal===
+
*El programa principal de nuestra aplicación es el siguientes
+
<source lang=cpp>
+
 
+
int main(int argc, char **argv)
+
{
+
  //Mesaje para el usuario de cómo usar el programa
+
  printInteraction();
+
 
+
  //Rutinas de inicialización
+
  glutInit(&argc, argv);
+
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); // Initialize the buffers
+
                                                            // including the depth buffer.
+
  glutInitWindowSize(500, 500);
+
  glutInitWindowPosition(100, 100);
+
  glutCreateWindow("circularAnnuluses.cpp Practica 1");
+
 
+
  //Dibuja nuestro escenario
+
  setup();
+
  glutDisplayFunc(drawScene);
+
  glutReshapeFunc(resize); 
+
  glutKeyboardFunc(keyInput);
+
  glutMainLoop();
+
 
+
  return 0; 
+
}
+
</source>
+
===[http://www.opengl.org/documentation/specs/glut/spec3/node9.html#SECTION00030000000000000000 Rutinas de inicialización de OpenGL y GLUT] ===
+
[http://www.opengl.org/documentation/specs/glut/spec3/node9.html#SECTION00030000000000000000 Ver referencia web en página oficial]
+
*Los  primeros métodos de la librería '''''glut''''' se invocan al principio
+
*Sirven para inicalizar la librería.
+
;void glutInit(int *argcp, char **argv);
+
:Inicializa la librería GLUT para que pueda usar una sesión con el sistema de ventanas. En caso de que no se pueda retorna un error
+
:'''''argcp'''''  Es un puntero a la variable argc del main (ver ''int main(char* argv, int argc); Sirve para poder pasar de la línea de comandos valores para GLUT
+
:'''''argcv''''' Igual que en el caso anterior, pero ahora a la variable '''''argv''''' del ''main()''.
+
*Toma los valores que le pasamos al main y se los envía a la bibliteca de GLUT
+
;void glutInitDisplayMode(unsigned int mode);
+
:Establece el modo de visualización incial.
+
*Este valor por defecto es RGBA (colores básicos y el canal Alpha)
+
*Se pueden concatenar bits para especificar el modo de visualización. ver la siguiente lista de valores posibles
+
*En nuestro caso el método es invocado '''''glutInitDisplayLaod(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);'''''
+
#GLUT_SINGLE establece un single buffered window.
+
#GLUT_RGB es como GLUT_RGBA establece este mode de visualización
+
#GLUT_DEPTH establece buffer de profundidad (para que objetos de adelante oculten a los de atrás, sin que éstos desaparezcan de la escena)
+
http://www.opengl.org/documentation/specs/glut/spec3/node12.html#SECTION00033000000000000000
+
;void glutInitWindowSize(int width, int height);
+
;void glutInitWindowPosition(int x, int y);
+
*Establecen el tamaño y la posición inicial de la ventana cuando es creada con el método '''''glutCreateWindow(...) '''''
+
;int glutCreateWindow(char *name);
+
*Crea la ventana de nivel superior de nuestra aplicación.
+
*el parámetro ''name'' será el título de la ventana
+
+
*El ''int'' que retorna servirá para identificar la ventana
+
*Este valor se puede usar al invocar al método '''''glutSetWindow'''''.
+
<source lang=cpp>
+
  glutInit(&argc, argv);
+
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); // Initialize the buffers
+
                                                            // including the depth buffer.
+
  glutInitWindowSize(500, 500);
+
  glutInitWindowPosition(100, 100);
+
  glutCreateWindow("circularAnnuluses.cpp Practica 1");
+
</source>
+
;
+
 
+
===Mensaje para usuario===
+
'''''void printInteraction(void)'''''
+
 
+
 
*Se  imprime un mensaje por la pantalla para interactuar con el usuario.
 
*Se  imprime un mensaje por la pantalla para interactuar con el usuario.
 
*Este contenido va a la consola no a la ventana windows
 
*Este contenido va a la consola no a la ventana windows
Línea 317: Línea 28:
 
   //cout << "Press the space bar to toggle between wirefrime and filled for the lower annulus." << endl;   
 
   //cout << "Press the space bar to toggle between wirefrime and filled for the lower annulus." << endl;   
 
   cout << "Presiona la barra espaciadora para alternar entre el anillo relleno de color y relleno de alambre ." << endl;   
 
   cout << "Presiona la barra espaciadora para alternar entre el anillo relleno de color y relleno de alambre ." << endl;   
 
 
}
 
}
 
</source>
 
</source>
 +
;void glutDisplayFunc(void (*func)(void));
 +
*[http://www.opengl.org/documentation/specs/glut/spec3/node46.html#SECTION00081000000000000000 glutDisplayFunc] Carga la funcion pasada como parámetro en la ventana de window actual
 +
;void glutReshapeFunc(void (*func)(int width, int height));
 +
[http://www.opengl.org/documentation/specs/glut/spec3/node48.html#SECTION00083000000000000000 glutReshapeFunc] vuelve a dibujar la ventana de window con la función que recibe como parámetro
 +
;void glutKeyboardFunc(void (*func)(unsigned char key,int x, int y));
 +
*[http://www.opengl.org/documentation/specs/glut/spec3/node49.html#SECTION00084000000000000000 glutKeyboardFunc] Asigna el callback del teclado a la ventana actual de windows, de forma que cuando presionemos una tecla la función pueda recoger el valor y reaccionar ante el evento
 +
 +
;glutKeyBoardFunc()
 +
;glutMainLoop()
 +
  
===Rutinas de incialización : glClearColor(...). glutInit( ...)
+
===Rutinas de incialización : glClearColor(...). glutInit( ...)===
  
 
*Es una función propia de '''''OpenGl''''' ''como todas las que empiezan por gl''
 
*Es una función propia de '''''OpenGl''''' ''como todas las que empiezan por gl''

Revisión de 03:10 9 jun 2013

Nuestro código

  • Una vez inicializado el entorno vienen nuestra acciones
  • El el programa principal son las siguientes invocaciones

<sourece lang=cpp>

printInteraction();
...
setup(); 
glutDisplayFunc(drawScene); 
glutReshapeFunc(resize);  
glutKeyboardFunc(keyInput);
glutMainLoop(); 
return 0;  

</source>

void printInteraction(void)
  • Se imprime un mensaje por la pantalla para interactuar con el usuario.
  • Este contenido va a la consola no a la ventana windows
  • es código c++ (objetos de la clase iostream)
  • Por ello hay que hacer el include de la clase iostream
  • El código de esta parte quedaría
...
#include <iostream>
...
void printInteraction(void)
{
   cout << "Interaction:" << endl;
   //cout << "Press the space bar to toggle between wirefrime and filled for the lower annulus." << endl;  
   cout << "Presiona la barra espaciadora para alternar entre el anillo relleno de color y relleno de alambre ." << endl;  
}
void glutDisplayFunc(void (*func)(void));
  • glutDisplayFunc Carga la funcion pasada como parámetro en la ventana de window actual
void glutReshapeFunc(void (*func)(int width, int height));

glutReshapeFunc vuelve a dibujar la ventana de window con la función que recibe como parámetro

void glutKeyboardFunc(void (*func)(unsigned char key,int x, int y));
  • glutKeyboardFunc Asigna el callback del teclado a la ventana actual de windows, de forma que cuando presionemos una tecla la función pueda recoger el valor y reaccionar ante el evento
glutKeyBoardFunc()
glutMainLoop()


Rutinas de incialización : glClearColor(...). glutInit( ...)

  • Es una función propia de OpenGl como todas las que empiezan por gl
  • La función glClearColor(float red, float green, flota green, float alpha)
  • Especifica el color que pasamos como argumentos con el que se borrara el buffer al hacer un glClear().
  • Los parámetros son valores reales entre 0 y 1
  • Los tres primeros espefician el color
  • El cuarto es el nivel de transparencia canal alpha.
// Rutinas de inicialización
void setup(void) 
{
   glClearColor(1.0, 1.0, 1.0, 0.0);  
}
Ahora es cuando vamos a hacer funcionar nuestro código
Dibujando el círculo o disco
drawDisc(float radio ,float x, float y, float z)
  • Dibuja un disco con un radio con un espesor y orientación , y una posición (x,y,z)
Estableciendo un color
glColor3f(float red, float green, float blue);
Dibujando el circulo sobreescrito
  • En este caso primero dibujamos un
Test de profundidad

El algoritmo del Z-buffer es del tipo espacio-imagen. Cada vez que se va a renderizar un pixel, comprueba que no se haya dibujado antes en esa posición un pixel que esté más cerca respecto a la cámara. Este algoritmo funciona bien para cualquier tipo de objetos: cóncavos, convexos, abiertos y cerrados. Para activarlo, hay que hacer una llamada a glEnable(GL_DEPTH_TEST) Esta llamada le dice a OpenGL que active el test de profundidad. Además