Anuncios Google

Lecciones 16-18 y Practicas 01-04

Tutoriales de Programaciones

16.- Las Listas Compiladas:

OpenGL no es muy rápido dibujando con “glBegin();” más incluso si utilizamos cálculos matemáticos para calcular los vértices. En el siguiente ejemplo utilizamos trigonometría para dibujar un polígono en este caso de cinco caras y radio 1. Pero cada vez que lo dibujemos hay que realizar los cálculos de nuevo, esto es una autentica chapuza. Y la solución no es meter los vértices con datos literales, puede que el programa nos pregunte el número de caras que tenga el polígono.

#define PI2 6.28318530717958647692
{
  glDisable( GL_CULL_FACE );
  glPolygonMode( GL_FRONT, GL_FILL );
  glPolygonMode( GL_BACK,  GL_LINE );
  GLint caras = 5; GLfloat radio = 1.0f;
  GLfloat x_aux = 0.0f, y_aux = 0.0f, z_aux = 0.0f, inc = PI2/caras;
  glBegin( GL_POLYGON );
    for ( GLfloat angulo = PI2;  angulo > 0.0f; angulo -= inc ) {
      x_aux = GLfloat( radio * sin(angulo) );
      y_aux = GLfloat( radio * cos(angulo) );
      glColor3ub( 255, 0, 0 );
      glVertex3f( x_aux, y_aux, z_aux );
    }
  glEnd();
}

Una solución a este problema es usar listas compiladas. Solo tenemos que dibujar la figura una vez entre las funciones “glNewList();” y “glEndList();”. Luego cuando queramos dibujarla solo tenemos que llamar a la función “glCallList();”. Y por último cuando ya no la necesitemos la borramos con “glDeleteLists();”. En la tabla inferior tenemos un ejemplo de todas estas funciones y su definición:

Definición de las Listas

glListBase( 0 );            // Valor inicial para glGenLists() normalmente 0.
 
GLuint lista = glGenLists(1); // Reserva espacio para una lista.
 
Compilación de una Lista
glNewList( lista, GL_COMPILE );
    /* DIBUJAR PRIMITIVAS */
glEndList();
 
Llamada y Eliminación de Listas
 
glCallList( lista );         // Dibuja la lista compilada
 
glDeleteLists( lista,  1 );   // Borra una lista

En una lista además de vértices y colores también se pueden compilar normales, materiales, luces, texturas de coordenadas, otras listas, objetos cuadráticos, curvas bezier, nurbs, y algunas otras funciones de las librerías GL y GLU. No os preocupéis por esto de momento, solo quedaros con que una lista puede incluir a otra/s lista/s pero lo que no puede incluir son “TEXTURAS”. Las texturas van aparte de forma similar a las listas, ya las veremos más adelante. Con todo esto el ejemplo anterior nos quedaría así:

#define PI2 6.28318530717958647692
glListBase( 0 );
GLuint lista = glGenLists(1);
glNewList( lista, GL_COMPILE );
  glDisable( GL_CULL_FACE );
  glPolygonMode( GL_FRONT, GL_FILL );
  glPolygonMode( GL_BACK,  GL_LINE );
  GLint caras = 5; GLfloat radio = 1.0f;
  GLfloat x_aux = 0.0f, y_aux = 0.0f, z_aux = 0.0f, inc = PI2/caras;
  glBegin( GL_POLYGON );
    for ( GLfloat angulo = PI2;  angulo > 0.0f; angulo -= inc ) {
      x_aux = GLfloat( radio * sin(angulo) );
      y_aux = GLfloat( radio * cos(angulo) );
      glColor3ub( 255, 0, 0 );
      glVertex3f( x_aux, y_aux, z_aux );
     }
  glEnd();
glEndList();

glCallList( lista );         // Dibuja la lista compilada

glDeleteLists( lista,  1 );   // Borra una lista

Una observación, si queremos compilar más de una lista solo hay que obrar de la siguiente forma:

glListBase( 0 );
GLuint lista = glGenLists( 3 );
glNewList( lista + 0, GL_COMPILE ); ... glEndList();
glNewList( lista + 1, GL_COMPILE ); ... glEndList();
glNewList( lista + 2, GL_COMPILE ), ... glEndList();
glCallList( lista + 0 );
glCallList( lista + 1 );
glCallList( lista + 2 );
glDeleteLists( lista,  3 );


17.- Transformaciones, Trasladar, Rotar y Escalar:

Como viene siendo habitual en OpenGL el orden siempre altera el resultado. Vamos a estudiar las tres transformaciones básicas: Trasladar, Rotar y Escalar...

glTranslatef( GLfloat x, GLfloat y, GLfloat z );
 
Esta función traslada el espacio de coordenadas en x, y, z unidades sobre sus respectivos ejes de coordenadas X, Y, Z.

glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z );
 
Realiza una rotación del espacio de coordenadas por una medida de (angle) tomados en grados a lo largo del vector determinado. Es recomendable que (x,y,z) sea un vector normalizado (o sea magnitud(x,y,z) = 1).

glScalef( GLfloat x, GLfloat y, GLfloat z );
 
Cambia la proporción de los objetos respecto a los ejes de coordenadas, lo que es equivalente a decir que los estira o encoge una cantidad determinada por los parámetros de la función x,y,z.

Normalmente primero trasladaremos un objeto, después lo giraremos y por último lo escalaremos. Esto es porque OpenGL trabaja con matices de 4x4 “GLfloat Matriz[4][4];” para hacer transformaciones multiplicándolas por la matriz de modelado. En el primer ejemplo trasladamos un cubo y después lo rotamos siendo evidente el resultado:

En este segundo ejemplo primero rotamos un cubo y luego lo trasladamos. Lo que pasa es que no rotamos el objeto sino todo el espacio, así cuando después trasladamos este no se encuentra donde nosotros pensábamos. Lo mismo pasa con el escalado, si primero agrandamos el cubo al doble, cuando lo traslademos se trasladará el doble y de nuevo no se encontrará donde habíamos pensado.

Como hemos visto, no trasladamos, ni giramos, ni escalamos los objetos sino que lo hacemos sobre el espacio por así decirlo. Y para colmo estas transformaciones son acumulativas, lo cual es un serio problema cuando queremos transformar varios objetos de diferentes formas cada uno.

Para este en farragoso asunto OpenGL nos da dos soluciones. La primera y más simple es una función que borra la matriz dejándola a cero pelotero “glLoadIdentity();”. Recordar que hay varias matrices así que borra la matriz actual. Y la segunda solución es más ingeniosa consiste en hacer una copia de la matriz para luego restaurarla mas tarde. Esto se consigue con las funciones “glPushMatix();” y “glPopMatix()”. ¿A que son graciosos estos nombres? Cuando haces PUSH... ya no hay POP... Por lo visto hacen referencia al ruido cuando introduces algo PUSH y cuando lo sacas POP como si fuesen dibujos animados. Bueno ya esta bien de cachondeo y guasa con el asunto.

Tabla con las funciones mencionadas

glMatrixMode( GL_PROJECTION ) // Selecciona la Matriz de Proyección. La Perspectiva y la Cámara.
glMatrixMode( GL_MODELVIEW )  // Selecciona la Matriz de Modelado. Donde dibujamos.
glMatrixMode( GL_TEXTURE )    // Selecciona la Matriz de Textura. Donde están las Coord. de Textura.
 
glLoadIdentity();   // Borra la matriz actual.
 
glPushMatrix();     // Mete en la Pila una Copia de la Matriz actual.
glPopMatrix();      // Saca de la Pila la última Copia de la Matriz.

Un ejemplo teórico usando listas compiladas:

glPushMatrix(); // Guardamos la Matriz de Modelado.
glTranslatef( 1.0f, 0.0f, 0.0f );   // Trasladamos X una unidad.
glRotatef( 45, 0.0f, 0.0f, 1.0f );  // Rotamos en Z 45 grados.
glScalef( 2.0f, 2.0f, 2.0f );       // Escalamos todo al doble.
glCallList( Lista + 0 );
glLoadIdentity();                   // Borramos la matriz.
glScalef( 2.0f, 2.0f, 2.0f );       // Escalamos todo al doble.
glRotatef( 45, 0.0f, 0.0f, 1.0f );  // Rotamos en Z 45 grados.
glTranslatef( 1.0f, 0.0f, 0.0f );   // Trasladamos en X dos unidades a 45 grados.
glCallList( Lista + 1 );
glLoadIdentity();                   // Borramos la matriz.
glPopMatrix(); // Restauramos la Matriz de Modelado.
glTranslatef( 0.0f, 1.0f, 0.0f );  // Trasladamos Y en una unidad.
glRotatef( 90, 0.0f, 1.0f, 0.0f ); // Rotamos en Y 90 grados.
glCallList( Lista + 2 );

Solo comentar que la función "glMultMatrixf();" multiplica la matriz actual por la indicada como argumento. Pero no voy ha explicar operaciones con matrizes de momento, solo que os suene...

GLfloat Matriz[4][4];
glMultMatrixf( (const GLfloat *) Matriz ); // Multiplica la Matriz Actual. 


18.- Los Objetos Cuadráticos de la librería GLU:

Para simplificar el trabajo la librería GLU permite dibujar rápidamente esferas, cilindros y discos. Esto nos va ha servir de iniciación a nuevos conceptos como las normales de iluminación y las texturas de coordenadas. Las normales de iluminación son vectores que definen como rebotan los rayos de luz en una superficie, jugando con ellos se pueden conseguir efectos de suavizado en los objetos. ¿Os suena esta tabla de abajo?

GL_FLAT   
            ||          GL_SMOOTH

Aunque parezca increíble es la misma esfera, con el mismo número de caras. La diferencia es que en la primera las normales de iluminación son perpendiculares a las caras y en la segunda son todas radiales desde el centro. De momento no vamos a adentrarnos mas en el tema, más adelante veremos como se pueden calcular estas normales pero por ahora dejaremos que sea OpenGL quien las calcule automáticamente.

El otro concepto nuevo son las coordenadas de textura, estas definen como se aplica una textura a un objeto. Sobre estas coordenadas hay mucho que estudiar pero por ahora no las vamos a usar. Yo no se muy bien que significa objeto cuadrático pero son objetos en los que sus vértices, normales y coordenadas de textura pueden calcularse matemáticamente. El ejemplo más típico es la esfera:

#include <cmath>
#define M_PI 3.14159265358979323846
void Esfera( float radio, int nlatitud, int nlongitud ) {
  float inct, incf;
  int i, j;
  float vertice[3];
  inct = 2 * M_PI / nlatitud;
  incf = M_PI / nlatitud;
  for( i=0; i<nlatitud; i++ ) {
    glBegin( GL_LINE_STRIP );
      vertice[0] = vertice[1] = 0;
      vertice[2] =- radio;
      glVertex3fv( vertice );
      for( j=1; j<nlongitud-1; j++ ) {
        vertice[0] = radio * cos(i*inct) * cos(j*incf-0.5*M_PI);
        vertice[1] = radio * sin(i*inct) * cos(j*incf-0.5*M_PI);
        vertice[2] = radio * sin(j*incf-0.5*M_PI);
        glVertex3fv( vertice );
        vertice[0]=radio*cos((i+1)*inct)*cos(j*incf-0.5*M_PI);
        vertice[1]=radio*sin((i+1)*inct)*cos(j*incf-0.5*M_PI);
        glVertex3fv(vertice);
      }
      vertice[0] = vertice[1] = 0;
      vertice[2] = radio;
      glVertex3fv( vertice );
  }
    glEnd();
}
glColor3ub( 255, 255, 255 );
Esfera( 2.0f, 32, 32 ); 

Pero no os preocupéis que no nos hace falta implementar todas estas funciones matemáticas para dibujar esferas, cilindros y discos. En la tabla inferior vemos listadas todas las funciones de la librería GLU sobre objetos cuadráticos.

gluNewQuadric(); // Crea un objeto cuadrático.
GLUquadricObj *Esfera = gluNewQuadric();
gluQuadricOrientation( GLUquadricObj *Quadratic, GLenum Parametros );
  Parámetros:       Determina la Orientación de las Normales de Iluminación.
  - GLU_OUTSIDE      Normales Exteriores
  - GLU_INSIDE       Normales Interiores
gluQuadricNormals( GLUquadricObj *Quadratic, GLenum Parametros );
  Parámetros:       Determina el tipo de Normales de Iluminación.
  - GLU_SMOOTH      Normales Suaves
  - GLU_FLAT        Normales Planas
gluQuadricDrawStyle( GLUquadricObj *Quadratic, GLenum Parametros);
  Parámetros:       Define la forma de dibujar.
  - GLU_FILL        Lleno.
  - GLU_LINE        Lineas
  - GLU_POINT       Puntos.
gluQuadricTexture( GLUquadricObj *Quadratic, GL_TRUE  );
              // Activa las Coordenadas de Textura.
gluSphere( GLUquadricObj *Quadratic, GLfloat radio, GLint Longitud, GLint Latitud );
gluCylinder( GLUquadricObj *Quadratic, GLfloat radioInferior, GLfloat radioSuperior, GLfloat altura, GLint segmentos, GLint pilas );
gluDisk( GLUquadricObj *Quadratic, GLfloat radioInterior, GLfloat radioExterior, GLint segmentos, GLint pilas );
gluPartialDisk( GLUquadricObj *Quadratic, GLfloat radioInterior, GLfloat radioExterior, segmentos, pilas, GLfloat anguloInicial, GLfloat anguloFinal );
gluDeleteQuadric( GLUquadricObj *Quadratic );   // Borra un objeto cuadrático.

El código de ejemplo que viene a continuación está sacado de la práctica número 04. Este tutorial es complementario a las prácticas, así que acostumbraros a ir viendo las prácticas a la vez que leéis este tutorial.

 Ejemplo de uso de objetos cuadráticos:
 
// -- CREAMOS LAS LISTAS COMPILADAS --
glListBase( 0 );
GLuint lista = glGenLists(6); // * * * CREAMOS 6 LISTAS * * *
glPointSize( 2.0f ); glLineWidth( 2.0f );
GLUquadricObj *Quadric = gluNewQuadric();
gluQuadricDrawStyle( Quadric, GLU_LINE );
glNewList( lista + 0, GL_COMPILE );
  glColor3ub( 255, 0, 0 );
  // -- ESFERA --------------------------------
  // -------------- Radio, Longitud, Latitud --
  gluSphere( Quadric, 1.0f, 12, 12 );
glEndList();
gluQuadricDrawStyle( Quadric, GLU_FILL );
glNewList( lista + 1, GL_COMPILE );
  glDisable( GL_CULL_FACE );
  glPolygonMode( GL_FRONT, GL_FILL );
  glPolygonMode( GL_BACK, GL_LINE );
  glColor3ub( 0, 255, 0 );
  // -- CILINDRO SIN TAPAS ----------------------------------------
  // ------- RadioInferior, R_Superior, Altura, Segmentos, Pilas --
  gluCylinder( Quadric, 1.0f, 0.5f, 1.0f, 12, 3 );
  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  glEnable( GL_CULL_FACE );
glEndList();
gluQuadricDrawStyle( Quadric, GLU_POINT );
glNewList( lista + 2, GL_COMPILE );
  glColor3ub( 0, 0, 255 );
  // -- DISCO -----------------------------------------
  // --- RadioInterior, R_Exterior, Segmentos, Pilas --
  gluDisk( Quadric, 0.5f, 1.0f, 12, 3 );
glEndList();
gluQuadricDrawStyle( Quadric, GLU_LINE );
glNewList( lista + 3, GL_COMPILE );
  glColor3ub( 255, 255, 0 );
  // -- DISCO PARCIAL --------------------------------------------------------
  // -- RadioInterior, R_Exterior, Segmentos, Pilas, AnguloInicial, AnguloFinal
  gluPartialDisk( Quadric, 0.5f, 1.0f, 12, 3, 0.0f, 270.f );
glEndList();
gluQuadricDrawStyle( Quadric, GLU_FILL );
glNewList( lista + 4, GL_COMPILE );
  glColor3ub( 255, 64, 64 );
  gluSphere( Quadric, 1.0f, 32, 32 );
glEndList();
gluQuadricNormals( Quadric, GLU_SMOOTH );  // -- ACTIVAMOS SUAVIZADO --
glNewList( lista + 5, GL_COMPILE );
  glPushAttrib( GL_LIGHTING_BIT );    // -- GUARDA EL ESTADO DE LAS LUCES --
  glEnable( GL_LIGHTING );            // -- ACTIVA LA LUZ --
  glEnable( GL_LIGHT0 );              // -- ACTIVA LA LUZ Nº 0 --
  glColor3ub( 64, 64, 255 );
  gluSphere( Quadric, 1.0f, 32, 32 );
  glPopAttrib();                      // -- RESTAURA EL ESTADO DE LAS LUCES --
glEndList();
glDeleteLists( lista,  6  );    // -- BORRAMOS LAS LISTAS --
gluDeleteQuadric( Quadric );    // -- BORRAMOS EL QUADRIC -- 

Aún no hemos estudiado las luces así que ignorar de momento las funciones "GL_LIGHT...", pero aquí tenemos otra vez las palabritas "PUSH" y "POP" en las funciones "glPushAttrib();" y "glPopAttrib();". Ellas guardan y restauran los atributos especificados con la función "glEnable();". Ahora no entraremos en más profundidad sobre el tema.


Práctica Nº 01 - Puntos y Líneas

Lo primero de todo, el entorno 3D está inicializado por la librería "SDL_con_OpenGL.h" , vamos a utilizar C++ (con sus librerías estándar), SDL y OpenGL.

En "Configuracion.h" están las definiciones comunes y en "TUTORIAL_OPENGL.h" hay información resumida sobre las funciones OpenGL utilizadas en las prácticas. De momento ignorar la clase "Fuentes_Bitmap.h" y "Entorno.h".

Sobre "Mirror.h" decir que invierte las imágenes, por alguna extraña razón SDL y OpenGL tiene el eje X de las imágenes invertidos. Para poder pasar imágenes de SDL a OpenGL y viceversa es necesario invertir X.

La estructura básica va ha ser la siguiente:

INCLUDES
INICIO DE MAIN
 
CREACIÓN DEL ENTORNO 3D ( Con o sin Entorno Envolvente )
VERIFICACIÓN COMPATIBILIDADES TARJETA GRAFICA
CREACIÓN DE FUENTES DE TEXTO
CREACIÓN DE LUCES
CREACIÓN DE MATERIALES
CARGA DE TEXTURAS
CREACIÓN DE LISTAS COMPILADAS
CÁLCULOS PROYECCIÓN DE SOMBRAS
CONFIGURACIÓN DE VISUALIZACIÓN
POSICIONAMIENTO DE LA CAMARA
BUCLE PRINCIPAL DE DIBUJADO 3D
 
POSICIONAMIENTO DE LUCES
ACTIVACIÓN DE MATERIALES
ACTIVACIÓN DE TEXTURAS
DIBUJADO DE SOMBRAS
LLAMADA A LAS LISTAS COMPILADAS
...
 
FIN BUCLE PRINCIPAL DE DIBUJADO 3D
MOSTRAR INFORMACIÓN DE ESTADOS
BORRADO DE OBJETOS
FIN DE MAIN

CONTROLES DE LA CAMARA:

  • Pulsando la "C": Mueves  la cámara a la derecha.
  • Pulsando la "Z": Mueves  la cámara a la izquierda.
  • Pulsando la "S": Acercas la cámara.
  • Pulsando la "X": Aleas   la cámara.
  • Pulsando la "D": Mueves  la cámara a arriba.
  • Pulsando la "A": Mueves  la cámara a abajo.
  • Pulsando la "N": Mueves  el enfoque de la cámara a la derecha.
  • Pulsando la "V": Mueves  el enfoque de la cámara a la izquierda.
  • Pulsando la "G": Mueves  el enfoque de la cámara a arriba.
  • Pulsando la "B": Mueves  el enfoque de la cámara a abajo.
  • Pulsando la "H": Acercas el enfoque de la cámara.
  • Pulsando la "F": Alejas  el enfoque de la cámara.
  • Pulsando la "E": Activas o Desactivas el enfoque de la cámara.

CONTROLES DE ROTACIÓN:

  • Pulsando los Cursores Rotas todos los objetos en X e Y.

CONTROLES DE ILUMINACIÓN:

  • Pulsando la "L": Activas o Desactivas la Iluminación.
  • Pulsando la "1": Activas o Desactivas la Luz Nº 0.
  • Pulsando la "2": Activas o Desactivas la Luz Nº 1.
  • Pulsando la "3": Activas o Desactivas la Luz Nº 2.

OTROS CONTROLES:

  • Pulsando la "J": Activas o desactiva la Niebla.
  • Pulsando la "M": Activas o desactiva Color Material.
  • Pulsando "Esc": Abandonas la Práctica.

Descargar Practica nº01 (Solo usuarios registrados)


Práctica Nº 02 - Triángulos

Dibujaremos Triángulos, con diferentes tamaños formas y colores. Que tengan diferentes vistas por delante que por detrás. Usaremos una textura de Patrón para rellenar un cuadrado.

Un detalle importante es la función "glEdgeFlag();" en el caso de dibujar un cuadrado usando dos triángulos en el tercer ejemplo. Con ella podemos ver el cuadrado sin una diagonal que lo cruce.

CONTROLES:

  • Pulsando los Cursores  Rotas todos los objetos en X e Y.

Así podrás rotarlos para ver las caras traseras.

Descargar Practica nº02 (Solo usuarios registrados)


Práctica Nº 03 - Cuadrados

Dibujar Cuadrados, con diferentes tamaños formas y colores. Que tengan diferentes vistas por delante que por detrás. Usar una textura de Patrón.

Descargar Practica nº03 (Solo usuarios registrados)


Práctica Nº 04 - Objetos Cuadráticos

Dibujar "GLUquadricObj" objetos Cuadráticos con la librería GLU. Activa la Iluminación y juega con activar o desactivar el color.

CONTTROLES:

  • Pulsando la "M": Activas o Desactivas el Color de los Objetos.
  • Pulsando la "L": Activas o Desactivas la Iluminación.
  • Pulsando la "1": Activas o Desactivas la Luz Nº 0.

Descargar Practica nº04 (Solo usuarios registrados)

4.575
Tu voto: Ninguno Votos totales: 4.6 (40 votos)

Anuncios Google

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Arreglar los links

Alguien puede por favor arreglar los links de los ejemplos 1 y 2 por favor

Imagen de PSPPRECIZO

Muchas

gracias por poner tutos aqui en scenebeta de OpenGL y tambien por explicarlos de esa forma asi hasta dan mas ganas de seguir leyendo,me seran de ayuda para aprender mas sobre esto :)

Saludos.


simpson
mgs

v10.0

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.