MANUAL Versión1

96
UNIVERSIDAD DEL MAR CAMPUS PUERTO ESCONDIDO LICENCIATURA EN INFORMÁTICA GRAFICACIÓN MANUAL APRENDA A GRAFICAR CON OPENGL EN 20 PRÁCTICAS Nivel Básico ISIDRO MOCTEZUMA CANTORÁN

Transcript of MANUAL Versión1

Page 1: MANUAL Versión1

UNIVERSIDAD DEL MAR CAMPUS PUERTO ESCONDIDO

LICENCIATURA EN INFORMÁTICA GRAFICACIÓN

MANUAL APRENDA A GRAFICAR CON OPENGL

EN 20 PRÁCTICAS

Nivel Básico

ISIDRO MOCTEZUMA CANTORÁN

Page 2: MANUAL Versión1

Primera edición en español: 2008 DR©2008, Universidad del Mar, Campus Puerto Escondido. Ciudad Universitaria, Vía Sola de Vega Km. 1.5 Carretera Puerto Escondido-Oaxaca. San Pedro Mixtepec, Júquila, Oaxaca, México, 71980. Prohibida la reproducción total o parcial de esta obra sin autorización de los editores y/o autor. Responsable de edición Isidro Moctezuma Cantorán Diseño de Portada Isidro Moctezuma Cantorán Colaboradores alumnos Aaron José Gaspar Darwin Sosa Gómez David Espíndola Rodríguez Elizabeth Mendoza Velázquez José Palácios Chávez Omar Hernández Reyes Edición con fines académicos Impreso en México Printed in México Cita correcta: MANUAL APRENDA A GRAFICAR CON OPENGL EN 20 PRÁCTICAS, Nivel Básico, Isidro Moctezuma Cantorán, Universidad del Mar, Campus Puerto Escondido- Puerto Escondido, San Pedro Mixtepec, Júquila, Oaxaca. México, 2008.

DIRECTORIO

Dr. Modesto Seara Vázquez Rector de la UMAR

[email protected]

M. C. Gerardo Esteban Leyte Morales Vice-Rector Académico

UMAR [email protected]

L. C. E. José Luís Ramos Espinoza

Vice-Rector Administrativo UMAR

[email protected]

M.C. Manuel A. Valdés Marrero Jefe de Carrera de Informática

UMAR [email protected]

M.C. José Edgar Lara Ramírez

Representante de la Academia de Tratamiento de imágenes e IA

UMAR [email protected]

M. C. Isidro Moctezuma Cantorán Responsable de la publicación [email protected]

Pagina electrónica: http://www.umar.mx

Page 3: MANUAL Versión1

PRESENTACIÓN

El presente trabajo es el producto de algunas prácticas realizadas a lo largo de tres cursos de la materia de graficación dirigida para alumnos de séptimo semestre de la carrera de Informática de la Universidad Mar, con el objetivo de auxiliar a los alumnos que quieren ser autodidactas en cursos sucesivos. El manual está dividido en 20 prácticas, cada práctica tiene un objetivo, un listado de acciones a realizarse, descripción de funciones de OpenGL en algunos casos, código fuente e imágenes; resultados de dichas prácticas. El orden de las prácticas permitirá al lector conocer funciones básicas de OpenGL y graficar de una manera fácil y sencilla.

El Autor

Page 4: MANUAL Versión1

PRÓLOGO En las últimas décadas se ha notado un gran avance en el área de la graficación y se ha estado dando a pasos agigantados, desde el manejo de las animaciones en los videojuegos con un realismo impresionante, hasta los dibujos animados, mejor conocidos como caricaturas, que dan una apariencia muy cercana a la realidad, ya que el manejo de los gráficos en tres dimensiones permite realizar una infinidad de efectos asombrosos. Una de las inquietudes de todo programador de computadoras, es conocer como se hacen las cosas, sobre todo aquellas que nos dejan una buena impresión, y cuando de juegos o animaciones por computadora se trata es una de las cosas que más llaman la atención y de las que menos se tiene información disponible. Por fortuna, se tiene este manual de graficación con OpenGL, una herramienta de las más utilizadas para cumplir con propósitos de animación en gráficos y una de las mejores en su ramo. Con este manual aprenderás las bases de la graficación, una vez que se termine de leer y hacer los ejercicios que en el vienen, bastará con echar a andar tu imaginación y descubrir hasta donde puedes llegar en el desarrollo de los gráficos, verás que podrás realizar cosas fascinantes, de las cuales tu mismo te sorprenderás. El autor de este documento, así como las personas que intervinieron para que fuera posible su creación, invirtieron muchas horas de esfuerzo y años de experiencia en el tema para dejar un buen sabor de boca al lector, además de hacer todo lo posible para poner al alcance un material de alta calidad, fácil de leer, de seguir y de entender. Se invita por lo tanto, a todos aquellos que tengan interés en aprender a graficar, que sigan el presente manual de principio a fin, con mucho ahínco y tenacidad, siendo persistentes en todo momento, hasta que obtengan los resultados deseados y cumplan con sus propias metas.

M. en C. Jorge Ochoa Somuano

Profesor/Investigador Universidad del Mar Campus Puerto Escondido

Page 5: MANUAL Versión1

ÍNDICE Introducción …………………………………………………………… 6 Práctica 1: Instalación de OpenGL ………………………………… 7 Práctica 2: Color de fondo y archivos de cabecera ……………… 8 Práctica 3: Generalidades de OpenGL ……………………………. 10 Práctica 4: Dibujar un rectángulo …………………………………... 13 Práctica 5: Funciones básicas de OpenGL ………………………. 16 Práctica 6: Dibujar un punto ………………………………………… 20 Práctica 7: Tamaño de un punto …………………………………… 24 Práctica 8: Dibujar líneas ……………………………………………. 31 Práctica 9: Más de líneas …………………………………………… 34 Práctica 10: Dibujo de triángulos …………………………………… 38 Práctica 11: Profundidad y eliminación de superficies y selectiva 43 Práctica 12: Polígonos ………………………………………………. 50 Práctica 13: Relleno de polígonos …………………………………. 53 Práctica 14: Polígonos en vista de puntos, líneas y rellenos …… 57 Práctica 15: Limpiar el buffer de color …………………………….. 62 Práctica 16: Rotación, translación y escalamiento ………………. 64 Práctica 17: Proyección ortogonal y en perspectiva ……………... 68 Práctica 18: Luz ambiental, difusa y especular …………………… 72 Práctica 19: Sombras ………………………………………………... 78 Práctica 20: Transparencia …………………………………………. 84 Ejemplos ……………………………………………………………… 87 Conclusiones ………………………………………………………… 94

Page 6: MANUAL Versión1

______________________________________________________________________________________________________________

______________________________________________________________________________________________ M.C. Isidro Moctezuma Cantorán

6

INTRODUCCIÓN La materia de graficación es sin duda la más dinámica, entretenida y divertida de la carrera de informática, por la facilidad de aprender a graficar en dos dimensiones (2D) y tres dimensiones (3D). OpenGL (Open Graphic Library), librería de gráficos abierta, maneja 10 primitivas básicas para graficar, que son: GL_POINTS. Para dibujar puntos. GL_LINES. Para dibujar líneas. GL_LlNE_STRIP. Para dibujar líneas continúas. GL_LINES_LOOP. Para dibujar líneas continúas, pero el último punto especificado se une con el primer punto. GL_TRIANGLES. Para dibujar triángulos. GL_TRIANGLE_STRIP. Dibuja un abanico de triángulos a partir del primer triángulo, apoyándose en los dos últimos puntos o vértices especificados del triángulo anterior. GL_TRIANGLES_LOOP. Para dibujar una serie de triángulos, donde todos tiene un punto común. GL_QUADS. Para dibujar cuadrados o rectángulos GL_QUAD_STRIP. Para dibujar un abanico de cuadrados o rectángulos GL_POLYGON. Para dibujar polígonos. Para la descripción de las prácticas presentadas en este manual, se tomaron como referencia bibliográfica los libros: OpenGL programación de Richard S. Wringht y C++ Builder 5 de Francisco Charte, ambos de la editorial Anaya multimedia. Los requerimientos mínimos que debe tener el lector para el desarrollo de las prácticas son: manejo del lenguaje de programación C ó C++, conocimientos básicos del entorno de C++ Builder 5, manejo de MS DOS (básico), nociones de 2D y 3D, y algo indispensable; el gusto graficación por computadora. El orden de las prácticas inicia desde instalar el componente de OpenGL en C++ Builder 5, uso de las primitivas básicas de OpenGL, descripción de funciones de OpenGL, hasta la aplicación de algunos efectos para dar más realismos a los gráficos.

Page 7: MANUAL Versión1

______________________________________________________________________________________________________________

______________________________________________________________________________________________ M.C. Isidro Moctezuma Cantorán

7

Práctica 1: Instalación de OpenGL Objetivo: Instalar el componente en C++ Builder 5 Para iniciar esta práctica se requiere del componente de OpenGL para C++ Builder 5, el cual puede descargarse en la página: http://www.opengl.org, Guarde los archivos en una carpeta llamada “ComponentesOpenGL”, para instalar el componente siga los siguientes pasos:

1.-Ejecute el archivo OpenGLPanel_DP, doble clic sobre el nombre del archivo, que se encuentra en la carpeta ComponentesOpenGL. 2.- De la carpeta ComponentesOpenGL:

• Copiar los archivos *.h a la carpeta GL de C++ Builder 5 • Copiar los archivos *.lib a la carpeta Lib de C++ Builder 5 • Copiar los archivos *.dll a la carpeta de sistem32 de Windows

Después de copiar los archivos en sus respectivas carpetas, en el Prompt del MS-DOS ir a la carpeta de Lib de C++ Builder5 y escribir: implib glut.lib c:\windows\system32\glut.dll implib glut32.lib c:\windows\system32\glut32.dll Una vez instalado OpenGL en C++ Builder 5, deberá aparecer el icono en la pestaña en la parte derecha de la ventana de C++ Builder 5 y al ejecutar la aplicación se mostrará la ventana o área de graficación de OpenGL, tal como se muestra en la figura 1.

Figura 1. Ventana de OpenGL

Ventana de OpenGL

Icono de OpenGL

Page 8: MANUAL Versión1

______________________________________________________________________________________________________________

______________________________________________________________________________________________ M.C. Isidro Moctezuma Cantorán

8

Práctica número 2: Color de fondo y archivos de cabecera Objetivo: Asignar un color de fondo a la ventana de de OpenGL y agregar los archivos de cabecera. Para asignarle color de fondo a la venta de OpenGL y declarar los archivos *.h siga los siguientes pasos:

1. Abrir un Nuevo proyecto en C++ Builder 5. 2. En el formulario agregar una ventana OpenGL de un tamaño que ocupe la

mitad del formulario. 3. En código, en la parte de declaraciones de librerías (después de

#include”Unit1.h”) agregar:

#include<gl/gl.h> #include<gl/glu.h>.

4. Regresar al formulario, seleccionar la ventana de OpenGL, en la ventana de inspector de Objeto (Object Inspector) seleccionar eventos, dar doble clic al evento OnInit, y en código agregar lo siguiente: glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

5. Regresar al formulario, seleccionar la ventana de OpenGL, en la ventana de

inspector de Objeto seleccionar eventos, dar doble clic al evento OnPaint, y en código agregar lo siguiente: glClear(GL_COLOR_BUFFER_BIT);

El archivo .CPP (código) deberá ser: #include <vcl.h> #pragma hdrstop #include "Unit1.h" #include<gl/gl.h> #include<gl/glu.h> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "OpenGLPanel" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { }

//--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender) { glClear(GL_COLOR_BUFFER_BIT); //aquí se dibuja todo } //-------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender) { glClearColor(0.0f,0.0f,1.0f,1.0f); }

Page 9: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

9

Al dar ejecutar (Run) su proyecto parecerá similar a la figura 2.

Figura 2. Color de fondo a la ventana de OpenGL

Ventana de OpenGL con Color de fondo

Page 10: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

10

Práctica número 3: Generalidades de OpenGL Objetivo. Conocer las generalidades de OpenGL. OpenGL OpenGL, del inglés Open Graphic Library (Librería de Gráficos Abierta o Libre) no es un Lenguaje es una API (Interfaz de Programación de Aplicación). Cuando se hace mención que una aplicación esta hecho en OpenGL, quiere decir que está hecho en algún lenguaje de programación: C, C++, Visual C++ Builder C++, Visual Basic, Java, etc., y que el lenguaje es el que llama a una o más bibliotecas de OpenGL. En este caso el lenguaje a utilizado es C++ Builder 5. En el encabezado en la parte de código se deben declarar las siguientes librerías básicas de OpenGL: #include <gl/gl.h> #include <gl/glu.h> Tipos de datos de OpenGL OpenGL maneja sus propios tipos de datos, los cuales son: Tipos de datos OpenGL

Representación interna

Tipo definido como C

GLbyte Entero de 8 dígitos Signed char GLshort Entero de 16 bits Short GLint, GLsizei Entero de 32 bits Long GLfloat, GLclampf Punto flotante de 32 bits float GLdouble, GLclamp Punto flotante de 64 bits double GLubyte, GLboolean Entero de 8 bits sin

signo unsigned char

GLushort Entero de 16 bits sin signo

unsigned short

GLuint, GLenum, GLbitfield

Entero de 32 bits sin signo

Unsigned long

Las variables GLboolean se utilizan para indicar condiciones verdaderas o falsas, GLenum para variables enumeradas, GLbitfield para variables que contienen campos de bits binarios. Los apuntadores y las matrices no tienen una mención especial, debido a que manejan similar a lenguaje C, por ejemplo:

Page 11: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

11

GLshort s[10]; GLdouble *d[10]; Para C++ Builder 5, puede utilizar los tipos de datos de OpenGL o C o C++. Convenio de denominaciones de funciones de OpenGL Formato general: <Prefijo de biblioteca><comando raíz><cuenta opcional de argumentos><tipo opcional de argumentos>. Ejemplo:

Por ejemplo glColor puede variar a, glColor3f, glColor4f, glColor3i, etc., dependiendo el número y tipo de datos que maneje. La función glClearColor(). Esta función permite establecer el color usando para borrar la ventana. Formato: glClearColor(GLclampf R, GLclampf V, GLclampf A, GLclampf Alfa), donde: R = rojo V = verde A = azul En OpenGL un color es la mezcla de los componentes rojo, verde y azul, cada componente o color puede variar de 0 a 1, similar a la especificación en Windows RGB (0-256). El último componente Alfa se usa para efectos de fusión y especiales como la translucidez. La translucidez se refiere a la capacidad de un objeto de permitir el paso de la luz a través de él.

glColor3f(…)Biblioteca GL

Comando Raíz Número de argumentos Tipo de

argumentos

Page 12: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

12

Algunos colores compuestos comunes son: Color compuesto Rojo Verde Azul Negro 0 0 0 Rojo 1 0 0 Verde 0 1 0 Amarillo 1 1 0 Azul 0 0 1 Magenta 1 0 1 Azul verdoso 0 1 1 Gris oscuro 0.25 0.25 0.25 Gris claro 0.75 0.75 0.75 Marrón 0.60 0.40 0.12 Naranja calabaza 0.98 0.625 0.12 Rosa pastel 0.98 0.04 0.7 Morado 0.60 0.40 0.70 Blanco 1 1 1 glClear (GL_COLOR_BUFFER_BIT) con la función glClearColor, hasta ahora solo se ha borrado (pintando la ventana de otro color), para un borrado real se usa glClear(GL_COLOR_BUFFER_BIT). La función glClear (GL_COLOR_BUFFER_BIT). Borra un buffer o una combinación de buffers determinada. Un buffer es una zona de almacenamiento de información de imagen, los componentes rojo, verde y azul de un dibujo normalmente se conocen colectivamente como búfer de color o buffer de píxeles (elimina el último dibujo de la ventana). Más adelante se dará detalle de dicha función.

Page 13: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

13

Práctica número 4: Dibujar un rectángulo Objetivo: Dibujar un rectángulo usando la función glRectf(); Para dibujar un rectángulo siga los siguientes pasos:

1. Abrir un nuevo proyecto en Builder 2. Agréguele un nombre al formulario (“Rectángulo”) 3. Guarde el proyecto 4. En el formulario agregue una ventana de OpenGL que cubra todo el

formulario 5. En el código, en la cabecera de librerías agregue las librerías gl.h y glu.h. 6. En el formulario seleccione la ventana de OpenGL, seleccione eventos en

la ventana de inspector de objeto, de doble clic en el evento OnInit, en código agregue lo siguiente

int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; //int nRange=OpenGLPanel1->Width/2; GLfloat nRango; // Evitar la división entre cero if(h == 0) h = 1; // Establecer el puerto de vista para las dimensiones de la ventana glViewport(0, 0, w, h); // Restablece el sistema de coordenadas glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Establecer el volumen de recorte (izquierda, derecha, inferior, superior, cerca, lejos nRango = (GLfloat)w / (GLfloat)h; if (w <= h) glOrtho (-100.0, 100.0, -100 / nRango, 100.0 / nRango, 1.0, -1.0); else glOrtho (-100.0 * nRango, 100.0 * nRango, -100.0, 100.0, 1.0, -1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

Page 14: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

14

7. En el formulario seleccione la ventana de OpenGL, seleccione eventos en la ventana de inspector de objeto, de doble clic en el evento OnPaint, en código agregue el siguiente código

// Limpiar la ventana con el color actual glClear(GL_COLOR_BUFFER_BIT); // Establecer el color rojo de dibujo actual // R G B glColor3f(1.0f, 0.0f, 0.0f); // dibujar el rectángulo relleno con el color actual glRectf(-25.0f, 25.0f, 25.0f, -25.0f);

Ejecute su programa (Run), Figura 3.

Figura 3. Rectángulo El programa utiliza la función:

void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,);

Para dibujar un rectángulo, en la cual los cuatro argumentos representan dos pares de coordenadas (x1, y1) y (x2, y2), el primer representa la esquina superior izquierda del rectángulo y el segundo par la esquina inferior derecha. La función glViewport () se usa para especificar el ancho y alto de la ventana, también se utiliza la proyección ortogonal para el volumen de recorte con la función glOrtho(); En el código antes de glOrtho se utilizan glMatrixMode(GL_PROJECTION);

Page 15: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

15

glLoadIdentity(); La matriz de proyección se encuentra en el lugar donde realmente definimos nuestro volumen de visualización y la llamada a glLoadIdentity() sirve para reestablecer el sistema de coordenadas antes de ejecutarse alguna manipulación de la matriz y glMatrixMode(GL_MODELVIEW); glLoadIdentity(); Sirven para indicarle a OpenGL que todas las transformaciones futuras afectarán a nuestros modelos (nuestro dibujo).

Page 16: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

16

Práctica número 5: Funciones básicas de OpenGL Objetivo: Conocer funciones básicas de OpenGL

• glClearColor Finalidad: Establece los valores de color y transparencia a usar para borrar los

búferes de color. Archivo include:

<gl.h>

Sintaxis: void glClearColor(GLclampf rojo, GLclampf verde, GLclampf azul, GLclampf alfa);

Descripción: Esta función establece los valores de relleno que se van a utilizar cuando se borren los búferes de rojo, verde, azul y transparencia (denominados conjuntamente búfer de color). Los valores especificados se ajustan al rango [0.0f, 1.0f]

Parámetros rojo: GLclampf: componente rojo del valor de relleno.

verde: GLclampf: componente verde del valor de relleno. azul: GLclampf: componente azul del valor de relleno. alfa: GLclampf: componente de transparencia (alfa) del valor de relleno.

Devuelve: Nada.

• glDisable, glEnable Finalidad: Habilita o deshabilita una característica de estado de OpenGL.

Archivo include:

<gl.h>

Sintaxis: void glDisable(GLenum característica ); void glEnable(GLenum característica );

Descripción: glDisable .- deshabilita una opción de dibujo de OpenGL glEnable .- Habilita una opción de dibujo de OpenGL.

Parámetros Característica: GLenum: Opción a activar o desactivar. En la especificación de

OpenGL se proporciona una lista completa de estados y crece regularmente con las nuevas actualizaciones. (Ver tabla 1.)

Devuelve: Nada. Tabla 1. Opciones activadas y desactivadas por glEnable /glDisable Opción Descripción GL_BLEND Fundido de color GL_CULL_FACE Seleccionar polígono GL_DEPTH_TEST Prueba detallada GL_DITHER Tramado

Page 17: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

17

GL_FOG Modo de niebla de OpenGL GL_LIGHTING Iluminación de OpenGL GL_LIGHTx Número de luz x de OpenGL (mínimo 8) GL_POINT_SMOOTH Suavizado de punto GL_LINE_SMOOTH Suavizado de línea GL_LINE_STIPPLE Punteo de línea GL_POLYGON_SMOOTH Suavizado de polígono GL_SCISSOR_TEST Recorte habilitado GL_STENCIL_TEST Prueba de plantilla GL_TEXTURE_xD Textura de xD (1, 2 ó 3) GL_TEXTURE_CUBE_MAP Mapa de texturas de cubo GL_TEXTURE_GEN Información de textura para x(S, T, R ó Q)

• glFinish Finalidad: Obliga a que se completen todos los comandos anteriores de

OpenGL Archivo include:

<gl.h>

Sintaxis: void glFinish(void) Descripción: Normalmente los comandos de OpenGL se apilan en la cola y se

ejecutan en secuencias de comandos para optimizar el rendimiento. El comando glFinish obliga a que se ejecuten todos los comandos OpenGL pendientes. Al contrario que glFlush, esta función no se devuelve hasta que hayan completado todas las operaciones de interpretación

Parámetros ninguno Devuelve: Nada.

• glFlush Finalidad: Limpia las colas y los búferes de comandos OpenGL. Archivo include:

<gl.h>

Sintaxis: void glFlush(void) Descripción: Normalmente los comandos de OpenGL se apilan en la cola y se

ejecutan en secuencias de comandos para optimizar el rendimiento. Algo que puede variar según el hardware, los controladores y las implantaciones de OpenGL. El comando glFlush hace que se ejecute cualquier comando que esté esperando a ejecutarse, algo que se debe conseguir en tiempo finito. Básicamente es la misma ejecución asíncrona de los comandos de gráficos porque glFlush se devuelve inmediatamente.

Parámetros: ninguno Devuelve: Nada.

Page 18: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

18

• glOrtho

Finalidad: Estable o modifica las extensiones del volumen de recorte. Archivo include:

<gl.h>

Sintaxis: void glOrtho(GLdouble Izquierda, GLdouble Derecha, GLdouble Abajo, GLdouble Arriba, GLdouble Cerca, GLdouble Lejos);

Descripción: Esta función describe un volumen de recorte paralelo. Esta proyección significa que los objetos que se encuentran lejos del espectador no parecen más pequeños (en contraste a una proyección en perspectiva). Piense en un volumen de recorte en función de las coordenadas cartesianas 3D, en las que izquierda y derecha son los valores mínimo y máximo de x, abajo y arriba son los valores mínimo y máximo de y, y cerca y lejos son los valores mínimo y máximo de z.

Parámetros: Izquierda: GLdouble: coordenada izquierda del volumen del recorte Derecha: GLdouble: coordenada derecha del volumen del recorte

Abajo: GLdouble: coordenada inferior del volumen del recorte Arriba: GLdouble: coordenada superior del volumen del recorte Cerca: GLdouble: Distancia mínima desde el origen hacia el espectador Lejos: GLdouble: Distancia máxima desde el origen hacia el espectador

Devuelve: Nada.

• glRect

Finalidad: Dibuja un rectángulo plano.

Archivo include:

<gl.h>

Sintaxis: void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);

Variantes: void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); void glRecti (GLint x1, GLint y1, GLint x2, GLint y2); void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2); void glRectdv(const GLdouble *v1, const GLdouble *v2); void glRectfv(const GLfloat *v1, const GLfloat *v2); void glRectiv(const GLint *v1, const GLint *v2); void glRectsv(const GLshort *v1, const GLshort *v2);

Descripción: Esta función proporciona un método sencillo para especificar el rectángulo como dos puntos de esquina. El rectángulo se dibuja en el plano xy, siendo z=0;

Parámetros x1, y1: Especifican las esquina superior izquierda del rectángulo

Page 19: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

19

x2,y2: Especifican las esquina inferior derecha del rectángulo *v1: Matriz de dos valores que especifican la esquina superior izquierda

del rectángulo. También se podría describir como v1 [2]. *v2: Matriz de dos valores que especifican la esquina inferior derecha

del rectángulo. También se podría describir como v2 [2]. Devuelve: Nada.

• glViewport

Finalidad: Establece la parte de una ventana dentro de la cual puede dibujar OpenGL.

Archivo include:

<gl.h>

Sintaxis: void glViewport(GLint X, GLint Y, GLsizei Ancho, GLsizei Alto); Descripción: Esta función establece la región dentro de una ventana que se usa

para trazar las coordenadas del volumen de recorte en las coordenadas físicas de la ventana.

Parámetros X: GLint: número de píxeles desde la parte izquierda de la ventana

para iniciar el puerto de vista. Y: GLint: número de píxeles desde la parte inferior de la ventana para

iniciar el puerto de vista ventana. Ancho: GLsizei: anchura del puerto de vista en píxeles

Alto: GLsizei: altura del puerto de vista en píxeles Devuelve: Nada.

Page 20: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

20

Práctica número 6: Dibujar un punto Objetivo: Graficar un punto en un espacio 2D. Para dibujar un punto realice los siguientes pasos:

1. Abrir un proyecto nuevo en C++ Builder 5 2. Guarde el proyecto 3. Etiquete al formulario con el siguiente nombre “Dibujar un Punto”. 4. Agregue en el formulario una ventana de OpenGL 5. De clic a la ventana de OpenGL. En la ventana de de inspector de objetos

busque la propiedad Alinear (Align) asigne alClient. 6. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el

inspector de objetos, elija eventos y en el evento OnInit de doble clic y en código agregue lo siguiente

GLfloat Rango; Rango=100; //área de volumen de visualización en el plano //cartesiano en x, y, z

if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Estableciendo el volumen de recorte Rango = (GLfloat)w / (GLfloat)h; if (w <= h) glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango, Rango); else glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango, Rango); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // color de fondo glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

7. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el

inspector de objeto, elija eventos y en el evento OnPaint de doble clic y en código agregue lo siguiente:

// Limpiar la ventana glClear(GL_COLOR_BUFFER_BIT); //aquí se dibuja todo // Los objetos se dibujarán con este color (verde) glColor3f(0.0f, 1.0f, 0.0f); Puntos();

Page 21: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

21

8. Habra el archivo Unith.h (según sea el nombre) declare la siguiente función y variables:

void Puntos(); int h, w;

9. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el inspector de objetos, elija eventos y en el evento OnResize de doble clic y en código agregue lo siguiente:

glViewport(0, 0, w, h); 10. En el evento OnCreate del Formulario de doble clic y en código inicialice

las variables de anchura y altura w=OpenGLPanel1->Width; h=OpenGLPanel1->Height;

11. Regrese al formulario de doble clic, en la parte inferior del archivo de código escriba lo siguiente:

void TForm1::Puntos() { glBegin(GL_POINTS); glVertex3f(0,0,0); glEnd(); }

12. Ejecute el programa (Run), y le aparecerá un punto verde en la coordenada (0, 0, 0), figura 4

Figura 4. Dibujar un punto.

Aquí está el punto

Page 22: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

22

• Más sobre puntos Para especificar un punto de dibujo se utiliza la función glVertex, la cual puede soportar hasta 4 parámetros, por ejemplo para especificar la coordenada (20,10, 0), se escribe: glVertex3f(20.0f,10.0f,0.0f); en el sistema de coordenadas específica que el punto está situado en la unidad 20 del eje x, 10 en el eje y, 0 en el eje z, tal como se muestra en la figura 5.

Figura 5. Sistema de coordenadas.

Aunque el punto anterior se puede representar como: glVertex2f(20.0f, 10.0f); especificando x, y y z toma el valor 0 por default, más adelante conocerá más sobre como usar glVertex con más argumentos.

Los argumentos glBegin y GL_POINTS le indican a OpenGL que los siguientes vértices se van a interpretar y dibujar como puntos, tal como se muestra a continuación:

glBegin(GL_POINTS); glVertex3f (0, 0, 0);

glEnd();

Dentro de glBegin y glEnd podemos listar más vértices a dibujar Por ejemplo:

(20, 10, 0)

Y

X

Z

Page 23: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

23

glBegin(GL_POINTS); glVertex3f (5, 10, 3);

glVertex3f (20,-15, 15); glEnd(); Lo anterior dibuja un punto en la coordenada (5, 10, 3) y dibuja un punto en la coordenada (20,-15,15), también puede especificarse como:

glBegin(GL_POINTS); glVertex3f (5,10,3);

glEnd();

glBegin(GL_POINTS); glVertex3f(20,-15,15);

glEnd(); Aunque este código se ejecutará más lentamente.

En el programa anterior muestre puntos en las siguientes coordenadas: • (-1,1,0) • (1,-1,0) • (-1,-1,0) • (0,1,2)

En este último especificamos un valor para z, pero debido a que no podemos mover nuestro sistema de coordenada gráficamente posiblemente no se vea dicho punto.

Debe escribir: glBegin(GL_POINTS); y glVertex3f(-1,1,0); glVertex3f(1,-1,0); glVertex3f(-1,-1,0); glVertex3f(0,1,2); glEnd();

Page 24: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

24

Práctica número 7: Tamaño de un punto Objetivo: Graficar un punto en un espacio 3D y aplicar tamaño Para saber como graficar un punto en el espacio 3D siga los siguientes pasos:

1. Abrir un proyecto nuevo en Builder 5 2. Guarde el proyecto 3. Etiquete al formulario con el siguiente nombre “Dibujar Puntos”. 4. Agregue en el formulario una ventana de OpenGL 5. De clic a la ventana de OpenGL, en la ventana de de inspector de objetos

busque la propiedad Alinear (Align) asigne alTop. 6. En el formulario en la parte inferior agregue dos ScrollBar (Los ScrollBar

están en la pestaña de Estándar de Builder), modifique las siguientes propiedades de los ScrollBar, las propiedades puede verlas en el inspector de objetos.

Min=-200 Max=200 LargeChange =2

7. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el inspector de objetos, elija eventos y en el evento OnInit de doble clic y en código agregue lo siguiente

int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; GLfloat Rango = 200.0f; if(h == 0) h = 1; glViewport(0, 0, w, h); //puerto de vista glMatrixMode(GL_PROJECTION); glLoadIdentity(); //proyección ortogonal if (w <= h) glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango, Rango); else glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango, Rango); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); //color de fondo

8. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el inspector de objetos, elija eventos y en el evento OnPaint de doble clic y en código agregue lo siguiente:

Page 25: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

25

// Limpiar ventana glClear(GL_COLOR_BUFFER_BIT); //aquí se dibuja todo // color verde para los objetos glColor3f(0.0f, 1.0f, 0.0f); // Guardar el estado de la matriz y hacer la rotación glPushMatrix(); //poner en la matriz glRotatef(xRot, 1.0f, 0.0f, 0.0f); // rotar en el eje x glRotatef(yRot, 0.0f, 1.0f, 0.0f); // rotar en el eje y

// UnPunto(); //llamada a función que dibuja un punto // VariosPuntos(); // dibuja puntos formando una circunferencia // VariosPuntos2(); // dibuja puntos formando un espiral //VariosPuntos3(); // dibuja puntos de diferente tamaño VariosPuntos4(); // dibuja puntos formando un espiral agregando tamaño a los puntos.

// Reestablecer transformaciones glPopMatrix();

9. Habra el archivo Unith.h (según sea el nombre) declare la siguiente función y variables:

void UnPunto(); //dibuja un punto void VariosPuntos(); //dibuja puntos formando una circunferencia void VariosPuntos2(); //dibuja puntos formando un espiral void VariosPuntos3(); //dibuja puntos de diferente tamaño void VariosPuntos4(); //dibuja puntos formando un espiral agradando tamaño a los puntos float xRot,yRot,GL_PI;

10. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el inspector de objetos, elija eventos y en el evento OnResize de doble clic y en código agregue lo siguiente:

int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; glViewport(0, 0, w, h);

11. En el evento OnCreate del Formulario de doble clic y en código inicialice

las variables xRot=0; yRot=0; GL_PI=3.1416;

12. Regrese al formulario de doble clic, en la parte inferior del archivo de código agregue dos funciones: UnPunto y Varios Puntos

//--------------------------------------------------------------- void TForm1::UnPunto()

Page 26: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

26

{ glBegin(GL_POINTS); glVertex3f(0,0,0); glEnd(); } //------------------------------------------------------------- void TForm1::VariosPuntos() { GLfloat x,y,z,i; glBegin(GL_POINTS); z = 0; for(i = 0.0f; i<= 360; i+= 5) { x = 50.0f*sin(i); y = 50.0f*cos(i); glVertex3f(x, y, z); } glEnd(); }

13. Regrese al formulario, de clic en el ScrollBar1, en el inspector de objetos, elija eventos, de doble clic en el evento OnChage y código agregue lo siguiente:

xRot=ScrollBar1->Position; OpenGLPanel1->Invalidate();

14. Regrese al formulario, de clic en el ScrollBar2, en el inspector de objetos, elija eventos, de doble clic en el evento OnChage y código agregue lo siguiente:

yRot=ScrollBar2->Position; OpenGLPanel1->Invalidate();

15. Regrese al formulario agregue dos etiquetas, una el rótulo Rotación X y otra con Rotación Y, colóquelas arriba de los ScrollBar respectivamente.

16. Ejecute el programa (Run), y le aparecerá un punto verde en la coordenada (0, 0, 0) y varios puntos alrededor formando una circunferencia, tal como se muestra en la figura 6.

Page 27: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

27

Figura 6. Un punto en el centro y varios puntos formando una circunferencia.

17. Agregue una función más, llámela VariosPuntos2() y agregue el siguiente código.

GLfloat x,y,z,i; glBegin(GL_POINTS); z=-50; for(i = 0.0f; i<= 360; i+= 0.1) { x = 50.0f*sin(i); y = 50.0f*cos(i); glVertex3f(x, y, z); z+=1; } glEnd();

18. En el evento onPaint de OpenGL realice la llamada a VariosPuntos2() y

ejecute el programa, al rotarla mostrará un espiral, tal como se muestra en la figura 7.

Page 28: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

28

Figura 7. Espiral con puntos.

19. Agregue una función más, llámela VariosPuntos3() y en diferentes

coordenadas visualice puntos. Para dar tamaño a un punto se utiliza la función glPointSize(glfloat Tamaño), donde Tamaño puede ser un valor desde 0.5 – 10.0 en algunas versiones de OpenGL puede variar el tamaño, verifique el tamaño mínimo y máximo. En esta función puede introducir este código glPointSize(1); glBegin(GL_POINTS); glColor3f(1,0,0); glVertex3f(1,1,1); glEnd(); glPointSize(2); glBegin(GL_POINTS); glColor3f(1,1,0); glVertex3f(10,10,10); glEnd();

Page 29: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

29

glPointSize(3); glBegin(GL_POINTS); glColor3f(1,0,1); glVertex3f(20,20,20); glEnd(); glPointSize(4); glBegin(GL_POINTS); glColor3f(1,0,0); glVertex3f(-1,-1,-1); glEnd(); glPointSize(0.50); glBegin(GL_POINTS); glColor3f(1,1,0); glVertex3f(-20,-10,10); glEnd(); glPointSize(50); glBegin(GL_POINTS); glColor3f(1,0,1); glVertex3f(-90,-20,-20); glEnd();

20 En el evento onPaint de OpenGL realice la llamada a VariosPuntos3() y ejecute el programa, visualizará una imagen similar a la figura 8.

Figura 8. Puntos de diferentes tamaños.

Page 30: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

30

21. Agregue una función más llámela VariosPuntos4() agregue el siguiente código GLfloat x,y,z,i, Tam; glColor3f(1,0,0); z=-20; Tam=0.1; for(i = 0.0f; i<= 60; i+= 0.3) { glPointSize(Tam); x = 50.0f*sin(i); y = 50.0f*cos(i); glBegin(GL_POINTS); glVertex3f(x, y, z); glEnd(); Tam+=0.1; z+=1; } glPointSize(0); nota: esta función dibuja un espiral e incrementa los tamaños de los puntos. 22. En el evento onPaint de OpenGL realice la llamada a VariosPuntos4() y ejecute el programa, mostrará un imagen similar a la de la figura 9

Figura 9. Espiral con puntos de diferente tamaño.

Page 31: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

31

Práctica número 8: Dibujar líneas Objetivo: Graficar Líneas en un espacio 3D Para dibujar líneas se utiliza la primitiva de dibujo GL_LINES, por ejemplo si se quiere dibujar una línea en el eje x desde la coordenada (0, 0, 0) hasta (10, 0, 0). Para que OpenGL dibuje la línea con los vértices mencionados es: glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(10, 0, 0); glEnd();

1. Realice un función llamada ejes que usando OpenGL que dibuje las siguientes líneas

Eje Coordenada inicial

CoordenadaFinal

x (100,0,0) (-100,0,0) y (0,100,0) (0,-100,0) Z (0,0,100) (0,0,-100)

2. Agregue una función (con el nombre EjesColor), tal que dibuje una línea en cada eje con el color respectivo:

Eje Color x Rojo y Verdez Azul

3. Agregue una función (Sol) que dibuje líneas alrededor del origen (0, 0,0) de

color amarillo.

• Líneas continuas Para realizar líneas continuas se utiliza la primitiva GL_LINE_STRIP, es decir, el vértice final sirve de inicio para la siguiente línea y así sucesivamente. Por ejemplo el siguiente código dibuja 2 líneas continuas dados tres vértices, figura 10. glBegin(GL_LINE_STRIP); glVertex3f(0,5,0); glVertex3f(100,5,0); glVertex3f(100,100,0); glEnd();

Page 32: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

32

0,0,0 100,0,0

100,5,0

Figura 10. Esquema de dibujo de líneas.

4. Agregue una función (LineaContinua), que dibuje la figura anterior de color gris oscuro.

• GL_LINE_LOOP

La primitiva GL_LINE_LOOP se comporta de manera similar a GL_LINE_STRIP a diferencia de que se dibuja una línea final entre el último vértice especificado con el primer vértice especificado, ejemplo el siguiente código: glBegin(GL_LINE_LOOP); glVertex3f(0,5,0); glVertex3f(0,5,100); glVertex3f(0,100,100); glEnd(); Dibujaría unas líneas similares a las mostradas en figura 11.

5. Agregue una función (LineasCiclo), que dibuje la figura anterior en el eje z de color gris oscuro.

6. Al ejecutar su programa mostrará similar a la figura 12:

Page 33: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

33

(100,100, 0)

(100,5, 0) (0,5, 0) X

Y

Z

Figura 12. Usando las primitivas de dibujo de OpenGL GL_LINES, GL_LINE_STRIP,

GL_LINE_LOOP.

Figura 11. Líneas usando GL_LINE_LOOP.

Page 34: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

34

Práctica número 9: Más de líneas Objetivo: Manejar el ancho y punteo de líneas. Para dibujar líneas con ancho y punteadas siga los siguientes pasos:

1. Abrir un proyecto y en OpenGL muestre en líneas los ejes x, y y z. en color rojo, verde y azul respectivamente.

2. Paso seguido genere una función (espiral) que realice un espiral similar al que se realizó en la práctica 7 con los puntos.

3. Agregue el mismo código cambie la primitiva GL_POINTS por GL_LINE_STRIP

void TForm1::Espiral() { GLfloat x,y,z,i; glBegin(GL_LINE_STRIP); z=-20; for(i = 0.0f; i<= 360; i+= 0.1) { x = 50.0f*sin(i); y = 50.0f*cos(i); glVertex3f(x, y, z); z+=1; } glEnd(); }

4. Ejecute el programa y tendrá una imagen similar a la figura 13

Figura 13. Espiral con líneas.

Page 35: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

35

5. Para establecer el acho de una línea se utiliza la función la función glLineWidth, void glLineWidth(GLfloat ancho); la función acepta un solo parámetro que específica la anchura en píxeles de una línea dibujada. Aplique el ancho de 1 al eje x, 2 al eje y y 3 al eje z.

6. Dibuje 10 líneas paralelas al eje z, desde y=-100 hasta y=100 de diferentes

anchuras, El tamaño permitido de las líneas es de 1.0 hasta 10.0 pero puede variar dependiendo la versión de OpenGL y plataforma de S.O usada, una forma de dibujar es:

void TForm1::LineasParalelas() { GLfloat x,y,z; x=0; float Inc=0; glColor3f(1,1,0); for(y=-100.0f; y<100.0f; y+=20) { glLineWidth(Inc); glBegin(GL_LINES); glVertex3f(x,y,100); glVertex3f(x,y,-100); glEnd(); Inc+=2; } }

7. Además de la anchura también podemos establecer un patrón de punteo en las líneas, para usar el punteo primero se tiene que habilitar el punteo, usando la función glEnable(GL_LINE_STIPPLE);

Después la función glLineStipple establece el patrón que usan las líneas para su dibujo. void glLineStipple( GLint Factor, GLshort patron); Nota: Para deshabilitar cualquier opción glEnable se usa glDisable. El patrón es un valor de 16 bits que específica un patrón a usar cuando se dibujan líneas. Cada bit representa una sección del segmento de la línea, que están activados o desactivados. De forma predeterminada cada bit se corresponde a un solo píxel, pero el parámetro factor sirve como multiplicador para incrementar la anchura del patrón.

Page 36: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

36

Por ejemplo, el establecer el factor en 5, cada bit del patrón representa cinco píxeles en una fila, que puede estar activado o desactivado Por ejemplo: Si patrón = 0X00FF = 255 0 0 F F Binario = 0000 0000 1111 1111

Patrón de línea= Línea = |_______ ______ _______ _______| Ejemplo: Si el patrón es 0x5555 = 21845 Binario: 0101 0101 0101 0101 Patrón de línea: Si factor = 5, es decir cada bit del patrón representa 5 píxeles en una fila Línea:

8. Agregue una función (Punteo) la cual permita dibujar 10 líneas punteadas paralelas al eje x desde y=-100 hasta y=100, con z=0.

GLfloat x,y,z; GLint factor=1; GLushort Patron= 0x5555; //habilitando el punteo glEnable(GL_LINE_STIPPLE); z=0; glColor3f(1,1,0); for(y=-100.0f; y<100.0f; y+=20) { glLineStipple(factor, Patron); glBegin(GL_LINES); glVertex3f(100,y,z); glVertex3f(-100,y,z);

X x x x x x x x

x x x x x x x x

Page 37: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

37

glEnd(); factor++; } //Deshabilitando el Punteo glDisable(GL_LINE_STIPPLE);

9. Ejecute su programa y le mostrará similar a la figura 14

Figura 14. Línea con ancho y líneas punteadas.

Page 38: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

38

Práctica número 10: Dibujo de Triángulos Objetivo: Graficar Triángulos en 3D. Para dibujar un triángulo en OpenGL se utiliza la primitiva GL_TRIANGLES, por ejemplo si se quiere mostrar un triángulo en las siguientes coordenadas; (0,0, 0), (100, 100, 0), (100, 0, 0), tiene que seguir los siguientes pasos: 1. Abrir un proyecto y en OpenGL muestre en líneas los ejes x, y y z. en color rojo, verde y azul respectivamente. 2. Dibuje un triángulo con las coordenadas anteriores de color amarillo

glColor3f(1,1,0); glBegin(GL_TRIANGLES); glVertex3f(0,0,0); glVertex3f(100,100,0); glVertex3f(100,0,0); glEnd();

3. Dibuje un triángulo más con las coordenadas (0,0,0), (-100,100,0), (-100,0,0) de color verde

glColor3f(0,1,0); glBegin(GL_TRIANGLES); glVertex3f(0,0,0); glVertex3f(-100,100,0); glVertex3f(-100,0,0); glEnd();

El triángulo amarillo de acuerdo al orden que especificaron las coordenadas Giran en el sentido de las manecillas del reloj, el triángulo verde las coordenadas fueron especificadas en el orden Sentido contrario a las manecillas del reloj, OpenGL considera que los polígonos que giran en el sentido contrario de las manecillas del reloj miran de frente, lo que significa que la figura del triángulo verde muestra la parte frontal triángulo y la figura del triángulo amarillo muestra la parte posterior del triángulo, figura 15 y 16.

Page 39: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

39

Figura 15. Triángulos.

Y

X

V1

V2V0

V4

V3V5

Figura 16. Figura derecha: triángulo dibujado en el sentido las manecillas del reloj, figura Izquierda: triángulo dibujado en el sentido contrario a las manecillas del reloj.

Page 40: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

40

¿Importancia del porqué saber la parte frontal o posterior de un triángulo? En ejercicios siguientes se aplicarán características físicas distintas en la parte frontal y posterior de un polígono, como aplicar color y una propiedad reflectante. Para invertir el comportamiento predeterminado de OpenGL debemos llamar a la siguiente función: glFrontFace (GL_CW); El parámetro GL_CW le indica a OpenGL que los polígonos girados en el sentido las agujas del reloj se van a considerar frontalmente, para cambiar de nuevo el giro se usa GL_CCW Primitiva GL_TRIANGLE_STRIP Dibuja un triángulo, y cada nuevo vértice se interpreta como un triángulo entre los dos anteriores vértices y el nuevo. Dibuje un triángulo en las siguientes coordenadas usando GL_TRIANGLE_STRIP (0,0,0), (50,0,0), (25,25,0) Ejecute el programa, figura 17.a, agregue la siguiente coordenada (60, 25, 0) y se formará un nuevo triángulo a partir de los dos vértices anteriores, figura 17.b, agregue la coordenada (50, 50, 0), figura 17.c, el código para dibujar la banda de triángulos es:

glColor3f(1,1,0); glBegin(GL_TRIANGLE_STRIP); glVertex3f(0,0,0); glVertex3f(50,0,0); glVertex3f(25,25,0); glColor3f(0.5,0.5,1); glVertex3f(60,25,0); glColor3f(0.5,0.5,0.5); glVertex3f(50,50,0); glEnd();

Figura 17. a.

Page 41: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

41

Figura 17. b.

Figura 17. c.

Primitiva GL_TRIANGLE_FAN Genera un conjunto de triángulos rellenos conectados entre sí, con la característica de que todos los triángulos tienen un vértice en común. El primer triángulo define el vértice común a todos los triángulos. Dibuje una serie de triángulos a partir del vértice (0, 0, 0) usando GL_TRIANGLE_FAN, el siguiente código genera los triángulos de la figura 18

glColor3f(1,0,0); glBegin(GL_TRIANGLE_FAN); glVertex3f(0,0,0); glVertex3f(25,-25,0); glVertex3f(35,0,0); glColor3f(1,1,0); glVertex3f(35,25,0);

Page 42: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

42

glColor3f(1,0,0); glVertex3f(0,35,0); glColor3f(1,0,1); glVertex3f(-25,25,0); glColor3f(0,1,1); glVertex3f(-35,0,0); glColor3f(1,1,1); glVertex3f(-25,-25,0); glColor3f(0.5,1,1); glVertex3f(0,-35,0); glColor3f(0.5,0.5,1); glVertex3f(25,-25,0); glEnd();

Figura 18. Abanico de triángulos usando GL_TRIANGLE_FAN.

Page 43: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

43

Práctica número 11: Profundidad y eliminación de superficies y selectiva. Objetivo: Usar el buffer de profundidad, eliminación de superficies y eliminación selectiva.

Para usar la buffer de profundidad, eliminación de superficies y eliminación selectiva, siga los siguientes pasos: 1. Abra un proyecto en el cual muestre los x, y, z de color diferente. 2. Aplique rotación en el eje x y y 3. En el evento OnInit de OpenGLPanel1 antes de asignar color agregue la

siguiente función glEnable(GL_DEPTH_TEST); 4. Modifique en el evento OnPaint por

glMatrixMode(GL_MODELVIEW); glLoadIdentity();//Remplaza la matriz identidad //aquí se dibuja todo glColor3f(0.0f,1.0f,0.0f); //color de dibujo glShadeModel(GL_FLAT);//Establece en plano el modelo de color de sombra //Polígonos con giro en el sentido de las agujas del reloj miran de frente //se invierte porque estamos usando un abanico glFrontFace(GL_CW); // EjesColor(); // llamada a función que dibuja líneas de color en los ejes x, y, z Triangulo();

5. Declare la función “triángulo” 6. Declare la librería math.h 7. En el archivo Unit.h (según sea el nombre declare las siguientes variables

float PI; bool iProfundidad, iContorno, iSeleccionar;

8. En el evento OnCreate del formulario inicialice PI=3.1415; OpenGLPanel1->Width=Form1->Width; OpenGLPanel1->Height=Form1->Height; iSeleccionar = 0; iContorno = 0; iProfundidad = 0;

Page 44: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

44

9. Agregue un Menú Emergente (PopupMenu), que tenga las siguientes opciones:

a. Eliminación Selectiva b. Profundidad c. Posterior al Polígono

10. De clic en panel de OpenGL, seleccione la propiedad PopUpMenu elija PopupMenu1.

11. En cada uno de los menús correspondientes agregue el código void __fastcall TForm1::Seleccionar1Click(TObject *Sender) { iSeleccionar = !iSeleccionar; } //--------------------------------------------------------------------------- void __fastcall TForm1::Profundidad1Click(TObject *Sender) { iProfundidad = !iProfundidad; } //--------------------------------------------------------------------------- void __fastcall TForm1::PosteriordelPoligono1Click(TObject *Sender) { iContorno = !iContorno; } //---------------------------------------------------------------------------

12. En la función “triángulo” agregue el siguiente código GLfloat x,y,angulo; //para almacenar las coordenadas y el ángulo int iPivote = 1; //para indicar los colores alternativos //Limpiar la ventana y el búfer de profundidad glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Cambiar a seleccionar si se ha establecido indicador if(iSeleccionar) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); // Activar prueba de profundidad si se ha establecido el indicador if(iProfundidad) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);

Page 45: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

45

// Dibujar la parte posterior sólo como estructura si se ha establecido indicador if(iContorno) glPolygonMode(GL_BACK, GL_LINE); //para relleno(s/n) else glPolygonMode(GL_BACK, GL_FILL); // Guardar estado de matrix y realizar la rotación. glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // iniciar un abanico de triángulos glBegin(GL_TRIANGLE_FAN); // La cúspide del cono es un vértice compartido para el abanico // movido hacia arriba en el z para producir un como en lugar de un circulo glVertex3f(0.0f, 0.0f, 75.0f); //Crear un bucle en un círculo y especificar puntos pares en el círculo //como vértices del abanico de triángulos for(angulo = 0.0f; angulo < (2.0f*PI); angulo += (PI/8.0f)) { // Calcular posiciones x e y de siguiente vértice x = 50.0f*sin(angulo); y = 50.0f*cos(angulo); // alternar color entre rojo y verde if((iPivote %2) == 0) glColor3f(0.0f, 1.0f, 0.0f); else glColor3f(1.0f, 0.0f, 0.0f); // Incrementar pivote para cambiar color la próxima vez iPivote++; // Especificar el siguiente vértice del abanico de triángulos glVertex2f(x, y); } // dibujar abanico para el cono glEnd(); // glFrontFace(GL_CCW); // Iniciar un nuevo abanico de triángulos para cubrir la parte inferior

Page 46: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

46

glBegin(GL_TRIANGLE_FAN); // El origen se encuentra en el centro del abanico glVertex2f(0.0f, 0.0f); for(angulo = 0.0f; angulo < (2.0f*PI); angulo += (PI/8.0f)) { // calcular la posición x e y del siguiente vértice x = 50.0f*sin(angulo); y = 50.0f*cos(angulo); // Alternar colores entre rojo y verde if((iPivote %2) == 0) glColor3f(0.0f, 1.0f, 0.0f); else glColor3f(1.0f, 0.0f, 0.0f); // incrementar eje para cambiar color la próxima vez iPivote++; // Especificar el siguiente vértice del abanico de triángulos glVertex2f(x, y); } //dibujar el dibujo del abanico que cubre la parte inferior glEnd(); //Reestablecer transformaciones glPopMatrix(); //Limpiar comandos de dibujo glFlush();

13. Ejecute el programa, figura 19.

Figura 19. Cono.

Page 47: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

47

Primeramente se dibuja el Cono posteriormente la parte inferior del cono en un plano xy. glShadeModel(GL_FLAT); Le especifica a OpenGL que rellene los polígonos con el color sólido del último vértice especificado. glShadeModel(GL_SMOOTH); Le especifica a OpenGL que sombreará los triángulos suavemente desde cada vértice.

• Eliminación de superficies Verifique que el rotar el cono la parte inferior se tambalea, es decir, en OpenGL el último objeto dibujado aparecerá sobre los anteriores, para corregir se usa una opción denominada prueba de profundidad, figura 20. Para activar llamamos a: glEnable(GL_DEPTH_TEST); En código encontrará esto:

// Activar prueba de profundidad si se ha establecido el indicador if(iProfundidad) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);

Figura 20. Prueba de Eliminación de superficies

• El búfer de profundidad

Limpiar la ventana y el búfer de profundidad es análogo al de color en cuánto qué contiene información sobre la distancia de los píxeles desde espectador, esta información se usa para determinar si algún píxel quedó oculto por píxeles que se encuentran más cerca del espectador. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Page 48: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

48

• Eliminación selectiva: Ocultar superficies para mejorar rendimiento En el término que usamos para describir la técnica de eliminar objetos geométricos que sabemos que nunca vamos a ver, es una selección de partes posteriores, en nuestro ejemplo usamos esta técnica para ocultar los objetos que están en la parte posterior, para saber si un objeto esta en la parte frontal o posterior es con el giro, figura 21. En código es: // Cambiar a seleccionar si se ha establecido indicador if(iSeleccionar) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);

Figura 21. Eliminación selectiva

Modos de Polígono

No es necesario rellenar los polígonos con el color actual, de forma predeterminada los polígono se rellenan de este color, pero puede cambiarse este comportamiento especificando que los polígonos deben dibujarse como esquemas o sólo puntos (sólo se tranzan los vértices). La función glPolygonMode permite interpretar los polígonos como elementos sólidos rellenos, como esquemas o como puntos, así como a ambos lados o sólo la parte posterior, figura 22 y figura 23. // Dibujar la parte posterior sólo como estructura si se ha establecido indicador if(iContorno) glPolygonMode(GL_BACK,GL_LINE); else glPolygonMode(GL_BACK,GL_FILL);

Page 49: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

49

Figura 22. Polígono relleno.

Figura 23. Polígono (Parte) sin relleno.

Page 50: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

50

Práctica número 12: Polígonos Objetivo: Dibujar Polígonos usando las primitivas GL_QUADS, GL_QUAD_STRIP y GL_POLYGON de OpenGL. Para conocer como dibujar polígonos siga los siguientes pasos:

1. En un proyecto nuevo dibuje los ejes x, y, y z de color diferente cada uno. 2. Aplique rotación en el eje x y y 3. Para dibujar un rectángulo se utiliza la primitiva GL_QUADS, por ejemplo si

se quiere dibujar un rectángulo, similar al de la figura 24.

Vértice 2

Vértice 1

Vértice 3

Vértice 4

Figura 24. Rectángulo.

Basta con especificar dichos vértices

glColor3f(1,0,0); glBegin(GL_QUADS); glVertex3f(-50,-50,50); glVertex3f(-50,50,50); glVertex3f(50,50,50); glVertex3f(50,-50,50); glEnd();

4. Para realizar una banda de cuadriláteros, se utiliza la primitiva

GL_QUAD_STRIP, ejemplo si se quiere tener una banda similar a la figura 25 deben especificarse los vértices de la siguiente manera.

//banda de cuadriláteros glColor3f(1,1,0); glBegin(GL_QUAD_STRIP); glVertex3f(-50,-50,-50); glVertex3f(-50,50,-50); glVertex3f(50,-50,-50); glVertex3f(50,50,-50);

Page 51: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

51

glColor3f(0,1,1); glVertex3f(100,-50,-50); glVertex3f(100,50,-50); glColor3f(1,1,1); glVertex3f(150,-50,-50); glVertex3f(150,50,-50); glEnd();

Vértice 2

Vértice 1

Vértice 3

Vértice 4 Vértice 1

Vértice 2

Vértice 3

Vértice 4

Vértice 5

Vértice 6

Figura 25. Banda de cuadriláteros.

Y al ejecutar el programa, mostrará similar a la figura 26

Figura 26. Usando las primitivas GL_QUADS y GL_QUAD_STRIP.

5. Para dibujar un polígono con cualquier número de lados, figura 27, se utiliza

la primitiva GL_POLYGON, Para dibujar un polígono similar al de figura 27 con el siguiente código:

//polígonos

Page 52: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

52

glColor3f(0,1,0); glBegin(GL_POLYGON); glVertex3f(-50,50,0); glVertex3f(40,40,0); glVertex3f(50,30,0); glVertex3f(50,-50,0); glVertex3f(-50,-50,0); glEnd();

Vértice 1 Vértice 2

Vértice 3

Vértice 4Vértice 6

Figura 27. Polígono.

Page 53: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

53

Práctica número 13: Relleno de polígonos Objetivo: Conocer como rellenar polígonos con punteo. Cuando genera un polígono, éste se rellena de forma sólida con el último color especificado, tal como se vio en la práctica 12, para rellenar un polígono en forma de punteo siga los siguientes pasos:

1. Abrir un proyecto en el cual muestre los ejes x, y y z de color diferente. 2. Aplique rotación en el x, y y z. 3. Dibuje un polígono con 8 lados de igual tamaño

Patrón de Relleno Para rellenar un polígono existen dos formas: texturas (no incluye en este manual) y un patrón de punteo, similar al de líneas realizado en la práctica nueve. Un patrón de punteo de polígonos es un mapa de bits de 32 x 32 que usa para el patrón de relleno. Para habilitar el punteo se utiliza

glEnable(GL_POLYGON_STIPPLE) Y enseguida se llama a glPolygonStipple(pBitmap);

donde: pBitmap es un apuntador a un área de datos que contiene el patrón de punteo. A partir de ese momento todos los polígonos se rellenarán con el patrón de punteo especificado por pBitmap (GLubyte *).

4. Dibuje una firma o iniciales en cuadricula de 32 X 32, ejemplo figura 28 5. Defina una matriz de tipo byte GLubyte Firma[]= {0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00

.

.

. 0x80, 0x00, 0xF0, 0x20

.

.

. }

Cada fila de la figura corresponderá a una fila de la matriz, la primera fila de la matriz corresponde a la última fila de la figura, los números de la matriz son en hexadecimal.

Page 54: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

54

Cada línea de la figura tiene 32 píxeles (cuadros), este se divide en grupos de 8 elementos, formando 4 grupos. Cada grupo representa un número en hexadecimal de dos cifras y cada numero se obtiene si la línea (cuadro) de la figura está marcado o no. 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

1 2 8

6 4

3 2

1 6

8 4 2 1 1 2 8

6 4

3 2

1 6

8 4 2 1 1 2 8

6 4

3 2

1 6

8 4 2 1 1 2 8

6 4

3 2

1 6

8 4 2 1

Figura 28. Firma en una cuadrícula.

Tomando una línea (marcada con x, figura 29) de la figura 28, los valores en hexadecimal corresponden a la tabla 1.

Page 55: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

55

Figura 29. Línea de la cuadricula

Tabla 1. Valores en hexadecimal correspondiente a la figura 29.

0x80 0x00 0xF0 0x20

Los cuatro cuadros siguientes, marcados con X, no están rellenos, por lo tanto, corresponde un 0. Los siguientes cuatro marcados con X, sólo, está relleno el tercero, por lo tanto, corresponde a un 8.

Los cuatro cuadros siguientes, marcados con X, no están rellenos, por lo tanto, corresponde un 0. Los siguientes cuatro marcados con X, no están rellenos, por lo tanto, corresponde un 0.

Los cuatro cuadros siguientes, marcados con X, no están rellenos, por lo tanto, corresponde un 0. Los siguientes cuatro marcados con X, están rellenos, por lo tanto, corresponde a F. Por la siguiente razón. cuadro 1 = 1, cuadro 2 = 2, cuadro 3 = 4 y cuadro 4 = 8. sumando 1 + 2+4+8 = 1515 = F.

Los primeros cuatro cuadros (derecha a izquierda), marcados con X, no están rellenos por lo tanto, corresponde un valor hexadecimal 0. Los siguientes cuatro cuadros, marcados con X, el segundo cuadro está relleno o pasa parte de la firma, por lo tanto, corresponde un 2.

y así sucesivamente se realiza para las demás líneas.

6. Declare la matriz

GLubyte fuego[128] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

Page 56: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

56

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x0f, 0x00, 0x1f, 0xe0, 0x1f, 0x80, 0x1f, 0xc0, 0x0f, 0xc0, 0x3f, 0x80, 0x07, 0xe0, 0x7e, 0x00, 0x03, 0xf0, 0xff, 0x80, 0x03, 0xf5, 0xff, 0xe0, 0x07, 0xfd, 0xff, 0xf8, 0x1f, 0xfc, 0xff, 0xe8, 0xff, 0xe3, 0xbf, 0x70, 0xde, 0x80, 0xb7, 0x00, 0x71, 0x10, 0x4a, 0x80, 0x03, 0x10, 0x4e, 0x40, 0x02, 0x88, 0x8c, 0x20, 0x05, 0x05, 0x04, 0x40, 0x02, 0x82, 0x14, 0x40, 0x02, 0x40, 0x10, 0x80, 0x02, 0x64, 0x1a, 0x80, 0x00, 0x92, 0x29, 0x00, 0x00, 0xb0, 0x48, 0x00, 0x00, 0xc8, 0x90, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 };

7. Agregue las funciones para habilitar el patrón de punteo antes de llamar a su función que dibuja el polígono.

// Activar el punteo del polígono glEnable(GL_POLYGON_STIPPLE); // Especifica un patrón de punteo especificado glPolygonStipple(fuego); glColor3f(1.0f,0.0f,0.2f); //rojo Poly() ; // función que dibuja un polígono

8. Ejecute su programa y el polígono dibujado estará relleno con el patrón de punteo (fuego), figura 30.

9. En un rectángulo especifique un patrón de punteo de una firma o iniciales. 10. En un Triángulo especifique un patrón de punteo de un ojo.

Page 57: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

57

Práctica número 14: Polígonos en vista de puntos, líneas y rellenos Objetivo: Conocer como dibujar polígonos válidos, así como en forma de líneas, puntos y rellenos. En OpenGL para dibujar un polígono debe seguir las siguientes reglas:

• Los polígonos deben ser planos (los vértices del polígono deben encontrarse en un solo plano)

• Los polígonos no pueden girarse o doblarse en el espacio (razón para la cual se usan los triángulos)

• Los bordes no deben intersecarse (cuando se cruzan sus líneas) y deben ser convexos (no pueden tener sangrías), es decir, dado un polígono y se traza una línea, esta no debe cruzar más de dos veces sobre el contorno del polígono, figura 31.

Figura 31. Polígonos válidos y no válidos

Ejemplo, si se quiere dibujar una estrella se puede dibujar usando varios polígonos, siga los siguientes pasos: 1. Abrir un proyecto nuevo 2. Agregue 2 ScrollBars, para rotar los ejes x y y. 3. Agregue una función llamada “triangulo”, agregue código tal que dibuje un

triángulo.

Polígonos Válidos Polígonos No Válidos

Page 58: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

58

bool bContorno=1; // guardar el estado de la matriz y hacer la rotación glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glBegin(GL_TRIANGLES); glEdgeFlag(bContorno); glVertex2f(-20.0f, 0.0f); glEdgeFlag(0); glVertex2f(20.0f, 0.0f); glVertex2f(0.0f, 40.0f); glEnd();

La función glPolygonMode permite cambiar el esquema de un polígono relleno a uno en líneas y con la función glEdgeFlag(); que admite un sólo parámetro (Falso o verdadero), nos permitirá indicar que si contorno o línea debe mostrarse o no.

4. defina las siguientes constantes en la cabecera del archivo .cpp #define MODO_SOLIDO 0 #define MODO_LINEA 1 #define MODO_PUNTO 2

5. declare las siguientes variables (después de TForm1 *Form1;) int iModo = MODO_SOLIDO; boolean bContorno = TRUE;

6. agregue un menú emergente con los siguientes submenús

7. En código agregue el código correspondiente /--------------------------------------------------------------------------- void __fastcall TForm1::MODOSOLIDO1Click(TObject *Sender) { iModo = MODO_SOLIDO; } //-----------------------------------------------------

Page 59: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

59

void __fastcall TForm1::MODOLINEA1Click(TObject *Sender) { iModo = MODO_LINEA; } //--------------------------------------------------------------------------- void __fastcall TForm1::MODOPUNTO1Click(TObject *Sender) { iModo = MODO_PUNTO; } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { PopupMenu1->Popup(X, Y); } //--------------------------------------------------------------------------- void __fastcall TForm1::Si1Click(TObject *Sender) { bContorno = TRUE; } //--------------------------------------------------------------------------- void __fastcall TForm1::No1Click(TObject *Sender) { bContorno = FALSE; } //---------------------------------------------------------------------------

8. Agregue una función denominada Estrella, con el siguiente código //--------------------------------------------------------------------------- void TForm1::ESTRELLA() { // limpiar ventana glClear(GL_COLOR_BUFFER_BIT); // Dibujar el polígono de acuerdo a la bandera if(iModo == MODO_LINEA)

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); if(iModo == MODO_PUNTO)

glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); if(iModo == MODO_SOLIDO) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

Page 60: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

60

// Guardar el estado de la matriz y hacer la rotación glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glBegin(GL_TRIANGLES); glEdgeFlag(bContorno); glVertex2f(-20.0f, 0.0f); glEdgeFlag(TRUE); glVertex2f(20.0f, 0.0f); glVertex2f(0.0f, 40.0f); glVertex2f(-20.0f,0.0f); glVertex2f(-60.0f,-20.0f); glEdgeFlag(bContorno); glVertex2f(-20.0f,-40.0f); glEdgeFlag(TRUE); glVertex2f(-20.0f,-40.0f); glVertex2f(0.0f, -80.0f); glEdgeFlag(bContorno); glVertex2f(20.0f, -40.0f); glEdgeFlag(TRUE); glVertex2f(20.0f, -40.0f); glVertex2f(60.0f, -20.0f); glEdgeFlag(bContorno); glVertex2f(20.0f, 0.0f); glEdgeFlag(TRUE); // Centro es un cuadrado formado con dos triángulos glEdgeFlag(bContorno); glVertex2f(-20.0f, 0.0f); glVertex2f(-20.0f,-40.0f); glVertex2f(20.0f, 0.0f); glVertex2f(-20.0f,-40.0f); glVertex2f(20.0f, -40.0f); glVertex2f(20.0f, 0.0f); glEdgeFlag(TRUE); glEnd(); glPopMatrix(); }

Page 61: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

61

9. Ejecute el programa, figura 32.

a) b)

c) d)

Figura 32. a) Polígono relleno, b) Polígono en modo línea, c) Polígono en modo puntos y d) Polígono en modo línea con contorno.

Page 62: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

62

Práctica número 15: Limpiar el buffer de color Objetivo: Conocer como limpiar el buffer de color en un determinado momento El buffer es una memoria donde se guarda los colores de la ventana de OpenGL, para limpiar dicho buffer se utiliza la función: glClear(GL_COLOR_BUFFER_BIT), en el ejemplo siguiente se limpia el buffer cuando se cumple una condición. 1. Abrir un proyecto nuevo 2. En el evento OnPaint de OpenGL agregue el siguiente código, el cual dibuja un

espiral con puntos:

//aquí se dibuja todo glColor3f(1.0f,0.0f,0.0f); //limpiando la ventana de azul glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); if (angulo<=0.2) glClear(GL_COLOR_BUFFER_BIT); // limpiar buffer glPointSize(3); glBegin(GL_POINTS); glVertex2d(radio*cos(angulo), radio*sin(angulo)); glEnd(); if(angulo>20) { radio=1; angulo=0; }

En la condición if (angulo<=0.2)

glClear(GL_COLOR_BUFFER_BIT); Se manda a limpiar el buffer cuando esta condición se cumple 3. Declare las siguientes variables en el archivo .h

GLdouble radio; GLdouble angulo;

4. Inicialícelas en OnCreate del formulario radio =0.1; angulo =0.1;

5. Agregue un timer y actualice las variables radio+=0.5; angulo+=0.1; OpenGLPanel1->Invalidate();

Page 63: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

63

6. Ejecute su programa, figura 33

Figura 33. Limpiar buffer

Page 64: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

64

Práctica número 16: Rotación, Translación y Escalamiento Objetivo: Aplicar Rotación, Translación y Escalamiento a objetos. El formato de Rotación, Translación y Escalamiento es el siguiente: Rotación void glRotatef(GLfloat angulo, GLfloat x, GLfloat y, GLfloat z); Realiza un giro alrededor del eje especificado (x, y y z). El ángulo de giro se encuentra en la dirección contraria a las agujas del reloj, medidos en grados y especificados en el argumento ángulo. Translación void glTranslatef(GLfloat x, GLfloat y, GLfloat z); Acepta como parámetros la cantidad de translación a los largo de los ejes x, y y z. Escalado glScalef(GLfloat x, GLfloat y, GLfloat z); Expande o reduce los objetos a lo largo de distintas direcciones en los ejes x, y y z. 1. En un proyecto nuevo dibuje un cubo 2. Agregue un ScrollBars, figura 34, para modificar el valor de cada uno de los

argumento de las tres funciones, utilice el evento OnChange de cada ScrollBar puede modificar el valor de cada argumento.

void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { xRot=ScrollBar2->Position; OpenGLPanel1->Invalidate(); } //------------------------------------------------- void __fastcall TForm1::ScrollBar3Change(TObject *Sender) { yRot=ScrollBar3->Position; OpenGLPanel1->Invalidate(); } //-------------------------------------------------

void __fastcall TForm1::ScrollBar4Change(TObject *Sender) { zRot=ScrollBar4->Position; OpenGLPanel1->Invalidate(); } void __fastcall TForm1::ScrollBar5Change(TObject *Sender) { xEsc=ScrollBar5->Position; OpenGLPanel1->Invalidate(); } //---------------------------------------------------------------------------

Page 65: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

65

void __fastcall TForm1::ScrollBar6Change(TObject *Sender) { yEsc=ScrollBar6->Position; OpenGLPanel1->Invalidate(); } //------------------------------------------------- void __fastcall TForm1::ScrollBar7Change(TObject *Sender) { zEsc=ScrollBar7->Position; OpenGLPanel1->Invalidate(); } //------------------------------------------------- void __fastcall TForm1::ScrollBar8Change(TObject *Sender) { xTra=ScrollBar8->Position; OpenGLPanel1->Invalidate(); } //------------------------------------------------- void __fastcall TForm1::ScrollBar9Change(TObject *Sender) { yTra=ScrollBar9->Position; OpenGLPanel1->Invalidate(); } //------------------------------------------------- void __fastcall TForm1::ScrollBar10Change(TObject *Sender) { zTra=ScrollBar10->Position; OpenGLPanel1->Invalidate(); }

Page 66: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

66

Figura 34. Scrollbars para Rotación, Translación y Escalamiento.

3. En código antes de dibujar el cubo llame las funciones para rotar, trasladar y

escalar glRotatef(xRot,1,0,0); glRotatef(yRot, 0,1,0);

glRotatef(zRot,0,0,1); glScalef(xEsc,yEsc,zEsc); glTranslatef(xTra,yTra,zTra);

4. Ejecute su programa, figura 35.

a) b)

Figura 35. a) Cubo, b) cubo con rotación, translación y escalamiento. Actividad: Dibujar el sistema solar, figura 36.

Page 67: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

67

Figura 36. Sistema Solar.

Page 68: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

68

Práctica número 17: Proyección Ortogonal y en Perspectiva Objetivo: Aplicar la proyección Ortogonal y en Perspectiva Proyección se define como la forma de visualizar los objetos en un plano tridimensional, existen dos formas de proyección: La primera es la forma ortogonal, este tipo de proyección define un volumen de vista rectangular, concretamente define un paralelepípedo de tamaño infinito, figura 38, para entender esta forma dibuje una caja rectangular, similar a la figura 37, como puede observar la caja no pierde tamaño en su forma al ser proyectada en 3D, esta forma es utilizada para visualizar edificios, planos, los cuales se requiere que conserven la forma a pesar de la distancia del observador, la función que permite visualizar los objetos en forma ortogonal es glOrtho, su formato: glOrtho(xmin,ymin, xmax,ymax, cerca, lejos); donde: xmin y ymin, representan la esquina inferior de una vista rectangular xmax y ymax, representan la esquina superior de una vista rectangular cerca y lejos son los planos de recorte de la vista rectangular, cerca y lejos respectivamente del observador. Nota: los objetos dibujados deben estar dentro de las coordenadas de los planos cerca y lejos, de lo contrario, si un objeto es dibujado fuera de este rango no se visualizará. Hasta aquí todos lo ejemplos mostrados se han graficado usando la proyección ortogonal, la función glOrtho() se encuentra especificada en el evento OnInit() de la ventana de OpenGL.

Figura 37. Proyección ortogonal de una caja.

Page 69: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

69

//--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender) { int h=OpenGLPanel1->Height; int w=OpenGLPanel1->Width; GLfloat Rango = 140.0f; if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango*2.0f, Rango*2.0f); else glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango*2.0f, Rango*2.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }

Figura 38. Proyección ortogonal.

La segunda proyección es la perspectiva, esta proyección permite visualizar los objetos que están más lejos se vean más chicos que los que están más cerca, es utilizada para cuando se grafican escenas de paisajes, así por ejemplo, una montaña aunque físicamente es más grande que una que está más cerca, se ve más chica que la que está más cerca del espectador, para visualizar la caja

Page 70: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

70

dibujada de la figura 37 en perspectiva en el código del evento On Init modifíquelo por: int h=OpenGLPanel1->Height; int w=OpenGLPanel1->Width; GLfloat Aspecto; if(h == 0) h = 1; glViewport(0, 0, w, h); Aspecto = w/h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Produce la proyección de perspectiva gluPerspective(70.0f, Aspecto, 1.0, 400.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); Al ejecutar su programa, se visualizará como la figura 40, la función que se utiliza es: gluPerspective(apetura, aspecto, pcerca plejos); donde: Apertura corresponde al ángulo de apertura de la cámara virtual, este ángulo puede tomar valores comprendidos entre 0º y 180º. El valor de aspect, vendrá dado por la relación entre el alto y ancho del plano de corte, por lo tanto aspect toma el valor de alto plano dividido entre largo plano. Los valores de pcerca y plejos corresponden a los planos de corte cercano y lejano. La proyección en perspectiva gráficamente se representa como la figura 39.

Figura 39. Proyección en Perspectiva.

Page 71: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

71

Figura 40. Proyección en Perspectiva de una caja.

Ejercicio: Al sistema solar graficado en la práctica 16, modifique su proyección a perspectiva.

Page 72: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

72

Práctica número 18: Luz ambiental, difusa y especular Objetivo: Aplicar luz ambiental, difusa y especular a los gráficos La luz permite dar una apariencia más real de los objetos, OpenGL maneja tres tipos de luz que son luz ambiental, difusa y especular. Luz Ambiental. Es la luz que proviene de muchas partes y que permite iluminar a un objeto, por ejemplo, la luz que existe en un cuarto cerrado, por tal motivo se llama ambiental, porque es la que existe en un ambiente, figura 41 a. Luz difusa. Es luz que proviene de un reflejo, que puede ser un ventana, un espejo, etc., figura 41 b. Luz especular. Es la luz que proviene de una fuente en específico, tal como, un foco, el sol, etc., figura 41 c.

a b c

Figura 41 a. Luz ambiental, c. Luz difusa, c. Luz especular. La combinación de las luces produce efectos sobre los objetos (materiales), tales como brillo y color, los cuales se les denomina reflectancia. La intensidad de iluminación de cada punto de las superficies de los materiales dependerá de: Intensidad= Luz ambiente + Luz difusa + Luz especular. OpenGL tiene las siguientes funciones para especificar la luz tanto de los materiales como de iluminación que son: glLightModelfv() y glLightfv(). Para dar una iluminación plana a los materiales se utiliza la función: glShadeModel (GL_FLAT ) y para una iluminación suave se utiliza la función: glShadeModel (GL_SMOOTH ) ; Para visualizar una esfera, figura 42, con iluminación el código fuente es el siguiente: En el archivo .cpp de c++ builder 5

#include <vcl.h> #pragma hdrstop

Page 73: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

73

#include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "OpenGLPanel" #pragma resource "*.dfm" TForm1 *Form1; // Rotación static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; // valores y coordenadas de la luz GLfloat PosicionLuz[] = { 0.0f, 0.0f, 75.0f, 1.0f }; GLfloat LuzEspecular[] = { 1.0f, 0.0f, 0.0f, 1.0f}; GLfloat Reflectancia[] = { 1.0f, 1.0f, 1.0f, 1.0f};

a)

b)

Figura 42. a) Iluminación en modo plano. b) Iluminación en modo suave.

Page 74: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

74

GLfloat LuzAmbiente[] = { 0.5f, 0.5f, 0.5f, 1.0f}; GLfloat DirPunto[] = { 0.0f, 0.0f, -1.0f }; // banderas para efectos #define MODO_PLANO 1 #define MODO_SUAVE 2 int Forma = MODO_PLANO; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Resize(TObject *Sender) { glViewport(0,0,OpenGLPanel1->ClientWidth,OpenGLPanel1->ClientHeight); } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender) { glEnable(GL_DEPTH_TEST); // Eliminar superficie oculta // glFrontFace(GL_CCW); // Polígonos que miran en el sentido contrario al de las //agujas del reloj // glEnable(GL_CULL_FACE); // no intentar mostrar los lados posteriores // activar iluminación glEnable(GL_LIGHTING); // Establecer y activar 0 de luz //suministrar una ligera luz ambiente para poder ver los objetos glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbiente); //La luz esta compuesta solamente de luz ambiente y especular glLightfv(GL_LIGHT0,GL_DIFFUSE,LuzAmbiente); glLightfv(GL_LIGHT0,GL_SPECULAR,LuzEspecular); glLightfv(GL_LIGHT0,GL_POSITION,PosicionLuz); //Especificar efectos de puntos //el ángulo de corte es de 60 grados glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,50.0f); //Activar esta luz en concreto glEnable(GL_LIGHT0); // Activar registro de color glEnable(GL_COLOR_MATERIAL); //activar las propiedades de color que siguen a glcolor glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); //a partir de ahora todos los materiales tienen una reflectancia //especular plena de un alto brillo glMaterialfv(GL_FRONT, GL_SPECULAR,Reflectancia); glMateriali(GL_FRONT, GL_SHININESS,128); // Fondo color negro

Page 75: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

75

glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); //función LuzPunto(); } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender) { int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; GLfloat fAspect; if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); fAspect = (GLfloat) w / (GLfloat) h; gluPerspective(35.0f, fAspect, 1.0f, 500.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -250.0f); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { OpenGLPanel1->Width=Form1->Width; OpenGLPanel1->Height=Form1->Height; xRot = 0.0f; yRot = 0.0f; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { OpenGLPanel1->Width=Form1->Width; OpenGLPanel1->Height=Form1->Height; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void TForm1::LuzPunto() { GLUquadricObj *pObj; pObj = gluNewQuadric(); gluQuadricNormals(pObj, GLU_SMOOTH); if(Forma == MODO_PLANO) glShadeModel(GL_FLAT); else // FORMA = MODO_SUAVE; glShadeModel(GL_SMOOTH); // Limpiar la venta con el color de borrado actual

Page 76: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

76

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Colocar primero la luz // Guardar las transformadas de las coordenadas glPushMatrix(); // Rotar el sistema de coordenadas glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); //Especificar la nueva posición y dirección en coordenada rotadas glLightfv(GL_LIGHT0,GL_POSITION,PosicionLuz); glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,DirPunto); // dibujar un cono rojo para introducir la fuente de luz glColor3ub(255,0,0); // glColor3ub(0,255,0); // Trasladar origen para mover el cono donde esta la luz situada glTranslatef(PosicionLuz[0],PosicionLuz[1],PosicionLuz[2]); // gluCylinder(pObj, 5,1,7, 15, 15); gluCylinder(pObj, 2,3,17, 15, 15); // Dibujar una esfera desplazada para denotar la bobilla de luz //guardar las variables de estado de iluminación glPushAttrib(GL_LIGHTING_BIT); // Apagar la iluminación y especificar una esfera amarilla brillante glDisable(GL_LIGHTING); //glColor3ub(255,255,0); glColor3ub(255,0,0); // gluSphere(pObj, 4, 15, 15); gluSphere(pObj, 2, 5, 5); // Restablecer las variables del estado de iluminación glPopAttrib(); // Restablecer las transformaciones de coordenadas glPopMatrix(); // Establecer el color del material y dibujar una esfera en el centro glColor3ub(255,0, 0 ); //rojo gluSphere(pObj, 55, 50, 50); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { xRot=ScrollBar1->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { yRot=ScrollBar2->Position; OpenGLPanel1->Invalidate(); }

Page 77: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

77

//--------------------------------------------------------------------------- void __fastcall TForm1::Plano1Click(TObject *Sender) { Forma = MODO_PLANO; } //--------------------------------------------------------------------------- void __fastcall TForm1::Suave1Click(TObject *Sender) { Forma = MODO_SUAVE; } //---------------------------------------------------------------------------

En el archivo .h de c++ builder 5 declare de forma pública la función “LuzPunto” public: // User declarations void LuzPunto();

Page 78: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

78

Práctica número 19: Sombras Objetivo: Agregar sombra a los gráficos La sombra es un efecto que permite dar una apariencia más real a los objetos graficados, una sombra es la ausencia de luz producida por la superposición de un cuerpo opaco entre una fuente de luz y otro cuerpo, en OpenGL para generar el efecto de sombra se tienen que especificar los siguientes puntos:

1. Graficar un objeto 2. Especificar un punto como fuente de luz 3. Generar una matriz de proyección en la cual se calculará el plano de

proyección donde se quiere la sombra. En la figura 43 se observa el efecto de sombra, donde la fuente de luz se representa por un círculo amarillo, el objeto opaco que se superpone a la luz y la sombra.

Figura 43. Sombra

El código correspondiente a la figura 43 es: #include <vcl.h> #pragma hdrstop #include "Unit1.h" #include <math.h> #include <math.h> //#include <GL/glaux.h> #include <GL/glut.h>

#include <GL/glu.h> #include <GL/gl.h> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "OpenGLPanel" #pragma resource "*.dfm" TForm1 *Form1; void Base();

Page 79: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

79

void Pinata(); void Sol(); void gltMakeShadowMatrix(GLfloat puntos[3][3], GLfloat lightPos[4], GLfloat destMat[16]); void gltGetNormalVector(const GLfloat vP1[], const GLfloat vP2[], const GLfloat vP3[], GLfloat vNormal[]); void gltSubtractVectors(const GLfloat vFirst[], const GLfloat vSecond[], GLfloat vResult[]); void gltVectorCrossProduct(const GLfloat vU[], const GLfloat vV[], GLfloat vResult[]); void gltNormalizeVector(GLfloat vNormal[]); void gltScaleVector(GLfloat vVector[], const GLfloat fScale); void gltGetPlaneEquation(GLfloat vPoint1[], GLfloat vPoint2[], GLfloat vPoint3[], GLfloat vPlane[]); GLfloat gltGetVectorLength(const GLfloat vVector[]); GLfloat gltGetVectorLengthSqrd(const GLfloat vVector[]); // Para realizar la rotación static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; GLfloat LuzPosicion[4] = {-75, 150.0f, 0, 0.0f }; // Una matriz de transformación para proyectar la sombra GLfloat shadowMat[16]; //cualquier de estos tres puntos en el suelo(en el sentido contrario a las agujas del reloj) GLfloat points[3][3] = {{ -30.0f, -149.0f, -20.0f },{ -30.0f, -149.0f, 20.0f }, { 40.0f, -149.0f, 20.0f }}; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Resize(TObject *Sender) {

glViewport(0,0,OpenGLPanel1->ClientWidth,OpenGLPanel1->ClientHeight); } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender) { glEnable(GL_DEPTH_TEST); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_LIGHT0); // color de fondo glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); //cálculo de la matriz de proyección para dibujar la sombra en el suelo gltMakeShadowMatrix(points, LuzPosicion, shadowMat); //funcion que dibuja el avión Sombra(); } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender) { int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; GLfloat fAspect; if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); fAspect = (GLfloat)w/(GLfloat)h; gluPerspective(60.0f, fAspect, 200.0, 500.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Mover en el eje z para que se pueda ver glTranslatef(0.0f, 0.0f, -400.0f);

Page 80: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

80

glLightfv(GL_LIGHT0,GL_POSITION,LuzPosicion); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { OpenGLPanel1->Width=Form1->Width; OpenGLPanel1->Height=Form1->Height; xRot = 0.0f; yRot = 0.0f; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { OpenGLPanel1->Width=Form1->Width; OpenGLPanel1->Height=Form1->Height; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void TForm1::Sombra() { // Borrar la ventana con el borrado actual glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Base(); // guardar el estado de la matriz y efectuar rotaciones glPushMatrix(); //dibujar el avión en la nueva orientación, situar la luz en la posición correcta antes de girar el avión glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0,GL_POSITION,LuzPosicion); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); Dibujo(0); // Reestablecer el estado de la matriz original glPopMatrix();

//Prepararse para dibujar la sombra del suelo //Desactiva la iluminación primero y guardad el estado de la proyección glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glPushMatrix(); // Multiplicar por la matriz de proyección de sombra glMultMatrixf((GLfloat *)shadowMat); // Girar ahora el avión en el espacio recién aplastado glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Pasar 1 para indicar dibujo de sombra Dibujo(1); // Reestablecer la proyección normal glPopMatrix(); // Dibujar la fuente de luz glPushMatrix(); Sol(); glPopMatrix(); // Reestablecer las variables de estado de iluminación glEnable(GL_DEPTH_TEST); } void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key) { if(Key ==(char)"A") xRot-= 5.0f; if(Key == (char)"B") xRot += 5.0f; if(Key == (char) "C") yRot -= 5.0f; if(Key == (char) "D") yRot += 5.0f; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar1Change(TObject *Sender) {

Page 81: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

81

xRot=ScrollBar1->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { yRot=ScrollBar2->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void TForm1::Dibujo(int Tipo) { if(Tipo == 0) glColor3ub(128, 128, 128); else glColor3ub(0,0,0); if(RadioButton2->Checked==true) glutWireSphere(15,15,15); if(RadioButton3->Checked==true) glutWireTeapot(25); } //crea una matriz de proyección de sombra a partir de los coeficientes //de la ecuación del plano y de la posición de la luz, el valor devuelto se guarda en destMat //------------------------------------------------------------------------------- void gltMakeShadowMatrix(GLfloat vPoints[3][3], GLfloat vLightPos[4], GLfloat destMat[16]) { GLfloat vPlaneEquation[4]; GLfloat dot; gltGetPlaneEquation(vPoints[0], vPoints[1], vPoints[2], vPlaneEquation); // punto producto del plano y de la posición de la luz dot = vPlaneEquation[0]*vLightPos[0] + vPlaneEquation[1]*vLightPos[1] + vPlaneEquation[2]*vLightPos[2] + vPlaneEquation[3]*vLightPos[3];

// Realizar ahora la proyección // primer columna destMat[0] = dot - vLightPos[0] * vPlaneEquation[0]; destMat[4] = 0.0f - vLightPos[0] * vPlaneEquation[1]; destMat[8] = 0.0f - vLightPos[0] * vPlaneEquation[2]; destMat[12] = 0.0f - vLightPos[0] * vPlaneEquation[3]; // Segunda columna destMat[1] = 0.0f - vLightPos[1] * vPlaneEquation[0]; destMat[5] = dot - vLightPos[1] * vPlaneEquation[1]; destMat[9] = 0.0f - vLightPos[1] * vPlaneEquation[2]; destMat[13] = 0.0f - vLightPos[1] * vPlaneEquation[3]; //Tercer columna destMat[2] = 0.0f - vLightPos[2] * vPlaneEquation[0]; destMat[6] = 0.0f - vLightPos[2] * vPlaneEquation[1]; destMat[10] = dot - vLightPos[2] * vPlaneEquation[2]; destMat[14] = 0.0f - vLightPos[2] * vPlaneEquation[3]; // Cuarta columna destMat[3] = 0.0f - vLightPos[3] * vPlaneEquation[0]; destMat[7] = 0.0f - vLightPos[3] * vPlaneEquation[1]; destMat[11] = 0.0f - vLightPos[3] * vPlaneEquation[2]; destMat[15] = dot - vLightPos[3] * vPlaneEquation[3]; } //------------------------------------------------------------- //// Gets the three coefficients of a plane equation given three points on the plane. void gltGetPlaneEquation(GLfloat vPoint1[], GLfloat vPoint2[], GLfloat vPoint3[], GLfloat vPlane[]) { // Get normal vector from three points. The normal vector is the first three coefficients // to the plane equation...

Page 82: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

82

gltGetNormalVector(vPoint1, vPoint2, vPoint3, vPlane); // Final coefficient found by back substitution vPlane[3] = -(vPlane[0] * vPoint3[0] + vPlane[1] * vPoint3[1] + vPlane[2] * vPoint3[2]); } //------------------------------------ // Given three points on a plane in counter clockwise order, calculate the unit normal void gltGetNormalVector(const GLfloat vP1[], const GLfloat vP2[], const GLfloat vP3[], GLfloat vNormal[]) { GLfloat vV1[3], vV2[3]; gltSubtractVectors(vP2, vP1, vV1); gltSubtractVectors(vP3, vP1, vV2); gltVectorCrossProduct(vV1, vV2, vNormal); gltNormalizeVector(vNormal); } //------------------------------ // Subtract one vector from another void gltSubtractVectors(const GLfloat vFirst[], const GLfloat vSecond[], GLfloat vResult[]) { vResult[0] = vFirst[0] - vSecond[0]; vResult[1] = vFirst[1] - vSecond[1]; vResult[2] = vFirst[2] - vSecond[2]; } //--------------------------------------------- // Calculate the cross product of two vectors void gltVectorCrossProduct(const GLfloat vU[], const GLfloat vV[], GLfloat vResult[]) { vResult[0] = vU[1]*vV[2] - vV[1]*vU[2]; vResult[1] = -vU[0]*vV[2] + vV[0]*vU[2]; vResult[2] = vU[0]*vV[1] - vV[0]*vU[1]; } //---------------------- // Scales a vector by it's length - creates a unit vector void gltNormalizeVector(GLfloat vNormal[]) { GLfloat fLength = 1.0f / gltGetVectorLength(vNormal); gltScaleVector(vNormal, fLength); }

//---------------------------- // Scales a vector by a scalar void gltScaleVector(GLfloat vVector[], const GLfloat fScale) { vVector[0] *= fScale; vVector[1] *= fScale; vVector[2] *= fScale; } ///----------------------------- // Gets the length of a vector GLfloat gltGetVectorLength(const GLfloat vVector[]) { return (GLfloat)sqrt(gltGetVectorLengthSqrd(vVector)); } //---------------------------------------------------------- // Gets the length of a vector squared GLfloat gltGetVectorLengthSqrd(const GLfloat vVector[]) { return (vVector[0]*vVector[0]) + (vVector[1]*vVector[1]) + (vVector[2]*vVector[2]); } //-------------------------- void Base() { //dibujar el suelo creamos manualmente una sombra con un verde //más oscuro en el suelo para dar la ilusión de profundidad glBegin(GL_QUADS); glColor3ub(0,32,0); glVertex3f(400.0f, -150.0f, -200.0f); glVertex3f(-400.0f, -150.0f, -200.0f); glColor3ub(0,255,0); glVertex3f(-400.0f, -150.0f, 200.0f); glVertex3f(400.0f, -150.0f, 200.0f); glEnd(); } //-------------- void Pinata() { glutSolidSphere(15, 30, 30); } //------------------------------------- void Sol() { glTranslatef(LuzPosicion[0],LuzPosicion[1], LuzPosicion[2]); glColor3ub(255,255,0); glutSolidSphere(15, 30, 30); }

Page 83: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

83

void __fastcall TForm1::RadioButton3Click(TObject *Sender) { OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioButton2Click(TObject *Sender) { OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::RadioButton1Click(TObject *Sender) { OpenGLPanel1->Invalidate(); }

void __fastcall TForm1::ScrollBar3Change(TObject *Sender) { LuzPosicion[0]=ScrollBar3->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar4Change(TObject *Sender) { LuzPosicion[1]=ScrollBar4->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar5Change(TObject *Sender) { LuzPosicion[2]=ScrollBar5->Position; OpenGLPanel1->Invalidate(); }

La función gltMakeShadowMatrix(), calcula la matriz de proyección, ésta función puede descargarse directamente de la página del autor Richard S. Wright: http://www.1av10.nu/~gerry/c/common/MatrixMath.c.

Page 84: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

84

Práctica número 20: Transparencia Objetivo: Agregar reflejo a los gráficos usando transparencia El reflejo es un efecto que permite dar una apariencia más real a los objetos graficados, para conseguir el efecto se utiliza la transparencia de la superficie reflectante, en OpenGL para generar el efecto se deben seguir los siguientes pasos:

1. Graficar el objeto de fondo (reflejo) 2. Graficar la superficie reflectante 3. Graficar de forma normal el objeto

Ejemplo, graficar una tetera con reflejo, figura 44, se grafica una tetera (fondo) con orientación inversa para dar el efecto de reflejo, enseguida se grafica la superficie que hará el papel de reflejo y por último sobre la superficie se grafica nuevamente la tetera de forma norma.

Figura 44. Usando transparencia para obtener el efecto reflejo.

El código correspondiente a la figura 44 es: include <vcl.h> #pragma hdrstop #include "Unit1.h" #include<gl/glut.h> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "OpenGLPanel"

#pragma resource "*.dfm" TForm1 *Form1; void DrawGround(void); //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)

Page 85: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

85

{ } //--------------------------------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender) { int w=OpenGLPanel1->Width; int h=OpenGLPanel1->Height; GLfloat fAspect; if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); fAspect = (GLfloat)w/(GLfloat)h; gluPerspective(60.0f, fAspect, 1.0, 300.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Mover en el eje z para que se pueda ver glTranslatef(0.0f, 0.0f, -100.0f); glEnable(GL_DEPTH_TEST); //color (RGB)del área de trabajo, glClearColor(0.0f,0.0f,1.0f,1.0); } //-------------------------------------------------- void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(5, 1.0f, 0.0f, 0.0f); glRotatef(5, 0.0f, 1.0f, 0.0f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glColor3f(1,0,0); Ejes(); //Para conseguir el efecto se requiere de dibujar el objeto de fondo, enseguida el de transparencia //Mover la luz debajo del suelo a la luz del objeto reflejado

glPushMatrix(); glFrontFace(GL_CW); glScalef(1,-1,1); glColor3f(0,0,0); Escena(); //fondo glFrontFace(GL_CCW); glPopMatrix(); //Dibujar el suelo transparente sobre el reflejo glDisable(GL_LIGHTING); glEnable(GL_BLEND); //fundido de color glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //efecto de dibujar un objeto transparente delante de algún objeto opaco glColor4f(0.5,0.5,0.5,0.5); Suelo(); //transparencia glColor4f(1,0,0,0.5); glDisable(GL_BLEND); glEnable(GL_LIGHTING); // Dibujar escena glColor3f(0,0,0); Escena(); // el objeto normal glPopMatrix(); } //--------------------------- void TForm1::Escena() { glTranslatef(0,30,0); // glutSolidSphere(20,30,30); glutWireTeapot(24); } //--------------------- void TForm1::Ejes() { glBegin(GL_LINES); glVertex3f(-200,0,0); glVertex3f(200,0,0); glVertex3f(0,-200,0); glVertex3f(0,200,0); glVertex3f(0,0,-200); glVertex3f(0,0,200); glEnd();

Page 86: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

86

} //--------------------------------------- void TForm1::Suelo() { glBegin(GL_QUADS); glVertex3f(200,0,200); glVertex3f(200,0,-200); glVertex3f(-200,0,-200); glVertex3f(-200,0,200); glEnd(); } //--------------------------------------------------------------------------- void DrawGround(void) { GLfloat fExtent = 200.0f; GLfloat fStep = 5; GLfloat y = 0.0f; GLfloat fColor; GLfloat iStrip, iRun; GLint iBounce = 0; glShadeModel(GL_FLAT); for(iStrip = -fExtent; iStrip <= fExtent; iStrip += fStep) { glBegin(GL_TRIANGLE_STRIP); for(iRun = fExtent; iRun >= -fExtent; iRun -= fStep) { if((iBounce %2) == 0) fColor = 1.0f; else

fColor = 0.0f; glColor4f(fColor, fColor, fColor, 0.5f); glVertex3f(iStrip, y, iRun); glVertex3f(iStrip + fStep, y, iRun); iBounce++; } glEnd(); } glShadeModel(GL_SMOOTH); } void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { xRot=ScrollBar1->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { yRot=ScrollBar2->Position; OpenGLPanel1->Invalidate(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { xRot=0; yRot=0; } //-----------------------------------------------------------

//-------------------------------------------------------------- Para que un objeto sea transparente se debe especificar la transparencia en la función glColor() en el cuarto argumento, para el ejemplo anterior antes de graficar el rectángulo (superficie transparente), a glColor4f(1,0,0,0.5); se modificó el cuarto argumento a un valor de 0.5 correspondiente a transparencia.

Page 87: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

87

Page 88: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

88

Page 89: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

89

Page 90: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

90

Page 91: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

91

Page 92: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

92

Page 93: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

93

Page 94: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

94

Conclusiones Para graficar se requieren de dos elementos básicos, conocer la herramienta para graficar; puede ser OpenGL, ActiveX u otro, y la creatividad para embonar figuras básicas, como puntos, líneas, triángulos, rectángulos, esferas, etc. que en conjunto representen un excelente gráfico, tal como los ejemplos anteriores. Los efectos 3D, color, iluminación, sombra, transparencia, sin duda alguna ayudan a tener gráficos con mayor realismo, otros no presentados en este manual son suavizado de bordes, texturas, manejo de líneas y superficies, música, etc. Este manual fue presentado con el fin de fomentar el arte por el manejo de los gráficos y para incrementar el acervo bibliográfico con material de calidad y utilidad.

Page 95: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

95

Agradecimientos

A la Universidad del Mar, campus Puerto Escondido, por facilitarnos tiempo, instalaciones y recursos económicos para la realización de este manual. Un especial agradecimiento a los alumnos que colaboraron en la realización de los gráficos presentados en la portada y ejemplos: Aarón, David, Darwin, Elizabeth, José y Omar, quienes dedicaron su mejor esfuerzo y muchas horas de trabajo. Por último, pero no menos importante un agradecimiento a mi familia; mi hija Azul, mi esposa, mis padres y hermanos, por su tiempo y compresión.

Page 96: MANUAL Versión1

________________________________________________________________________________________

______________________________________________________________________ M.C. Isidro Moctezuma Cantorán

96

Bibliografía

Programación OpenGL, Richard S. Wringht / Benjamín Lipchak, Anaya

Multimedia, 2005.

Programación C++ Builder 5, Programación, Francisco Charte, Anaya Multimedia, 2006.

Gráficos por computadora con OpenGL, Donald Hearn, M. Pauline Baker,

Prentice Hall, 2006.

http://www.opengl.org, 2008.

http://www.1av10.nu/~gerry/c/common/MatrixMath, 2008