miércoles, 25 de abril de 2012

Circulo y Elipse


La ecuación del Círculo
En la mayoría de las gráficas generadas por fórmulas, la formula está dado en la forma
y = f(x)
Tal forma hace muy facil encontrar los puntos en la gráfica. Todo lo que hay que hacer es elegir x, calcular f(x) (= alguna expresión dada que implique a x) y tendremos el valor correspondiente de y.
Sin embargo, cualquier ecuación concerniente a x e y puede ser usada como la propiedad compartida por todos los puntos de la gráfica. La diferencia principal es que en ecuaciones más complicadas, después de elegir la x, encontrar la y correspondiente requiere trabajo extra, ( y algunas veces es más fácil elegir la y y encontrar la x).
 Quizá la gráfica más conocida de este tipo es el círculo de radio R, cuya ecuación es 

x2  +  y2  =   R2
Dibujar un círculo de radio R centrado en el origen O de un sistema de ejes (x,y). Determinado algún punto P en el círculo con los valores especificados de (x,y), dibujar una línea perpendicular desde P hasta el punto A en el eje de las x. Luego

x = OA        y = AP       R = OP

Aquí x y/o y pueden ser negativas, si están hacia la izquierda del eje de las y o por debajo del eje de las x, pero a pesar del signo, x2 e y2 son ambas siempre positivas. Puesto que el triángulo OAP tiene un ángulo de 90°, por el  teorema de Pitágoras, para cualquier elección de P, la relación de abajo siempre contiene:
OA2  +  AP2  =   OP2
También se puede escribir
x2  +  y2  =   R2
La ecuación del círculo es cumplida por cualquier punto localizado en el. Por ejemplo, si la gráfica está definida por la ecuación:
 
  
x2  +  y2  =   25
esta ecuación se cumple por todos los puntos listados abajo: 
 

  x
  5 
  4 
  3 
  0 
  -3 
  -4 
  -5 
  -4 
  -3 
  0 
  3 
  4 
( 5 ) 
  y
  0 
  3 
  4
  5 
  4
  3 
  0 
  -3 
  -4 
  -5 
  -4 
  -3
( 0 ) 

  
 
La Ecuación de una Elipse
La ecuación del círculo aún expresa la misma relación si ambos lados se dividen por R2:
(x2/R2)  +  (y2/R2) =   1
La ecuación de una elipse es esa misma con una pequeña modificación:
 
  
(x2/a2)  +  (y2/b2) =   1
donde (a,b) son dos números dados, por ejemplo (8,4). ¿Cual será la gráfica de esa ecuación? Cerca del eje x y es muy pequeña y la ecuación se acerca casi a 
(x2/a2)  =   1
De donde


x2 = a2 y por lo tanto x = a ó x = -a   (a veces combinado con x = ±a)


La gráfica en esas cercanías se asemeja a la sección de un círculo de radio a, cuya ecuación
(x2/a2)  +  (y2/a2)  =   1
en esta región también está cercana a x2 = a2. De la misma forma  puede observar que cerca del eje de las y, donde x es pequeña, la gráfica corta el eje en y=±b y su figura aparenta la de un círculo de radio b.
  

glutLookAt


glutLookAt

Esta es la función que determina dónde y cómo está dispuesta la cámara. Cuidado que la posición de la cámara no tiene nada que ver con el tipo de proyección que hayamos definido. La proyección se define sólo una vez, típicamente al principio del programa en una función inicializadora, mientras que la cámara se mueve continuamente.

glTranslatef

Produce una traducción de x y z. La matriz actual (ver glMatrixMode) se multiplica por la matriz de traducción, con el producto sustitución de la matriz actual, como si glMultMatrix fueron llamados con la siguiente matriz de su argumento.


lunes, 23 de abril de 2012

El Carro

#include <GL/glut.h>
GLfloat anguloCuboX = 0.0f;
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.0f;




GLint ancho=600;
GLint alto=400;
 int ang =0 ;
 int movx = 0;
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(1.0f, 1.0f, 1.0f);
 glScalef(1.5f,0.0f,1.5f);
    glBegin(GL_QUADS);     
    glVertex3f( 10.0f,-10.0f, -10.0f);
    glVertex3f( 10.0f,-10.0f,  10.0f);
    glVertex3f(-10.0f,-10.0f,  10.0f);
    glVertex3f(-10.0f,-10.0f, -10.0f);
    glEnd();
}
void carro(void)
{
    glColor3f(1.0f, 0.0f, 0.0f);


    glBegin(GL_POLYGON);     
    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(0.0f, 0.0f, -5.0f);
    glRotatef(15, 1.0f, 0.0f, 0.0f);
    glRotatef(15, 0.0f, 1.0f, 0.0f);
     Piso();
 

 glLoadIdentity();




  glColor3f(0.0f, 0.0f, 1.0f);
  glTranslatef(movx,0.0,0.0);
  carro();
  glLoadIdentity();
      
  glTranslatef(-.5f,0.5f,-1.0f);
  glColor3f(0.0f, 0.0f, 1.0f);
  glRotatef(ang,1.0,0.0,0.0);
  glTranslatef(movx,0.0,0.0);
  glutSolidSphere(0.5f, 16, 16);
  glLoadIdentity();




  glTranslatef(3.0f,0.5f,-1.0f);
  glColor3f(0.0f, 1.0f, 0.0f);
  glRotatef(ang,1.0,0.0,0.0);
  glTranslatef(movx,0.0,0.0);   
      glutSolidSphere(0.5f, 16, 16);
      glLoadIdentity();
    glFlush();
    glutSwapBuffers();
}
void init()
{
    glClearColor(0,0,0,0);
    glEnable(GL_DEPTH_TEST);
    ancho = 600;
    alto = 900;
}
void idle()
{
    display();
}
void specialkeyevent( int key, int Xx, int Yy )
{   
 switch ( key ) {
  
  case GLUT_KEY_LEFT:
   movx-=1;
   ang-=1;
   display();
   break;
  case GLUT_KEY_RIGHT:
   movx+=1;
   ang-=1;
   display();
   break;  
 }
 glutPostRedisplay();
}
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(ancho, alto);
    glutCreateWindow("Coche en movimiento");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutSpecialFunc(specialkeyevent );
    glutMainLoop();
    return 0;
}





lunes, 26 de marzo de 2012

Resumen Unidad 3


Hardware

El API de ogl 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
En principio, 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.

En “Primeros Pasos en OpenGL” se mencionaba de manera general algunos conceptos relacionados con las transformaciones en OpenGL, específicamente la proyección. Es recomendable revisar y entender “Primeros Pasos en OpenGL” antes de aventurarse a leer el presente tutorial.

En los “Hola Mundo 3d en OpenGL” y “Hola Complicado Mundo OpenGL-win32” se utilizaron algunas transformaciones de proyección y viewport para ajustar la inicialización de la ventana, pero sin entrar mucho en detalle acerca de su funcionamiento.
 

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

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.

Definición: Producto escalar en cualquier espacio. Espacio euclídeo.

Cualquier operación en un espacio vectorial que cumpla las anteriores propiedades, diremos  que es un producto escalar (aunque no se trate del producto escalar usual).

Llamaremos espacio euclídeo a un espacio vectorial dotado de un producto escalar.


Conceptos geométricos obtenidos del producto escalar.

Por analogía con lo que ocurre en el plano o el espacio con el producto escalar usual,  podemos definir los siguientes conceptos, siempre referidos a un cierto producto escalar.
Nos situamos en V, un espacio euclídeo.

. Vectores ortogonales.
Dos vectores u, v son ortogonales si su producto escalar es cero:  u · v = 0. Se denota u v.
Diremos que un conjunto de vectores es un conjunto ortogonal si cada uno de ellos es  ortogonal a todos los demás.
•  Notar que si dos vectores u, v son ortogonales entonces también lo son sus múltiplos α u  y  β v  (α, β escalares).
Norma o módulo de un vector.
La norma o módulo de un vector es   | v |= v · v La noción corresponde, intuitivamente, a  la “longitud” del vector. También se puede denotar  || v || .
Distancia entre dos vectores.
La distancia entre u y v es la norma del vector diferencia entre ambos.
dist (u, v) = | u – v |
Ángulo entre dos vectores.
Es sabido que para el producto escalar usual de  ² se tiene que u · v = | u | | v |  cos α ,  donde α  es el ángulo que forman ambos vectores. Por tanto, para generalizar la noción de  ángulo a cualquier espacio euclídeo.

jueves, 22 de marzo de 2012

Rebote de Pelota

#include <gl/glut.h>
#include <Math.h>    
#define PI 3.14159265f
     
char title[] = "Rebote de Pelota"; 
int windowWidth  = 640;    
int windowHeight = 480;    
int windowPosX   = 50;     
int windowPosY   = 50;     
  
GLfloat ballRadius = 0.2f;  
GLfloat xPos = 0.0f;        
GLfloat yPos = 0.0f;
GLfloat xPosMax, xPosMin, yPosMax, yPosMin;
GLdouble xLeft, xRight, yBottom, yTop;    
GLfloat xSpeed = 0.02f;     
GLfloat ySpeed = 0.007f;
int refreshMillis = 10;     
     
void initGL() {
   glClearColor(0.0, 1.0, 0.0, 0.0);
}
 
void display() {
   glClear(GL_COLOR_BUFFER_BIT);
 
   glLoadIdentity();              
   glTranslatef(xPos, yPos, 0.0f); 

   glBegin(GL_TRIANGLE_FAN);
      glColor3f(0.0f, 0.0f, 1.0f);
      glVertex2f(0.0f, 0.0f);      
      int numSegments = 100;
      GLfloat angle;
      for (int i = 0; i <= numSegments; i++) {
         angle = i * 2.0f * PI / numSegments; 
         glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
      }
   glEnd();
  
   glutSwapBuffers(); 
  
 
   xPos += xSpeed;
   yPos += ySpeed;
  
   if (xPos > xPosMax) {
      xPos = xPosMax;
      xSpeed = -xSpeed;
   } else if (xPos < xPosMin) {
      xPos = xPosMin;
      xSpeed = -xSpeed;
   }
   if (yPos > yPosMax) {
      yPos = yPosMax;
      ySpeed = -ySpeed;
   } else if (yPos < yPosMin) {
      yPos = yPosMin;
      ySpeed = -ySpeed;
   }
}
 
void reshape(GLsizei weight, GLsizei height) {
   if (height == 0) height = 1;             
   GLfloat aspect = (GLfloat)weight / height;
  
   glViewport(0, 0, weight, height);
  
  
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();           
   if (weight <= height) {
      xLeft   = -1.0;
      xRight  = 1.0;
      yBottom = -1.0 / aspect;
      yTop    = 1.0 / aspect;
   } else {
      xLeft   = -1.0 * aspect;
      xRight  = 1.0 * aspect;
      yBottom = -1.0;
      yTop    = 1.0;
   }
   gluOrtho2D(xLeft, xRight, yBottom, yTop);
 
  
   yPosMin = yBottom + ballRadius;
   yPosMax = yTop - ballRadius;
  
  
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();          
}
 
void Timer(int value) {
 glutPostRedisplay();  
 glutTimerFunc(refreshMillis, Timer, 0);
}
  
int main(int argc, char** argv) {
   glutInit(&argc, argv);           
   glutInitDisplayMode(GLUT_DOUBLE);
   glutInitWindowSize(windowWidth, windowHeight); 
   glutInitWindowPosition(windowPosX, windowPosY);
   glutCreateWindow(title);     
   glutDisplayFunc(display);  
   glutReshapeFunc(reshape);  
   glutTimerFunc(0, Timer, 0);  
   initGL();                    
   glutMainLoop();             
   return 0;
}












miércoles, 14 de marzo de 2012


Proyección Ortogonal.



El tipo de proyección que hemos utilizado hasta ahora es una proyección ortogonal. Una proyección ortogonal define un volumen de la vista de tipo paralelepipédico tal y como se muestra en la siguiente figura. La principal característica de esta proyección es que el tamaño de los objetos es independiente de la distancia a la que estén del observador, por ejemplo, dos cilindros del mismo tamaño, uno a cinco unidades y el otro a diez unidades de distancia del observador se proyectarán con el mismo tamaño.







Para definir una proyección ortogonal en OpenGL hay que dar los siguientes pasos:



glMatrix(GL_PROJECTION); /* Voy a manejar la matriz de proyección */
glLoadIdentity(); /* Cargo inicialmente la identidad */
/* Y ahora defino la proyección ortogonal */
void glOrtho(izquierda, derecha, abajo, arriba, cerca, lejos);


Si lo que deseamos es trabajar con una proyección ortogonal 2D:

void gluOrtho2D(izquierda, derecha, abajo, arriba);

que no es más que una proyección ortogonal donde el plan delantero está en -1 y el trasero en 1.


Proyección Perspectiva.
La proyección ortogonal no da sensación de profundidad porque el tamaño de los objetos no depende de su distancia al observador. Para conseguir este efecto necesitamos definir una proyección perspectiva. Esta proyección define un volumen de la vista que es un prisma truncado de base rectangular, como el de la siguiente figura:







la función OpenGL que establece este tipo de perspectiva es:
void glFrustum(izquierda, derecha, abajo, arriba, cerca, lejos);

Este modo de definir la proyección perspectiva no es demasiado intuitivo, es más sencillo establecerla con un esquema como el que se muestra en la siguiente figura:






y la función OpenGL que la establece es:
void gluPerspective(fovy, aspecto, cerca, lejos);
donde fovy es el ángulo de apertura del objetivo de la cámara, en grados, y aspecto es la relación ancho/alto de la base de la pirámide.



Aplicandole Transformaciones
En el ejemplo vamos a aplicar transformaciones de rotacion y traslación. La de escalado no la vamos a utilizar principalmente para evitar "malos hábitos" debido a que este comando es MUY lento y el uso continuo del mismo hace descender nuestro queridos FPS.

    Para las transformaciones geométricas, OpenGL utiliza, al igual que D3D, matrices de 4x4. Aunque al contrario que D3D, OGL no se apoya directamente en la notación matemática y en su lugar, utiliza la traspuesta de la  matemática.

    Los comandos de traslación, rotación y escalado vienen explicados en Apendice 1: Visualización así que aquí me limitaré a nombrarlos.

   Traslación

void glTranslate{fd}(TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de traslación que mueve el objeto.s


   Rotación

void glRotate{fd}(TYPE angle,TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de rotación que rota el objeto en la dirección de las agujas del reloj sobre el radio de origen en el punto x,y,z.


   Escalado

void glScale{fd}(TYPE x, TYPE y, TYPE z);

            Multiplica la matriz actual por una matriz que cambia el tamaño del objeto a lo largo de los ejes. Las coordenadas

            x, y, z de cada objeto es multiplicada por los parámetros x, y, z.

C    Como dijimos anteriormente en nuestro ejemplo solamente aplicaremos las transformaciones de rotación y traslación. Para poder mover y rotar el cuadrado, vamos a declarar unas variables globales:

float fRotx,fRoty;

float fDesz=-3.0f;

Las dos primeras son los ángulos que vamos a rotar con respecto al eje x e y respectivamente. La tercera variable corresponde con el desplazamiento a travez del eje z (perpendicular a la pantalla). Gráficamente sería:
    

Pila de Matrices

En la función display() se encuentran las llamadas a dos funciones de matrices

 glPushMatrix() y glPopMatrix().

glTranslatef() que se utiliza para posicionar uno de los objetos.

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().

glGetDoublev() Con esta función se obtiene la matriz actual de una de las pilas, a la que se indica que matriz se quiere obtener.

Viewport

Es poco probable que necesites usar el control Viewport (Vista) directamente. Es mucho más probable que uses el control ScrolledWindow, el cual usa un Viewport.

Un control de vista permite colocar un control más grande dentro de él de tal forma que se pueda ver una parte de él de una vez. Usa Adjustments para definir el área que se ve.

Un Viewport se crea con la función:

  viewport = gtk.Viewport(hadjustment=None, vadjustment=None)

Como se puede ver se pueden especificar los Adjustments horizontal y vertical que el control usa cuando se crea. Creará sus propios ajustes si se le pasa None como valor de los argumentos o simplemente no se le pasan argumentos.

Se pueden consultar y fijar los ajustes después de que el control se haya creado usando los siguientes cuatro métodos:

  viewport.get_hadjustment()

  viewport.get_vadjustment()

  viewport.set_hadjustment(adjustment)

  viewport.set_vadjustment(adjustment)

El otro método que se usa para modificar la apariencia es:

  viewport.set_shadow_type(type)

Los valores posibles para el parámetro type son:

  SHADOW_NONE         # sin sombra
  SHADOW_IN           # sombra hacia adentro
  SHADOW_OUT          # sombra hacia afuera
  SHADOW_ETCHED_IN    # sombra marcada hacia adentro
  SHADOW_ETCHED_OUT   # sombra marcada hacia fuera

Investigaciones


Proyección Ortogonal.



El tipo de proyección que hemos utilizado hasta ahora es una proyección ortogonal. Una proyección ortogonal define un volumen de la vista de tipo paralelepipédico tal y como se muestra en la siguiente figura. La principal característica de esta proyección es que el tamaño de los objetos es independiente de la distancia a la que estén del observador, por ejemplo, dos cilindros del mismo tamaño, uno a cinco unidades y el otro a diez unidades de distancia del observador se proyectarán con el mismo tamaño.







Para definir una proyección ortogonal en OpenGL hay que dar los siguientes pasos:



glMatrix(GL_PROJECTION); /* Voy a manejar la matriz de proyección */

glLoadIdentity(); /* Cargo inicialmente la identidad */

/* Y ahora defino la proyección ortogonal */

void glOrtho(izquierda, derecha, abajo, arriba, cerca, lejos);



Si lo que deseamos es trabajar con una proyección ortogonal 2D:



void gluOrtho2D(izquierda, derecha, abajo, arriba);



que no es más que una proyección ortogonal donde el plan delantero está en -1 y el trasero en 1.









Proyección Perspectiva.



La proyección ortogonal no da sensación de profundidad porque el tamaño de los objetos no depende de su distancia al observador. Para conseguir este efecto necesitamos definir una proyección perspectiva. Esta proyección define un volumen de la vista que es un prisma truncado de base rectangular, como el de la siguiente figura:







la función OpenGL que establece este tipo de perspectiva es:



void glFrustum(izquierda, derecha, abajo, arriba, cerca, lejos);



Este modo de definir la proyección perspectiva no es demasiado intuitivo, es más sencillo establecerla con un esquema como el que se muestra en la siguiente figura:







y la función OpenGL que la establece es:



void gluPerspective(fovy, aspecto, cerca, lejos);



donde fovy es el ángulo de apertura del objetivo de la cámara, en grados, y aspecto es la relación ancho/alto de la base de la pirámide.











Aplicandole Transformaciones



    En el ejemplo vamos a aplicar transformaciones de rotacion y traslación. La de escalado no la vamos a utilizar principalmente para evitar "malos hábitos" debido a que este comando es MUY lento y el uso continuo del mismo hace descender nuestro queridos FPS.

    Para las transformaciones geométricas, OpenGL utiliza, al igual que D3D, matrices de 4x4. Aunque al contrario que D3D, OGL no se apoya directamente en la notación matemática y en su lugar, utiliza la traspuesta de la  matemática.



    Los comandos de traslación, rotación y escalado vienen explicados en Apendice 1: Visualización así que aquí me limitaré a nombrarlos.



   Traslación

void glTranslate{fd}(TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de traslación que mueve el objeto.s



   Rotación

void glRotate{fd}(TYPE angle,TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de rotación que rota el objeto en la dirección de las agujas del reloj sobre el radio de origen en el punto x,y,z.



   Escalado

void glScale{fd}(TYPE x, TYPE y, TYPE z);

            Multiplica la matriz actual por una matriz que cambia el tamaño del objeto a lo largo de los ejes. Las coordenadas

            x, y, z de cada objeto es multiplicada por los parámetros x, y, z.

C    Como dijimos anteriormente en nuestro ejemplo solamente aplicaremos las transformaciones de rotación y traslación. Para poder mover y rotar el cuadrado, vamos a declarar unas variables globales:

float fRotx,fRoty;

float fDesz=-3.0f;

Las dos primeras son los ángulos que vamos a rotar con respecto al eje x e y respectivamente. La tercera variable corresponde con el desplazamiento a travez del eje z (perpendicular a la pantalla). Gráficamente sería:



                 

Pila de Matrices

En la función display() se encuentran las llamadas a dos funciones de matrices

 glPushMatrix() y glPopMatrix().

glTranslatef() que se utiliza para posicionar uno de los objetos.

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().

glGetDoublev() Con esta función se obtiene la matriz actual de una de las pilas, a la que se indica que matriz se quiere obtener.















Viewport

Es poco probable que necesites usar el control Viewport (Vista) directamente. Es mucho más probable que uses el control ScrolledWindow, el cual usa un Viewport.

Un control de vista permite colocar un control más grande dentro de él de tal forma que se pueda ver una parte de él de una vez. Usa Adjustments para definir el área que se ve.

Un Viewport se crea con la función:

  viewport = gtk.Viewport(hadjustment=None, vadjustment=None)

Como se puede ver se pueden especificar los Adjustments horizontal y vertical que el control usa cuando se crea. Creará sus propios ajustes si se le pasa None como valor de los argumentos o simplemente no se le pasan argumentos.

Se pueden consultar y fijar los ajustes después de que el control se haya creado usando los siguientes cuatro métodos:

  viewport.get_hadjustment()

  viewport.get_vadjustment()

  viewport.set_hadjustment(adjustment)

  viewport.set_vadjustment(adjustment)

El otro método que se usa para modificar la apariencia es:

  viewport.set_shadow_type(type)

Los valores posibles para el parámetro type son:

  SHADOW_NONE         # sin sombra
  SHADOW_IN           # sombra hacia adentro
  SHADOW_OUT          # sombra hacia afuera
  SHADOW_ETCHED_IN    # sombra marcada hacia adentro
  SHADOW_ETCHED_OUT   # sombra marcada hacia fuera