Transformaciones en OpenGL

Proyección
Como ya se ha visto en tutoriales anteriores, OpenGL maneja 2 tipos de proyección, en perspectiva y ortográfica, donde la primera corresponde a la visión “realista” de la escena, mientras que la segunda es una “plana” que no deforma las dimensiones de los objetos dependiendo de su distancia a la cámara.

Ortográfica: Para ajustar la proyección ortográfica se utiliza el siguiente grupo de funciones:

glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

Esta función permite controlar los parámetros del volumen de vista izquierdo, derecho, abajo, arriba, cerca y lejos. Hay que recordar que debido a que no se posee percepción de profundidad en este modo el valor del volumen deberá corresponder en la mayoría de los casos a un volumen suficientemente grande para contener los objetos de la escena.

gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);

Esta función es simplemente una forma de la anterior, en donde se ha despreciado el valor de Z asignando los valores near = -1 y far = 1, generalmente se utiliza para escenas planas, en las que los objetos carecen de profundidad.

Perspectiva: Existen dos manera de manejar la proyección en perspectiva, a través de de una función gl o mediante la librería glu (una tercera puede ser realizar los cálculos de la matriz “manualmente”. En el primer caso:

glFrustrum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)

Esta función crea una matriz y la multiplica por la matriz de proyección actual, la matriz tiene la forma:

formula

Estos no son datos fácilmente digeribles por muchos, así que glu ofrece una versión alternativa, mucho más fácil de entender:

void gluPerspective(GLdouble fov, GLdouble aspect, GLdouble near, GLdouble far);

Donde fov se refiere al Field of View: el ángulo medido en la dirección Y dado en grados que es visible al usuario, el aspect que es una razón entre el alto y el ancho de la ventana y los otros dos valores corresponden a la distancia con respecto al plano mas cercano y mas lejano de proyección, tomando la cámara (0,0,0) como el punto de partida. Los valores “usuales” para estas variables de inicialización son fov = 45, aspect= ancho_ventana/alto_ventana, near = 1.0 y far=100.0 o el valor que sea para estos dos últimos, según las necesidades (ambos tienen que ser positivos).

Bueno, las modificaciones a las matrices de perspectiva por parte de estas funciones son de realizarse por lo común una vez durante la creación de una aplicación, mientras que las siguientes funciones se utilizan rutinariamente en la creación de gráficos.

Transformaciones ModelView

Una tarea muy común en la creación de gráficos 2d, 3d y videojuegos es la de mover objetos par crear cierta animación. La primera idea que se nos viene a la cabeza en el caso de OpeGL es que todo modelo está formado por primitivas, toda primitiva por puntos y finalmente todo punto por una tripleta de coordenadas XYZ, así que si se cambian las coordenadas todo de ahí hacia arriba se mueve.

Después de un tiempo tal vez se requieran realizar unas tareas un poco mas complicadas como rotar el objeto alrededor de su centro, o alrededor de la posición donde se encuentra con respecto al sistema coordenada. Esta tarea no es tan simple y requiere algo de conocimiento en matemático para hacerse, debido a que probablemente implique la implementación de un sistema para almacenar y operar matrices, implementación de coordenadas homogéneas, etc. OpenGL provee de estos sistemas y utiliza algunas simples funciones para su acceso, contando con tres operaciones básicas: mover, rotar y escalar un conjunto de vértices.

void glRotate[fd](GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

Realiza una rotación del espacio coordenado por una medida de (angle) tomados en grados a lo largo del vector determinado por (x,y,z). Es recomendable que (x,y,z) representen un vector normalizado (o sea magnitud(x,y,z) = 1), debido a que si no es así OpenGL intentará normalizarlo. La rotación se lleva siguiendo la regla de la mano derecha, teniendo en cuenta que el vector (x,y,z) apunta con el “pulgar” hacia adentro (hacia uno).

void glTranslate[fd](GLfloat x, GLfloat y, GLfloat z);

Esta función traslada el espacio coordenado en x, y, z unidades sobre sus respectivos ejes coordenados X, Y, Z.

void glScalef(GLfloat x, GLfloat y, GLfloat z);

Cambia la proporción de los objetos respecto a los ejes coordenados, 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.

Hay que tener en cuenta las siguientes características a la hora de utilizar estas funciones:

  • Estas tres operaciones afectan la matriz actual seleccionada, bien sea MODELVIEW o PROJECTION, generalmente para propósitos de rotar objetos dentro de la escena se utiliza la matriz MODELVIEW.
  • El eje coordenado de referencia para las operaciones tanto en MODELVIEW como en PROJECTION se denomina “eye coordinates”, que traduce coordenadas de “ojo” o mejor “vista”. Este es un sistema inamovible y en ausencia de cualquier transformación, la “cámara” está situada en (0,0,0) apuntando hacia la dirección Z negativa, con el vector “arriba” en el sentido Y positivo.
  • Cada operación que afecta la matriz MODELVIEW crea otro sistema coordenado para los objetos que se dibujen después de realizada la trasformación, dicho sistema difiere del “básico”, es decir de las llamadas coordenadas de vista (eye coordinates) dependiendo de todo el conjunto de transformaciones realizadas desde el momento en que la matriz MODELVIEW dejo de ser la identidad.
  • Una consecuencia de lo anterior es que las operaciones no son conmutativas, es decir que un llamado de glRotatef(), seguido de uno de glTranslatef() produce un efecto diferente a llamar las operaciones en orden inverso. Esto se ve mejor ilustrado en el gráfico:
  • Transrot

  • Es importante aprender a utilizar correctamente glPushMatrix(), glPopMatrix() y otras operaciones que permitan salvar y restaurar estados de matriz, debido a que permiten realizar translaciones y rotaciones especificas para un cierto objeto, sin alterar los otros.

1 2 3

Compartir esta entrada

DiggReddit
  • Juanxo

    Ola..disculpa la molestia pero..me podrias explicar mejor el sentido de glPushMatrix() y glPopMatrix()..y porque es necesario captarlo

  • http://black-byte.com/ jotatsu

    glPushMatrix() guarda la matriz de transformación actual en una pila y y glPopMatrix() la restaura. Para el caso de la matriz MODELVIEW para guardar diferentes transformaciones de los objetos, para el caso de PROYECTION salva la transformación actual del frustrum, TEXTURE guarda las coordenadas de la transformación de textura.

    En el caso practico sin embargo, para mover y transladar objetos cada uno debería tener su propia matriz de transformación, por lo que glPush y glPop son mas bien de aprendizaje.

  • Sergio

    Hola creo que es un gran tutorial, pero me gustaría poder echar un vistazo a los ejemplos, que ahora mismo no estan disponibles, sabes cuando podrás restaurarlos?

  • Jotatsu

    saludos Sergio.

    Los ejemplos estaràn disponibles de nuevo en el curso de esta semana. Estoy realizando algunas reparaciones por problemas con el host.

  • Lore

    excelente tutorial, felicitaciones