miércoles, 28 de marzo de 2012

Unidad III: Graficacion 3D

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.

La matriz identidad
El “problema” del uso de estas funciones surge cuando se tiene más de un objeto en la escena. Estas funciones tienen efectos acumulativos.

La matriz de proyección
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. Está delimitado por una serie de planos de trabajo. De estos planos, los más importantes son los planos de corte, que son los que nos acotan el volumen de visualización por delante y por detrás. En el plano más cercano a la cámara (znear) es donde se proyecta la escena para luego pasarla a la pantalla. Todo lo que esté más adelante del plano de corte más alejado de la cámara (zfar) no se representa.

Transformaciones
Las transformacion en OPENGL no sirven para poder tener funciones que permitan acceder directamente a las matrices que representen los estados de las transformaciones.

Algunas matrices como:
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 .
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.
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’ = AM, 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.
Estas operaciones afectan directamente las matrices mencionadas anteriormente, debido a que las operaciones de “alto nivel” (trasladar, rotar, escalar) que existen mas adelante se concatenan, es decir su efecto se acumula sobre matriz actual, existen dos operaciones que permiten guardar la matriz actual en una pila y restaurarla cuando sea necesario, estas son:

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.

Proyección
Una proyección es la forma en la que se pueden ver las cosas las cuales dependiendo de la forma en la que la veamos pueda cambiar lo que realmente es, tanto como sus dimensiones.
Hay dos formas de vistas las cuales son:

ORTOGRAFICA. La cual se maneja con la funciones glOrtho() y solo se ve el dibujo sin tener tamaños reales.

PERSPECTIVA la cual se ocupa con la libreria glFrustum() y otras funciones, esta ayuda para tener una profundidad y tamaño de las cosas reales.
La función es es void gluPerspective(GLdouble fov, GLdouble aspect, GLdouble near, GLdouble far);

Dentro de ellas existen transformaciones y modificaciones.

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.
Transformaciones ModelView
Para las transformaciones modelview se necesita mas que el conocimiento de las coordenadas x,y,z si no tambien de conocimientos matematicos para hacer distintas funciones, lo bueno es que ya estan realizadas en bibliotecas y solo basta utilizarlas

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.

Rotacion
void glRotate[fd](GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
Realiza una rotación del espacio coordenado por una medida de (angle) tomados en grados a lo largo del vector determinado por (x,y,z)

Traslacion
void glTranslate[fd](GLfloat x, GLfloat y, GLfloat z);
Esta función traslada el espacio coordenado en x, y, z unidades sobre sus respectivos ejes coordenados X, Y, Z.

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

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

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

Propiedades del producto escalar usual.
1.  Conmutativa.  u · v = v  · u
2.  Distributiva.  u · ( v + w)  = u · v  +  u · w
3.  Reubicación del escalar. a (u · v) = (a u) · v = u · (a v)
4.  Definida positiva: v · v = 0, y se da la igualdad v · v = 0 solamente para el vector v =  0 .
Vectores ortogonales lo son cuando 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. (Exigimos además que ninguno de los vectores sea el G0 ).

Módulo de un vector
El módulo de un vector es la longitud del segmento orientado que lo define.
El módulo de un vector es un número siempre positivo y solamente el vector nulo tiene módulo cero.

Distancia entre dos puntos
La distancia entre dos puntos es igual al módulo del vector que tiene de extremos dichos puntos.

jueves, 22 de marzo de 2012

Pelota Rebote

Código


#include <gl/glut.h>
#include <Math.h>
#define PI 3.14159265f


char title[] = "Rebote de una 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, 0.0, 0.0, 0.0);
}


void display() {
glClear(GL_COLOR_BUFFER_BIT);


glLoadIdentity();
glTranslatef(xPos, yPos, 0.0f);


glBegin(GL_TRIANGLE_FAN);
glColor3f(1.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;
}


jueves, 15 de marzo de 2012


Cubo en 3D

Código

#include <gl/glut.h>
GLfloat anguloCuboX = 0.0f;
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.0f;
GLfloat x,y,z, ang, paso, dtx, dtz,pasoc,pasoa;
GLfloat pasob=-0.5;
GLint ancho=400;
GLint alto=400;
GLfloat trasy=0.0;
GLfloat a,b,c=2;
void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor3f(1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
}
int hazPerspectiva = 0;
void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
        glOrtho(-4,4, -4, 4, 1, 10);
        glMatrixMode(GL_MODELVIEW);
        ancho = width;
        alto = height;
}

void dibujarCube()
{
    glColor3f(1.0f, 0.0f, 1.0f);
    glBegin(GL_QUADS);  //cara frontal
    glVertex3f(a-1.0f, b-1.0f,  c+1.0f);
    glVertex3f(a+ 1.0f,b-1.0f, c+1.0f);
    glVertex3f( a+1.0f, b+1.0f,  c+1.0f);
    glVertex3f(a-1.0f,  b+1.0f,  c+1.0f);
    glEnd();
    glColor3f(0.0f, 1.0f, 0.0f);
  glBegin(GL_QUADS);       //cara trasera
    glVertex3f( a+1.0f, b-1.0f, c-1.0f);
    glVertex3f(a-1.0f, b-1.0f, c-1.0f);
    glVertex3f(a-1.0f,  b+1.0f, c-1.0f);
    glVertex3f( a+1.0f,  b+1.0f, c-1.0f);
    glEnd();
    glColor3f(1.1f, 0.0f, 1.0f);
glBegin(GL_QUADS);       //cara lateral izq
    glVertex3f(a-1.0f,b-1.0f, c-1.0f);
    glVertex3f(a-1.0f,b-1.0f,  c+1.0f);
    glVertex3f(a-1.0f, b+1.0f,  c+1.0f);
    glVertex3f(a-1.0f, b+1.0f, c-1.0f);
    glEnd();
    glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);     //cara lateral dcha
    glVertex3f(a+1.0f, b-1.0f,  c+1.0f);
    glVertex3f(a+1.0f, b-1.0f, c-1.0f);
    glVertex3f(a+1.0f,  b+1.0f, c-1.0f);
    glVertex3f(a+1.0f,  b+1.0f,  c+1.0f);
    glEnd();
    glColor3f(1.0f,0.0, 1.0f);
    glBegin(GL_QUADS);       //cara arriba
    glVertex3f(a-1.0f, b+1.0f,  c+1.0f);
    glVertex3f( a+1.0f, b+1.0f,  c+1.0f);
    glVertex3f( a+1.0f, b+1.0f, c-1.0f);
    glVertex3f(a-1.0f, b+1.0f, c-1.0f);
    glEnd();
    glColor3f(0.0f,1.0f, 0.0f);
  glBegin(GL_QUADS);      //cara abajo
    glVertex3f( a+1.0f,b-1.0f, c-1.0f);
    glVertex3f( a+1.0f,b-1.0f,  c+1.0f);
    glVertex3f(a-1.0f,b-1.0f,  c+1.0f);
    glVertex3f(a-1.0f,b-1.0f, c-1.0f);
    glEnd();
}
void gldrawCubo()
{
    float xMark = -1.0f;
    float yMark = -1.0f;
    float zMark = 1.0f;
    for (int i = 0; i < 2; i++)
    //moves back one unit on z-axis
    {
        for (int j = 0; j < 2; j++)
        //moves up one unit on y-axis
        {
            for (int k = 0; k < 2; k++)
            //builds 3 cubes along x-axis
            {
                dibujarCube();
                a=xMark;
                b=yMark;
                c=zMark;
                xMark++;
            }
            xMark = -1.0f;
            yMark++;
        }
        yMark = -1.0f;
        zMark--;
    }
}

void display()
{  
    glShadeModel(GL_SMOOTH);
    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);
    //glScalef(2.0f,2.0f,2.0f);
    gldrawCubo();
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
   // glRotatef(anguloEsfera, 1.0f, 0.0f, 0.0f);
    glColor3f(1.0f, 1.0f, 1.0f);   
    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();
}

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



Resultado


lunes, 12 de marzo de 2012


Proyeccion 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 siguiente 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.



3. 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 una 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.

 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.

4.
Transformaciones geométricas en OpenGL.
OpenGL proporciona funciones para controlar la traslación, rotación y escalado. Estas tranformaciones se representan como matrices 4x4 ordenadas como vectores columna.
La familia de funciones que implementan las transformaciones es:

void glTranslate{fd}(TIPO x, TIPO y, TIPO z);
void glTranslatef(float x, float y, float z);
void glTranslated(double x, dluble y, double z);
void glRotate{fd}(TIPO angulo_en_grados, TIPO x, TIPO y, TIPO z);
void glScale{fd}(TIPO sx, TIPO sy, TIPO sz);

Escalado
                    Traslación
                                                                 Rotación
        
Observa que la traslación modifica el último vector columna,miestras que el escalado y las rotaciones comparten los elementos de la submatriz 3x3 superior izquierda.

Has de tener en cuenta que las tranformaciones no son conmutativas entre sí, es decir, el resultado no es el mismo si sobre un objeto efectúas una rotación y luego una traslación, que si efectúas primero una traslación y luego una rotación. Es más, en general las rotaciones tampoco son conmutativas entre si. El orden de aplicación de las transformaciones es muy importante.

Otro detalle que has de tener muy en cuenta es el orden de aplicación de las transformaciones en OpenGL. Observa el siguiente fragmento de código:

glTranslatef(1.0f, 1.0f, 1.0f);
glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
glScalef(2.0f, 2.0f, 2.0f);
objeto();


En este fragmento, la transformación que primero se aplica al objeto es el escalado, luego la rotación y por último la traslación.
En este ejemplo, las matrices se aplican en el siguiente orden T R S (objeto), y la matriz resultante se almacena en la matriz modelo-vista.
La regla general es que la transformación que primero se aplica es la más cercana al objeto.