Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Tutorial de OpenGL y Manual de Las Prácticas de OpenGL
Tutorial de OpenGL y Manual de Las Prácticas de OpenGL
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
Tabla de contenido
TecnunLogo: un logo en tres dimensiones
0. Introduccin
0.1
Objetivo del documento
0.2
Descripcin de logo
0.3
Entorno de visualizacin tridimensional
0.4
Contenido del documento
1. Introduccin a OpenGL: dibujando una tortuga con OpenGL
1.1
Qu es OpenGL?
1.2
Abriendo una ventana con OpenGL
1.3
Dibujando un Toroide en la ventana
1.4
Definiendo el rea de proyeccin inicial
1.5
Interactuandocon el teclado
1.6
Representando una tortuga
2. Transformaciones: dando rdenes a la tortuga (forward, right, left, up y down)
2.1
Transformaciones de modelado y de proyeccin
2.2
Interpretando los comandos
2.3
Traslacin
2.4
Rotacin
2.5
Escalado
2.6
Orden de las transformaciones
2.7
Ejemplo de bucle repeat
2.8
puntos a realizar
3. Operaciones con matrices: dibujando el camino
3.1
La pila de matrices
3.2
Dibujando un rastro
3.3
Mostrar texto
3.4
puntos a realizar
4. Viendo la escena desde otro punto de vista: cmaras
4.1
Transformaciones de vista
4.2
Transformaciones de proyeccin
4.3
Diferentes modos de mover la cmara
4.4
Trabajos propuestos
5. Iluminando la escena
5.1
Aadiendo iluminacin a la escena
5.2
Creando fuentes de luz con OpenGL
5.3
Introduciendo luces al programa TecnunLogo
5.4
Trabajos propuestos
6. Tipos de fuentes de luz
6.1
Tipos de luces
6.2
Control de los distintos tipos de luces
6.3
Trabajos propuestos
7. Leyendo objetos: otras tortugas y el escenario
7.1
Representacin de un objeto en formato Wavefront
7.2
Varias tortugas
7.3
Trabajos propuestos
8. Opciones de visualizacin: propiedades de Open GL
8.1
Trabajos propuestos
9. Creando objetos: lectura de coordenadas de vrtices
9.1
Digitalizacin de modelos
9.2
Caractersticas de la mquina de medir por coordenadas
9.3
Proceso de captura de coordenadas
9.4
Digitalizacin por fotografa
10.
El mapeado de texturas
10.1 Cargando y pegando una textura
10.2 Cargando y pegando una textura en tecnunLogo
10.3 Trabajo propuesto
Bibliografa
1
3
3
3
3
4
5
5
5
7
8
9
10
12
12
13
15
15
16
17
17
18
19
19
20
24
24
25
25
26
28
32
38
38
38
39
44
53
53
54
60
61
61
62
64
65
65
66
66
66
67
67
68
68
70
71
72
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
0. INTRODUCCIN
0.1 OBJETIVO DEL DOCUMENTO
La intencin de este guin es ensear los conceptos de la librera grfica OpenGL, es
decir la aplicacin de los conceptos de grficos por computador con una implementacin
concreta, la de OpenGL. Por ello, no se explican los fundamentos de estos conceptos, que
se pueden adquirir en la asignatura de Grficos por computador y multimedia o en la
amplia bibliografa existente.
A lo largo de los captulos de este guin se describe la realizacin de una aplicacin
con OpenGL, de modo que al final se disponga de una aplicacin til, prcticamente
distribuible a usuarios finales. Se ha preferido dar una unidad a todas las prcticas, en lugar
de estudiar los temas de forma independiente, para comprender mejor la estructura de una
aplicacin grfica, a la vez que se puede comprobar el resultado de lo realizado.
La aplicacin que se ha elegido realizar es TecnunLogo, que consiste en una
aplicacin del lenguaje de programacin Logo, desarrollado por el MIT en los aos 70 y
que ha sido el primer de contacto de innumerables personas con el mundo de la
informtica. Lo caracterstico de TecnunLogo es que se realiza en un entorno
tridimensional con lo que se gana enormemente en realismo y permite nuevas aplicaciones
del Logo para la enseanza.
0.2 DESCRIPCIN DE LOGO
Logo es un lenguaje que esta pensado para ensear conceptos matemticos y de
programacin especialmente a nios. En sus comienzos se daba rdenes (FORWARD,
RIGHT, ) desde le teclado a un pequeo robot
conectado al ordenador mediante un cable y este se mova
por el suelo respondiendo a las rdenes.
Por su aspecto, a este dispositivo se le denomin
tortuga, y al lenguage Logo se le denomina el lenguaje de
la tortuga.
Cuando los ordenadores dispusieron de capacidades
grficas, la tortuga se dibujaba en la pantalla del
ordenador. Uno de estos programas es el que se muestra
en la figura (la tortuga se representa en este caso con un
tringulo).
0.3 ENTORNO DE VISUALIZACIN TRIDIMENSIONAL
En tecnunLogo la tortuga o el objeto que se maneja se representa en un espacio
tridimensional, esto es, los objetos tienen tres dimensiones por lo que lo que se muestra en
la pantalla, es una proyeccin. En una representacin tridimensional, adems de la
proyeccin aparecen nuevos conceptos como son el del modelado de los objetos, los
parmetros de visualizacin, la iluminacin, las texturas, etc.
A lo largo de los distintos captulos se van a ir incorporando distintas caractersticas
a la aplicacin, que van a convertir a TecnunLogo, en un entorno de visualizacin
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
Para poder utilizar las libreras OpenGL y GL Utility Toolkit (GLUT) es necesario
incluir el archivo glut.h como se muestra en la primera lnea de cdigo.
La funcin principal main(), incluye la llamada a glutInit() que es la funcin que
inicializa la librera GLUT. Esta librera interacciona con el sistema de ventanas para la
apertura de nuevas ventanas. Sus parmetros son los mismos que los de la funcin main().
A continuacin, glutInitDisplayMode() define el modo en el que se debe dibujar la
ventana. Sus parmetros, como en muchas de las funciones OpenGL, se definen con flags
o mscaras de bits. En este caso, GLUT_RGB indica el tipo de modelo de color con el que
se dibujar (Red-Green-Blue), GLUT_DEPTH indica que se debe incluir un buffer de
profundidad y GLUT_DOUBLE que se debe utilizar un doble buffer.
Antes de crear una ventana, es necesario definir sus propiedades. Con la funcin
glutInitWindowSize() se define el tamao de la ventana en pxeles (anchura y altura) y
con la funcin glutInitWindowPosition(), la distancia horizontal y vertical con respecto
de la esquina superior izquierda del monitor donde la ventana deber aparecer. Finalmente,
con la funcin glutCreateWindow() se crea propiamente la ventana, y el string que se
pasa como argumento, es utilizado como nombre de la nueva ventana.
Ahora que la ventana ha sido creada, es necesario mostrarla. Para ello la funcin
main llama a la funcin glutDisplayFunc(). Esta funcin es la ms importante de las
funciones callback. Gracias a la definicin de las funciones callback, GLUT hace posible
una dinmica de programacin de aplicaciones OpenGL. Una funcin callback ser
llamada por GLUT para hacer alguna operacin especifica cada vez que se produzca un
evento. En este caso, glutDisplayFunc(display), define que la funcin display que es
pasada como argumento sea ejecutada cada vez que GLUT determine que la ventana debe
ser dibujada (la primera vez que se muestra la ventana) o redibujada (cuando se maximiza,
cuando se superponen varias ventanas, etc).
La ultima funcin que es llamada en el main es glutMainLoop(). Esta funcin se
encarga de pasar el control del flujo del programa a la GLUT, de manera que cada vez que
ocurra un evento sean llamadas las funciones definidas como callbacks hasta que el la
ventana se cierre.
La funcin display(), definida como funcin callback para dibujar o redubujar la
ventana cada vez que sea necesario, esta tambin contenida en el archivo tecnunlogo.c.
Como todas las funciones callback que sern utilizadas, display() es del tipo void. Como
este ejercicio es bastante simple y no se va a dibujar ninguna figura en la ventana, el
contenido de la funcin es bastante sencillo. En ella solo se van a definir las funciones que
siempre deben aparecer en cualquier funcin display callback.
void display(void) {
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
UN
TOROIDE
EN
LA
Figura 1
Ventana inicial
VENTANA
En este ejemplo sern introducidas tres nuevas funciones GL (una funcin OpenGL y
dos funciones GLUT). La funcin OpenGL glColor3f() establece el color actual con el que
se va a dibujar una figura. El color ser el mismo hasta que se cambie el estado de esta
variable con la funcin glColor3f nuevamente. Esto es lo que se quiere decir cuando se
habla de OpenGL como una maquina de estados. Todas las funciones de OpenGL
comienzan con el prefijo gl y en muchas (como es el caso de glColor3f) aparece un
sufijo compuesto por un nmero y una letra. El nmero simboliza el numero de parmetros
que se debe pasar a la funcin y la letra, el tipo de estos parmetros. En este caso, se deben
pasar 3 parmetros de tipo float. Al estar trabajando en un modelo de color de tipo RGB
(Red-Green-Blue), cada uno de estos parmetros representa el valor de cada color
respectivamente.
La funcin GLUT glutWireTorus(0.25, 0.75, 28, 28) dibuja un toroide de frame de
hilos cuyo radio interno es el double 0,25; radio externo el double 0,75; el primer entero 28
representa el numero de lados que se puede observar en cada seccin radial y el segundo
entero 28 el numero de divisiones radiales del toroide.
La funcin GLUT glutWireCube(0.60) dibuja un cubo cuyo tamao queda
determinado por su nico parmetro de valor float.
El resultado es el que se muestra en la figura:
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
X
Z
Observador
Figura 3
De nuevo, como toda funcin callback, la funcin reshape() es del tipo void. Se le
pasan como argumentos el ancho y el alto de la ventana despus del reescalado. La funcin
glViewport define la porcin de ventana donde OpenGL podr dibujar. Sus parmetros
son: primero la distancia horizontal y vertical de la esquina superior izquierda del cuadro
donde OpenGL puede dibujar con respecto a la ventana; segundo, el ancho y alto de la
ventana.
A continuacin, glMatrixMode() especifica la matriz de transformacin sobre la que
se van a realizar las operaciones siguientes (de nuevo, recordar que OpenGL es una
maquina de estados). Los tres tipos de matrices que existen son: matriz de proyeccin
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
La funcin keyboard() que es pasada como parmetro ser llamada cada vez que
ocurra un evento en el teclado. Se define a continuacin la funcin keyboard():
void keyboard(char key, int x, int y) {
switch (key) {
case h:
printf("help\n\n");
printf("c
- Toggle culling\n");
printf("q/escape
- Quit\n\n");
break;
case c:
if (glIsEnabled(GL_CULL_FACE))
glDisable(GL_CULL_FACE);
else
glEnable(GL_CULL_FACE);
break;
case 1:
glRotatef(1.0,1.,0.,0.);
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
10
break;
case 2:
glRotatef(1.0,0.,1.,0.);
break;
case q:
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
11
Bucle for:
Comparar la utilizacin de
glBegin(GL_LINE_LOOP);
glBegin(GL_POLYGON);
Figura 5
Figura 6
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
12
13
Abreviatura
Descripcin
Argumento
FORWARD
fd
Unidades de distancia
RIGHT
rt
Gira a la derecha
Grados (0 360)
LEFT
lt
Gira a la izquierda
Grados (0 360)
BACK
bk
Retrocede
Unidades de distancia
UPPITCH
up
Grados (0 360)
DOWNPITCH
down
Grados (0 360)
EXIT
exit
HOME
home
Posicionarse en el inicio
14
Se emplea la funcin char* strtok(s, ct) de la librera <string.h> que busca elementos
en la cadena s , separados por los carcteres ct . En este caso los caracteres separadores
es el espacio en blanco.
El primer elemento strToken0 es la instruccin Logo y el segundo elemento
strToken1 es el argumento. A continuacin se compara el texto de la instruccin con las
distintas posibilidades (fd, rt, lt, ...) y se ejectua la accin correspondiente. En este caso, el
cuerpo de la accin muy reducido, se inserta a continuacin en lugar de realizar una
funcin separada.
Para introducir las instrucciones Logo, se debe pasar al modo interprete. Esto se
realiza pulsando la tecla i , con lo que los caracteres introducidos a continuacin se
almacenan en una cadena hasta que se pulsa la tecla retorno (ASCII: 13).
Se aade la librera stdio.h y las variables globales command y strCommand que
indican respectivamente si est en modo comando y la cadena de texto introducida hasta el
momento:
#include <stdio.h>
boolean command = FALSE;
char strCommand[256];
/* command mode */
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
15
Figura 1
Posicin inicial
Figura 2
2.4 ROTACIN
La funcin de OpenGL para aplicar una rotacin es glRotate(). Tiene cuatro
argumentos: el primero es el ngulo que se desea girar en grados sexagesimales en sentido
contrario a las agujas del reloj; los siguientes tres argumentos definen las coordendas x, y,
z del eje alrededor del cual se realiza el giro. El eje pasa por el origen de coordendas, por
lo tanto, si el objeto est alejado de este eje, se producir un desplazamiento causado por la
rotacin, es decir, no solo girar. Si de desea evitar este desplazamiento ser necesario
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
16
{ // RIGTH
{ // LEFT
{ // UP
{ // DOWN
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
17
AbreviaDescripcin
Argumento
tura
rr
Rota hacia la derecha segn el eje Grados (0 360)
de avance
LEFTROLL
lr
SCALEX
sx
SCALEY
sy
SCALEZ
sz
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
18
Este comando realiza n veces las instrucciones escritas entre corchetes. Admite
anidaciones de cualquier nivel como en todos los lenguajes de programacin.
En la aplicacin tecnunLogo se implementa este comando con una inclusin en la
funcin parseCommand() y la funcin insideRepeat():
char * insideRepeat(char* strCommandInside) {
char *ini, *fin;
ini = strchr(strCommandInside,[);
if (ini == NULL) return NULL;
ini++;
fin = strrchr(strCommandInside,]);
if (fin == NULL) return NULL;
strCommandInside[fin-strCommandInside]=0;
return ini;
}
19
20
observa la pila en la situacin inicial con una sola matriz, al llamar a la funcin
glPushMatrix() se duplica la matriz superior. Las siguientes transformaciones que se
realizan se aplican slo a la matriz superior de la pila, quedando la anterior con los valores
que tena en el momento de llamar a la funcin glPushMatrix().
La funcin glPopMatrix() elimina la matriz superior, quedando en la parte superior
de la pila la matriz que estaba en el momento de llamar a la funcin glPushMatrix().
Push
Figura 1
Translate
Pop
PushMatrix y PopMatrix
0;
[10000];
[10000];
[10000];
Para obtener la matriz actual de una de las pilas se dispone de la funcin de OpenGL
glGetDoublev() a la que se indica que matriz se quiere obtener, GL_MODELVIEW en
nuestro caso, y un puntero a un vector de 16 posiciones donde se rellenarn los valores de
la matriz.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
21
Hay que tener en cuenta que OpenGL almacena esta matriz por columnas de modo
que los elementos son:
m1
m
M = 2
m3
m4
m5
m6
m7
m8
m9
m10
m11
m12
m13
m14
m15
m16
En realidad todo este proceso lo que ha hecho ha sido inicializar la matriz que
represena mModel con la matriz identidad.
Para guardar las distintas transformaciones que se realizan con las instrucciones de
logo (FORWARD, RIGHT, ...), se carga la matriz mModel en la pila, antes del bloque de
if que determinan que instruccin se va a realizar:
glPushMatrix();
glLoadIdentity();
glMultMatrixd(mModel);
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
22
void addPointToTrace() {
int i;
GLdouble m[16];
glGetDoublev (GL_MODELVIEW_MATRIX, m);
// print the matrix
printf ("\nMatrix:\n");
for (i = 0; i < 4; i++) {
printf ("Row %i: %f \t%f \t%f \t%f \n",
i+1, m[i+0],m[i+4],m[i+8],m[i+12]);
}
// if is the first point
if (np == 0) { // add the first point
px [0] = 0;
py [0] = 0;
pz [0] = 0;
np++;
}
px [np] = m[0] * px [0] + m[4] * py [0] + m[8] * pz [0] + m[12];
py [np] = m[1] * px [0] + m[5] * py [0] + m[9] * pz [0] + m[13];
pz [np] = m[2] * px [0] + m[6] * py [0] + m[10] * pz [0] + m[14];
printf ("Point %i: %f \t%f \t%f \n",
np, px[np],py[np],pz[np]);
np++;
}
La matriz se obtiene de la pila en lugar de ser mModel, porque esta ltima todava no
tiene incorporada la ultima transformacin realizada.
El proceso de la funcin addPointToTrace() consiste en:
obtener la matriz,
la imprime a efectos informativos, la matriz se imprime de la forma habitual que
es con la traslaccin como ltima columna de la matriz, por ello en la primera fila
se imprimen los elementos 0, 4 ,8 y 12.
si es el primer punto de la lista lo introduce directamente, en este caso es el
origen,
calcula las coordenadas del nuevo punto como producto de la matriz por el vector
de coordenadas del primer punto
Para que se realice la representacin de la ruta es necesio invocar estas dos funciones
en el cdigo.
La llamada a addPointToTrace() se introduce despues de las llamadas a
glTranslatef() en las instrucciones correspondientes al FORWARD y BACK.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
23
addPointToTrace();
Figura 2
5
3
Figura 3 GL_QUAD_STRIP
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
24
Figura 5
Helicoidal
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
25
La persona que est desarrollando un programa para visualizar una escena, suele
tener en mente un sistema de coordenadas en el que situa los distintos objetos y luces. La
cmara la sita de forma similar, es decir colocndoloa en una posicin determinada y
apuntando a un lugar concreto. La funcin gluLookAt() est disponible para este
propsito. La declaracin de la funcin es de la siguiente:
void gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz );
El punto en el que se sita la cmara se especifica por los argumentos eyex, eyey, y
punto al que mira la cmara se especifica por los argumentos centerx, centery, y
Estos dos puntos definenen la lnea de visin. Los argumentos upx, upy, y upz
determinan la direccin que se considera hacia arriba (equivale al vector que va de los pies
a la cabeza del observador). Estos argumentos se muestran en la figura 3.1.
eyez. El
centerz.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
26
up X
up Y
up Z
eye X
eye Y
eye Z
center X
center Y
center Z
Proyeccin en perspectiva
El efecto principal que se observe en la proyeccin en perspectiva es la disminucin
del tamao de un objeto en la proyeccin cuanto ms alejado est de la cmara. La causa
de este efecto es que el volmen de visin en este caso es un tronco de pirmide; en
realidad el volmen de visin sera una pirmide de altura infinita, pero se corta por dos
planos para definir un espacio finito de visin. La proyeccin de los objetos se realiza en
direccin al punto de vista, que corresponde al vrtice comn de los lados de la pirmide.
Los objetos ms cercanos al punto de vista ocupan un rea relativa ms grande del
volmen de visin que los objetos ms cercanos.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
27
void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar
La figura 3.2. muestra las caractersticas del volumen de visin especificado por la
rutina gluPerspective() as como el significado de los argumentos de la funcin.
w
h
fovy
aspect = w/h
near
far
Proyeccin Ortogonal
En la proyeccin ortogonal, la direccin de proyeccin es perpendicular al plano de
proyeccin, con lo que el volumen de visin es en este caso un paraleleppedo. En la
proyeccin ortogonal el tamao de los objetos proyectados es independiente de la distancia
a la cmara.
El volumen de visin en la proyeccin ortogonal se define con la funcin glOrtho(),
perteneciente a la librera bsica de OpenGL:
void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far );
top
left
far
right
bottom
near
Figura 3.3. Volumen de visin Ortogonal especificado por glOrtho().
La figura 3.3. muestra las caractersticas del volumen de visin especificado por la
rutina glOrtho() as como el significado de los argumentos de la funcin.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
28
Para ello se necesita definir un interface de cmara que guarde los datos de la cmara
y una serie de funciones auxiliares para cada movimiento de la cmara. En el proyecto se
incluyen los siguientes archivos:
contiene las declaraciones de las variables y de las funciones de manejo
de cmara.
camera.c
contiene las definiciones de las funciones para el manejo de la cmara.
A su vez, se necesitan ciertas funciones para el manejo de vectores, las cuales estan
definidas en los siguientes ficheros, que tambin se incluyen en el proyecto:
camera.h
vector_tools.h
vector_tools.c
Se debes declarar una variable global que contendr el interface de cmara, es decir,
los datos de la cmara con los cuales se alimenta a las funciones que realizan las
transformaciones de vista y de proyeccin. Puesto que los movimientos de la cmara se
realizan con el ratn, se necesita conocer las coordenadas en las que estaba el puntero justo
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
29
Mediante esta sentencia se coloca la cmara en (0,1,-3) mirando hacia (0,0,0). Para
poder manejar la cmara, bien en un modo o en otro, se utilizan las siguientes teclas:
F1
F2
Modo Examinar
F3
Modo Caminar
La funcin SpecialKey() que es pasada como parmetro ser llamada cada vez que
ocurra un evento de pulsado de una tecla especial entre las que se incluyen las teclas de
funciones, las flechas de desplazamiento y las de Inicio, Fin, Avance pgina y Retroceso
pgina. Se define a continuacin la funcin SpecialKey():
static void SpecialKey ( int key, int x, int y ){
switch(key) {
case GLUT_KEY_F1:
glutPassiveMotionFunc(MouseMotion);
LOCAL_MyCamera->camMovimiento = CAM_STOP;
break;
case GLUT_KEY_F2:
glutPassiveMotionFunc(Examinar);
LOCAL_MyCamera->camMovimiento = CAM_EXAMINAR;
break;
case GLUT_KEY_F3:
glutPassiveMotionFunc(MouseMotion);
LOCAL_MyCamera->camMovimiento = CAM_PASEAR;
LOCAL_MyCamera->camAtY = 0;
LOCAL_MyCamera->camViewY = 0;
SetDependentParametersCamera( LOCAL_MyCamera );
break;
case GLUT_KEY_HOME: //Reset Camera
LOCAL_MyCamera->camAtX =0;
LOCAL_MyCamera->camAtY =0;
LOCAL_MyCamera->camAtZ =0;
LOCAL_MyCamera->camViewX = 0;
LOCAL_MyCamera->camViewY = 1;
LOCAL_MyCamera->camViewZ = -3;
SetDependentParametersCamera( LOCAL_MyCamera );
break;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
30
default:
printf("key %d %c X %d Y %d\n", key, key, x, y );
}
glutPostRedisplay();
}
Por otro lado, se debe indicar al programa qu funcin controlar los movimientos
del ratn cuando se pulsa algn botn de este. Para ello se dispone de la funcin callback
glutMouseFunc(), que se incluye en la funcin main del programa y que responde a los
eventos de pulsado de botones del ratn:
glutMouseFunc(mouse);
La funcin mouse() que es pasada como parmetro ser llamada cada vez que ocurra
un evento de pulsado de un botn del ratn. En ella se define qu operaciones se realizan
cuando se pulse un botn y se encuentra en un modo de movimiento de cmara o en otro:
void mouse(int button, int state, int x, int y){
old_x = x;
old_y = y;
switch(button){
case GLUT_LEFT_BUTTON:
switch(LOCAL_MyCamera->camMovimiento){
case CAM_EXAMINAR:
if (state == GLUT_DOWN) glutMotionFunc(Zoom);
if (state == GLUT_UP){
glutPassiveMotionFunc(Examinar);
glutMotionFunc(NULL);
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
31
break;
case CAM_PASEAR:
if (state == GLUT_DOWN) glutMotionFunc(Andar);
if (state == GLUT_UP) glutMotionFunc(NULL);
break;
}
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) ;
break;
default:
break;
}
glutPostRedisplay();
}
Para que todos los movimientos de cmara que se realizan se vean reflejados se debe
incluir en la funcin display() una llamada a la funcin que se encarga de actualizar los
valores de la cmara a aquellos que tiene guardados el interface de cmara y que son los
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
32
que se han modificado al realizar movimientos de cmara. Para ello se debe incluir en la
funcin display() la siguiente sentencia:
SetGLCamera( LOCAL_MyCamera );
Por ltimo, la funcin reshape() necesita un cambio para que al cambiar el aspecto
de la ventana se mantengan las proporciones de la escena y esta no se deforme. Quedar de
la siguiente forma:
void reshape(int width, int height) {
glViewport(0, 0, width, height);
SetGLAspectRatioCamera( LOCAL_MyCamera );
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
33
#ifndef CAMERA_H
#define CAMERA_H
#define CAM_PARALLEL 1
#define CAM_CONIC 2
#define CAM_STOP 0
#define CAM_EXAMINAR 1
#define CAM_PASEAR 2
typedef struct _Camera
{
// we consider a rigth handed reference system for the camera
// V point where the camera is placed (world coordinates)
// A point the camera is looking at
(world coordinates)
// up vector : unit vector, perpendicular to AV (world componnents)
// origin camera reference system : at V
// Z camera : defined by vector from A to V (penetrates the viewers eye)
// Y camera : defined by up vector
// X camera : looking from V towards A goes rigthwards
float
camViewX; // View point
float
camViewY;
float
camViewZ;
float
camAtX;
// look At point
float
camAtY;
float
camAtZ;
float
camUpX;
// Up vector
float
camUpY;
float
camUpZ;
float
camAperture; // field of view radians
// NOTE : OpenGL uses degrees
// defined as they are used by OpenGL
// always => positive ; Far > Near (distance from plane to camera origin)
float
camNear;
float
camFar;
int
camProjection; // PARALLEL or CONIC
int
camMovimiento; // EXAMINAR, ANDAR, TRIPODE or PAN
// ****** dependent values ******
// window system dependent
float
aspectRatio;
// for ortho projection
float
x1, x2, y1, y2, z1, z2;
// camera i j k vectors in world coordinates
float
camIX, camIY, camIZ;
float
camJX, camJY, camJZ;
float
camKX, camKY, camKZ;
} camera;
void DestroyCamera ( camera **theCamera );
camera *CreatePositionCamera( float positionX, float positionY, float positionZ );
void SetCamera( camera *thisCamera, float viewX, float viewY, float viewZ,
float atX,
float atY,
float atZ,
float upX,
float upY,
float upZ );
void
void
void
// Free camera advances "step" following vector VA, step admits negative values
void AvanceFreeCamera( camera *thisCamera, float step );
// ROTATION
void YawCamera( camera *thisCamera, float angle );
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
34
#include <GL/glut.h>
#include "camera.h"
#include "vector_tools.h"
void DestroyCamera ( camera **theCamera ){
camera *thisCamera = *theCamera;
if( ! thisCamera ) return;
free( thisCamera );
*theCamera = NULL;
}
camera *CreatePositionCamera( float positionX, float positionY, float positionZ ){
camera *newCamera;
int
ierr = 0;
newCamera = (camera *) malloc( sizeof(camera) * 1 );
newCamera->camViewX
newCamera->camViewY
newCamera->camViewZ
= positionX;
= positionY;
= positionZ;
// looks towards
newCamera->camAtX
newCamera->camAtY
newCamera->camAtZ
= 0.0f;
= 0.0f;
= 0.0f;
newCamera->camUpX
newCamera->camUpY
newCamera->camUpZ
= 0.0f;
= 1.0f;
= 0.0f;
float
float
float
float
float
float
int
viewX
viewY
viewZ
atX
atY
atZ
upX
upY
upZ
ix,
jx,
kx,
atX,
upX,
viewX,
ierr =
=
=
=
=
=
=
=
=
=
iy,
jy,
ky,
atY,
upY,
viewY,
0;
iz;
jz;
kz;
atZ;
upZ;
viewZ;
thisCamera->camViewX;
thisCamera->camViewY;
thisCamera->camViewZ;
thisCamera->camAtX;
thisCamera->camAtY;
thisCamera->camAtZ;
0.0f;
1.0f;
0.0f;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
35
thisCamera->camKY = ky;
thisCamera->camKZ = kz;
thisCamera->camIX = ix;
thisCamera->camIY = iy;
thisCamera->camIZ = iz;
thisCamera->camJX = jx;
thisCamera->camJY = jy;
thisCamera->camJZ = jz;
thisCamera->camUpX = jx;
thisCamera->camUpY = jy;
thisCamera->camUpZ = jz;
}
void SetGLCamera( camera *thisCamera ){
float
fovy;
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
if( thisCamera->camProjection == CAM_CONIC ){
fovy = thisCamera->camAperture*RAD_TO_DEGREE;
gluPerspective(fovy, thisCamera->aspectRatio, thisCamera->camNear, thisCamera->camFar
);
}
else { // CAM_PARALLEL
glOrtho(thisCamera->x1, thisCamera->x2, thisCamera->y1, thisCamera->y2,
thisCamera->z1,thisCamera->z2);
}
gluLookAt(thisCamera->camViewX, thisCamera->camViewY, thisCamera->camViewZ,
thisCamera->camAtX, thisCamera->camAtY, thisCamera->camAtZ,
thisCamera->camUpX, thisCamera->camUpY, thisCamera->camUpZ );
glMatrixMode( GL_MODELVIEW ); //* GL_MODELVIEW *
}
void SetGLAspectRatioCamera( camera *thisCamera ){
GLint
viewport[4];
glGetIntegerv( GL_VIEWPORT, viewport );
if( viewport[3] > 0 )
thisCamera->aspectRatio = (float) viewport[2] / (float) viewport[3];
else
thisCamera->aspectRatio = 1.0f;
// width/height
SetDependentParametersCamera( thisCamera );
}
void
thisCamera->camViewX
thisCamera->camViewY
thisCamera->camViewZ
thisCamera->camAtX =
thisCamera->camAtY =
thisCamera->camAtZ =
thisCamera->camUpX =
thisCamera->camUpY =
thisCamera->camUpZ =
= viewX;
= viewY;
= viewZ;
atX;
atY;
atZ;
upX;
upY;
upZ;
SetDependentParametersCamera( thisCamera );
}
void AvanceFreeCamera(camera *thisCamera, float step) {
float
vaX, vaY, vaZ;
vaX= step * thisCamera->camKX;
vaY= step * thisCamera->camKY;
vaZ= step * thisCamera->camKZ;
// Set V & A
thisCamera->camViewX=thisCamera->camViewX+vaX;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
36
thisCamera->camViewY=thisCamera->camViewY+vaY;
thisCamera->camViewZ=thisCamera->camViewZ+vaZ;
thisCamera->camAtX = thisCamera->camAtX + vaX;
thisCamera->camAtY = thisCamera->camAtY + vaY;
thisCamera->camAtZ = thisCamera->camAtZ + vaZ;
SetDependentParametersCamera( thisCamera );
}
void YawCamera(camera *thisCamera, float angle){
float vIn[3];
vIn[0]=thisCamera->camAtX-thisCamera->camViewX;
vIn[1]=thisCamera->camAtY-thisCamera->camViewY;
vIn[2]=thisCamera->camAtZ-thisCamera->camViewZ;
VectorRotY( vIn, angle );
thisCamera->camAtX=thisCamera->camViewX+vIn[0];
thisCamera->camAtY=thisCamera->camViewY+vIn[1];
thisCamera->camAtZ=thisCamera->camViewZ+vIn[2];
SetDependentParametersCamera( thisCamera );
}
void Rotar_Longitud(camera *thisCamera,float inc){
float vIn[3];
vIn[0]=thisCamera->camViewX-thisCamera->camAtX;
vIn[1]=thisCamera->camViewY-thisCamera->camAtY;
vIn[2]=thisCamera->camViewZ-thisCamera->camAtZ;
VectorRotY( vIn, inc );
thisCamera->camViewX=thisCamera->camAtX+vIn[0];
thisCamera->camViewZ=thisCamera->camAtZ+vIn[2];
SetDependentParametersCamera( thisCamera );
}
void Rotar_Latitud(camera *thisCamera,float inc){
float vIn[3];
vIn[0]=thisCamera->camViewX-thisCamera->camAtX;
vIn[1]=thisCamera->camViewY-thisCamera->camAtY;
vIn[2]=thisCamera->camViewZ-thisCamera->camAtZ;
VectorRotXZ( vIn, inc, TRUE );
thisCamera->camViewX=thisCamera->camAtX+vIn[0];
thisCamera->camViewY=thisCamera->camAtY+vIn[1];
thisCamera->camViewZ=thisCamera->camAtZ+vIn[2];
SetDependentParametersCamera( thisCamera );
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
37
#ifndef TOOLS_H
#define TOOLS_H
#include <math.h>
#ifndef TRUE
#define TRUE
#define FALSE
#endif
1
0
// *** Mathematics
#define VECTOR_EPSILON
#define DISTANCE_EPSILON
#define ANGLE_EPSILON
0.00001f
1e-08f
0.00872665f
// 0.5 degrees
3.14159265359f
0.0174533f /* 2.0 * 3.1415927 / 360.0 */
57.2958f
/* 360 / ( 2.0 * 3.1415927 ) */
void VectorNormalize( int *ierr, float *vX, float *vY, float *vz );
void UnitVectorPP( int *ierr, float *wX, float *wY, float *wZ,
float aX, float aY, float aZ,
float bX, float bY, float bz );
void UnitVectorVV( int *ierr, float *wX, float *wY, float *wZ,
float uX, float uY, float uZ,
float vX, float vY, float vz );
void VectorRotY( float *v, float inc );
// rotates vector : around Y axis like moving its end on its
parallel
void VectorRotXZ( float *vIn, float inc, int flagStop );
// rotates vector : like moving its end on its meridiam
#endif /* TOOLS_H */
X
Z
VectorRotXZ()
VectorRotY()
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
38
5. ILUMINANDO LA ESCENA
En este captulo se explican las funciones que OpenGL pone a disposicin para
manejar la iluminacin de la escena y a crear, posicionar y dar propiedades a diferentes
tipos de luces. La posicin de las luces se realiza mediante el ratn con funciones similares
a las utilizadas para posicionar la cmara en el modo examinar.
5.1 AADIENDO ILUMINACIN A LA ESCENA
Para que OpenGL pueda realizar los clculos correspondientes a la iluminacin es
necesaria la siguiente informacin de la escena:
1. Los vectores normales de cada vrtice de los objeto que definen la orientacin de
cada punto respecto a las lueces.
2. La posicin y caractersticas de cada una de las luces.
3. Las propiedades de los materiales de los objetos.
La presente prctica se va a centrar exclusivamente en el segundo punto. Se utilizar
como objeto una tortuga en 3D realizada con esferas, de forma que las normales para
dichas esferas viene definidas como parte de la rutina glutSolidSphere(). Las propiedades
del material de los objetos se realizar asignando directamente un color en lugar de definir
materiales y posteriormente asignarlos a los objetos.
5.2 CREANDO FUENTES DE LUZ CON OPENGL
5.2.1
Comando glLight*( )
El comando usado para especificar todas las propiedades luces es glLight*(); esta
funcin toma tres argumentos: el primero de ellos identifica la luz para la cual se est
especificando una propiedad, la propiedad que se desea especificar y el valor para dicha
propiedad. La forma de la funcin es la siguiente:
void glLight{if}(GLenum light, GLenum pname, TYPE param);
void glLight{if}v(GLenum light, GLenum pname, TYPE *param);
Parameter Name
GL_AMBIENT
GL_DIFFUSE
GL_SPECULAR
GL_POSITION
GL_SPOT_DIRECTION
GL_SPOT_EXPONENT
GL_SPOT_CUTOFF
GL_CONSTANT_ATTENUATION
GL_LINEAR_ATTENUATION
GL_QUADRATIC_ATTENUATION
Default Value
Meaning
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
39
El parmetro light que identifica la luz puede tomar los valores GL_LIGHT0,
GL_LIGHT1,..., GL_LIGHT7, de forma que se pueden tener hasta 8 luces diferentes
simultneamente en la escena.
El parmetro pname controla la propiedad de la luz que se desea especificar. Las
diferentes propiedades de la luz que se pueden modificar, su significado, as como los
valores por defecto de cada propiedad se muestran en la tabla 5.1.
5.3 INTRODUCIENDO LUCES AL PROGRAMA TECNUNLOGO
5.3.1
Tipos de luces
5.3.2
Interface de usuario
Para que el usuario de la aplicacin pueda interactuar con las luces que se van a
poner a su disposicin, se debe definir un inteface de usuario. Este interface constar de
una serie de teclas que permitan pasar al Modo Luces y pasar el control de una luz a otra,
as como encender y apagar cada una de las luces (Tabla 5.2).
Puesto que a estas alturas el programa ya dispondr de al menos dos modos de
interaccin, a saber, modo cmara y modo luces, se va a hacer que para pasar de un modo a
otro no se pueda hacer directamente sino que haya que desactivar previamente el modo en
curso. Mediante el ratn ser posible cambiar la posicin de las luces (Tabla 5.3).
Tecla
Accin
F1
F8
Modo luces. Cada vez que se pulsa se pasa de una luz a otra.
F9
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
40
Accin
Adelante/Atrs
Izquierda/Derecha
Adelante/Atrs con
botn izquierdo pulsado
Modificaciones en el cdigo
Se va a dotar al programa de tres luces que permitirn en el siguiente captulo
observar las diferencias entre los distintos tipos de luces y su efecto en la escena. Para ello
se permitir interactuar con la posicin y direccin de cada una de ellas y mantenerlas
encendidas o apagadas independientemente una de otra.
Se necesita definir un interface de luz que guarde los datos de la luz y una serie de
funciones auxiliares para el movimiento de las luces. En el proyecto incluiremos los
siguientes archivos:
light.h
light.c
Adems se necesitan una serie de funciones que dibujan primitivas. Entre estas
primitivas estn una tortuga modelada con esferas, el trazado de meridianos y paralelos en
un punto y otras. Se incluyen en el proyecto los siguientes ficheros:
primitivas.h
primitivas.c
Se debe declarar una variable global que contendr el interface de cada una de las
tres luces, es decir, los datos de cada luz con los cuales alimentaremos a la funcin que
efectivamente realiza los cambios en la luz, glLight*(). A su vez se necesita una variable
global que indique la luz con la cual se est interactuando en cada momento. Adems se
definir una variable global que indique el modo en el que se est trabajando (modo
examinar, modo andar, modo luces). Se incluyen las siguientes lneas en el fichero
tecnunLogo.c inmediatamente despus de los ficheros de cabecera:
static light
**LOCAL_MyLights;
static int current_mode = 0;
static int current_light = -1;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
41
Inicialmente se debe crear el interface para las luces y asignrselo a la variable global
que se acaba de declarar. Adems se deben dar las caractersticas a cada una de las luces.
De esta forma quedan definidos los interfaces para las tres luces en un array. Esto lo
realizamos incluyendo las siguientes sentencias en la funcin main() del programa:
int i;
...
//Reservamos memoria para tres interfaces de luces
LOCAL_MyLights = (light **) malloc( 3 * sizeof(light *));
//Creamos las luces y damos a cada una sus caractersticas
for(i=0;i<3;i++){
LOCAL_MyLights[i] = CreateDefaultLight();
LOCAL_MyLights[i]->type = AGA_DIRECTIONAL;
LOCAL_MyLights[i]->id = GL_LIGHT0 + i;
LOCAL_MyLights[i]->position[0] = 1.0f;
LOCAL_MyLights[i]->position[1] = 1.0f;
LOCAL_MyLights[i]->position[2] = 1.0f;
LOCAL_MyLights[i]->position[3] = 0.0f;
LOCAL_MyLights[i]->pointAtInfinity[0] = LOCAL_MyLights[0]->position[0];
LOCAL_MyLights[i]->pointAtInfinity[1] = LOCAL_MyLights[0]->position[1];
LOCAL_MyLights[i]->pointAtInfinity[2] = LOCAL_MyLights[0]->position[2];
}
La funcin SpecialKey() quedar de la siguiente manera una vez que se incluyen las
sentencias necesarias para definir las teclas que permiten pasar al Modo Luces:
static void SpecialKey ( int key, int x, int y ){
switch(key) {
case GLUT_KEY_F1:
current_mode = 0;
glutPassiveMotionFunc(MouseMotion);
LOCAL_MyCamera->camMovimiento = CAM_STOP;
current_light = -1;
break;
case GLUT_KEY_F2:
if (current_mode != 0) break;
current_mode = 1;
glutPassiveMotionFunc(Examinar);
LOCAL_MyCamera->camMovimiento = CAM_EXAMINAR;
break;
case GLUT_KEY_F3:
if (current_mode != 0) break;
current_mode = 2;
glutPassiveMotionFunc(MouseMotion);
LOCAL_MyCamera->camMovimiento = CAM_PASEAR;
LOCAL_MyCamera->camAtY = 0;
LOCAL_MyCamera->camViewY = 0;
SetDependentParametersCamera( LOCAL_MyCamera );
break;
case GLUT_KEY_F8:
if (current_mode != 0 && current_mode != 7) break;
current_mode = 7;
if (current_light == -1) glutPassiveMotionFunc(Mouse_Luces);
if (current_light != 2) current_light++;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
42
else current_light = 0;
printf("Luz actual = %d\n",current_light);
break;
case GLUT_KEY_F9:
if (current_light != -1)
if ( LOCAL_MyLights[current_light]->switched )
SwitchLight( LOCAL_MyLights[current_light], FALSE);
else SwitchLight( LOCAL_MyLights[current_light], TRUE);
break;
case GLUT_KEY_HOME: //Reset Camera
LOCAL_MyCamera->camAtX =0;
LOCAL_MyCamera->camAtY =0;
LOCAL_MyCamera->camAtZ =0;
LOCAL_MyCamera->camViewX = 0;
LOCAL_MyCamera->camViewY = 1;
LOCAL_MyCamera->camViewZ = -3;
SetDependentParametersCamera( LOCAL_MyCamera );
break;
default:
printf("key %d %c X %d Y %d\n", key, key, x, y );
}
glutPostRedisplay();
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
43
}else{
switch(LOCAL_MyCamera->camMovimiento){
case CAM_EXAMINAR:
if (state == GLUT_DOWN) glutMotionFunc(Zoom);
if (state == GLUT_UP){
glutPassiveMotionFunc(Examinar);
glutMotionFunc(NULL);
}
break;
case CAM_PASEAR:
if (state == GLUT_DOWN) glutMotionFunc(Andar);
if (state == GLUT_UP) glutMotionFunc(NULL);
break;
}
}
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) ;
break;
default:
break;
}
glutPostRedisplay();
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
44
Direction[0] = - LOCAL_MyLights[current_light]->position[0];
Direction[1] = - LOCAL_MyLights[current_light]->position[1];
Direction[2] = - LOCAL_MyLights[current_light]->position[2];
Draw_Parallel(At);
Draw_Meridian(At);
Draw_Vector(At, Direction);
break;
default:
break;
}
glPopMatrix();
glutSwapBuffers();
}
Por ltimo, en la funcin keyboard() hay que aadir el siguiente cdigo para que
cuando se pulse escape para abandonar el programa, se libere la memoria que se a
reservado dinmicamente:
case 27:
DestroyCamera(&LOCAL_MyCamera);
DestroyLight( LOCAL_MyLights[0] );
DestroyLight( LOCAL_MyLights[1] );
DestroyLight( LOCAL_MyLights[2] );
free (LOCAL_MyLights);
exit(0);
break;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
45
#ifndef LIGHT_H
#define LIGHT_H
#define AGA_DIRECTIONAL
#define AGA_POSITIONAL
#define AGA_SPOT
1
2
3
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
46
#include <GL/glut.h>
#include "light.h"
#include "vector_tools.h"
light *CreateDefaultLight() {
light
*newLight;
newLight = (light *) malloc( sizeof(light) * 1 );
SetDefaultLight( newLight );
return newLight;
}
void SetDefaultLight( light *thisLight ) {
int
ierr = 0;
float intensity;
float vx, vy, vz;
// directional light
thisLight->type
=
thisLight->id
=
thisLight->switched
thisLight->white
thisLight->attenuation
thisLight->needsUpdate
AGA_DIRECTIONAL;
-1;
= FALSE;
= TRUE;
= FALSE;
= TRUE;
intensity = 0.0f;
thisLight->ambient[0]
thisLight->ambient[1]
thisLight->ambient[2]
thisLight->ambient[3]
=
=
=
=
intensity;
intensity;
intensity;
1.0f;
intensity = 0.8f;
thisLight->diffuse[0]
thisLight->diffuse[1]
thisLight->diffuse[2]
thisLight->diffuse[3]
=
=
=
=
intensity;
intensity;
intensity;
1.0f;
intensity = 0.0f;
thisLight->specular[0]
thisLight->specular[1]
thisLight->specular[2]
thisLight->specular[3]
=
=
=
=
intensity;
intensity;
intensity;
1.0f;
thisLight->position[0]
thisLight->position[1]
thisLight->position[2]
thisLight->position[3]
=
=
=
=
1.0f;
1.0f;
1.0f;
1.0f;
&vz );
vx;
vy;
vz;
0.0f;
//
So
light
rays
flow
in
the
-1.0f;
&vy, &vz );
= vx;
= vy;
= vz;
= 0.0f;
thisLight->spotExponent
thisLight->spotCutOff
= 10.0f;
= 30.0f;
thisLight->a = 0.1f;
thisLight->b = 0.0f;
// GL_QUADRATIC_ATTENUATION
// GL_LINEAR_ATTENUATION
// must be degrees
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
47
// GL_CONSTANT_ATTENUATION
}
void DestroyLight( light *thisLight ) {
if( ! thisLight ) return;
free( thisLight );
thisLight = NULL;
}
void SwitchLight( light *thisLight, int status ) {
if( ! thisLight ) return;
if(
thisLight->id < GL_LIGHT0 ) return;
thisLight->switched = status;
if( status ) {
glEnable( thisLight->id );
thisLight->needsUpdate = TRUE;
}
else {
glDisable( thisLight->id );
}
}
void SetLight( light *thisLight ) {
int
lightId;
if( ! thisLight ) return;
if( ! thisLight->switched ) return;
if(
thisLight->id < GL_LIGHT0 ) return;
lightId = thisLight->id;
// Geometric parameters will be always set when the scene is redrawn
if( thisLight->type == AGA_DIRECTIONAL ) {
glLightfv( lightId, GL_POSITION,
thisLight->pointAtInfinity );
}
else if( thisLight->type == AGA_POSITIONAL ) {
glLightfv( lightId, GL_POSITION,
thisLight->position );
}
else {
glLightfv( lightId, GL_POSITION,
thisLight->position );
glLightfv( lightId, GL_SPOT_DIRECTION,
thisLight->spotDirection );
}
// These other parameters are seldom changed
// So, they will be set only when any one of them is changed. The user
interface
// must set "needsUpdate" to TRUE, whenever any of these parameters changes
if( thisLight->needsUpdate ) {
thisLight->needsUpdate = FALSE;
glLightfv( lightId, GL_AMBIENT,
thisLight->ambient );
glLightfv( lightId, GL_DIFFUSE,
thisLight->diffuse );
glLightfv( lightId, GL_SPECULAR,
thisLight->specular );
if( thisLight->type == AGA_SPOT ) {
glLightf( lightId, GL_SPOT_EXPONENT,
thisLight->spotExponent );
glLightf( lightId, GL_SPOT_CUTOFF,
thisLight->spotCutOff );
}
else {
glLighti( lightId, GL_SPOT_EXPONENT,
0 );
glLighti( lightId, GL_SPOT_CUTOFF,
180 );
}
if( ! thisLight->attenuation || thisLight->type == AGA_DIRECTIONAL ) {
glLighti( lightId, GL_CONSTANT_ATTENUATION,
1 );
glLighti( lightId, GL_LINEAR_ATTENUATION,
0 );
glLighti( lightId, GL_QUADRATIC_ATTENUATION, 0 );
}
else {
glLightf( lightId, GL_CONSTANT_ATTENUATION,
thisLight->c );
glLightf( lightId, GL_LINEAR_ATTENUATION,
thisLight->b );
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
48
49
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
50
#include <GL/glut.h>
#include "vector_tools.h"
void Draw_Parallel (float *At) {
double radius, angle;
float vectorX,vectorZ, vectorX1, vectorZ1;
int lightingFlag;
lightingFlag = glIsEnabled( GL_LIGHTING );
if( lightingFlag ) glDisable( GL_LIGHTING );
radius = sqrt(At[0]*At[0]+At[2]*At[2]);
vectorZ1=radius;
vectorX1=0.0;
glBegin(GL_LINE_STRIP);
for(angle=0.0f;angle<=(2.0f*3.14159);angle+=0.01f){
vectorX=radius*(float)sin((double)angle);
vectorZ=radius*(float)cos((double)angle);
glVertex3d(vectorX1,At[1],vectorZ1);
vectorZ1=vectorZ;
vectorX1=vectorX;
}
glEnd();
}
void Draw_Meridian (float *At) {
double radius, alfa, beta;
float vectorX, vectorY, vectorZ, vectorX1, vectorY1, vectorZ1;
int lightingFlag;
lightingFlag = glIsEnabled( GL_LIGHTING );
if( lightingFlag ) glDisable( GL_LIGHTING );
radius = sqrt(pow(At[0],2)+pow(At[1],2)+pow(At[2],2));
alfa = atan2(At[2],At[0]);
vectorX1=radius*(float)cos((double)alfa);
vectorY1=0;
vectorZ1=radius*(float)sin((double)alfa);
glBegin(GL_LINE_STRIP);
for(beta=0.0f;beta<=(2.0f*3.14159);beta+=0.01f){
vectorX=radius*(float)cos((double)beta)*(float)cos((double)alfa);
vectorY=radius*(float)sin((double)beta);
vectorZ=radius*(float)cos((double)beta)*(float)sin((double)alfa);
glVertex3d(vectorX1,vectorY1,vectorZ1);
vectorX1=vectorX;
vectorY1=vectorY;
vectorZ1=vectorZ;
}
glEnd();
}
void Draw_Vector(float *At, float *Direction) {
int ierr, lightingFlag;
float mod;
float alpha,beta;
float length = .2f;
float vectorX, vectorY, vectorZ;
lightingFlag = glIsEnabled( GL_LIGHTING );
if( lightingFlag ) glDisable( GL_LIGHTING );
mod = sqrt(pow(Direction[0],2)+pow(Direction[1],2)+pow(Direction[2],2));
alpha = atan2(Direction[0],Direction[2]);
beta = asin(Direction[1]/mod);
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(At[0], At[1], At[2] );
glVertex3f(At[0]+Direction[0]*length,At[1]+Direction[1]*length,At[2]+Direction
[2]*length);
glEnd();
VectorNormalize( &ierr, &Direction[0], &Direction[1], &Direction[2]);
vectorX = At[0] + Direction[0]*(length-0.05);
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
51
}
void drawSphereTurtle() {
int slices = 40;
int stacks = 40;
glPushMatrix();
glScalef(1.0f,.3f,1.0f);
glutSolidSphere(1.0,slices,stacks);
glPopMatrix();
glPushMatrix();
glTranslatef(.7f,0.0f,.7f);
glutSolidSphere(.3,slices,stacks);
glPopMatrix();
glPushMatrix();
glTranslatef(-.7f,0.0f,.7f);
glutSolidSphere(.3,slices,stacks);
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
52
glPopMatrix();
glPushMatrix();
glTranslatef(.7f,0.0f,-.7f);
glutSolidSphere(.3,slices,stacks);
glPopMatrix();
glPushMatrix();
glTranslatef(-.7f,0.0f,-.7f);
glutSolidSphere(.3,slices,stacks);
glPopMatrix();
glPushMatrix();
glScalef(1.0f,.6f,1.0f);
glTranslatef(0.0f,0.0f,-1.2f);
glutSolidSphere(.4,slices,stacks);
glPopMatrix();
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
53
Direccional
El primer tipo referido, se conoce como fuente de luz direccional. En este caso se
define la direccin de la que proviene la luz, como si la fuente de luz estuviera situada en
el infinito, por lo que todos los rayos son paralelos.
Los argumentos de la funcin glLight*() es un vector de cuatro valores (x,y,z,w) para
el parmetro GL_POSITION. En las luces direccionales, el valor de w, es cero y los
valores (x,y,z) describen la direccin.
6.1.2
Posicional
El segundo tipo referido se conoce como fuente de luz posicional, ya que su posicin
exacta dentro de la escena determina el efecto que tiene sobre esta, especficamente, la
direccin desde la cual vienen los rayos de luz.
Los argumentos de la funcin glLight*() es un vector de cuatro valores (x,y,z,w) para
el parmetro GL_POSITION. En las luces direccionales el valor, w, es distinto de cero y
los valores (x,y,z) definen la localizacin de la fuente de luz.
Otro efecto que se produce en la realidad es que la intensidad de la luz decrece al
aumentar la distancia de la luz. Esto es aplicable nicamente a las luces posicionales, ya
que las direccionales estn situadas en el infinito. La forma de definir la atenuacin en
OpenGL es mediante un factor de atenuacin:
factor de atenuacin =
donde
d
1
kc + kl d + k q d 2
kc
: GL_CONSTANT_ATTENUATION
kl
: GL_LINEAR_ATTENUATION
kq
: GL_QUADRATIC_ATTENUATION
6.1.3
Focal
Una luz posicional irradia en todas las direcciones, pero se puede restringir la
direccin en que acta de forma que se produzca un cono de luz definiendo lo que se
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
54
conoce como una luz de tipo foco (spotlight) (un ejemplo puede ser un foco o una lmpara
tipo flexo).
En las luces focales hay que definir, adems de la posicin por ser posicional:
1. La direccin del foco
2. El ngulo del cono de luz.
3. La intensidad de la distribucin de la luz en el cono.
La direccin del eje del cono de luz se define con el parmetro
GL_SPOT_DIRECTION que es un vector de 3 posicones (x, y, z).
El ngulo del cono de luz se define con el parmetro GL_SPOT_CUTOFF que
define el ngulo entre el eje del cono y una arista de dicho cono. En la figura 2 se muestra
este ngulo. El valor por defecto anula el efecto de la luz focal al ser de 180 grados e
irradiar todo el espacio. Los valores posibles de este parmetro es de 0 a 90 grados.
GL_SPOT_CUTOFF
Figura 2.
Parmetro GL_SPOT_CUTOFF
Tipos de luces
Las tres luces de que dispone el programa tecnunLogo, actualmente las tres del
mismo tipo, se van a cambiar para que cada una sea de un tipo: una de tipo direccional, una
de tipo posicional y una de tipo spotlight. Esto permitir estudiar las diferentes
caractersticas de los tipos de luces y cuales son sus efectos sobre la escena tanto al
cambiar su posicin o direccin como al cambiar las componentes propias de la luz.
Adems, permitiendo que puedan ser encendidas o apagadas de forma independiente se
pueden estudiar los efectos de combinaciones entre ellas.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
55
6.2.2
Interface de usuario
El interface de usuario actual permite pasar al Modo Luces y pasar el control de una
luz a otra, encender y apagar cada una de las luces e indicar la direccin de las luces
direccionales. Se va a aadir la posibilidad de controlar la direccin y ngulo de la luz de
tipo spotlight (Tabla 6.1).
Mediante el ratn ser posible cambiar la posicin de las luces (Tabla 6.2) y para el
caso de la luz tipo spotlight cambiar tambin la direccin de la luz y el ngulo de apertura
del cono de luz (Tabla 6.3).
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
56
6.2.3
Modificaciones en el cdigo
Se va a dotar al programa de los tres tipos de luces expuestas en el apartado anterior
que permitirn observar las diferencias entre ellas y su efecto en la escena. Para ello se
permitir interactuar con la posicin y direccin de cada una de ellas y mantenerlas
encendidas o apagadas independientemente una de otra. Para ello se utilizar el interface
de luz definido en la prctica 5 y se realizarn modificaciones al cdigo.
Tecla
F1
Accin
Desactivar luces (en general, desactivar cualquier modo)
Modo luces. Cada vez que se pulsa se pasa de una luz a otra:
F8
F9
Direccional
Posicional
Spotlight
F10
Posicin
Direccin
Accin
Adelante/Atrs
Izquierda/Derecha
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
57
Accin
Adelante/Atrs
Izquierda/Derecha
Incremento/Decremento
apertura del spotlight..
del
ngulo
de
Tabla 6.3. Control de la direccin y apertura del cono de luz del spotlight
Para la luz del tipo spotlight har falta una variable ms que indique si se est
interactuando con la posicin de la luz o con el vector de direccin.. Se incluyen las
siguientes lneas en el fichero tecnunLogo.c inmediatamente despus de los ficheros de
cabecera:
static int spot_move = 0;
Se deben dar las caractersticas a cada una de las luces. Esto lo realizamos
modificando las siguientes sentencias en la funcin main() del programa:
//Creamos las luces y damos a cada una sus caractersticas
//DIRECCIONAL
LOCAL_MyLights[0] = CreateDefaultLight();
LOCAL_MyLights[0]->type = AGA_DIRECTIONAL;
LOCAL_MyLights[0]->id = GL_LIGHT0 + i;
LOCAL_MyLights[0]->position[0] = 1.0f;
LOCAL_MyLights[0]->position[1] = 1.0f;
LOCAL_MyLights[0]->position[2] = 1.0f;
LOCAL_MyLights[0]->position[3] = 0.0f;
LOCAL_MyLights[0]->pointAtInfinity[0] = LOCAL_MyLights[0]->position[0];
LOCAL_MyLights[0]->pointAtInfinity[1] = LOCAL_MyLights[0]->position[1];
LOCAL_MyLights[0]->pointAtInfinity[2] = LOCAL_MyLights[0]->position[2];
//POSICIONAL
LOCAL_MyLights[1] = CreateDefaultLight();
LOCAL_MyLights[1]->type = AGA_POSITIONAL;
LOCAL_MyLights[1]->id = GL_LIGHT1;
LOCAL_MyLights[1]->position[0] = 1.0f;
LOCAL_MyLights[1]->position[1] = 1.0f;
LOCAL_MyLights[1]->position[2] = -1.0f;
LOCAL_MyLights[1]->position[3] = 1.0f;
//SPOT
LOCAL_MyLights[2] = CreateDefaultLight();
LOCAL_MyLights[2]->type = AGA_SPOT;
LOCAL_MyLights[2]->id = GL_LIGHT2;
LOCAL_MyLights[2]->position[0] = -1.0f;
LOCAL_MyLights[2]->position[1] = 1.0f;
LOCAL_MyLights[2]->position[2] = 1.0f;
LOCAL_MyLights[2]->spotDirection[0] = 1.0f;
LOCAL_MyLights[2]->spotDirection[1] = -1.0f;
LOCAL_MyLights[2]->spotDirection[2] = -1.0f;
De esta forma quedan definidos los interfaces para las tres luces en un array. Con el
ndice 0 se tiene una luz direccional, con el ndice 1 se tiene una luz posicional y con el
ndice 2 se tiene una luz tipo spotlight.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
58
59
glutMotionFunc(NULL);
}
break;
case CAM_PASEAR:
if (state == GLUT_DOWN) glutMotionFunc(Andar);
if (state == GLUT_UP) glutMotionFunc(NULL);
break;
}
}
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) ;
break;
default:
break;
}
glutPostRedisplay();
}
60
Draw_Meridian(At);
Draw_Vector(At, Direction);
break;
case 1:
At[0] = LOCAL_MyLights[current_light]->position[0];
At[1] = LOCAL_MyLights[current_light]->position[1];
At[2] = LOCAL_MyLights[current_light]->position[2];
Draw_Parallel(At);
Draw_Meridian(At);
glTranslatef(At[0],At[1],At[2]);
glColor3f(1.0,0.0,0.0);
glutSolidSphere(0.05,28,28);
break;
case 2:
At[0] = LOCAL_MyLights[current_light]->position[0];
At[1] = LOCAL_MyLights[current_light]->position[1];
At[2] = LOCAL_MyLights[current_light]->position[2];
Direction[0] = LOCAL_MyLights[current_light]->spotDirection[0];
Direction[1] = LOCAL_MyLights[current_light]->spotDirection[1];
Direction[2] = LOCAL_MyLights[current_light]->spotDirection[2];
Draw_Parallel(At);
Draw_Meridian(At);
glColor3f(1.0,0.0,0.0);
Draw_Vector(At, Direction);
Draw_Sphere_Spot(At, Direction);
glTranslatef(At[0],At[1],At[2]);
glutSolidSphere(0.05,28,28);
break;
default:
break;
}
glPopMatrix();
glutSwapBuffers();
}
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
61
*object;
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
62
63
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
64
El resultado se muestra en
la figura 2, en la que se han
introducido 4 tortugas, 3 de
ellas con el objeto de un
vehculo.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
65
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
66
67
Palpador: elemento en el que se montan las agujas que realizan el contacto con la
pieza. El palpador empleado habitualmente, PH), dispone de dos grados de libertad que le
permite orientarse en cualquier direccin del espacio.
Agujas: son unas esferas de rub unidas a un cilindro que se montan en el palpador.
Mando de control: permite mover los tres carros para efectuar el contacto de la aguja
con la pieza, dispone tambin de controles para cambiar la velocidad (posicionamiento y
medicin), registrar puntos de posicionamiento, potencimetro para graduar la velocidad
en modo de medicin y los de seguridad (hombre muerto y emergencia).
Ordenador: una aplicacin de software para controlar la mquina.
9.3 PROCESO DE CAPTURA DE COORDENADAS
El primer paso es determinar los puntos del vehculo que se van a digitalizar. Para
ello se traza una malla sobre el modelo. Los puntos de interseccin de las lneas
horizontales y verticales determinan los puntos a digitalizar. La separacin de las lneas se
establece en funcin de la curvatura de las superficies, de modo que en aquellos puntos que
la curvatura es mayor, las lneas se encuentran ms prximas.
A continuacin se capturarn las coordenadas. En este caso de todas las formas de
medicin de que dispone la mquina, se elige la ms simple, que es la de medicin de un
punto, ya que interesan las coordenadas x, y, z de cada vrtice.
Con las coordenadas capturadas se pasan a un fichero de datos que es necesario
convertir en un objeto Wavefront. Para ello, a la geometra capturada se aade la topologa
que define los vrtices que forman cada cara.
La digitalizacin se realiza para uno de los lados del vehculo, ya que la otra mitad se
obtiene por simetra.
9.4 DIGITALIZACIN POR FOTOGRAFA
Si no se dispone de una mquina de medir por coordinadas, se puede realizar una
aproximacin de este mtodo mediante varias fotografas de un objeto desde los distintos
ejes. Al menos son necesarias dos fotografas. Podran obtenerse desde dos direcciones
arbitrarias, pero el proceso se simplifica si se realiza desde dos direcciones ortogonales.
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
68
GL_TEXTURE_WRAP_S, GL_REPEAT);
GL_TEXTURE_WRAP_T, GL_REPEAT);
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
69
glDisable(GL_TEXTURE_2D);
glutSwapBuffers() ;
}
void reshape(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)height / (GLfloat)width, 1.0, 128.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 1.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("tecnunLogo");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Como puede observarse, la funcin main() y reshape() son muy similares a las ya
vistas en prcticas anteriores. Para entender el proceso de mapeado de texturas se va a
explicar nicamente la funcin display().
Las texturas en OpenGL pueden ser 1D, 2D o 3D. Las 1D tienen anchura pero no
altura; las 2D son imgenes que tienen una anchura y una altura de ms de 1 pxel, y son
generalmente cargadas a partir de un archivo .bmp (aunque puede ser en principio
cualquier formato). En este capitulo no se hablar de las texturas 3D (volumen). Un
aspecto muy importante a tener en cuenta es que en OpenGL las dimensiones de las
imgenes deben ser potencia de 2 (2, 4, 8, 16, 32...)
Antes de definir la textura, se carga una imagen a partir de un archivo (.bmp en este
caso). Para esto es necesario incluir dos punteros, TexInfo y TexBits, para almacenar la
informacin de la imagen (header) y los bits que componen la imagen respectivamente. Se
carga la imagen con la funcin LoadDIBitmap() y se le pasa como argumentos el nombre
de la imagen ( escudo.bmp en este caso) y el puntero que guardar la informacin de
dicha imagen (header).
Para definir las texturas, OpenGL pone a disposicin las funciones glTexImage1D y
glTexImage2D (la nica diferencia entre ambas es que en la segunda se define, adems, la
altura de la imagen). La funcin glTexImage2D tiene 9 argumentos:
void glTexImage2D(GLenum target, GLint level, GLint components, GLsezei width, GLsizei height, GLint
border, GLenum format, GLenum type, const GLvoid *pixels)
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
70
Una vez cargada la imagen y definida la textura, se define la manera de cmo ser
aplicada la textura a cada pxel de la superficie que queremos texturizar por medio de la
funcin glTexParameteri().
t
La textura tiene 2 coordenadas, la s para el
(0.0, 1.0)
(1.0, 1.0)
eje horizontal y la t para el eje vertical, y toma
valores de 0.0 a 1.0. Para la coordenada s 0.0
representa el extremo izquierdo de la textura y
1.0 el extremo derecho. Para la t el 0.0
representa el extremo inferior y el 1.0 el
s
superior.
(0.0, 0.0)
(1.0, 0.0)
CARGANDO
TECNUNLOGO
Para cargar una imagen y pegar una textura en tecnunLogo se siguen los mismos
pasos que en la aplicacin previa. Estos pasos son:
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
71
GL_TEXTURE_WRAP_S, GL_REPEAT);
GL_TEXTURE_WRAP_T, GL_REPEAT);
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Figura 1.
tecnunLogo con
Imagen
TRABAJO PROPUESTO
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.
72
BIBLIOGRAFA
OpenGL Programming Guide: The Official Guide to Learning OpenGL, Version 1.4, 4/E
Dave Shreiner, Mason Woo, Jackie Neide, Tom Davis
ISBN: 0-321-17348-1, Addison Wesley Professional, 2004, 816 pp
Computer Graphics with OpenGL, Third Edition
Donald Hearn, M. Pauline Baker
ISBN: 0-13-120238-3, Prentice Hall, 2004, 857 pp
OpenGL : SuperBible
Richard S. Wright, Jr. , Michael Sweet
ISBN: 1-57169-164-2, Waite Group Press, 1999, 696 pp
A 3D Case Study Using OpenGL
Fotis Chatzinikos
The Developers Gallery, 1999, 93 pp
The OpenGL Utiliy Toolkit (GLUT) Programming Interface
Mark J. Kilgard
Silicon Graphics, Inc, 1996, 62 pp
Copyright 2003 Nicols Serrano Brcena, Fernando Alonso Blzquez, Carlos Melara Ortiz. Todos los derechos reservados. Est prohibida
la reproduccin total o parcial con fines comerciales y por cualquier medio del contenido de estas pginas. Slo esta permitida su impresin y
utilizacin con fines personales.