Informática Gráfica Práctica 3. Modelado geométrico.

1. Vas a construir, paso a paso, una rutina que dibuje una supercuádrica. Esta función calcula un conjunto de puntos 3d de la superficie y al mismo tiempo los dibuja unidos mediante líneas utilizando la primitiva de OpenGL GL_LINE_LOOP. Para empezar, copia y pega la siguiente rutina en tu fichero glig.c. Observa el código y mira lo que ocurre al fijar el valor de v a 0.5 y hacer variar la u entre 0 y 1.

void igCreateQuadricObject (float R, float s1, float s2)

{
float u, v, inc_u;
float x, y, z;
int   i, pu = 10;  /* pu es el numero de divisiones en u */

v= 0.5f;
u =0.0f;
inc_u= 1.0f/pu;

glBegin (GL_LINE_LOOP);
for (i= 0; i< 10; i++)

{

x= xSuperQuadric (u, v, R, s1, s2);
y= ySuperQuadric (u, v, R, s1, s2);
z= zSuperQuadric (u, v, R, s1, s2);
glVertex3f (x, y, z);
u= u+ inc_u;
}
glEnd();
}

Llama a esta función con R, s1 y s2 a 1.0 desde la función Dibuja. Acuérdate de declararla en el fichero glig.h y de incluir este en examinar.c.

2. Si ya has entendido el código anterior, modifícalo para que la v también varíe entre 0 y 1 de forma que se dibuje una circunferencia para cada valor diferente de v. Como resultado debes obtener algo similar a la siguiente figura.

3. En el ejercicio anterior has conseguido dibujar los paralelos de la esfera. Ahora vas a dibujar los meridianos. Para ello, además de iterar la u entre 0 y 1 para cada valor de v, vas a iterar la v entre 0 y 1 para cada valor de u. Debes obtener un resultado similar al que se muestra en la siguiente figura

4. Ahora que ya has terminado la rutina vamos a añadir dos nuevos parámetros que permitan al usuario especificar el número de puntos que en u (pu) y en v (pv) se han de calcular (hasta ahora estaban fijados a 10. La declaración de la función es de la siguiente forma:

void igCreateQuadricObject (int pu, int pv, float R, float s1, float s2);

5. Para completar la función, vas a añadir dos nuevos parámetros que permitan acotar el rango de u y v de forma que puedan variar, cada uno de ellos, entre 0 y un valor especificado por el usuario (uMax, vMax). Con ello permitirás que se dibujen primitivas tales como medias esferas. La declaración de la función queda de la siguiente forma:

void igCreateQuadricObject (int pu, int pv, float uMax, float vMax, float R, float s1, float s2);

6. Añade las siguientes funciones a tu biblioteca de forma que cada una de ellas llame a la función igCreateQuadricObject con los parámetros oportunos para que dibuje la primitiva correspondiente en cada caso:

void igWireSphere (int pu, int pv); /* s1 y s2 a 1 */
void igWireRulo (int pu, int pv); /* s1= 0.5, s2= 1 */
void igWireDado (int pu, int pv); /* s1= 0.5, s2 =0.5 */
void igWireSemiSphere (int pu, int pv); /* s1 y s2 a 1, uMax= 1, vMax= 0.5 */

7. Añade a tu biblioteca la primitiva geométrica Cubo mediante la función void igWireCubo (void) . Esta primitiva debe tener de lado 1 y estar centrada en el origen de coordenadas. Haz un esquema en el papel para determinar en primer lugar los valores de las coordenadas de los ocho vértices. Después, crea una vector con las coordenadas de los vértices y, finalmente, escribe el código que dibuje sus aristas.

Las llamadas a función para dibujar las figuras se encuentran en la función IniciaCuadricas

igWireSphere

igWireSemisphere

igWireRulo

igWireDado

examinar.h


/*************************************************************************/
/*                                                                       */
/*   examinar.h                                                          */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

#ifndef EXAMINAR_H
#define EXAMINAR_H

/* Variables Globales del modulo */
int VentanaAncho = 500, VentanaAlto = 500; /* Tamanyo de la ventana */
int VentanaX = 100, VentanaY = 100; /* Posicion de la ventana */
GLdouble  alfa = 0.0, beta = 0.0;
GLuint cuadrica;

/* Abre una ventana OpenGL */
void AbreVentana (int numeroArgumentos, char ** listaArgumentos);

/* Funcion de dibujado */
void Dibuja(void);

/* Establece el area visible */
void TamanyoVentana (int alto, int ancho);

/* Inicia las funciones de Callback */
void IniciaFuncionesCallback (void);

/* Define las acciones tras una pulsacion del teclado */
void Teclado (unsigned char tecla, int x, int y);

/* Define las acciones tras una pulsacion del teclado ampliado */
void TecladoAmpliado (int tecla, int x, int y);
/*Dibuja un Cubo*/
void igWireCubo (void);

void igCreateQuadricObject (int pu, int pv,  float uMax, float vMax,float R, float s1, float s2);
void igWireSphere (int pu, int pv); /* s1 y s2 a 1 */
void igWireRulo (int pu, int pv); /* s1= 0.5, s2= 1 */
void igWireDado (int pu, int pv); /* s1= 0.5, s2 =0.5 */
void igWireSemiSphere (int pu, int pv); /* s1 y s2 a 1, uMax= 1, vMax= 0.5 */

void salir();
#endif

examinar.c


/*************************************************************************/
/*                                                                       */
/*   examinar.c                                                          */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

/***************** INCLUDES DE LAS LIBRERIAS NECESARIAS ******************/
//#include <GL/freeglut.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include "examinar.h"
#include "glig.h"

/******************************************************************************************/
/* Establece el area visible y el tipo de proyeccion                                      */
/* Parametros: int ancho --> Ancho del area visible                                       */
/*             int alto --> Alto del area visible                                         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TamanyoVentana (GLsizei ancho, GLsizei alto)
{
/* Definicion del viewport */
glViewport(0, 0, ancho, alto);

/* Definicion de la vista */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0*(GLfloat)alto/(GLfloat)ancho, 2.0*(GLdouble)alto/(GLfloat)ancho, -2.0, 2.0);
}

/******************************************************************************************/
/* Abre una ventana OpenGL                                                                */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void AbreVentana (int numeroArgumentos, char ** listaArgumentos)
{
glutInit(&numeroArgumentos, listaArgumentos);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (VentanaAncho, VentanaAlto);
glutInitWindowPosition (VentanaX, VentanaY);
glutCreateWindow (listaArgumentos[0]);
glutDisplayFunc (Dibuja);
glutReshapeFunc (TamanyoVentana);
glClearColor (0.0f, 0.0f, 0.0f, 0.0f); /* Establece el color de borrado */
glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
glColor3f (1.0f, 1.0f, 1.0f); /* Establece el color de dibujo */
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado                                     */
/* Parametros: unsigned char key --> Codigo de la tecla pulsada                           */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Teclado (unsigned char tecla, int x, int y)
{
switch (tecla)
{
case 27 : /* Codigo de la tecla de Escape */
exit(0);
break;
}
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado ampliado                            */
/* Parametros: unsigned char key --> Codigo de la tecla pulsada                           */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TecladoAmpliado (int tecla, int x, int y)
{
switch (tecla)
{
case GLUT_KEY_UP : /* Pulsacion cursor arriba del teclado ampliado */
beta = beta + 15.0;
if (beta > 360.0) beta = beta - 360.0;
break;

case GLUT_KEY_DOWN : /* Pulsacion cursor abajo del teclado ampliado */
beta = beta - 15.0;
if (beta < 0.0) beta = beta + 360.0;
break;

case GLUT_KEY_RIGHT : /* Pulsacion cursor derecha del teclado ampliado */
alfa = alfa + 15.0;
if (alfa > 360.0) alfa = alfa - 360.0;
break;

case GLUT_KEY_LEFT : /* Pulsacion cursor izquierda del teclado ampliado */
alfa = alfa - 15.0;
if (alfa < 0.0) alfa = alfa + 360.0;
break;
}
glutPostRedisplay ();
}

/* Rutina de definiciÛn de eventos */
/******************************************************************************************/
/* Inicia las funciones de callback                                                       */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void IniciaFuncionesCallback (void)
{
glutKeyboardFunc (Teclado);
glutSpecialFunc (TecladoAmpliado);
}

/******************************************************************************************/
/* Funcion de dibujado                                                                    */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Dibuja (void)
{
glClear (GL_COLOR_BUFFER_BIT);

/* Transformacion de la camara */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated (beta, 1.0,0.0,0.0);
glRotated (-alfa, 0.0,1.0,0.0);

glCallList (cuadrica);
/* Objetos */
//glutWireTeapot(1.0);
//glutWireIcosahedron();
//glutWireTetrahedron();
//glutWireOctahedron();
//glutWireDodecahedron();
//glutWireTorus(0.2,0.9,18,20);
//glutWireCone(0.5, 2.0, 14, 14);
//glutWireCube(1.0);
//glutWireSphere(1, 20,50);

//igCreateQuadricObject(50,80,0,0,1.0, 1, 1);
//igWireSphere (50, 50);

//igWireRulo (200, 200);
//igWireDado (60, 60);
//igWireSemiSphere (50, 50); // s1 y s2 a 1, uMax= 1, vMax= 0.5 */
//igWireCubo();
glFlush();
}

void igCreateQuadricObject (int pu, int pv, float uMax, float vMax, float R, float s1, float s2)
{
/* pu es el numero de divisiones en u */
/* pv es el numero de divisiones en v*/
float u, v;
float iniu,iniv;
float inc_u; //incremento de u
float inc_v; //incremento de v
float x, y, z; /*almanezaran las coordenadas en el espacio tridimensional*/
int   i,j;/*contadores para los bucles for*/
v= uMax;
u =vMax;
iniu=u;
iniv=v;
/*El maximo valor de u y v es 1 y el minimo es 0 por lo tanto debemos de distribuir
las partes exigidas en la distancia establecida entre el valor de inicialización y
el maximo valor*/
inc_u= (1.0f-u)/pu;
inc_v= (1.0f-v)/pv;

//Dibujamos los paralelos de la esfera
//tantas circunfencias como partes de v
for (j=0;j<pv;j++)
{
glBegin (GL_LINE_LOOP);//Indicamos a openGL el modo de dibujado
//indicamos los puntos (partes de u) que formaran la circunferencia
for (i= 0; i<= pu; i++)
{
x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
u= u+ inc_u;//avanzamos hasta el siguiente putno
//printf("valor de v=%f valor de u=%f\n",v,u);
if (u>1){u=iniu;}
}
glEnd();//indicamos a openGL que hemos acabado de indicar los puntos de la circunferencia

v+=inc_v;//avanzamos a la siguiente circunferencia paralela
}

u=iniu;
v=iniv;
//Dibujamos os meridianos de la esfera
//tantos meridianos como partes de v
for (j=0;j<pu;j++)
{
glBegin(GL_LINE_STRIP);//Indicamos a OpenGL el modo de dibujado
//Indicamos los puntos (partes de v) que formaran el meridiano
v=iniv;
for(i=0;i<=pv;i++)
{
x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
v+=inc_v;//avanzamos hasta el siguiente punto

//printf("valor de v=%f valor de u=%f\n",v,u);
}
//printf("Meridiano dibujado\n\n");
glEnd();//Indicamos a openGL que ya hemos señalado los puntos del meridiano
u+=inc_u;//avanzamos al siguiente meridiano

}
}

void igWireSphere (int pu, int pv)
{
/* s1 y s2 a 1 */
igCreateQuadricObject(pu,pv,0,0,1.0, 1, 1);

}

void igWireRulo (int pu, int pv)
{
/* s1= 0.5, s2= 1 */
igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 1);

}

void igWireDado (int pu, int pv)
{
/* s1= 0.5, s2 =0.5 */
igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 0.5);

}
void igWireSemiSphere (int pu, int pv)
{

/* s1 y s2 a 1, uMax= 1, vMax= 0.5 */
igCreateQuadricObject(pu,pv,0,0.5,1.0, 1, 1);

}

void igWireCubo (void)
{
//Centramos en el origen de las coordenadas
//El radio es 1
glBegin (GL_LINE_LOOP);
//aristas traseras
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(0.5, -0.5, -0.5);
glVertex3f(0.5,0.5,-0.5);
glVertex3f(-0.5,0.5,-0.5);
glVertex3f(-0.5,-0.5,-0.5);
//parte delantera
glVertex3f(-0.5,-0.5,0.5);
glVertex3f(-0.5,0.5,0.5);
glVertex3f(0.5,0.5,0.5);
glVertex3f(0.5,-0.5,0.5);
glVertex3f(-0.5,-0.5,0.5);
//lado izquierdo
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(-0.5,-0.5,0.5);
glVertex3f(-0.5,0.5,0.5);
glVertex3f(-0.5,0.5,-0.5);
glVertex3f(0.5,0.5,-0.5);
glVertex3f(0.5,0.5,0.5);
glVertex3f(0.5,-0.5,0.5);
glVertex3f(0.5,-0.5,-0.5);
glEnd ();
}

void IniciaCuadricas (void)

{

cuadrica = glGenLists (1);

if (cuadrica != 0) /* Cero no es un identificador valido para una display list */

{

glNewList (cuadrica, GL_COMPILE);

//igCreateQuadricObject (20,20,0,0,1.0f, 1.0f, 1.0f);

//igWireCubo();

//igWireDado(20,20);

//igWireRulo(10, 20);

igWireSemiSphere(20,20);

glEndList ();

}

}

/******************************************************************************************/
/* Funcion principal                                                                      */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Un entero que se devuelve al sistema al acabar la ejecucion del programa       */
/******************************************************************************************/
int main(int numArgumentos, char ** listaArgumentos)
{
/* CreaciÛn de la ventana de la aplicaciÛn */
AbreVentana (numArgumentos, listaArgumentos);

/* Rutinas para el control de eventos */
IniciaFuncionesCallback ();

IniciaCuadricas();
/* A la espera de eventos.... */
glutMainLoop();

return (0);
}