viernes, 4 de mayo de 2012

Unidad IV. Iluminación y sombreado


4.1 Relleno de polígonos
Color de relleno
Para elegir el color de los polígonos, basta con hacer una llamada a glColor entre la definición de cada polígono. Por ejemplo, modificando el código que dibujaba dos triángulos:
glBegin(GL_TRIANGLES);
      glColor3f(1.0f, 0.0f, 0.0f);
      glVertex3f(0.0f,0.0f, 0.0f);
      glVertex3f(2.0f,0.0f, 0.0f);
      glVertex3f(1.0f,1.0f, 0.0f);

      glColor3f(0.0f,1.0f, 0.0f);
      glVertex3f(-1.0f,0.0f, 0.0f);
      glVertex3f(-3.0f,2.0f, 0.0f);
      glVertex3f(-2.0f,0.0f, 0.0f);
glEnd();
Esta modificación provocará que el primer triángulo se pinte en rojo y el segundo en verde. La función glColor define el color de rellenado actual y lleva como parámetros los valores de las componentes RGB del color deseado y, opcionalmente, un cuarto parámetro con el valor alpha. Estos parámetros son flotantes y se mueven en el rango [0.0,1.0]. Con ello se pueden componer todos los colores del modo de video usado en ese instante.

Rellenos de Polígonos en OpenGL.
Es el método que utiliza OpenGL para rellenar de color los polígonos. Se especifica con la función glShadeModel. Si el parámetro es GL_FLAT, ogl rellenará los polígonos con el color activo en el momento que se definió el último parámetro; si es GL_SMOOTH, ogl rellenará el polígono interpolando los colores activos en la definición de cada vértice.
Este código es un ejemplo de GL_FLAT:

glShadeModel(GL_FLAT);
glBegin(GL_TRIANGLES);  
      glColor3f(1.0f, 0.0f, 0.0f);  // activamos el color rojo
      glVertex3f(-1.0f, 0.0f, 0.0f);
      glColor3f(0.0f, 1.0f, 0.0f);  // activamos el color verde
      glVertex3f(1.0f, 0.0f, 0.0f);
      glColor3f(0.0f, 0.0f, 1.0f);  // activamos el color azul
      glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();

Técnicas de sombreado clásicas y avanzadas
Clásicas: iluminación local

Cálculos de iluminación por vértices
Para aplicar iluminación a un objeto necesitamos asociar un vector normal a cada vértice del objeto.  Cuando tenemos la normal calculada tenemos que normalizarla, o sea, dividir ese vector por su propio modulo para que sea unitario, pero también podemos hacer que se encargue la OpengGl activando la normalización con el comando glEnable GL_NORMALIZE o desactivarla con glDisable GL_NORMALIZE.
El usar GL_NORMALIZE dependerá de nuestra aplicación ya que si forzamos a que sea OpenGl el que las utilice se ralentiza por que le estamos obligando a hacer mas cálculos de los que debe.
Para definir las normales en opengl utilizaremos la función glNormal3f(X,Y,Z) por ejemplo para definir una cara con 4 vértices la definiremos de la siguiente manera:
GlBegin GL_QUADS
glNormal3f nX,nY,nZ
glvertex3f x,y,z
glvertex3f x,y,z
glvertex3f x,y,z
glvertex3f x,y,z
glEnd

Renderizado en Tiempo real
La idea fundamental del procesado en tiempo real es que todos los objetos deben ser descompuestos en polígonos. Estos polígonos serán descompuestos a su vez en triángulos. Cada triángulo será proyectado sobre la ventana bidimensional y rellenado con los colores adecuados para reflejar los efectos de la iluminación, texturas, etc. Una vez se han generado los triángulos, en la pipeline existen dos partes claramente diferenciadas: una primera etapa operaciones realizadas sobre cada uno de los vértices, y después de que éstos se proyecten sobre la ventana, entonces comienza una segunda fase de cálculos realizados para cada pixel cubierto por triángulos.

Iluminación global
              Considera la luz reflejada por un punto teniendo en cuenta toda la luz que llega
              No solo procedente de las luces
              Efectos
             producen sombras
             reflexión de un objeto en los otros
             transparencias

Trazado de Rayos
El trazado de rayos computa la interacción de la luz desde un punto de vista determinado y es particularmente adecuado para superficies reflectantes. Puede utilizarse como propiedad específica de un determinado material.

Radiosidad
Está basado en principios generales que se pueden encontrar en un manual general sobre rendering. En el estadio inicial la escena consta de dos tipos de objetos: objetos que emiten luz y objetos que reciben luz. A partir de aquí, en una primera vuelta, se computa la luz que recibe cada objeto o, en una aproximación más exacta, cada parte de un objeto, según una subdivisión cuya densidad puede precisarse en sucesivas aproximaciones.

Cálculos de iluminación por pixel
La iluminación por píxel en tiempo real es una tecnología revolucionaria ofrecida como primicia por NVIDIA Shading Rasterizer. La iluminación dinámica a nivel de píxel libera a los desarrolladores de las restricciones de otros sistemas de iluminación y pone a su alcance toda una gama de sofisticados efectos. Antes de que el color final del píxel sea decidido, un cálculo de iluminación debe ser computado para sombrear a los píxeles basados en alguna luz que puede estar presente en la escena.

Alto Acabado
Sombreado Constante o plano. Un cálculo para todo el polígono. Obtenemos una intensidad  que aplicamos a un conjunto de puntos de un objeto (p.ej. todo un triángulo). Aceleramos el proceso de síntesis.  Correcto si se verifica: Fuente de luz en el infinito. Observador en el infinito. El polígono representa una superficie plana real del objeto que se modela y no es una aproximación de un objeto curvo.

Sombreado Constante o Plano
 Obtenemos una intensidad que aplicamos a un conjunto de puntos de un objeto
  *Aceleramos el proceso de síntesis
  *Correcto si se verifica.
  * Fuente de luz en el infinito
  *Observador en el infinito

Sombreado de Gouraud
• Es un  método todo incremental que una interpolación de intensidades.
• En cada vértice del polígono se calcula la intensidad. La intensidad de los puntos intermedios se calcula por interpolación bilineal.
Cálculo
 11 Calcular intensidad en los vértices
 1.1. Calcular normal en el vértice: para evitar visualizar las aristas la normal se calcula como la las aristas, la normal se calcula como la media de las normales de polígonos adyacentes.
1.2. Calcular la intensidad del vértice Iv  según el modelo de iluminación de Phong
2. Calcular la intensidad de los puntos interiores p p por interpolación lineal de las de los vértices.

Sombreado de Phong
• Es un método todo incremental que realiza una interpolación de normales (en vez de   interpolación de intensidades).
• En cada vértice del polígono se calcula la normal como media de las normales de los polígonos adyacentes. La normal de los adyacentes. La normal de los puntos intermedios se calcula por  interpolación lineal.
• En cada punto se aplica el modelo de iluminación de Phong.
Cálculo
• 1 Calcular normal en los vértices
– Como en el sombreado de Gouraud, para evitar visualizar las aristas, la normal se calcula como la media de las normales de los polígonos adyacentes.
• 2. Calcular la normal de los puntos interiores por interpolación lineal de las de los vértices.
• 3. Calculo de la intensidad:
– Calcularla en cada punto mediante el modelo de iluminación de Phong.
– Ahora se puede introducir también la reflexión especular

Ray Tracing
En muchas formas, ray tracing es una extensión al enfoque de rendering con un modelo de iluminación local. Está basado en la observación previa que, de los rayos de luz saliendo de una fuente, los únicos que contribuyen a la imagen son aquellos que entran al lente de la cámara sintética y pasan por el centro de proyección.

Buffer Stencil.
Stencill Buffer es una memoria intermedia que analiza y actualiza píxeles (con sus operaciones) junto con “depth buffer” o buffer de profundidad. Añade planos de bits adicionales para cada píxel además de los bits de color y profundidad.
 Stencil buffer es similar al buffer de profundidad en que los dos son colección de planos de bit que no se pueden mostrar. Del mismo modo que el buffer de profundidad asocia a cada píxel de la ventana un valor de profundidad, el stencil buffer asocia su propio valor a cada píxel mostrado. Cuando el buffer de profundidad esta activado los valores de profundidad son usados para aceptar o rechazar fragmentos, del mismo modo los valores de Stencil buffer son usados para aceptar o rechazar fragmentos.

Buffer de Acumulación
Normalmente se usa un buffer de acumulación para unir  dos imágenes

Fuentes de Luz
La luz puede dejar una superficie mediante dos procesos fundamentales:
              Emisión propia
              Reflexión
 Normalmente se piensa en una fuente de luz como un objeto que emite luz solo mediante fuentes de energía internas, sin embargo, una fuente de luz, como un foco, puede reflejar alguna luz incidente a esta del ambiente.

 Fuentes de Luz
La luz puede dejar una superficie mediante dos procesos fundamentales:
·         Emisión propia
·         Reflexión

Luz Ambiente
La luz ambiente ilumina por igual todas las zonas en sombra para simular el efecto de interacción entre objetos que hace que las partes en sombra de los objetos queden parcialmente iluminadas.

Spotlights (direccionales)
Los spotlights se caracterizan por un rango delgado de ángulos por los cuales se emite luz. Se puede construir un spotlight sencillo de una fuente de punto limitando los ángulos de donde la luz de la fuente se puede ver. Se puede usar un cono cuyo ápice está en ps, apuntando en la dirección ls, y cuyo ancho está determinado por el ángulo θ.
Fuentes:
http://cannes.itam.mx/Alfredo/Espaniol/Cursos/Grafica/Sombreado.pdf
http://dac.escet.urjc.es/docencia/IG/08-IluminacionSombreado4.pdf
http://sabia.tic.udc.es/gc/Tutorial%20OpenGL/tutorial/cap3.htm


martes, 17 de abril de 2012

Funciones para graficar círculos y elipses


Ecuación Ordinaria de la Circunferencia

Dados las coordenadas del centro de la circunferencia C(h;k) y el radio "r" de la misma, podemos utilizar la siguiente ecuación para determinar el valor de "y" correspondiente a un valor de "x".

Ejemplo:

Hallar la ecuación de la circunferencia cuyo centro es C(2;6) y con radio r = 4

(x - 2)² + (y - 6)² = 4²

Ecuación Canónica de la Circunferencia

Sean ahora las coordenadas del centro de la circunferencia C(0;0) y el radio "r", podemos utilizar la siguiente ecuación para determinar el valor de "y" correspondiente a un valor de "x".

Ejemplo:

Hallar la ecuación de la circunferencia cuyo centro es el origen y con radio r = 3

x ² + y ² = 3²



Forma cartesiana centrada en origen
La ecuación de una elipse en coordenadas cartesianas, con centro en el origen, es:
donde a > 0 y b > 0 son los semiejes de la elipse, donde si a corresponde al eje de las abscisas y b al eje de las ordenadas la elipse es horizontal, si es al revés, entonces es vertical. El origen O es la mitad del segmento [FF']. La distancia entre los focos FF' se llama distancia focal y vale 2c = 2ea, siendo e la excentricidad y a el semieje mayor.
Forma cartesiana centrada fuera del origen
Si el centro de la elipse se encuentra en el punto (h,k), la ecuación es:
Forma polar centrada en origen
En coordenadas polares, con origen en su centro, la ecuación de la elipse es:

Formas polares centradas en un foco



En coordenadas polares, con el origen en uno de sus focos, la ecuación de la elipse es:
REFERENCIAS:

lunes, 16 de abril de 2012

gluLookAt()

La función gluLookAt() en Open gl nos sirve para observar un objeto como si lo viéramos por una cámara que capta las imágenes.
Permite definir de forma específica donde se va a situar la cámara, hacía donde mirará ésta y cuál será el orden de los ejes de coordenadas.

gluLookAt(eyeX, eyeY, eyeZ, atX, atY, atZ, upX, upY, upZ)

Las primeras tres coordenadas es en que punto en el espacio se ubicara la cámara, las siguientes tres coordenadas es hacia que punto mirara la cámara y las ultimas tres es un vector en que tanto estará elevada la cámara para enfocar el punto al que se mira.

glTranslatef y GlutAt() se comportan de la misma manera en cuestion de que el objeto se puede ver como nosotros lo deseemos en un punto especifico la diferencia esta que en glTranslatef el obejto es movido, las coordenadas originales son modificadas, cambia su ubicacion en el espacio, mientras que en GlutAt() el objeto no es movido del espacio sino el angulo o forma en que se visualiza ese objeto por el lente de la "camara", lo que hace que se comporten de manera similar.


Ejecucion de codigo

domingo, 15 de abril de 2012

Carro con movimiento

#include
GLfloat anguloCuboX = 0.0f;
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.0f;
GLfloat TrasPisox=0.0f;
GLfloat TrasPisoy=0.0f;
GLfloat TrasPisoz=-5.0f;

GLfloat TrasRueda1x=3.0f;
GLfloat TrasRueda1y=0.5f;
GLfloat TrasRueda1z=-1.0f;

GLfloat TrasRueda2x=-0.5f;
GLfloat TrasRueda2y=0.5f;
GLfloat TrasRueda2z=-1.0f;

GLfloat TrasCarrox=0.0f;
GLfloat TrasCarroy=0.0f;
GLfloat TrasCarroz=-5.0f;

GLfloat e;
GLint ancho=400;
GLint alto=400;
int hazPerspectiva = 0;
void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(hazPerspectiva)
               gluPerspective(60.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f);
     else
       glOrtho(-4,4, -4, 4, 1, 10);
       glMatrixMode(GL_MODELVIEW);
    ancho = width;
    alto = height;
}
void Piso(void)
{
    glColor3f(0.0f, 0.0f, 1.0f);
    glScalef(1.5f,0.0f,1.5f);
    glBegin(GL_QUADS);       //cara abajo
    glVertex3f( 1.0f,-1.0f, -1.0f);
    glVertex3f( 1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f, -1.0f);
    glEnd();
}
void carro(void)
{
    glColor3f(1.0f, 0.0f, 1.0f);

    glBegin(GL_POLYGON);       //carro
    glVertex3f(-1.5f,0.5f, -2.0f);
    glVertex3f( 3.5f,0.5f, -2.0f);
    glVertex3f(3.5f,2.0f,  -2.0f);
    glVertex3f(2.0f,2.0f, -2.0f);
    glVertex3f(1.f,3.0f, -2.0f);
    glVertex3f(-0.5f,3.0f, -2.0f);
    glVertex3f(-1.5f,2.0f, -2.0f);
    glEnd();
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
glTranslatef(TrasPisox,TrasPisoy,TrasPisoz);
    glRotatef(15, 1.0f, 0.0f, 0.0f);
    glRotatef(15, 0.0f, 1.0f, 0.0f);
    // dibuja piso
    Piso();
 
// dibuja rueda
    glLoadIdentity();
    glTranslatef(TrasRueda1x,TrasRueda1y,TrasRueda1z);
    glColor3f(1.0f, 1.0f, 1.0f);
    glutSolidSphere(0.5f, 16, 16);
 
//dibuja 2da rueda
    glLoadIdentity();
    glTranslatef(TrasRueda2x,TrasRueda2y,TrasRueda2z);
    glColor3f(1.0f, 1.0f, 1.0f);
    glutSolidSphere(0.5f, 16, 16);


    glLoadIdentity();
    glTranslatef(TrasCarrox,TrasCarroy,TrasCarroz);
    glColor3f(1.0f, 1.0f, 1.0f);
    carro();
    glFlush();
    glutSwapBuffers();
}
void init()
{
    glClearColor(0,0,0,0);
    glEnable(GL_DEPTH_TEST);
    ancho = 400;
    alto = 400;
}
void idle()
{
    display();
}


void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'p':
    case 'P':
 hazPerspectiva=1;
 reshape(ancho,alto);
 break;
    case 'o':
    case 'O':
 hazPerspectiva=0;
 reshape(ancho,alto);
 break;
    case 'i':
    case 'I':

   TrasRueda1x-=.10;
   TrasRueda2x-=.10;
   TrasCarrox-=.10;

 break;

case 'd':
    case 'D':
    TrasRueda1x+=.10;
TrasRueda2x+=.10;
    TrasCarrox+=.10;

      break;
    }
}



int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(ancho, alto);
    glutCreateWindow("Carrito");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}




Piso y esfera

#include

GLfloat anguloCuboX = 0.0f;
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.0f;
GLfloat TrasEsferax= 3.0f;
GLfloat TrasEsferay= 0.0f;
GLfloat TrasEsferaz= -5.0f;

GLint ancho=400;
GLint alto=400;

int hazPerspectiva = 0;

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
   
    if(hazPerspectiva)
 gluPerspective(60.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f);
    else
 glOrtho(-6,6, -6, 6, 2, 12);
    glMatrixMode(GL_MODELVIEW);

    ancho = width;
    alto = height;
}

void drawCube(void)
{
    glColor3f(0.0f, 1.0f, 1.0f);
    glBegin(GL_QUADS);       //piso
    glVertex3f( 1.0f,-1.0f, -1.0f);
    glVertex3f( 1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f, -1.0f);
    glEnd();
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -5.0f);

   glRotatef(5, 1.0f, 0.0f, 0.0f);
   glRotatef(5, 0.0f, 1.0f, 0.0f);
    drawCube();
    glLoadIdentity();
    glTranslatef(TrasEsferax,TrasEsferay,TrasEsferaz);

    glColor3f(1.0f, 1.0f, 0.0f);
    glutWireSphere(0.3f, 6, 6);
    glFlush();
    glutSwapBuffers();

}
void init()
{
    glClearColor(0,0,0,0);
    glEnable(GL_DEPTH_TEST);
    ancho = 400;
    alto = 400;
}

void idle()
{
    display();
}

void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'p':
    case 'P':
 hazPerspectiva=1;
 reshape(ancho,alto);
 break;

    case 'o':
    case 'O':
 hazPerspectiva=0;
 reshape(ancho,alto);
 break;
 case 'i':
    case 'I':
    TrasEsferax-=1.0;
  break;
 case 'D':
    case 'd':
    TrasEsferax+=1.0;
  break;
 case 'A':
    case 'a':
    TrasEsferay+=1.0;
  break;
 case 'B':
    case 'b':
    TrasEsferay-=1.0;
  break;
 case 'c':
    case 'C':
    TrasEsferaz+=0.5;
  break;
 
 case 'l':
    case 'L':
    TrasEsferaz-=0.5;
  break;

    }
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(ancho, alto);
    glutCreateWindow("Piso_pelota");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}

lunes, 26 de marzo de 2012

Representación de objetos en 3 dimensiones y visualización de objetos

Matrices
Las matemáticas que hay tras estas transformaciones se simplifican gracias a las matrices. Cada una de las transformaciones de las que se acaba de hablar puede conseguirse multiplicando una matriz que contenga los vértices por una matriz que describa la transformación.

Ejemplos de matrices en OpenGL:
void glMatrixMode( enum mode ); Permite seleccionar la matriz sobre la cual se realizaran las operaciones, los posibles valores de mode son TEXTURE, MODELVIEW, COLOR o PROJECTION . Por ahora las más interesantes son MODELVIEW y PROJECTION, las otras se verán en su momento.

Void glLoadMatrix{fd} (T m[16]); Recibe una matriz de 4×4 que reemplaza la actual seleccionada. El arreglo es ordenado en forma de una matriz que tiene orden Y, a diferencia de las matrices convencionales que tienen orden X, lo que quiere decir que tiene la forma

void glMultMatrix{fd}( T m[16] ); Multiplica la matriz actual por la matriz m[16] y reemplaza la matriz actual con el resultado de la operación. La operación resultante sería algo así como A’ = A M , donde A es la matriz actual, M es la matriz suministrada y A’ es la nueva matriz que resulta de la operación y que reemplaza a A.

void glLoadTransposeMatrix{fd}( T m[16] ); Realiza una función similar a LoadMatrix(), con la diferencia que trabaja sobre una matriz en orden X así: que es evidentemente la transpuesta de la m que recibe LoadMatrix.

void glPushMatrix( void ); Coloca una copia de la matriz actual en la parte superior de la pila correspondiente.

void glPopMatrix( void ); Saca el elemento superior de la pila, que pasa a reemplazar a la matriz actual.
void glGetFloatv(enum value, float *data); Permite obtener una copia de aquello que se indica en value. Por ejemplo si se pasan como parámetros MODELVIEW_MATRIX y un apuntador a un arreglo de flotantes tamaño 16 se obtiene una copia de dicha matriz a través del arreglo.

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”.

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.

Coordenadas oculares
Las coordenadas oculares se sitúan en el punto de vista del observador, sin importar las transformaciones que tengan lugar. Por tanto, estas coordenadas representan un sistema virtual de coordenadas fijo usado como marco de referencia común.

Transformaciones
Las transformaciones son las que hacen posible la proyección de coordenadas 3D sobre superficies 2D. También son las encargadas de mover, rotar y escalar objetos. En realidad, estas transformaciones no se aplican a los modelos en sí, si no al sistema de coordenadas, de forma que si se quiere rotar un objeto, no lo se le rota, sino que se rota el eje sobre el que se sitúa.

El modelador
En esta sección se recogen las transformaciones del observador y del modelado puesto que, como se verá en el apartado 4.2.1.3, constituyen, al fin y al cabo, la misma transformación.

Transformaciones del observador

La transformación del observador es la primera que se aplica a la escena, y se usa para determinar el punto más ventajoso de la escena. Por defecto, el punto de vista está en el origen (0,0,0) mirando en dirección negativa del eje z. La transformación del observador permite colocar y apuntar la cámara donde y hacia donde se quiera. Todas las transformaciones posteriores tienen lugar basadas en el nuevo sistema de coordenadas modificado.


Transformaciones del modelo
Estas transformaciones se usan para situar, rotar y escalar los objetos de la escena. La apariencia final de los objetos depende en gran medida del orden con el que se hayan aplicado las transformaciones.

Transformaciones de la proyección
 La transformación de proyección se aplica a la orientación final del modelador. Esta proyección define el volumen de visualización y establece los planos de trabajo.

Transformaciones de la vista
 En el momento en que se ha terminado todo el proceso de transformaciones, solo queda un último paso: proyectar lo que hemos dibujado en 3D al 2D de la pantalla, en la ventana en la que estamos trabajando. 

Matrices

 Las matemáticas que hay tras estas transformaciones se simplifican gracias a las matrices. Cada una de las transformaciones de las que se acaba de hablar puede conseguirse multiplicando una matriz que contenga los vértices por una matriz que describa la transformación. Por tanto todas las transformaciones ejecutables con ogl pueden describirse como la multiplicación de dos o más matrices.

El canal de transformaciones

 Para poder llevar a cabo todas las transformaciones de las que se acaba de hablar, deben modificarse dos matrices: la matriz del Modelador y la matriz de Proyección. OpenGL proporciona muchas funciones de alto nivel que hacen muy sencillo la construcción de matrices para transformaciones. Éstas se aplican sobre la matriz que este activa en ese instante. Para activar una de las dos matrices utilizamos la función glMatrixMode.

La matriz del modelador

La matriz del modelador es una matriz 4x4 que representa el sistema de coordenadas transformado que se está usando para colocar y orientar los objetos. Si se multiplica la matriz del vértice (de tamaño 1x4) por ésta se obtiene otra matriz 1x4 con los vértices transformados sobre ese sistema de coordenadas.