Proyección ortogonal
Una proyección ortogonal 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.
Una aproximación menos técnica pero mas comprensible de esta proyección es imaginar que se tiene
un objeto fabricado con un material deformable, y se aplasta literalmente como
una pared. Se obtendría el mismo objeto, pero plano, liso. Pues eso es lo que se
vería por pantalla.
Para definir la matriz de proyección ortográfica y
multiplicarla por la matriz activa (que debería ser en ese momento la de
proyección, GL_PROJECTION), se utiliza la función
glOrtho, que se define de la siguiente
forma:
glOrtho(limiteIzquierdo, limiteDerecho, limiteAbajo, limiteArriba, znear, zfar)
siendo todos flotantes. Los
valores de znear y zfar no son las posiciones de esos planos en el espacio 3D.
Representan la distancia desde el centro de proyección, con valor positivo hacia
delante y negativo hacia atrás. Con esto simplemente se acota lo que será
el volumen de visualización (un cubo).
Por ejemplo, la ilustración 4.5 es un render de un coche con proyección ortográfica, visto desde
delante.
Ilustración 4 .5
glOrtho(-0.5f, 0.5f, -0.5f, 0.5f, 0.01f, 20.0f
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.
El volumen de visualización creado por una perspectiva se
llama frustum. Un frustum es
una sección piramidal, vista desde la parte afilada hasta la base (ilustración
4.6).
Ilustración 4 .6
Se puede definir esta proyección utilizando la función glFrustum. Pero existe otra función de la librería GLU
llamada gluPerspective que hace el proceso más
sencillo. Se define de la siguiente forma:
Void gluPerspective(angulo, aspecto, znear, zfar);
Los parámetros de gluPerspective
son flotantes y definen las características mostradas en la ilustración 4.7, el
ángulo para el campo de visión en sentido vertical, el aspecto que es la
relación entre la altura (h) y la anchura (w) y las
distancias znear y zfar de
los planos que acotan el fustrum al observador.
Los valores de znear y zfar no son las posiciones de esos planos en el
espacio 3D, representan la distancia desde el centro de proyección, con valor
positivo hacia delante y negativo hacia atrás.
Ilustración 4 .7
La ilustración 4.8 muestra la escena del coche de la sección
anterior, esta vez con una proyección en perspectiva:
Ilustración 4 .8
El código utilizado para definir la proyección ha
sido:
gluPerspective(45.0f,(GLfloat)(width/height),0.01f,100.0f);
Se usan 45º de ángulo, la relación entre el ancho y alto de
la pantalla (width y height
son el ancho y alto actual de la ventana) y las distancias a los planos de corte
znear y zfar son 0.01 y 100
respectivamente.
CODIGOSLa escena consiste en un cubo de colores girando sobre si mismo y una esfera blanca de alambre
#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;
}
Segundo codigo
// Le digo a OpenGL que voy a cambiar la matriz de proyeccion glMatrixMode(GL_PROJECTION); // Le digo a OpenGL que use proyeccion perspectiva. Uso el ancho // y alto de mi viewport para calcular el segundo parametro gluPerspective(60.0f, (float)rect.right/(float)rect.bottom, 0.5f, 50.0f);
// Muevo para atras el objeto. El punto de vista esta // en la posicion 0,0,0 porque no lo he cambiado, asi que // alejo el objeto para poder verlo. glTranslatef(0,0,-4.0f); // Giro el objeto 30 grados en el eje x, luego otros // 30 en el eje y. Es para que quede bonito. glRotatef(30,1,0,0); glRotatef(30,0,1,0);// y pinto el objeto con coordenadas genericas alrededor // del eje de coordenadas. Estas coordenadas que pongo // ahora son modificadas por las modificaciones que // hemos hecho en la matriz modelview (glTranslate, glRotate). // Le digo a OpenGL que voy a pintar y con cuadrados: glBegin(GL_QUADS); // Cara de arriba glColor3f(1,0,0); // rojo 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); // Cara de abajo glColor3f(1,0,0); // rojo 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); // Cara frontal glColor3f(0,0,1); // azul 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); // Cara trasera glColor3f(0,0,1); // azul 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); // Cara izquierda glColor3f(0,1,0); // verde 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); // Cara derecha glColor3f(0,1,0); // verde 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();Compilamos, ejecutamos y si tenemos suerte veremos esto: Como siempre sugiero cambiar parametros, funciones, ... para experimentar.
No hay comentarios:
Publicar un comentario