jueves, 29 de marzo de 2012

Graficacion 3D "Unidad 3"

Enlace 1:
Configuración:
instalación:
Hardware:

El API de OpenGL está pensado para trabajar bajo el respaldo de un hardware capaz de realizar las operaciones necesarias para el renderizado, pero si no se dispone de ese hardware, estas operaciones se calcularan por medio de un software contra la CPU del sistema.

Windows:

Cualquier versión de windows viene con las librerías necesarias para ejecutar cualquier aplicación que utilice OpenGL. Para el desarrollo de las mismas, el Microsoft Visual Studio, y en particular Visual C++ trae también todo lo necesario.

Linux:

Para visualizar aplicaciones OpenGL en XFree86 necesitarás instalar un paquete para el soporte de las librerías Mesa (que es el equivalente en software libre de OpenGL) y de las utilidades GLU y GLUT. Para realizar desarrollo necesitarás, a mayores, los paquetes equivalentes en modo dev.

Tutorial:

Qué es OpenGL?

Es una interfaz software de hardware gráfico. Es un motor 3D cuyas rutinas están integradas en tarjetas gráficas 3D.

OpenGL como máquina de estados:

Cuando se activan o configuran varios estados de la máquina, sus efectos perdurarán hasta que sean desactivados.

El pipeline de renderizado de OpenGL:

La mayor parte de las implementaciones de ogl siguen un mismo orden en sus operaciones, una serie de plataformas de proceso que, en su conjunto crean lo que se suele llamar el “OpenGL Rendering Pipeline”.




Escribir código basado en OpenGL:

Sintaxis:

Todas las funciones de ogl comienzan con el prefijo “gl” y las constantes con “GL_”. Como ejemplos, la función glClearColor() y la constante GL_COLOR_BUFFER_BIT.
En ogl existen 8 tipos distintos de datos, de una forma muy parecida a los tipos de datos de C o C++. Además, ogl viene con sus propias definiciones de estos datos (typedef en C).

Sufijo
Tipo de dato
Corresponde en C al tipo...
Definición en ogl del tipo
b
Entero 8-bits
signed char
GLbyte
s
Entero 16-bits
short
GLshort
i
Entero 32-bits
int o long
GLint, GLsizei
f
Punto flotante 32-bits
float
GLfloat, GLclampf
d
Punto flotante 64-bits
double
GLdouble, GLclampd
ub
Entero sin signo 8-bits
unsigned char
GLubyte, GLboolean
us
Entero sin signo 16-bits
unsigned short
GLushort
ui
Entero sin signo 32-bits
unsigned int
GLuint,GLenum, GLbitfield



Librerías relacionadas con OpenGL:


OpenGL contiene un conjunto de poderosos pero primitivos comandos de muy bajo nivel. Además la apertura de una ventana donde pintar, en el sistema grafico que utilicemos (win32, X11, etc.), no entra en el ámbito de OpenGL. Por eso las siguientes librerías son muy utilizadas en la programación de aplicaciones de ogl:
OpenGL Utility Library (GLU): contiene bastantes rutinas que usan ogl a bajo nivel para realizar tareas como transformaciones de matrices, para tener una orientación especifica, subdivisión de polígonos, etc.
GLX y WGL: GLX da soporte para máquinas que utilicen X Windows System, para inicializar una ventana, etc. WGL sería el equivalente para sistemas Microsoft.
OpenGL Utility Toolkit (GLUT): es un sistema de ventanas, escrito por Mark Kilgard, que es independiente del sistema de ventanas usado, dándonos funciones tipo abrir_ventana().

Hello Word:

#include <GL/glut.h>
void reshape(int width, int height){ glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -1, 1); glMatrixMode(GL_MODELVIEW);} void display(){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1,1,1); glLoadIdentity(); glBegin(GL_TRIANGLES); glVertex3f(-1,-1,0); glVertex3f(1,-1,0); glVertex3f(0,1,0); glEnd(); glFlush();} void init(){ glClearColor(0,0,0,0);} int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(500, 500); glutCreateWindow("Hello OpenGL"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0;}

Dibujando en 3D:

El dibujo 3D en OpenGL se basa en la composición de pequeños elementos, con los que se va construyendo la escena deseada. Estos elementos se llaman primitivas. Todas las primitivas de ogl son objetos de una o dos dimensiones, abarcando desde simples puntos y líneas, a polígonos complejos. Las primitivas se componen de vértices, que no son más que puntos 3D. En este capítulo se pretende presentar las herramientas necesarias para dibujar objetos en 3D a partir de estas formas más sencillas. Para ello hay que deshacerse de la mentalidad en 2D de la computación gráfica clásica y definir el nuevo espacio de trabajo, ya en 3D.

Moviendonos por nuestro espacio en 3D:

#include <GL/glut.h>

GLfloat anguloCuboX = 0.0f; 
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.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(-4,4, -4, 4, 1, 10); 
     glMatrixMode(GL_MODELVIEW);      
     ancho = width;    alto = height; 
} 
 void drawCube(void){     
     glColor3f(1.0f, 0.0f, 0.0f);     
     glBegin(GL_QUADS);       //cara frontal     
     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();     
     glColor3f(0.0f, 1.0f, 0.0f);

    glBegin(GL_QUADS);       //cara trasera 
    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(); 
    glColor3f(0.0f, 0.0f, 1.0f); 
    glBegin(GL_QUADS);       //cara lateral izq 
    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(); 
    glColor3f(1.0f, 1.0f, 0.0f);     
    glBegin(GL_QUADS);       //cara lateral dcha 
    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(); 
    glColor3f(0.0f, 1.0f, 1.0f);     
    glBegin(GL_QUADS);       //cara arriba     
    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();  
   glColor3f(1.0f, 0.0f, 1.0f);     
   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 display(){ 
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      
   glLoadIdentity();  
   glTranslatef(0.0f, 0.0f, -5.0f);      
   glRotatef(anguloCuboX, 1.0f, 0.0f, 0.0f); 
   glRotatef(anguloCuboY, 0.0f, 1.0f, 0.0f);  
   drawCube();      
   glLoadIdentity();  
   glTranslatef(0.0f, 0.0f, -5.0f);     
   glRotatef(anguloEsfera, 0.0f, 1.0f, 0.0f); 
   glTranslatef(3.0f, 0.0f, 0.0f);      
   glColor3f(1.0f, 1.0f, 1.0f);     
   glutWireSphere(0.5f, 8, 8);  
   glFlush();     
   glutSwapBuffers();      
   anguloCuboX+=0.1f; 
   anguloCuboY+=0.1f; 
   anguloEsfera+=0.2f; 
} 
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 27:   // escape       
                exit(0); 
                break; 
 } 
 int main(int argc, char **argv){     
   glutInit(&argc, argv); 
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
   glutInitWindowPosition(100, 100); 
   glutInitWindowSize(ancho, alto);     
   glutCreateWindow("Cubo 1");     
   init();     
   glutDisplayFunc(display);     
   glutReshapeFunc(reshape);     
   glutIdleFunc(idle); 
   glutKeyboardFunc(keyboard); 
   glutMainLoop(); 
   return 0; 

Enlace 2:

Proyección: Trasforman una escena 3d “abstracta”, en una imagen plana que puede ser visualizada en una pantalla.
Viewport: Ajustan el producto de la proyección a las dimensiones de un rectángulo contenedor (ventana).
De vista: Que definen y afectan la posición desde la cual se visualizan las escenas tridimensionales.
Modelado: Sirven para manipular los objetos en la escena, permitiendo trasladarlos, rotarlos y deformarlos (escalarlos).
Modelo-Vista: Son la combinación de las dos transformaciones anteriores, que desde un punto de vista práctico son semejantes.
 
 
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: m = [a1 ,a2 ,a3 ,a4 ,a5 ,a6 ,a7 ,a8 ,a9 ,a10, a11, a12, a13, a14, a15, a16]
es interpretada internamente por OpenGL como:

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.

Enlace 3:

Proyección:

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);

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)


glu ofrece una versión alternativa, mucho más fácil de entender:

void gluPerspective(GLdouble fov, GLdouble aspect, GLdouble near, GLdouble far);
  
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.

Enlace 4:

Enlace 5:

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

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

4.2.1 El modelador.

Se recogen las transformaciones del observador y del modelado.

4.2.1.2 Transformaciones del modelo.

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.

4.2.2 Transformaciones de la 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.

4.2.3 Transformaciones de la vista.

Proyectar lo que hemos dibujado en 3D al 2D de la pantalla, en la ventana en la que estamos trabajando. Esta es la denominada transformación de la vista.

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

4.3.1 El canal de transformaciones.

Beben modificarse dos matrices: la matriz del Modelador y la matriz de Proyección. Para activar una de las dos matrices utilizamos la función glMatrixMode. Hay dos parámetros posibles:

glMatrixMode(GL_PROJECTION);
 
y
 
glMatrixMode(GL_PROJECTION);
 
 
4.3.2 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.

4.3.2.1 Translacion.

Los parámetros de glTranslate son las unidades a desplazar en el eje x, y y z, respectivamente. Pueden ser valores negativos, para trasladar en el sentido contrario.

4.3.2.2 Rotacion.

Para rotar, tenemos también una función de alto nivel que construye la matriz de transformación y la multiplica por la matriz activa, glRotate. Lleva como parámetros el ángulo a rotar (en grados, sentido horario), y después x, y y z del vector sobre el cual se quiere rotar el objeto.

4.3.2.3 Escalado.

Una transformación de escala incrementa el tamaño de nuestro objeto expandiendo todos los vértices a lo largo de los tres ejes por los factores especificados.

4.3.3 La matriz de proyección.

Especifica el tamaño y la forma del volumen de visualización. El volumen de visualización es aquel cuyo contenido es el que se representa en pantalla. 

4.3.3.1 Proyección ortográfica.

Una proyección ortográfica es cuadrada en todas sus caras. Esto produce una proyección paralela, útil para aplicaciones de tipo CAD o dibujos arquitectónicos, o también para tomar medidas, ya que las dimensiones de lo que representan no se ven alteradas por la proyección.

4.3.3.2 Proyecciones perspectivas.

Una proyección en perspectiva reduce y estirar los objetos más alejados del observador. Es importante saber que las medidas de la proyección de un objeto no tienen por qué coincidir con las del objeto real, ya que han sido deformadas.

 

jueves, 22 de marzo de 2012

Rebote de pelota

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#define WIDTH 640
#define HEIGHT 480
  
    void reshape(int width, int height){
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-WIDTH/2,WIDTH/2-1,-HEIGHT/2,HEIGHT/2-1,-1,1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
     glColor3f(1.0,1.0,0.0);
        glBegin (GL_LINES);
    }
  
    void init(void){
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPointSize(0.0);
 
 
    }
  
    void Timer(int ex)
    {
  
  
    glutPostRedisplay();
    glutTimerFunc(30,Timer,0);
    }
  
    int k=20;
    void circle(int p,int m)
    {
    int x=0,y,d,r;
    r=m;
    y=r;
    d=3-2*r;
    while(x<=y)
    {
    glVertex2i(-x,y+p);
     glVertex2i(x,y+p);
    glVertex2i(y,x+p);
    glVertex2i(-x,y+p);
    glVertex2i(-y,x+p);
    glVertex2i(-x,-y+p);
    glVertex2i(-y,-x+p);
    glVertex2i(y,-x+p);
   glVertex2i(x,-y+p);
    if(d<0)
    d=d+4*x+6;
    else
    {
    d=d+4*(x-y)+10;
    y--;
    }
    x++;
    }
    }
  
int r=50,flag=0;
  
    void display(void)
    {
  
           typedef GLfloat point2[2];
  point2 vertice[6] = {
  {-100.0,-100.0},
  {-500.0,-100.0},
  {-50.0,50.0},
  {-50.0,50.0},
  {100.0,50.0},
  {100.0,50.0}
 };
  glColor3f(1.5,0.0,0.0);
  {
   glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_QUADS);
          glVertex2f (-500.0, -240.0);
          glVertex2f (500.0, -240.0);
          glVertex2f (100.0, -100.0);
          glVertex2f (-500.0, -200.0);
           glVertex2f (100.0, -300.0);
          glVertex2f (100.0, -200.0);
           glVertex2f (100.0, -300.0);
          glVertex2f (100.0, -200.0);
    }
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.1,0.5,1.0);
    glBegin(GL_POINTS);
    circle(k,r);
  
  
    if(flag==0)
    {
    if((k+r)<=240)
    {
    k=k+10;
  
    }
  
    if((k+r)>=240){
    flag=1;
  
    }
    }
  
    if(flag==1)
    {
    k=k-10;
  
  
    if((k-r)<=-210)
    {
flag=0;
}
    }
  
    glEnd();
    glutSwapBuffers();
    }
  
void idle(void){
 
}
  
    int main(int argc, char **argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowPosition(0,0);
    glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow(argv[0]);
init();
glutIdleFunc(idle);
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutTimerFunc(0,Timer,0);
    glutMainLoop();
    return(1);
    }




miércoles, 14 de marzo de 2012

Cubo en 3D

#include <gl/glut.h>
GLfloat angr, delta;
GLfloat z;

void idleevent()
{
 angr += delta;
 glutPostRedisplay();
}
void displayevent(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glEnable( GL_DEPTH_TEST );
 glLoadIdentity();
 glTranslatef( -0.5, -0.5, z );
 glRotatef( angr, 0,1,0 );
 glColor3f(0,0,1);
 glBegin( GL_QUADS ); // frontal
  glVertex3f( 0,  0,  0 );
  glVertex3f( 1,  0,  0 );
  glVertex3f( 1,  1,  0 );
  glVertex3f( 0,  1,  0 );
 glEnd();
 glColor3f(0,1,0);
 glBegin( GL_QUADS ); // lateral derecha
  glVertex3f( 1, 0,  0 );
  glVertex3f( 1, 0, -1 );
  glVertex3f( 1, 1, -1 );
  glVertex3f( 1, 1,  0 );
 glEnd();
 glColor3f(1,0,0);
 glBegin( GL_QUADS ); // superior
  glVertex3f( 0, 1,  0 );
  glVertex3f( 1, 1,  0 );
  glVertex3f( 1, 1, -1 );
  glVertex3f( 0, 1, -1 );
 glEnd();
 glColor3f(0,1,1);
 glBegin ( GL_QUADS ); //lateral izquierda
  glVertex3f(  0,  0,  0 );
  glVertex3f(  0,  0, -1 );
  glVertex3f(  0,  1, -1 );
  glVertex3f(  0,  1,  0 );
 glEnd();
 glColor3f(1,0,1);
 glBegin ( GL_QUADS ); //tracera
  glVertex3f( 0,  0, -1 );
  glVertex3f( 1,  0, -1 );
  glVertex3f( 1,  1, -1 );
  glVertex3f( 0,  1, -1 );
 glEnd();
 glColor3f(1,1,0);
 glBegin ( GL_QUADS ); //inferior
  glVertex3f( 0,  0,  0 );
  glVertex3f( 1,  0,  0 );
  glVertex3f( 1,  0, -1 );
  glVertex3f( 0,  0, -1 );
 glEnd();
 glutSwapBuffers();
}
void specialkeyevent( int key, int Xx, int Yy )
{

 switch ( key ) {
 case GLUT_KEY_UP:    z += 0.1;
  break;
 case GLUT_KEY_DOWN:  z -= 0.1;
  break;
  case GLUT_KEY_F1:    delta += 0.1;
  break;
 case GLUT_KEY_F2:    delta -= 0.1;
  break;
 }
 glutPostRedisplay();
}
void reshapeevent(GLsizei width, GLsizei height)
{
 glViewport(0,0,width,height);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(40,(GLfloat)width/(GLfloat)height,  0.01, 20);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}

int main(int argc, char** argv)
{
 glutInit( &argc, argv );
 glutInitWindowSize( 300, 300 );
 glutInitWindowPosition( 100, 100 );
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
    glutCreateWindow( "" );
 glutSetWindowTitle( "Cubo" );
 delta  = 0;
 angr  = 0;
 z = -5;
    glutReshapeFunc (reshapeevent);
 glutDisplayFunc( displayevent );
 glutSpecialFunc( specialkeyevent );
 glutIdleFunc( idleevent );
 glutMainLoop();
 return 0;
}

martes, 13 de marzo de 2012

Investigacion.

1.Proyección en OpenGL.
Ortogonal:
# Include <GL / gl.h>
#include < GL / glut.h > # Include <GL / glut.h>
#include < windows.h > # Include <windows.h>
#include < stdio.h > # Include <stdio.h>



int w1; int w1;
int h1; int h1;


void orthogonalStart ( void ) { orthogonalStart vacío (void) {
glMatrixMode ( GL_PROJECTION ) ; glMatrixMode (GL_PROJECTION);
glPushMatrix ( ) ; glPushMatrix ();
glLoadIdentity ( ) ; glLoadIdentity ();
gluOrtho2D ( 0, w1, 0, h1 ) ; gluOrtho2D (0, w1, 0, H1);
glScalef ( 1, - 1, 1 ) ; glScalef (1, - 1, 1);
glTranslatef ( 0, - h1, 0 ) ; glTranslatef (0, - h1, 0);
glMatrixMode ( GL_MODELVIEW ) ; glMatrixMode (GL_MODELVIEW);
} }


void orthogonalEnd ( void ) { orthogonalEnd vacío (void) {
glMatrixMode ( GL_PROJECTION ) ; glMatrixMode (GL_PROJECTION);
glPopMatrix ( ) ; glPopMatrix ();
glMatrixMode ( GL_MODELVIEW ) ; glMatrixMode (GL_MODELVIEW);
} }


void display ( void ) { void display (void) {
glClearColor ( 1.0,0.0,0.0,1.0 ) ; glClearColor (1.0,0.0,0.0,1.0);
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ( ) ; glLoadIdentity ();


orthogonalStart ( ) ; orthogonalStart ();

glBegin ( GL_QUADS ) ; glBegin (GL_QUADS);
glVertex2f ( 125, 125 ) ; glVertex2f (125, 125);
glVertex2f ( 125, 375 ) ; glVertex2f (125, 375);
glVertex2f ( 375, 375 ) ; glVertex2f (375, 375);
glVertex2f ( 375, 125 ) ; glVertex2f (375, 125);
glEnd ( ) ; glEnd ();


orthogonalEnd ( ) ; orthogonalEnd ();

glutSwapBuffers ( ) ; glutSwapBuffers ();
} }


void reshape ( int w, int h ) { anular remodelar (int w, int h) {
glViewport ( 0, 0, ( GLsizei ) w, ( GLsizei ) h ) ; glViewport (0, 0, (GLsizei) w, (GLsizei) yh);
glMatrixMode ( GL_PROJECTION ) ; glMatrixMode (GL_PROJECTION);
glLoadIdentity ( ) ; glLoadIdentity ();
gluPerspective ( 60, ( GLfloat ) w / ( GLfloat ) h, 0.1, 1000.0 ) ; gluPerspective (60, (GLfloat) W / (GLfloat) h, 0,1, 1000,0);
w1 = w; w1 = w;
h1 = h; h1 = h;
glMatrixMode ( GL_MODELVIEW ) ; glMatrixMode (GL_MODELVIEW);
} }


int main ( int argc, char * * argv ) { int main (int argc, char ** argv) {
glutInit ( & argc, argv ) ; glutInit (& argc, argv);
glutInitDisplayMode ( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA
) ; );
glutInitWindowSize ( 500, 500 ) ; glutInitWindowSize (500, 500);
glutInitWindowPosition ( 100, 100 ) ; glutInitWindowPosition (100, 100);
glutCreateWindow ( “A Basic Window) ; glutCreateWindow ("Una ventana de base");
glutDisplayFunc ( display ) ; glutDisplayFunc (pantalla);
glutIdleFunc ( display ) ; glutIdleFunc (pantalla);
glutReshapeFunc ( reshape ) ; glutReshapeFunc (reformar);
glutMainLoop ( ) ; glutMainLoop ();
return 0; return 0;
} }


Perspectiva:
#include <GL/gl.h>
#include <GL/glut.h>


long v[8][3] = {
 {-1, -1, -1},
 {-1, -1,  1},
 {-1,  1,  1},
 {-1,  1, -1},
 { 1, -1, -1},
 { 1, -1,  1},
 { 1,  1,  1},
 { 1,  1, -1}
};
int path[16] = {
 0, 1, 2, 3,
 0, 4, 5, 6,
 7, 4, 5, 1,
 2, 6, 7, 3
};

void drawcube() {
 int i;

 glClear(GL_COLOR_BUFFER_BIT);
 glColor3f(0.0, 0.0, 0.0); 

 glBegin(GL_LINE_STRIP);
 for (i=0; i < 16; i++)
  glVertex3i(v[path[i]][0], v[path[i]][1], v[path[i]][2]);
 glEnd();
 glFlush();
}

main(int argc, char **argv) {
 glutInit(&argc, argv);
 glutInitWindowSize(600, 400);
 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
 glutCreateWindow("glLookat example");

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(30.0, 1.5, 0.1, 10.0);
 gluLookAt(5.0, 4.0, 6.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0);
       
 glMatrixMode(GL_MODELVIEW);

 glClearColor(1.0, 1.0, 1.0, 0.0);  /* white */

 glutDisplayFunc(drawcube);
 glutMainLoop();
 return 0;
}

2.Transformaciones geometricas:

Ejemplo de rotación, traslación y escalar.
/*
 Programa que demuestra la ejecución de transformaciones del tipo
 mover, rotar, escalar en 3D de modo interactivo mediante el mouse.
 Se utiliza un sistema de menú para la selección de las distintas operaciones.
*/ 

#include <GL/glut.h>
#include <GL/glaux.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

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

struct Face
 {
 int vertexIndices[3];
 int smoothingGroup;
 Point3f normal[3];
 Point3f faceNormal;
 };

struct Object3D
 {
 int nVertices;
 Point3f *pVertices;   
 int nFaces;
 Face *pFaces;      
 };

enum {ROT_EJE_X, ROT_EJE_Y, ROT_EJE_Z,
   MOV_EJE_X,MOV_EJE_Y,MOV_EJE_Z,MOV_EJE_XY,   
   SCAL_EJE_X,SCAL_EJE_Y,SCAL_EJE_Z,SCAL_EJE_XYZ};
Object3D obj;
int moving, begin_x,begin_y;
int newModel = 1;
GLfloat trasl_x, trasl_y;
GLfloat escala_x, escala_y;
GLfloat angle =0.f;
GLboolean ROTAR=FALSE;
GLboolean MOVER=FALSE;
GLboolean ESCALAR=FALSE;
GLfloat EJE_X=0.0;
GLfloat EJE_Y=0.0;
GLfloat EJE_Z=0.0;
float LightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f};         
float LightAmb[] = { 0.2f, 0.2f, 0.2f, 1.0f};         
float LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f};           
float LightSpc[] = { 0.5f, 0.5f, 0.5f, 1.0f};   

void CargarModelo(char *filename, Object3D &object)
{
 FILE  *file;
 char  *tempString = new char [80];
 char  trash[15];
 float tempX, tempY, tempZ;
 int   tempA, tempB, tempC;
 int   indexSmoothing;
 int   i;
 
 if((file = fopen(filename, "rt"))==NULL)
 {
 printf("File Not Found : %s\n",filename);
 exit(1);
 }
 while(strncmp(tempString, "Vertices",8))
 {
 fscanf(file, "%s", tempString);
 if (feof(file))
  {
  printf("String \"Vertices\" no existe\n");
  exit(1);
  }
 }
 fgetc(file);    
 fscanf(file, "%d", &object.nVertices);
 object.pVertices = new Point3f[object.nVertices];
 for (i=0; i<object.nVertices; i++)
 {
  fscanf(file, "%f %f %f\n", &tempX, &tempY, &tempZ);
 object.pVertices[i].x=tempX;
 object.pVertices[i].y=tempY;
 object.pVertices[i].z=tempZ;
 }
 while(strncmp(tempString, "Faces",5))
 {
 fscanf(file, "%s", tempString);
 if (feof(file))
  {
  printf("String \"Faces\" no existe\n");
  exit(1);
  }
 }
 fgetc(file);    
 fscanf(file, "%d", &object.nFaces);
 object.pFaces = new Face[object.nFaces];
 for (i=0; i<object.nFaces; i++)
 {
  fscanf(file, "%d %d %d\n", &tempA, &tempB, &tempC);
 fscanf(file, "%s %d\n", &trash, &indexSmoothing);
 object.pFaces[i].vertexIndices[0]=tempA;
 object.pFaces[i].vertexIndices[1]=tempB;
 object.pFaces[i].vertexIndices[2]=tempC;
 object.pFaces[i].smoothingGroup=indexSmoothing;
 }
}


void applySmoothingGroups(Object3D &object)
{
int i,j,k,l,smoothingGroup;
float length;

for (i=0; i<object.nFaces; i++)
 {
 smoothingGroup = object.pFaces[i].smoothingGroup;
 for (j=i+1; j<object.nFaces; j++)
  {
  if (smoothingGroup == object.pFaces[j].smoothingGroup)
   {
   for (k=0; k<3; k++)
    {
    for (l=0; l<3; l++)
     {
     if (object.pFaces[i].vertexIndices[k] == object.pFaces[j].vertexIndices[l])
      {
      object.pFaces[i].normal[k].x += object.pFaces[j].faceNormal.x;
      object.pFaces[i].normal[k].y += object.pFaces[j].faceNormal.y;
      object.pFaces[i].normal[k].z += object.pFaces[j].faceNormal.z;
      object.pFaces[j].normal[l].x += object.pFaces[i].faceNormal.x;
      object.pFaces[j].normal[l].y += object.pFaces[i].faceNormal.y;
      object.pFaces[j].normal[l].z += object.pFaces[i].faceNormal.z;
      }
     }
    }
   }
  }
 for (k=0; k<3; k++)
  {
  length = sqrt(pow(object.pFaces[i].normal[k].x,2.0) +
          pow(object.pFaces[i].normal[k].y,2.0) +
          pow(object.pFaces[i].normal[k].z,2.0));

  if (length == 0)
   {
   object.pFaces[i].normal[k].x = 1;
   object.pFaces[i].normal[k].y = 1;
   object.pFaces[i].normal[k].z = 1;
   }
  else
   {
   object.pFaces[i].normal[k].x /= length;
   object.pFaces[i].normal[k].y /= length;
   object.pFaces[i].normal[k].z /= length;
   }
  }
 }
}


void CalcularNormales(Object3D &object)
{
 float x1, y1, z1;
 float x2, y2, z2;
 float x3, y3, z3;
 float length;
 int   a, b, c;
 int   i;

 for (i=0; i<object.nFaces; i++)
 {
 Face& face = object.pFaces[i];
 a = face.vertexIndices[0];
 b = face.vertexIndices[1];
 c = face.vertexIndices[2];
 x1 = object.pVertices[b].x - object.pVertices[a].x;
 y1 = object.pVertices[b].y - object.pVertices[a].y;
 z1 = object.pVertices[b].z - object.pVertices[a].z;
 x2 = object.pVertices[c].x - object.pVertices[a].x;
 y2 = object.pVertices[c].y - object.pVertices[a].y;
 z2 = object.pVertices[c].z - object.pVertices[a].z;
 z3 = x1*y2 - y1*x2;
 x3 = y1*z2 - z1*y2;
 y3 = z1*x2 - x1*z2;
 length = sqrt(x3*x3 + y3*y3 + z3*z3);
 if (length == 0)
  {
  face.faceNormal.x=1;
  face.faceNormal.y=1;
  face.faceNormal.z=1;
  }
 else
  {
  face.faceNormal.x=x3/length;
  face.faceNormal.y=y3/length;
  face.faceNormal.z=z3/length;
  }
 face.normal[0].x=face.normal[1].x=face.normal[2].x=face.faceNormal.x;
 face.normal[0].y=face.normal[1].y=face.normal[2].y=face.faceNormal.y;
 face.normal[0].z=face.normal[1].z=face.normal[2].z=face.faceNormal.z;
 }
}


void killObject(Object3D &object)
{
 delete[] object.pFaces;
 object.pFaces = NULL;
 object.nFaces = 0;
 delete[] object.pVertices;
 object.pVertices = NULL;
 object.nVertices = 0;
}


void mouse(int button, int state, int x, int y)
{
 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
 moving = 1;
 begin_x = x;
 begin_y = y;
 }
 if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
 moving = 0;
 }
}


void movimiento(int x, int y)
{ //Captura el movimiento del mouse.
 if (moving) {  
 trasl_x=(GLfloat)(x - begin_x)/100.0;
 trasl_y=(GLfloat)(y - begin_y)/100.0;
 angle = (GLfloat)(x - begin_x)/5.0;
 escala_x=(GLfloat)(x - begin_x)/20.0;
 if(escala_x < -0.9f) 
  escala_x=-0.9;
 begin_x = x;
 begin_y = y;
 newModel = 1;
 glutPostRedisplay();
 }
}


void controlTransf(int value)
{//Casos del menu de opciones.
 switch (value)
 {
 //printf (" Se ha seleccionado la opcion de rotar en el eje X\n");
 case ROT_EJE_X:
  ROTAR=TRUE;
  MOVER=FALSE;
  ESCALAR=FALSE;
  EJE_X=1.0;
  EJE_Y=0.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de rotar en el eje Y\n");
 case ROT_EJE_Y:
  ROTAR=TRUE;
  MOVER=FALSE;
  ESCALAR=FALSE;
  EJE_X=0.0;
  EJE_Y=1.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de rotar en el eje Z\n");
 case ROT_EJE_Z:
  ROTAR=TRUE;
  MOVER=FALSE;
  ESCALAR=FALSE;
  EJE_X=0.0;
  EJE_Y=0.0;
  EJE_Z=1.0;
  break;
 //printf (" Se ha seleccionado la opcion de mover en el eje X\n");
 case MOV_EJE_X:
  ROTAR=FALSE;
  MOVER=TRUE;
  ESCALAR=FALSE;
  EJE_X=1.0;
  EJE_Y=0.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de mover en el eje Y\n");
 case MOV_EJE_Y:
  ROTAR=FALSE;
  MOVER=TRUE;
  ESCALAR=FALSE;
  EJE_X=0.0;
  EJE_Y=1.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de mover en el eje Z\n");
 case MOV_EJE_Z:
  ROTAR=FALSE;
  MOVER=TRUE;
  ESCALAR=FALSE;
  EJE_X=0.0;
  EJE_Y=0.0;
  EJE_Z=1.0;
  break;
 //printf (" Se ha seleccionado la opcion de mover en los ejes XY\n");
 case MOV_EJE_XY:
  ROTAR=FALSE;
  MOVER=TRUE;
  ESCALAR=FALSE;
  EJE_X=1.0;
  EJE_Y=1.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de escalar en el eje X\n");
 case SCAL_EJE_X:
  ROTAR=FALSE;
  MOVER=FALSE;
  ESCALAR=TRUE;
  EJE_X=1.0;
  EJE_Y=0.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de escalar en el eje Y\n");
 case SCAL_EJE_Y:
  ROTAR=FALSE;
  MOVER=FALSE;
  ESCALAR=TRUE;
  EJE_X=0.0;
  EJE_Y=1.0;
  EJE_Z=0.0;
  break;
 //printf (" Se ha seleccionado la opcion de escalar en el eje Z\n");
 case SCAL_EJE_Z:
  ROTAR=FALSE;
  MOVER=FALSE;
  ESCALAR=TRUE;
  EJE_X=0.0;
  EJE_Y=0.0;
  EJE_Z=1.0;
  break;
 //printf (" Se ha seleccionado la opcion de escalar en los ejes XYZ\n");
 case SCAL_EJE_XYZ:
  ROTAR=FALSE;
  MOVER=FALSE;
  ESCALAR=TRUE;
  EJE_X=1.0;
  EJE_Y=1.0;
  EJE_Z=1.0;
  break;
 }
 glutPostRedisplay();
}


void recalcModelView(void)
{
 glPopMatrix();
 if(ROTAR) //Transformación de rotacion
 glRotatef(angle, EJE_X, EJE_Y, EJE_Z); 
 if(MOVER)//Transformación de traslación
 glTranslatef(trasl_x*EJE_X, -trasl_y*EJE_Y,trasl_x*EJE_Z );
 if(ESCALAR)//Transformación de escalado
 glScaled(1.0 + escala_x*EJE_X, 1.0 +escala_x*EJE_Y, 1.0 + escala_x*EJE_Z); 
 glPushMatrix();
 newModel = 0;
}


void redibuja(void)
{
 GLfloat mat_ambient[] = { 0.02f, 0.16f, 0.16f, 1.0f };
 GLfloat mat_diffuse[] = { 0.1f, 0.9f, 1.0f, 1.0f };
 GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
 GLfloat mat_shininess[] = { 100.0f };
 int a, b, c;
 int i;

 if (newModel)
 recalcModelView();
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glPushMatrix();
 
 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

 glBegin(GL_TRIANGLES);
 for (i=0; i<obj.nFaces; i++)
 {
 const Face& face = obj.pFaces[i];
 a=face.vertexIndices[0];
 b=face.vertexIndices[1];
 c=face.vertexIndices[2];
 glNormal3f(face.normal[0].x, face.normal[0].y, face.normal[0].z); 
 glVertex3f(obj.pVertices[a].x, obj.pVertices[a].y, obj.pVertices[a].z);
 glNormal3f(face.normal[1].x, face.normal[1].y, face.normal[1].z); 
    glVertex3f(obj.pVertices[b].x, obj.pVertices[b].y, obj.pVertices[b].z);
 glNormal3f(face.normal[2].x, face.normal[2].y, face.normal[2].z); 
    glVertex3f(obj.pVertices[c].x, obj.pVertices[c].y, obj.pVertices[c].z);
 }
 glEnd();

 glPopMatrix();
 glFlush();
 glutSwapBuffers();
}


void init(void)
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glShadeModel(GL_SMOOTH);
 glCullFace(GL_BACK);
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_CULL_FACE);
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 glEnable(GL_DEPTH_TEST);
 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);       
 glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);        
 glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);       
 glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc);     
 glEnable(GL_LIGHT0);                               
 glEnable(GL_LIGHTING);
 CargarModelo("ship.dat", obj);
 CalcularNormales(obj);
 applySmoothingGroups(obj);
}


int main(int argc, char **argv)
{
 int menu_rotar, menu_mover, menu_escalar;
 
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
 glutInitWindowSize(400, 400);
 glutCreateWindow("Transformaciones con el mouse");
 glutDisplayFunc(redibuja);
 glutMouseFunc(mouse);
 glutMotionFunc(movimiento);
 menu_rotar=glutCreateMenu(controlTransf);
 glutAddMenuEntry("eje x", ROT_EJE_X);
 glutAddMenuEntry("eje y", ROT_EJE_Y);
 glutAddMenuEntry("eje z", ROT_EJE_Z);
 menu_mover=glutCreateMenu(controlTransf);
 glutAddMenuEntry("eje x", MOV_EJE_X);
 glutAddMenuEntry("eje y", MOV_EJE_Y);
 glutAddMenuEntry("eje z", MOV_EJE_Z);
 glutAddMenuEntry("ejes xy", MOV_EJE_XY);
 menu_escalar=glutCreateMenu(controlTransf);
 glutAddMenuEntry("eje x", SCAL_EJE_X);
 glutAddMenuEntry("eje y", SCAL_EJE_Y);
 glutAddMenuEntry("eje z", SCAL_EJE_Z);
 glutAddMenuEntry("ejes xyz", SCAL_EJE_XYZ);
 glutCreateMenu(controlTransf);
 glutAddSubMenu("Rotar", menu_rotar);
 glutAddSubMenu("Mover", menu_mover);
 glutAddSubMenu("Escalar", menu_escalar);
 glutAttachMenu(GLUT_RIGHT_BUTTON);
 init();
 /* Se establece la vista del cubo.*/
 glMatrixMode(GL_PROJECTION);
 gluPerspective(45.0, 1.0, 1.0, 10.0);
 glMatrixMode(GL_MODELVIEW);
 gluLookAt(0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.);      
 glPushMatrix();       
 glutMainLoop();
 killObject(obj);
 return 0; 
}

Translaciones

El caso de las translaciones en el espacio es idéntico al de las translaciones en el plano.

En esta ocasión también es posible realizar el desplazamiento sin necesidad de multiplicar por la matriz de transformación, basta simplemente con sumar a cada coordenada del punto el desplazamiento en el eje correspondiente que se desea realizar.

Escalado

Al igual que en el caso anterior, el escalado 3D no es más que una extensión del de dos dimensiones. Existen tres factores de escalado, uno para cada eje: Ex, Ey y Ez.

Al igual que en el escalado bidimensional: Si los tres factores son iguales la imagen resultante guardará proporcionalidad con la original. En el caso especial de que los tres factores tengan valor 1, la imagen no sufrirá cambios.

Rotaciones

La rotaciones 3D puede que no resulten tan simples de ver como las 2D.
Antes de nada, es necesario aclarar como se realizan este tipo de rotaciones. En este caso, al disponer de 3 ejes de coordenadas podemos realizar tres tipos de rotaciones: una rotación en el eje X, en el eje Y o en el eje Z.
Por ejemplo, una rotación en el eje X quiere decir que se realiza la rotación moviendo el eje Y hacia el eje Z, de forma que el X permanece inmóvil.
Las matrices de transformación para las rotaciones 3D de un ángulo 'o' son las siguientes: Para rotaciones en el eje X:


En el eje Y:


Y, en el eje Z:


3.Manejo de Matrices.
La transformación de las coordenadas se realiza internamente en OpenGL a partir de las
matrices de transformación y de las coordenadas de modelado del objeto. Sin embargo, para
representar el rastro que dibuja la tortuga al desplazarse, se realizará explícitamente la
transformación de la coordenada en la que se encuentra la tortuga. De esta forma se actúa
directamente en la matriz de transformación.

4.Pila de Matrices.
En la función display() se encuentran las llamadas a dos funciones. Se trata de glPushMatrix() y glPopMatrix(). Para comprender su funcionamiento, primero se experimenta que es lo que ocurre cuando están llamadas.
 void display(void) {
...
// glPushMatrix();
...
glTranslatef(0.0, 0.0, .5);
...
// glPopMatrix();
glutSwapBuffers();
}
Una pila es un almacén con funcionamiento LIFO, el último en entrar es el primero en
salir, por lo que suele comparar a una pila de platos en la que sólo se puede dejar uno encima
de la pila o coger el superior que es el último depositado. La pila de matrices tiene el mismo
funcionamiento sustituyendo los platos por matrices. La matriz superior de la pila es sobre la
que se aplican las distintas transformaciones, multiplicándola por la matriz que generan las
disntintas funciones.

La función glPushMatrix() realiza una copia de la matriz superior y la pone encima de
la pila, de tal forma que las dos matrices superiores son iguales.
La función glPopMatrix() elimina la matriz superior, quedando en la parte superior de
la pila la matriz que estaba en el momento de llamar a la función glPushMatrix().

Fuentes de información:
http://www.oocities.org/valcoey/mouse.html
http://www.alobbs.com/revistas/opengl3