UNIVERSIDAD AUSTRAL DE CHILE SEDE PUERTO MONTT ESCUELA DE INGENIERIA EN COMPUTACION

Integración de Tecnologías .Net y OpenGL, Aplicadas al Desarrollo de un Editor para Escenarios 3D.

Seminario de Titulación para optar al título de Ingeniero en Computación

PROFESOR PATROCINANTE: Sr. Mauricio Henríquez Schott CO-PATROCINANTE: Sr. Pablo Mansilla Ojeda

Felipe Andrés Morales Saldivia PUERTO MONTT - CHILE 2008-2009

A Mi Madre por su apoyo incondicional... Agradezco públicamente a las siguientes personas:

Al Sr. Mauricio Henríquez Schott por guiarme durante el desarrollo del presente proyecto.

Al Sr. Pablo Mansilla Ojeda por apoyarme en la realización de este proyecto.

Muchas Gracias INDICE

Síntesis Abstract 1. Introducción ...... 1 2. Planteamiento del problema ...... 5 2.1 Antecedentes ...... 5 2.1.1 Definición del problema ...... 5 2.1.2 Esfuerzos anteriores ...... 23 2.1.3 Solución Propuesta ...... 29 2.2 Justificación ...... 31 2.2.1 Situación sin proyecto: ...... 31 2.2.2 Situación con proyecto: ...... 31 2.3 Delimitación ...... 32 3. Objetivos ...... 34 3.1 Objetivo General ...... 34 3.2 Objetivos Específicos ...... 34 4. Metodología ...... 35 5. Plan de Trabajo y Cronograma ...... 39 5.1 Actividades ...... 39 5.2 Carta Gantt ...... 42 6. Recursos...... 43 6.1 Hardware ...... 43 6.2 Software ...... 43 7. Análisis de la Solución ...... 44 7.1 Descripción de la solución ...... 44 7.1.1 Módulo Editor 3D...... 45 7.1.1.1 Caso de uso: Crear/Editar/Eliminar Mundo...... 46 7.1.1.2 Caso de uso: Crear/Editar/Eliminar Objeto...... 49 7.1.1.3 Caso de uso: Crear/Editar/Eliminar Luz...... 52 7.1.1.4 Caso de uso: Nueva/Guardar/Cargar Escena...... 53 7.1.2 Módulo Generador de Código Fuente...... 54 7.1.2.1 Caso de uso: Generar código Fuente Escena...... 54 7.2 Establecimiento de herramientas de desarrollo ...... 55

7.3 Investigación de Tecnologías ...... 56 7.3.1 ...... 56 7.3.2 Visual Studio 2008 ...... 59 7.3.3 Microsoft .NET Framework versión 2.0 (x86)...... 59 6.3.4 Tecnología de desarrollo basadas Reflection de Plataforma .NET...... 60 7.3.5 Tecnología XML 1.0...... 61 7.3.6 2.4 y MonoDevelop 2.0...... 62 7.4 Validación de Requerimientos ...... 63 8. Diseño de la Solución ...... 64 8.1 Diagrama de clases ...... 65 8.2 Diccionario de clases de editor OpenGL ...... 66 8.4 Casilla de Responsabilidades...... 144 8.5 Diagrama de Procesos...... 145 8.5.1 Diagrama de Proceso Creación y edición de un Objeto 3D...... 145 8.5.2 Diagrama de Proceso Guardar escena...... 147 8.5.3 Diagrama de Proceso Cargar escena...... 148 8.5.4 Diagrama de Proceso Generación código Fuente de la escena Diseñada con el Editor 3D...... 149 8.5.5 Diagrama de Proceso de Selección de objetos Mediante el Mouse...... 150 9. Construcción del Software ...... 152 9.1 Construcción Aplicación versión Beta (solo Funcionalidad de Editor 3D)...... 152 9.1.1 Construir una ventana que despliegue un Objeto en el mundo. 152 9.1.2 Capacidad de agregar en forma dinámica objetos al mundo y además que se desplieguen...... 154 9.1.3 Crear una clase que ofrezca Primitivas OpenGL personalizadas...... 154 9.1.4 Definir tipos Objetos que derivan de Entity...... 155 9.1.5 Crear interfaz visual y lógica para creación de Objetos...... 156 9.1.6 Exhibir las propiedades del mundo y objetos en una paleta de propiedades...... 158 9.1.7 Seleccionar el mundo o los objetos desplegados en la ventana mediante el Mouse...... 159 9.1.8 Trasladar/Rotar/Escalar objetos en forma dinámica mediante el Mouse y Paleta de Propiedades...... 165 9.1.9 Trasladar/Rotar la cámara en forma dinámica mediante el Mouse y Paleta de Propiedades...... 169

9.1.10 Selección de cámaras...... 170 9.1.11 Crear una interfaz visual para la aplicación...... 171 9.1.12 Aplicar Texturas a Objetos de tipo Entity...... 177 9.1.13 Construir funcionalidad que permita crear Objetos Entity compuestos de Otros...... 180 9.1.14 Construir Funcionalidad que permita aplicar planos de corte a objetos de tipo Entity...... 181 9.1.15 Construir funcionalidad que permita crear y editar fuentes de Luz...... 183 9.1.16 Construir funcionalidad que permita editar el mundo y sus Objetos mediante el teclado...... 186 9.1.17 Construir funcionalidad que permita revisar la escena mediante una animación Básica que rote la cámara por la escena...... 190 9.1.18 Construir funcionalidad que permita guardar y cargar la escena mediante el uso de la Tecnología Xml...... 191 9.1.19 Integración de funcionalidades...... 199 9.2 Construcción aplicación versión Final (Editor 3D + Generador de código Fuente)...... 202 9.2.1 Generador de clase que despliegue la escena diseñada con la aplicación...... 202 9.2.2 Generador de Proyecto .Net que despliegue la escena diseñada con la aplicación...... 207 10. Pruebas ...... 209 10.1 Conceptos generales de las pruebas realizadas...... 209 10.1.1 Pruebas de Unidad...... 209 10.1.2 Pruebas de Integración...... 209 10.1.3 Pruebas de Sistema y Evaluación...... 210 10.2 Plan de pruebas...... 211 10.2.1 Pruebas Funcionales...... 211 10.2.2 Estrategias de las Pruebas...... 212 10.2.3 Tipos de Pruebas...... 213 11. Conclusiones y Recomendaciones ...... 215 12. Bibliografía ...... 224 13. Anexos ...... 226

Síntesis

El objetivo de este seminario es el desarrollo de un editor de gráficos 3D con funcionalidad de exportación del modelo a código fuente # y OpenGL, lo cual implica:

 Construcción de un software para diseño 3D usando la API OpenGL, que

ofrezca las funcionalidades básicas y comunes a todos los software de

diseño de este tipo.

 Construcción de un módulo que permita exportar el código de la escena

diseñada al formato nativo de llamadas a funciones, tipos y estructuras

de la librería 3D.

 Desarrollar el software siguiendo un estándar de definición de interfaces

entre clases, lo cual permitirá que la escena generada sea consumible

por otros procesos.

 Utilización de herramientas y técnicas de programación de punta para

este tipo de desarrollos, como Reflection y XML, entre otras.

Para este seminario de Titulación, la metodología elegida es XP

(eXtreme Programming), esto basándose en la naturaleza del proyecto, se decidió usar una metodología ágil, y dentro de éstas XP es una de las mejores evaluadas.

El desarrollo de esta aplicación proporcionó como producto un entorno de diseño de escenarios en tres dimensiones, el cual puede ser utilizado en entornos matemáticos, robótica y propósito general, con el cual el desarrollador puede sin ser experto en OpenGL, diseñar modelos complejos, que sin la ayuda de esta herramienta le sería muy arduo.

Otro producto obtenido del desarrollo de esta aplicación fue la encapsulación de la dificultad del trabajo con OpenGL, ya que parte de esta aplicación dió como producto una biblioteca de clases llamada ZeroFxCore, la cual permite crear desde escenarios simples hasta complejos, esto sin necesidad de usar la aplicación propiamente tal. Además, con el uso de biblioteca antes mencionada, el diseño de las escenas en forma programática reduce drásticamente la cantidad de líneas de código, con lo cual se puede concluir, que el uso de la librería ZeroFxCore dá como resultado una disminución del código necesario para desplegar una primitiva, en una escala promedio de 5 es a 1.

Finalmente, relacionada con la extensibilidad de la aplicación, queda totalmente abierta para agregar nuevas funcionalidades tales como aplicación de Físicas, Animaciones avanzadas, aplicación de motor de partículas entre otras muchas funcionalidades aplicables, por lo cual a juicio del alumno tesista es un muy buen tema a retomar como parte una nueva tesis.

Abstract

The objective of this seminar is the development of a 3D graphics editor with the functionality to export the model to C# code and OpenGL, which involves:

 Construction of a 3D design software using the OpenGL API that provides

basic functionality common to all the design software of this type.

 Construction of a module that allows to the designed scene be exported

to native format functions calls, types and structures of the 3D .

 Software Developing using standard interfaces definitions between

classes, which allow the generated scene to be consumed by other

processes.

 Use of tools and cutting edge programming techniques for such

developments, such as Reflection and XML, among others.

For this project, the chosen methodology was XP (eXtreme

Programming), that based on the nature of the project, we decided to use an agile methodology, and within these XP is one of the best evaluated.

The development of this application provides as a product an environment for three dimensions scene design, that can be used in

mathematical environments, robotics and general purpose, with which the developer without been and OpenGL expert can designing complex models, without the help of this tool will be very hard.

Another product of the development of this application was the OpenGL difficulty encapsulation, as part of this application a class library called

ZeroFxCore was produced, which allows the creation from simple to complex scenarios, without using the application itself. Furthermore, the use of the library mentioned above, the design of programmatically scenes drastically reduces the amount of code lines, so that it can be concluded that the use of the library

ZeroFxCore results in a decrease of the code for deploy a primitive, on a average scale of 5 to 1.

Finally, related to the extensibility of the application, is completely open to add new functionality such as application of Physics, advanced Animations, particle engine among many other features, so the view of the thesis student is that it is a very good topic for further thesis works.

1. Introducción

La computación gráfica se centra en el estudio, diseño y visualización de imágenes por computadora. Entre las principales áreas de aplicación se encuentran: el diseño asistido por computador (CAD - Computer Assisted

Design), gráficos interactivos (IG - Interactive Graphics), manufactura asistida por computador (CAM - Computer Assisted Manufacturing), graficación interactiva en los negocios, estadística, cartografía, arte, sistemas multimediales, entretenimiento, medicina, simulación y animación para visualización científica, entre otras.

El área de aplicación que se abordará con el desarrollo de éste proyecto es el CAD. Dentro de los problemas que se encuentran en él, tenemos que para su desarrollo y estudio, se deben usar complejas APIs (Application Program

Interface, Interfaz para programas de Aplicación, por sus siglas en inglés) o también llamada librerías gráficas, que requieren un conocimiento avanzado de programación y manejo de la misma. No obstante, existen herramientas que permiten a un usuario sin experiencia usar todas las características de estas librerías, sin embargo enmascaran en su totalidad el manejo de éstas, no permitiendo que el usuario o programador, conozca el funcionamiento de las mismas; además, impiden la reutilización de las llamadas nativas generadas

1

internamente por la herramienta, esto debido a que trabajan con formatos de archivos propietarios, los cuales son interpretados sólo por la aplicación.

En el siguiente documento se describirá como se pretende abordar el problema, para lo cual, en la primera parte se estudiarán algunas APIs disponibles y sus características, además se expondrá algunos editores 3D para su manipulación, se explicará porque se hace necesario el uso de éstos y también se mostrarán algunos Engines o “Motores Gráficos”, los cuales se presentan como otra opción para la manipulación de las APIs. Tanto para los editores 3D como para los motores gráficos, se expondrán sus características, ejemplos, ventajas y desventajas. En especial se analizará el porqué se imposibilita al programador tomar el código fuente generado internamente por la herramienta para ser usado directamente, lo cual se pretende solucionar con el desarrollo del proyecto.

También se abordarán los esfuerzos anteriores en cuanto a lo que herramientas exportadoras de tipos y estructuras de datos de modelos hechos con editores 3D o Engines se refiere. Sin embargo, este tipo de herramientas tampoco se presentan como una solución completa al problema que se pretende resolver en términos de la exportación de código fuente y llamadas nativas a la API.

2

Posteriormente se abordará la metodología de desarrollo de software que se uso para llevar a cabo este proyecto, se describirán las etapas de la metodología y dejará establecido los roles que cumplirán el alumno tesista y el profesor a cargo en cada una de las etapas del proyecto, además se expondrá la cronología de cada una de estas etapas, esbozada en la correspondiente carta Gantt.

En el contexto de implementación del la aplicación, se abordarán las fases de ésta, tales como análisis, la cual abordará la toma de requerimientos mediante la técnica de casos de uso, esta fase también involucra la selección de herramientas de desarrollo lo cual se abordará mediante una adecuada investigación de las herramientas que finalmente fueron seleccionadas.

Otra etapa de la implementación que se abordará es el diseño, la cual describirá y mostrará diversos diagramas de diseño necesarios para la correcta construcción de la aplicación.

Posteriormente, se describirá paso a paso la fase de construcción del software, esta etapa y las antes nombradas (análisis, diseño) esta dirigidas por la metodología XP.

3

Finalmente, en el contexto de implementación, se abordará la etapa de pruebas, la cual describirá las diversas pruebas a las que fue sometida la aplicación para asegurar su correcto desempeño y funcionamiento.

4

2. Planteamiento del problema

2.1 Antecedentes

2.1.1 Definición del problema

Hoy las gráficas tridimensionales son usadas en un gran número de ambientes, que van desde su uso en la cinematografía, video juegos y simulación, hasta el diseño gráfico asistido por computadora, CAD (Computer

Assisted Design, Diseño Asistido por Computador, por sus siglas en inglés).

Las dos APIs para desarrollo de gráficas 3D más populares son DirectX de Microsoft y OpenGL, originalmente de Silicon Graphics. Las diferencias entre ambas librerías, van desde las estructuras internas utilizadas, lógica que se emplea para su manipulación, hasta la forma en la que se distribuyen; por ejemplo mientras que OpenGL es un software libre y gratuito, soportado por un gran número de empresas, desarrolladores y usuarios; para DirectX, se deben pagar licencias para su utilización y además, la comunidad de programadores y empresas es menor.

5

Las grandes empresas que requieren de diseño gráfico, especialmente

3D, si bien utilizan las dos APIs antes mencionadas, por lo general no trabajan con estas a nivel de lenguaje nativo (directamente con la librería que implementa la API en particular), sino más bien usando software de interfaz gráfica para su manipulación, tales como “Maya” o “3D Studio Max”, los cuales son softwares comerciales, y sus licencias, en sus versiones más básicas, no bajan de los $500 mil pesos chilenos o 800 euros, aún cuando también existen versiones libres u OpenSource ampliamente difundidas como “Blender”, por ejemplo.

Éste tipo de software, permite a un usuario sin experiencia en programación, a través del Mouse, teclado y otros dispositivos de entrada, diseñar complejos entornos 3D, incluyendo las animaciones de movimientos necesarias. Posteriormente, de ser requerido, a estas escenas tridimensionales, se le puede agregar lógica de comportamiento a través de programación especializada.

Dentro de las alternativas gratuitas se encuentra la anteriormente mencionada “Blender”, el cual es un programa multiplataforma, dedicado especialmente al modelado y creación de gráficos tridimensionales. Este programa fue inicialmente distribuido de forma gratuita, pero sin el código fuente, con un manual disponible para la venta. Actualmente “Blender” es

6

totalmente Opensource, cabe destacar que es compatible con todas las versiones de Windows, Mac OS X, Linux, Solaris, FreeBSD e IRIX.

Actualmente, se está llevando a cabo la producción del primer largometraje animado realizado íntegramente con Software Libre, usando a

“Blender” como herramienta principal. Se trata de “Plumíferos”, proyecto que está impulsando aun más el desarrollo de este programa, sobre todo a nivel de animación y manejo de librerías a gran escala. Se espera el estreno de este film durante el 2009.

Dentro de las alternativas comerciales como se mencionó anteriormente, se tiene a “Autodesk 3D Studio Max”, el cual es un programa de creación de gráficos y animación 3D desarrollado por Autodesk Media & Entertainment

(anteriormente conocidos como Discreet y Kinetix). Fue desarrollado como sucesor para sistemas operativos Win32 del 3D Studio creado para DOS.

Kinetix fue más tarde fusionada con la última adquisición de Autodesk, Discreet

Logic.

“3D Studio Max” es uno de los programas de animación 3D más utilizados, dispone de una sólida capacidad de edición, una potente arquitectura de plugins y una larga tradición en plataformas , este programa es utilizado en mayor medida por los desarrolladores de videojuegos,

7

aunque también lo es en el desarrollo de proyectos de animación, como películas o anuncios de televisión, efectos especiales y en arquitectura en general.

La siguiente figura, muestra la interfaz de “3D Studio Max” (Figura 1), con simples selecciones y movimientos del mouse o uso del teclado podemos diseñar escenarios partir de figuras predefinidas (elipse en la imagen).

Figura 1

8

En la siguiente figura (Figura 2), podemos ver como se ha modelado un

Bolígrafo usando 3D Studio Max a partir de objetos predefinidos tales como cilindros, discos, conos, esferas, cajas y otros objetos. Además, después de terminar de agregar los objetos necesarios para crear el bolígrafo, podemos agregar texturas a éstos para mejorar aun más el detalle del modelo.

Figura 2

9

El problema es, que desde el punto de vista del programador, una de las desventajas principales de este tipo de software para asistir el diseño 3D, además de su alto costo en el caso de las versiones comerciales, es el hecho de que una vez que está la escena terminada o lista para agregar lógica de programación adicional, el software de diseño no entrega las llamadas a la API nativa (OpenGL o DirectX), sino que trabajan con formatos de archivos propietarios, los cuales son interpretados sólo por la aplicación misma. Por lo cual, para poder trabajar con la escena generada, se debe pagar o desarrollar complejos parseadores o exportadores que obtengan las estructuras y tipos nativos de la librería.

A continuación, se mostrará una sección de un archivo de 3D Studio

Max, el cual representa el diseño de un cubo (box). Mediante comentarios se distinguirán las secciones más relevantes de este archivo.

10

*3DSMAX_ASCIIEXPORT 200 *COMMENT "AsciiExport Version 2,00 - Sun May 11 14:51:21 2008" //configuración del escenario *SCENE { *SCENE_FILENAME "Box.max" *SCENE_FIRSTFRAME 0 *SCENE_LASTFRAME 100 *SCENE_FRAMESPEED 30 *SCENE_TICKSPERFRAME 160 *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000 *SCENE_AMBIENT_STATIC 0.0000 0.0000 0.0000 } //sección de materiales *MATERIAL_LIST { *MATERIAL_COUNT 0 } //definición del objeto Box01 *GEOMOBJECT { *NODE_TM { *NODE_NAME "Box01"//nombre del objeto *INHERIT_POS 0 0 0 *INHERIT_ROT 0 0 0 *INHERIT_SCL 0 0 0 *TM_ROW0 0.9476 -0.3154 0.0514 *TM_ROW1 0.3157 0.9488 0.0020 *TM_ROW2 -0.0494 0.0144 0.9987 *TM_ROW3 -1.0049 -1.7364 0.0000 *TM_POS -1.0049 -1.7364 0.0000//posición del objeto *TM_ROTAXIS 0.0194 0.1576 0.9873//rotaciones del objeto *TM_ROTANGLE 0.3253 //cantidad de rotación *TM_SCALE 1.0000 1.0000 1.0000//escala del objeto *TM_SCALEAXIS 0.0000 0.0000 0.0000//escala de los ejes *TM_SCALEAXISANG 0.0000 //del objeto } //mapeado de los vértices del objeto *MESH { *TIMEVALUE 0 *MESH_NUMVERTEX 8 *MESH_NUMFACES 12 *MESH_VERTEX_LIST { *MESH_VERTEX 0 -15.0845 -11.6455 -0.5533 *MESH_VERTEX 1 4.3299 -18.1078 0.4991 *MESH_VERTEX 2 -6.3397 14.6349 -0.4991 *MESH_VERTEX 3 13.0747 8.1727 0.5533 *MESH_VERTEX 4 -15.9390 -11.3969 16.7365 *MESH_VERTEX 5 3.4754 -17.8592 17.7889 *MESH_VERTEX 6 -7.1942 14.8836 16.7907 *MESH_VERTEX 7 12.2202 8.4213 17.8431 }

} *PROP_MOTIONBLUR 0 *PROP_CASTSHADOW 1 *PROP_RECVSHADOW 1 *WIREFRAME_COLOR 0.6941 0.5804 0.1059//color del objeto }

11

Como se puede ver, en este archivo existen secciones con información respecto a la escena, materiales y objetos, en éste caso en particular con el objeto “Box01”, en la sección del objeto podemos distinguir:

 NODE_NAME: nombre del objeto.

 TM_POS: posición del objeto en coordenadas xyz.

 TM_SCALE: escala del objeto en los ejes xyz.

 TM_SCALEAXIS: escala de los ejes xyz del objeto.

 TM_ROTAXIS: proporción en que esta rotado el objeto en los ejes xyz.

 TM_ROTANGLE: ángulo en que esta rotado el objeto.

 WIRE_FRAME_COLOR: color del objeto en los tres componentes RGB.

 MESH: en esta sección va todo lo referente a los vértices del objeto con

los cuales se construye.

Otra característica de este archivo, es que la jerarquía de objetos se representa mediante nodos los cuales son parte de un árbol.

Como se mostró anteriormente para un único objeto, la cantidad de información es abundante, además ésta no es análoga a ningún lenguaje de programación, ni llamadas nativas de alguna librería gráfica, por lo tanto para utilizar el diseño, en alguna aplicación que lo requiera, se hace necesario un parseador o exportador, que convierta la información desde el archivo hasta

12

algún lenguaje de programación agregando las llamadas nativas de alguna librería gráfica (OpenGL o DirectX).

El archivo generado por 3D Studio Max (.3DS) ya es un formato que se puede considerar como estándar en el mundo 3D, ya que prácticamente no hay software que no sea compatible con éste, Lightwave, Maya, 3D Studio MAX,

Truespace, Blender.

Para que quede aún más clara la nula similitud entre la estructura del archivo Max y las llamadas nativas en OpenGL, se mostrará el código necesario para construir un cubo de 6 caras, al igual que en el ejemplo con 3D Studio

Max.

//Método que construye un cubo public static void RenderCube(double x) { Gl.glPushMatrix(); RenderSquare(x); // llamada a método que construye el cuadrado 1 Gl.glRotated(90, 1, 0, 0); RenderSquare(x); // llamada a método que construye el cuadrado 2 Gl.glRotated(90, 1, 0, 0); RenderSquare(x); // llamada a método que construye el cuadrado 3 Gl.glRotated(90, 1, 0, 0); RenderSquare(x); // llamada a método que construye el cuadrado 4 Gl.glRotated(90, 0, 1, 0); RenderSquare(x); // llamada a método que construye el cuadrado 5 Gl.glRotated(180, 0, 1, 0); RenderSquare(x); // llamada a método que construye el cuadrado 6 Gl.glPopMatrix(); }

13

//Método que construye un cuadrado public static void RenderSquare(double x) { Gl.glPushMatrix(); // Se establece el método de construcción del cuadrado Gl.glBegin(Gl.GL_POLYGON); // Coordenadas vértice 1 para aplicación texturas Gl.glTexCoord2f(1.0f, 1.0f); // Coordenada vértice 1 Gl.glVertex3d(x, x, x); // Coordenadas vértice 2 para aplicación texturas Gl.glTexCoord2f(0.0f, 1.0f); // Coordenada vértice 2 Gl.glVertex3d(x, -x, x); // Coordenadas vértice 3 para aplicación texturas Gl.glTexCoord2f(0.0f, 0.0f); // Coordenada vértice 3 Gl.glVertex3d(-x, -x, x); // Coordenadas vértice 4 para aplicación texturas Gl.glTexCoord2f(1.0f, 0.0f); // Coordenada vértice 4 Gl.glVertex3d(-x, x, x); // Se finaliza la construcción del cuadrado Gl.glEnd(); Gl.glPopMatrix(); }

Durante los últimos años, se han desarrollado también “Motores

Gráficos” (Graphic Engines), especialmente diseñados para facilitar la construcción de juegos y/o simulaciones.

Estos motores gráficos, de igual forma que los software de diseño 3D antes mencionados, se basan en la utilización interna de OpenGL o DirectX, pero limitan la cantidad de acciones, sobre las figuras predefinidas u otros elementos que el programador puede realizar dentro del motor, así como

14

también limita las acciones que se pueden asociar a estas figuras (acciones predefinidas). No obstante lo anterior, si bien estos motores tienen algunas limitaciones, no es menos cierto que también incorporan muchas características ampliamente desarrolladas; tales como:

 Detección de colisiones: conjunto de algoritmos matemáticos que

nos permiten simular el comportamiento de los objetos en la realidad.

Por ejemplo, que dos objetos no se intersequen, o que un personaje

camine sobre el suelo y luego pueda subir gradas. La detección de

colisiones es un tema bastante complejo que debe estar dentro del

núcleo de cualquier motor 3D.

 Generadores de partículas: algoritmos para crear efectos mediante

el uso partículas o puntos en el espacio, con estos generan efectos

de fuego, polvo, lluvia, nieve y otros.

 Inteligencia Artificial: algoritmos para modelar el comportamiento de

los jugadores no humanos (NPC en inglés, PNJ en castellano), y para

ello la IA debe estar dentro del núcleo del motor 3D.

 Físicas: conjunto de algoritmos que buscan simular la física del

mundo real.

 Utilización de todas las capacidades de la tarjeta gráfica: los

motores gráficos se caracterizan por utilizar todas las tecnologías

disponibles al tiempo de desarrollo de éste, un caso puntual es la

15

tecnología pixel shader (abreviatura PS), la cual es un programa de

sombreado, normalmente ejecutado en la unidad de procesamiento

gráfico. En OpenGL, se conoce como fragmento de sombreado, esta

tecnología fue inmediatamente implementada por los nuevos motores

gráficos no así por los software de diseño 3D.

El objetivo principal de estos motores, es el desarrollo de video juegos, muchas de las características antes nombradas no están presentes en los editores gráficos convencionales.

Un buen ejemplo de estos motores son “UnrealEngine 3”, “CrisisEngine

2” y “Star War Unleashed Engine”, con los cuales están hechos la mayoría de los juegos conocidos como “NextGen” (juegos diseñados para las consolas y computadoras de última generación) [Edge2007] a continuación una lista de ellos.

Unreal Engine 3 [EpicGames2008]:

 Bioshock (2007) Irrational Games.

 Brothers In Arms: Hell's Highway (2007) Gearbox Software.

 Gears of War (2006) Epic Games.

 Unreal Tournament 3 (2007) Epic Games.

16

Crisis Engine 2 [CrytekGames2008]:

 Crysis (2007) Crytek.

 Entropia Universe (2008) Crytek.

El Engine de Star Wars: Force Unleashed, es el que promete revolucionar lo que se denomina Next-Gen, y que dota de un realismo nunca antes visto. Hasta acciones tan simples como las de caminar, saltar o subir unas escaleras [SerranoLobo2007].

La principal característica de este motor es que combina tres tecnologías de punta las cuales son , DMM () y .

Euphoria es una tecnología de IA (Inteligencia Artificial) aplicada a físicas, la cual se genera en tiempo real, no hay absolutamente ningún detalle que responda a scripts previstos por adelantado, que es la principal característica, la cual proporciona un realismo muy superior a lo antes visto. Un ejemplo práctico de esto es lo que ocurre al lanzar a un oponente sobre una superficie, esto tendrá decenas de resultados diferentes, además Euphoria dota a los rivales de un instinto de preservación que les empujará a tratar de tomarse de lo que tengan a mano, incluso si es otro rival. Los títulos más famosos

17

diseñados con esta Tecnología son Star Wars: Force Unleashed y Grand Theaf

Auto IV, el estreno de estos dos ocurrió durante primer semestre del 2008.

En el caso DMM (Digital Molecular Matter), su tarea se basa en representar la resistencia de los materiales de forma realista. En un juego como

Star Wars: Force Unleashed, en el que la destrucción de objetos es muy común, no se puede pasar por alto que la madera no se comporta como el metal (uno se quiebra, el otro antes se dobla). Así tenemos que nuestro personaje afecta al mundo que lo rodea y lo modifica siempre de manera diferente, según la fuerza de los impactos, el ángulo y la parte dañada, por lo cual se ha producido un gran avance tecnológico, frente al clásico objeto que siempre se destruye en el mismo lugar.

Otra tecnología de punta que ocupa el Engine de Star War: Force

Unleashed es Havok Game Dynamics SDK. Es un motor físico (simulación dinámica) utilizado en videojuegos y recrea las interacciones entre objetos y personajes del juego. Por lo que detecta colisiones, gravedad, masa y velocidad en tiempo real llegando a recrear ambientes mucho más realistas y naturales.

Havok en sus últimas versiones se ejecuta por entero por hardware mediante el uso de la GPU (procesador gráfico), liberando así de dichos cálculos a la CPU.

Este se apoya en las librerías de Direct3D y OpenGL compatibles con Shader

Model 3.0.

18

Por otra parte, cabe mencionar que existen motores que no hacen uso de las APIs convencionales. Un caso puntual de ésto, es el Cristal Tools, el cual utiliza la API Open GL/ES, que es una versión optimizada para el uso del procesador Cell Broadband (CPU PlayStation 3), la empresa desarrolladora de este motor es una de las más reconocidas en el rubro de video juegos a nivel mundial, hablamos de SquareEnix, actualmente se está desarrollando un video juego con Cristal Tools, el cual es uno de los más esperados para Playstation 3 según la opinión de expertos en el tema [Sinclair2008], este será

XIII, se espera el estreno de éste durante el año 2010 solo para esta consola.

En la siguiente figura (Figura 3), se muestra el motor del juego Warcraft

III, con el uso simple del mouse y teclado se puede construir escenarios con objetos preconstruidos (elipse en la imagen), dentro de estos hay terrenos, puertas, ventanas, unidades, etc. Además, existen diferentes variantes por cada uno de ellos, con una simple selección del mouse en la paleta de la derecha, ya podemos empezar a crear nuestro escenario al cual, una vez terminado se puede agregar inteligencia artificial a las unidades.

19

Figura 3

En la siguiente figura (Figura 4), podemos ver las variantes de terrenos que hay a disposición (elipse en la imagen). Además a éstos se le pueden aplicar relieves. También se muestra un escenario terminado (pantalla del centro) el cual ya puede ser utilizado por el juego Warcarft 3 o DotaAllstar

(juego que también hace uso del Motor de Warcraft 3)

20

Figura 4

Por ejemplo, los archivos que genera el motor de Warcraft 3 en estructura son muy similares a los generados 3D Studio Max, poseen la mismas secciones y agregan algunas como efectos gráficos avanzados y generación de partículas, pero a diferencia de los archivos 3DS Max, éstos se generan en dos archivos, uno del modelo (muy similar a los 3Ds Max) y otro de Inteligencia

Artificial, éste posee un lenguaje de script muy similar a uno de programación,

21

pero que es propio del motor, el cual es para describir el comportamiento de las unidades controladas por la CPU; el siguiente diagrama muestra el contenido de cada uno de los archivos mencionados.

Motor gráfico Warcraft 3

Archivo de Modelo (secciones) Archivo IA . Objetos . Script de . Texturas comportamiento de . Motor de partículas jugador no humano . Efectos gráficos avanzados . Animaciones

Figura 5

Por último, cabe mencionar que la alternativa en la que el desarrollador use directamente alguna de estas librerías de desarrollo 3D (no mediante software de diseño o de motores gráficos), para lo cual, se requiere tener un manejo avanzado de las instrucciones de las APIs, además de un buen manejo en lenguajes de programación, lo cual se traduce en que la curva de aprendizaje se torne ardua y dificultosa, incluso para labores sencillas.

22

2.1.2 Esfuerzos anteriores

Cabe mencionar que ninguna de las herramientas de diseño 3D antes expuestas proporcionan información que pueda ser usada por el programador directamente. Sin embargo, existen algunas soluciones externas a estos softwares que si lo permiten.

Existen varias alternativas de exportación de información del modelo diseñado con herramientas de diseño 3D, algunas sólo exportan información del modelo, otras van un poco más lejos exportando las llamadas nativas de alguna

API gráfica.

A continuación se tratará el tema más en detalle, ya que representan los esfuerzos llevados a cabo antes del proyecto que se quiere concretar.

Una de estas alternativas es la librería Lib3ds [Kyprianidis2007] que nos permite exportar información de los modelos diseñados con 3D Studio Max a partir del archivo de la aplicación.

 Configuración de Atmósfera.

 Configuración mapa de sombras.

 Establecimiento de Viewport.

 Materiales.

23

 Cámaras.

 Luces.

 Mallas.

 Fotogramas clave.

 Jerarquía.

Cabe destacar que esta Libreria es gratuita, OpenSource y funciona bajo la plataforma Linux, actualmente está disponible para ser descargada la versión

1.30.

El siguiente código obtiene e imprime información referente a las cámaras, usando la librería de cámara de Lib3ds.

#include //conjunto #include // de librerías lib3ds #include //necesarias para obtener información #include // de las cámaras #include #include void lib3ds_camera_dump(Lib3dsCamera *camera) { ASSERT(camera);//se selecciona la cámara // Se imprime el nombre de la cámara printf(" name: %s\n", camera->name); // Se imprime la posición de la cámara printf(" position: (%f, %f, %f)\n", camera->position[0], camera->position[1], camera->position[2]); // Se imprime objetivo de la cámara printf(" target (%f, %f, %f)\n", camera->target[0], camera->target[1], camera->target[2]);

24

// Se imprime el tipo de cámara printf(" see_cone: %s\n", camera->see_cone ? "yes" : "no"); // Se imprime la posición más cercana que ve la cámara printf(" near_range: %f\n", camera->near_range); // Se imprime la posición más lejana que ve la cámara printf(" far_range: %f\n", camera->far_range); printf("\n"); }

La información de la cámara fue obtenida mediante la librería lib3ds como se aprecia en el código anterior, posteriormente ésta debe ser tomada por el programador para ser usada en la API que éste estime conveniente, lo que implica que el programador debe dominar la API elegida.

Otra alternativa es “The Maya Exporter Factfile” [Bateman2004], a diferencia de lib3ds es un conjunto de plugins que se utilizan para obtener información de los modelos diseñados con Maya. Este esfuerzo fue desarrollado por Robert Bateman en el año 2004, este conjunto de plugins son capaces de obtener los siguientes datos.

 Texturas

 Materiales

 Luces

 Cámaras

 Transformaciones

 Animaciones

25

 Bump Maps

 Poligonal Meshes.

Estos plugins obtienen información del modelo mediante el archivo maya, lo que implica que el programador debe saber usar OpenGL, para poder tomar estos datos y representar el modelo, cabe mencionar que estos plugins no están incluidos en maya y funcionan a partir de la versión 4.0, este esfuerzo, es uno los mas similares al proyecto que se quiere concretar.

A continuación, se mostrará parte del código fuente que usa estos plugins, el cual obtiene datos acerca de los objetos en la escena, tenemos que tomar en consideración que al igual que el archivo de 3Ds Max los objetos

(figuras 3D) son nodos llamados Mesh, los cuales son parte de un árbol.

Código que obtiene el nombre de los Mesh.

#include//conjunto de plugins #include// maya exporter // Se crea un iterador para recorrer todos los Mesh MItDag it(MItDag::kDepthFirst,MFn::kMesh); while(!it.isDone()) { // Asignamos la función al Objeto MFnMesh fn(it.item());

if( !fn.isIntermediateObject() ) { // Imprime el nombre del Mesh

26

cout<<"Mesh "<< fn.name().asChar() <

}

// Siguiente objeto it.next(); }

El código anterior sólo recorre el árbol e imprime los nombres de los objetos en la escena, el siguiente código es un poco más complejo, ya que obtiene las coordenadas de los vértices de los objetos en la escena.

#include>// plugin maya exporter void outputMeshVertices(MObject& obj) { // Asignamos la función al Objeto MFnMesh fn(obj);

// Arreglo que contendrá la posición de los vértices MPointArray vts;

// Se obtiene los las posiciones de los vértices fn.getPoints(vts);

// Imprime el número de vértices cout << "NumVerts " << vts.length() << endl;

// Imprime la posición de los vértices for(int i=0;i!=vts.length();++i) {

// print vertex cout << vts[i].x <<" " << vts[i].y <<" " << vts[i].z << "\n";

} }

27

La información fue obtenida usando los algoritmos anteriores, a través de algunos de los plugins que componen el Maya Exporter, ahora teniendo éstos datos, el programador debe codificar el modelo usando la API que estime conveniente (OpenGL o DirectX).

Existen motores gráficos que también se pueden considerar esfuerzos anteriores, ya que poseen kits de desarrollo para .Net y Java, un caso de esto es Ogre3d [Ogre3d2008], éste genera las instrucciones, por ejemplo en C# y llamadas OpenGL de lo diseñado con él, no obstante la curva de aprendizaje del programador se torna ardua ya que este código es sumamente complejo, y además se debe considerar que las instrucciones de la API se enmascaran totalmente, lo cual no permite el aprendizaje de ésta por parte del programador.

A continuación se mostrará uná línea de código fuente usando los kits de desarrollo de Ogre3d en donde solamente se diseñó un cubo con textura (cubo preconstruido) de tamaño 10.

// Código C usando kits Ogre 3d mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 10);

Como se puede apreciar, el uso de la API está totalmente enmascarada, más aun, el programador esta ceñido al uso de kits de desarrollo de Ogre3d para usar el modelo en otra aplicación, no obstante se puede ver que la

28

cantidad de líneas para diseñar un cubo es menor, que usando la API directamente.

2.1.3 Solución Propuesta

Considerando lo anteriormente expuesto, se propone el desarrollo de un entorno de diseño 3D, el cual por un lado entregará funcionalidades similares a las que un editor 3D tradicional, y por otro proveerá de la opción de entregar código nativo de la API que se requiere para la generación de la escena, permitiendo al programador iniciado en el tema de las graficas 3D el uso de la librería, o incluso al programador avanzado, desarrollar gran parte del entorno 3D requerido en esta herramienta, para luego exportar el código a su propia aplicación para continuar con su desarrollo, agregando lógica compleja o específica de la solución que se desea implementar.

Otra área de aplicación de esta herramienta, es la del diseño de los escenarios tridimensionales que sean consumidos por otros programas que lo requieran, por ejemplo, representar figuras 3D a partir de ecuaciones matemáticas, o representación de mundos tridimensionales para entornos de automatización y robótica en general.

29

Dentro de las funcionalidades de editor 3D se incluirán las siguientes características:

 Objetos 3D tales como esferas, cilindros, cajas y otros.

 Objetos 2D tales como discos, círculos, planos, polígonos y triángulos.

 Objetos de robótica tales como tanques y cámaras.

 Cámaras en modo normal y multivista.

 Aplicación de Texturas, las cuales se podrá aplicar a la mayoría de los

objetos antes mencionados, para mejorar el detalle del diseño.

 Aplicación de planos de corte para los objetos antes nombrados.

 Diseño mediante mouse, con el cual se podrá seleccionar, mover,

escalar y rotar los objetos.

 Movimiento de la cámara en la escena mediante teclado y mouse.

 Se dispondrá de una grilla de propiedades, como lo hay en programas

similares, para la edición de propiedades de los objetos presentes en la

escena.

30

2.2 Justificación

2.2.1 Situación sin proyecto:

Actualmente no existe ninguna herramienta de diseño en tres dimensiones basadas en OpenGL diseñada en Chile.

Actualmente no existe una herramienta para diseñar escenarios tres dimensiones que genere código OpenGL a partir de la escena, ya que las existentes trabajan con formatos de archivos propietarios, los cuales son interpretados sólo por la aplicación misma. Por lo cual, para poder trabajar con la escena generada, se debe pagar o desarrollar complejos parseadores o traductores que obtengan las estructuras y tipos nativos de la librería OpenGL.

2.2.2 Situación con proyecto:

El desarrollo del proyecto proporcionará un entorno de diseño de escenarios en tres dimensiones, el cual puede ser utilizado en entornos matemáticos, robótica y propósito general, con el cual el desarrollador puede sin ser experto en OpenGL, diseñar modelos complejos, que sin la ayuda de esta herramienta le sería muy arduo. Además el desarrollador puede utilizar el

31

modelo generado con la herramienta y luego exportarlo a llamadas nativas

OpenGL, algo muy similar a lo que hace la librería Lib3ds, las cuales pueden ser ocupadas en lo que el desarrollador estime conveniente.

Cabe mencionar, que en la solución propuesta, la funcionalidad de exportación estará integrada al software de diseño a diferencia de la librería

Lib3ds que no lo está con 3D Studio Max o así mismo con los plugins externos para Maya.

2.3 Delimitación

. El editor de escenarios en 3 dimensiones usará la API OpenGL, no se

contempla el uso de otras APIs, como sí lo hace 3D Studio Max y otros.

 Se pondrá a disposición un conjunto de figuras 3D básicas para la

construcción de escenarios tales como esferas, cilindros, cajas, discos,

círculos, polígonos, planos entre otras, con las cuales, ya sea

modificando, escalando, rotando o cortando, se pueden construir

escenarios más complejos.

 Existirán herramientas de animación básica como el movimiento de la

cámara para la revisión de la escena.

32

 Este proyecto no involucra el desarrollo de herramientas de animación

avanzadas para las figuras (mover éstas de acuerdo a una ecuación),

como lo hace 3D Studio Max.

. El software no será compatible con otros editores (3D Studio Max, Maya,

Blender, etc.).

. No tendrá soporte para manejo de físicas, generación de partículas y

otras técnicas complejas como si lo hacen los motores gráficos

(Engines).

. Tendrá la funcionalidad de exportar a llamadas nativas OpenGL del

modelo generado, las características exportables del modelo son:

configuración de la escena (posición de la cámara y otras

configuraciones) y figuras en la escena (posición, color, escala, planos

de corte, texturas, luces y parámetros propios de la figura), no obstante

no se exportarán mapa de sombras.

33

3. Objetivos

3.1 Objetivo General

Desarrollo de un editor de gráficos 3D con funcionalidad de exportación del modelo a código fuente C# y OpenGL.

3.2 Objetivos Específicos

. Construcción de un software para diseño 3D usando la API OpenGL, que ofrezca las funcionalidades básicas y comunes a todos los software de diseño de este tipo.

. Exportar el código de la escena diseñada al formato nativo de llamadas a funciones, tipos y estructuras de la librería 3D, para proveer la posibilidad de utilizarlo en el desarrollo de otros programas.

. Desarrollar el software siguiendo un estándar de definición de interfaces entre clases, lo cual permitirá que la escena generada sea consumible por otros procesos que la requieran (representaciones matemáticas, mundos 3D para automatización en general, entre otros).

. Utilización de herramientas y técnicas de programación de punta para este tipo de desarrollos, como Reflection y XML, entre otras.

34

4. Metodología

Para este seminario de Titulación, la metodología elegida es XP

(eXtreme Programming), esto basándose en la naturaleza del proyecto, y debido a que continuamente hay que repetir el ciclo de investigación y desarrollo, se decidió usar una metodología ágil, y dentro de éstas XP es una de las mejores evaluadas [Flower2003].

XP es una metodología ágil centrada en potenciar las relaciones interpersonales como clave para el éxito en desarrollo de software, promoviendo el trabajo en equipo, preocupándose por el aprendizaje de los desarrolladores, y propiciando un buen clima de trabajo. XP se basa en realimentación continua entre el cliente y el equipo de desarrollo, comunicación fluida entre todos los participantes, simplicidad en las soluciones implementadas y coraje para enfrentar los cambios. XP se define como especialmente adecuada para proyectos con requisitos imprecisos y muy cambiantes, y donde existe un alto riesgo técnico [XtremePrograming2007].

En este caso, el desarrollador es el alumno tesista, y el cliente será el profesor patrocinante. Además este último, cumple el rol de encargado de pruebas.

35

Si bien es cierto, la descripción específica de XP no calza en su totalidad con el trabajo requerido, sí se ajusta en gran medida con el desempeño requerido en las etapas de desarrollo del proyecto.

En la carta Gantt que se presenta más adelante se detallan las iteraciones (ciclo de tareas) que se consideraron necesarias de efectuar en cada etapa.

El ciclo de vida de XP consta de 5 fases o etapas: Etapa de

Exploración, Etapa de Planificación, Etapa de Producción, Etapa de

Mantenimiento y Etapa de Muerte del Proyecto.

I Etapa de Exploración:

En esta fase, se identificará el ámbito del proyecto y se definirá en términos generales lo que el software realizará en base al análisis de los requerimientos. Se establecerán las herramientas de desarrollo a utilizar y por

último se investigarán algunas tecnologías necesarias para el proyecto tales como XML y OpenGL, el estudiante tesista en esta etapa está encargado de todas las tareas antes mencionadas.

II Etapa de Planificación:

36

Se validan los requerimientos, se modela la solución, se diseña y finalmente se construye el software, esta etapa es la más importante, el diseño y construcción del software está a cargo del estudiante tesista, la revisión del correcto desarrollo de estas tareas está a cargo del profesor patrocinante.

III Etapa de Producción:

Se implementa la marcha blanca, que se refiere a corrección de errores, de ser necesario optimización de código, entrega de manuales de usuario del software y la entrega final del proyecto. Las tareas de esta etapa son desarrolladas por el alumno tesista y revisadas por el profesor patrocinante.

IV Etapa de Mantenimiento:

No será detallada en el proyecto, por corresponder a la parte posterior a la entrega del mismo. No obstante, ésta se refiere a algunas modificaciones puntuales que pueden ser requeridas por el cliente (profesor patrocinante) después de entregado el proyecto y el encargado de hacer estas modificaciones es el alumno tesista.

37

V Etapa de Muerte:

Solo se nombra en la carta Gantt, como una de las etapas del ciclo de vida elegido, pero no se lleva a cabo.

38

5. Plan de Trabajo y Cronograma

Como la metodología lo indica, en cada una de las fases del ciclo de vida de la aplicación existen tareas que se deben completar y son las que a continuación se detallan.

5.1 Actividades

I. Etapa de Exploración

1. Análisis de requerimientos

Se definirá en términos generales lo que el software hará en base

al análisis del los requerimientos.

2. Establecimiento de herramientas de desarrollo

Se establecerán las herramientas de desarrollo que se utilizarán

para desarrollar el proyecto.

3. Investigación de Tecnologías

Se investigarán las tecnologías que se utilizarán para el desarrollo

del proyecto, las cuales son: OpenGL, XML y Reflection en un

primer momento.

II. Etapa de Planificación

1. Validación de Requerimientos:

39

En esta parte del proyecto se probará que los requerimientos que

definen el software son lo que el cliente realmente necesita.

2. Modelo de la solución

2.1 Iteración Etapa de Planificación - Modelo de

Solución

Se diseñarán los diagramas de clases del software. Estos

serán revisados por el cliente y de ser necesario serán

nuevamente rediseñados y revisados nuevamente.

3. Diseño de la Solución

3.1 Iteración Etapa de Planificación - Diseño de la

Solución

Se entregará un prototipo del software sin funcionalidades

sólo interfaz, el cual pasará por un ciclo de revisión y

corrección hasta que el cliente quede conforme.

3.2 Aceptación del diseño de la solución (Cliente)

Teniendo en cuenta que los diagramas de clases y el

prototipo de la solución han sido revisados y aceptados se

procede con la siguiente etapa.

4. Construcción del Software

40

4.1 Iteración Etapa de Planificación - Construcción del

Software Beta

Se procede con a la codificación del software con

funcionalidades mínimas. Éste pasará por un ciclo de

revisión y aplicación de mejoras al código, al menos una

vez.

4.2 Iteración Etapa de Planificación - Construcción del

Software versión 1.0

Se precede con a la codificación del software con

funcionalidades completas, éste pasará por un ciclo de

revisión y aplicación de mejoras al código, al menos una

vez hasta que el cliente quede conforme.

4.3 Fabricación de manual de usuario

Se procede con la redacción del manual de usuario del

software.

III. Etapa de Producción

1. Marcha blanca

Se completarán pruebas de desempeño del software y se

realizarán ajustes de ser necesarios. Además, serán revisados los

manuales de usuario.

2. Entrega Final del proyecto

41

Se entregará el proyecto al final de la marcha blanca, esto será

entregado al cliente en 2 copias en CD. Cada copia contendrá el

ejecutable del software más su código fuente y su correspondiente

manual de usuario.

IV. Etapa de Mantenimiento

De ser necesario y el cliente lo solicita se harán modificaciones al

software.

5.2 Carta Gantt

La calendarización del proyecto contempla el trabajo de 5 días por semana, con un total de 8 horas diarias. El total de horas trabajadas en el proyecto corresponde a 1800 horas hombre o 12 meses, y los recursos son: el alumno tesista, que hará las veces de programador, y el profesor guía que hará de jefe de proyecto, para más detalle ver carta Gantt resumen adjunta en los anexos digitales en la ruta “\Anexos\CartaGantt\”.

42

6. Recursos

6.1 Hardware

- CPU AMD Turion X2 de 2 GHZ.

- 1 GB de RAM.

- 256 MB ATI X1600 DDR3.

- Disco duro de 120 GB.

6.2 Software

- Visual Studio 2005 ó 2008 bajo Windows XP y lenguaje C#.

- Librerías OpenGL en sistemas operativos Windows y Linux.

- Estándar XML versión 1.2.

- Mono/MonoDevelop en Linux para pruebas de códigos fuentes

generados por la aplicación.

43

7. Análisis de la Solución

De acuerdo a las características que presenta este proyecto de Tesis, el software es parte fundamental para concretar los objetivos planteados por el cliente, lo que se centraliza finalmente en un software con las funcionalidades de un editor de gráficos 3D y además la funcionalidad de generación de código fuente.

El sistema de construcción para este software esta guiado por la metodología de desarrollo XP, que se puede englobar dentro de las metodologías ligeras, las cuales son aquellas que priorizan los resultados directos y que reducen la documentación tradicional que ofrecen la mayoría de las metodologías. XP es una metodología que permite un desarrollo de software adaptable más que previsible, se basa en la simplicidad, la comunicación y la realimentación o reutilización del código desarrollado; lo cual posibilita un software escalable y de un mejoramiento futuro de forma dinámica.

7.1 Descripción de la solución

Los requerimientos solicitados por el cliente consisten en el desarrollo de un editor de escenarios 3D con todas las funcionalidades básica que implica un software de este tipo y además la funcionalidad de generación de código fuente

44

de lo diseñado. En consecuencia, con lo anterior la construcción de esta solución se dividirá en dos módulos, los cuales son: un Editor 3D y un

Generador de código fuente de lo diseñado con el editor.

A continuación se analizarán los requerimientos solicitados por el cliente mediante la técnica de “casos de uso”, la cual sirve para la captura de requisitos potenciales de una aplicación como ésta.

7.1.1 Módulo Editor 3D.

Las funcionalidades deben ser similares a las que un editor 3D presenta, las cuales a grandes rasgos ofrecen un mundo en tres dimensiones sobre el cual construir escenarios con el uso de primitivas 3D como: cubos, esferas, conos, luces, cámaras y otros. Además ofrecer múltiples interfaces para la manipulación de éstos (mouse, teclado y paleta de propiedades) para así hacer la tarea de construir estos escenarios menos compleja para el usuario. Con lo anterior, se proponen los siguientes diagramas de casos de uso como se observa en el diagrama [1] para la construcción de esta solución.

45

Diagrama Nº [1]: Modelo de Casos de Uso Módulo Editor 3D.

Existen 4 casos de uso a nivel macro en lo que se refiere al Editor 3D, los cuales a su vez incluyen casos de usos especializados, a continuación se abordaran estos casos de uso.

7.1.1.1 Caso de uso: Crear/Editar/Eliminar Mundo.

Este caso de uso incluye los siguientes subcasos.

46

Diagrama Nº [2]: Modelo de Casos de Uso Crear/Editar/Eliminar Mundo

ACTOR (ES): USER APLICACIÓN 1. Crea un nuevo mundo al 2. Muestra el nuevo mundo. seleccionar en el menú la opción nueva escena o al presionar el botón “limpiar escena”. 3. Edita el mundo mediante el 4. Refleja los cambios en el mouse, teclado y paleta de mundo. propiedades. 5. Elimina el mundo al presionar el 6. Elimina la escena (Mundo y botón “Limpiar escena”. Objetos) y crea una totalmente nueva. 7. Selecciona el mundo Mediante el 8. Carga sus propiedades en la mouse. paleta para su edición y habilita la edición con el Mouse del mundo. 9. Selecciona una cámara mediante 10. Muestra el mundo desde la el menú. cámara seleccionada.

47

11. Configura dinámicamente modalidades de traslación, rotación, escalamiento del mundo y sus objetos, de manera que estas queden de manera óptima para la cámara seleccionada. 12. Habilita animación básica 13. Despliega una animación mediante paleta de propiedades básica que consiste en la y menú. rotación de la cámara por el mundo. 14. Selecciona la modalidad de 15. Despliega el mundo en la despliegue del mundo ya sea en modalidad seleccionada. modo Design o Render. 16. Habilita la Traslación de la 17. Refleja Trasladando la cámara cámara mediante el mouse, al mover el mouse. seleccionando el botón “Trasladar” en el formulario principal de la aplicación o presionando [CTRL + ] teniendo en cuenta que el mundo debe estar seleccionado. 18. Habilita la Rotación de la cámara 19. Refleja Rotando la cámara al mediante el mouse y teclado, mover el mouse. seleccionando el botón “Rotar” en el formulario principal de la aplicación o presionando [CTRL + r] teniendo en cuenta que el mundo debe estar seleccionado. 20. Traslada la cámara con las teclas 21. Refleja Trasladando la direccionales, esta traslación se cámara. comportará dependiendo del tipo de traslación que se seleccionó en el menú de la aplicación o de la cámara que está seleccionada actualmente. 22. Habilita el despliegue del valor 23. Despliega el valor de los que representa el número de frames por segundo en el frames por segundo que muestra encabezado de la ventana por la ventana por donde se visualiza donde se muestra el mundo el mundo 3D esto mediante la 3D. paleta de propiedades, teniendo

48

en cuenta que el mundo debe estar seleccionado. 24. Habilita o deshabilita los planos coordenados mediante paleta de propiedades.

25. Configura el nivel de detalle de los objetos presentes en el mundo mediante menú y paleta de propiedades.

7.1.1.2 Caso de uso: Crear/Editar/Eliminar Objeto.

Este caso de uso Crear/Editar/Eliminar Objetos, posee especializaciones que corresponden a todos los objetos que soportará la aplicación, a continuación el detalle de estos casos de uso correspondiente a un tipo de objeto del total que soportará la aplicación, ya que todos los casos de uso

Crear/Editar/Eliminar de los de los otros tipos de objetos son similares o iguales al que se describirá a continuación (esfera), no obstante estos casos de uso se incluirán en anexos.

49

Diagrama Nº [3]: Modelo de Casos de Uso Crear/Editar/ Eliminar Esfera.

Independiente de haber mostrado el diagrama casos de uso de

Crear/Editar/ Eliminar una esfera, a continuación se abordará la descripción de casos de uso desde el punto de vista de un Objeto general que representa todos los tipos de objetos representables por la aplicación.

ACTOR (ES): USER APLICACIÓN 1. Crea un nuevo objeto mediante el 2. Muestra el nuevo objeto teclado o formulario de creación y creado. edición de objetos. 3. Edita el objeto mediante el 4. Refleja los cambios en el Mouse, teclado y paleta de objeto. propiedades. 5. Elimina el objeto al presionar el 6. Refleja la eliminación del botón “Eliminar” en el formulario objeto.

50

de creación y edición de objetos y mediante teclado presionando “Suprimir”. 7. Selecciona el objeto Mediante el 8. Carga sus propiedades en la Mouse. paleta para su edición y habilita la edición con el Mouse del objeto.

9. Configura el nivel de detalle del objeto mediante menú y paleta de propiedades.

10. Asigna una textura al objeto 11. Carga la textura y se la asocia mediante paleta de propiedades. al objeto.

12. Habilita Planos de corte para el 13. Refleja la aplicación del plano objeto mediante paleta de de corte al objeto. propiedades. 14. Habilita la Traslación del objeto 15. Refleja Trasladando el objeto mediante el Mouse, en el mundo al mover el seleccionando el botón Trasladar Mouse. en el formulario principal de la aplicación teniendo en cuenta que el objeto debe estar seleccionado. 16. Habilita la Rotación del objeto 17. Refleja Rotando el objeto en el mediante el Mouse, mundo al mover el mouse. seleccionando el botón “Rotar” en el formulario principal de la aplicación presionado [CTRL + q] teniendo en cuenta que el objeto debe estar seleccionado. 18. Habilita la Escala del objeto 19. Refleja Escalando el objeto en mediante el mouse, el mundo al mover el mouse. seleccionando el botón “Escalar” en el formulario principal de la aplicación presionado [CTRL + q] teniendo en cuenta que el objeto debe estar seleccionado. 20. Crea objeto de tipo Custom en el formulario de creación y edición

51

de objetos el cual puede estar compuesto por uno o más objetos. 21. Edita objeto de tipo Custom en el formulario de creación y edición de objetos ya sea eliminado, editando, desvinculando a objetos hijos. Excepciones: a. Las texturas no se visualizan si la escena está en modalidad de diseño. b. No todos los tipos de objetos soportan texturas. c. La Textura debe ser cuadrada de tamaño potencia de 2.

7.1.1.3 Caso de uso: Crear/Editar/Eliminar Luz.

ACTOR (ES): USER APLICACIÓN 1. Crea una nueva Luz al 1. Muestra la nueva fuente de luz. seleccionar el botón “Luz” en el menú de la aplicación o presionado [CTRL + l]. 2. Edita la fuente de luz mediante 3. Refleja los cambios de la luz en paleta de propiedades, mouse. el mundo. 4. Elimina la luz seleccionado la luz y presionando el botón “Suprimir”. 5. Selecciona la luz Mediante el 6. Carga sus propiedades en la Mouse. paleta para su edición y habilita la edición con el Mouse de la fuente de luz. 7. Habilita la Traslación de la 8. Refleja Trasladando la fuente Fuente de Luz mediante el de luz en el mundo al mover el mouse, seleccionando el botón mouse. “Trasladar” en el formulario principal de la aplicación o presionando [CTRL + q] teniendo en cuenta que la fuente de luz debe estar seleccionada. Excepciones:

52

a. Las fuentes de luz no se pueden rotar ni escalar. b. La aplicación resiste un máximo de ocho Fuentes de luz. c. La ubicación de la luz solo es visualizable en modalidad Design, en modalidad Render solo se visualiza el efecto de esta sobre los objetos de la escena.

7.1.1.4 Caso de uso: Nueva/Guardar/Cargar Escena.

ACTOR (ES): USER APLICACIÓN 1. Crea una nueva escena mediante 2. Despliega una escena Limpia y el menú de la aplicación lista para diseñar. seleccionando la opción “Nueva Escena”. 3. Guarda una escena mediante el 4. Genera un archivo de respaldo menú de la aplicación que contiene toda la escena seleccionando la opción “Guardar usando como soporte la Escena”, posteriormente debe tecnología XML. Este archivo digitar el nombre del archivo es guardado con el nombre donde se guardara la escena y especificado por el usuario. por ultimo debe presionar el botón “Guardar”. 5. Carga una escena mediante el 6. Despliega la escena que fue menú de la aplicación cargada desde el archivo XML. seleccionando la opción “Cargar Escena”, posteriormente debe seleccionar el archivo de la escena y por último debe presionar el botón “Abrir”. Observaciones: a. La aplicación guardara en el documento XML las texturas asociadas a los objetos de escena, esto debe hacerlo en forma binaria.

53

7.1.2 Módulo Generador de Código Fuente.

Las funcionalidades de este módulo se centra en generar el código fuente de lo diseñado con el módulo del Editor 3D, para poder usar este código en lo que el Actor “USER” desee, el código fuente generado por esta solución será en el lenguaje de programación C#.

A continuación se presenta el diagrama Nº [2] de casos de uso para el módulo “Generador de Código Fuente”.

Diagrama Nº [4]: Modelo de Casos de Uso Módulo “Generador de Código fuente”.

7.1.2.1 Caso de uso: Generar código Fuente Escena.

54

ACTOR (ES): USER APLICACIÓN 1. Genera el código fuente en una 2. Genera un archivo con clase C# seleccionando en el extensión “cs” con la lógica menú de la aplicación la opción necesaria para generar una “Generar archivo clase”. escena. 3. Genera el código fuente en un 4. Genera un Proyecto del tipo proyecto “VS2008” seleccionando “Visual. Studio 2008” listo para en el menú de la aplicación la compilar y ejecutar. opción “Generar código fuente” en “proyecto VS”. 5. Genera el código fuente en un 6. Genera un proyecto del tipo proyecto “VS2008” seleccionando “Visual. Studio 2008” y además en el menú de la aplicación la ejecuta Visual Studio 2008. opción “Generar código fuente” Con el proyecto ya cargado en “proyecto VS” ejecutando solo hace falta compilar y “VS2008”. ejecutar. Excepciones: a. El fuente generado al compilarse y ejecutarse desplegará la escena en modalidad Render ya que la modalidad Design solo está destinada a el editor 3D.

7.2 Establecimiento de herramientas de desarrollo

Para establecer las herramientas de desarrollo del software solicitado, se tomaron en cuenta las solicitudes del cliente y otras establecidas por la naturaleza de la aplicación.

Las herramientas o tecnologías que se usaron en esta solución son las siguientes.

1. Tao Framework 2.1 el cual incluye:

55

1. Tao.OpenGl 2.1.0.12.

2. Tao.FreeGlut 2.4.0.2.

2. Microsoft .NET Framework versión 2.0 (x86).

3. IDE Microsoft Visual Studio 2008 (C#).

4. Tecnología de desarrollo basadas en Reflection de Plataforma .Net.

5. Tecnología XML 1.0.

6. Mono Framework 2.4.

7. IDE MonoDevelop 2.0.

Las herramientas mencionadas anteriormente para el desarrollo de la aplicación serán descritas en la etapa de Investigación de Tecnologías.

7.3 Investigación de Tecnologías

7.3.1 Tao FrameWork

Una de las tecnologías que se usó para el desarrollo de la aplicación es

Tao Framework 2.1.0, la cual es una colección de librerías multiplataforma orientadas a gráficos y multimedia, además facilita la portabilidad entre los

Frameworks .NET y Mono. Una de las librerías que se usarán en la aplicación es OpenGL (Open Graphics Library) la cual viene contenida dentro de un

56

“Wrapper/Envoltorio” llamado Tao.OpenGl, esto debido a que no puede ser usada directamente por entornos manejados ya que está diseñada para ser usada en el lenguaje de programación C, por tanto Tao.OpenGl permite el uso de esta en .Net/Mono. OpenGL es una especificación estándar que define una

API multilenguaje y multiplataforma para escribir aplicaciones que produzcan gráficos 2D y 3D. La interfaz consiste en más de 250 funciones diferentes que pueden usarse para dibujar escenas tridimensionales complejas a partir de primitivas geométricas simples, tales como puntos, líneas y triángulos. Fue desarrollada originalmente por Silicon Graphics Inc. (SGI) en 1992 y se usa ampliamente en CAD, realidad virtual, representación científica, visualización de información y simulación. También se usa en desarrollo de videojuegos, donde compite con Direct3D para plataformas de Microsoft Windows. La descripción más completa de la API esta en los antecedentes del proyecto.

Otra librería que se ocupará de este FrameWork es FreeGlut, la cual es una biblioteca de utilidades para programas OpenGL. Esta al igual que OpenGL no puede ser usada directamente por entornos manejados, por ende usaremos un “Wrapper/Envoltorio” llamado Tao.FreeGlut. FreeGlut principalmente proporciona diversas funciones de entrada/salida con el sistema operativo.

Entre las funciones que ofrece se incluyen declaración y manejo de ventanas y la interacción por medio del teclado y ratón. También posee rutinas para el dibujo de diversas primitivas geométricas (tanto sólidas como en modo

57

wireframe/enrejado) que incluyen cubos, esferas, entre otros. También tiene soporte para creación de menús emergentes.

En resumen Tao.OpenGl y Tao.FreeGlut son solo “Wrappers/Envoltorios” de las librerías OpenGL y FreeGlut, las cuales están escritas en el lenguaje de programación C y compiladas según la plataforma, por lo tanto desde un entorno de maquina virtual como lo es .NET/Mono y C#, es imposible acceder a ellas si no es mediante un “wrapper”.

Otras librerías que contiene Tao Framework 2.1 no ocupadas en la aplicación son las siguientes:

1. Tao.OpenAl 1.1.0.1 (librería multiplataforma para el manejo de audio

tridimensional).

2. Tao.Cg 2.0.0.0 (define un nuevo lenguaje similar a C para programación

de shaders/sombras).

3. Tao.DevIl 1.6.8.3 (librería para cargar y guardar gran cantidad de

formatos de imágenes).

4. Tao.Sdl 1.2.13.0 (proporcionan funciones básicas para realizar

operaciones de dibujo, gestión de efectos de sonido, música, carga y

gestión de imágenes con apoyo de otras librerías).

58

5. Tao.Ode 0.9.0.0 (librería para la simulación de la dinámica de cuerpos

rígidos.).

7.3.2 Visual Studio 2008

Otra tecnología que se usará para el desarrollo de la solución es el entorno de desarrollo integrado (IDE, por sus siglas en inglés) Visual Studio

2008 y el lenguaje C#, se eligió esta tecnología debido a que es una de las plataformas de desarrollo más usadas a nivel mundial y dentro del país; por tanto adquirir experiencia en el uso de esta agrega valor agregado al desarrollo, además es una de las herramientas solicitadas por el cliente para el desarrollo de la aplicación. Una de las características de Visual Studio 2008 es la posibilidad de seleccionar el Framework, aún cuando para la aplicación se usara el .NET 2.0 ya que fue solicitado por el cliente, no obstante la aplicación quedara fácilmente portable a versiones más recientes como por ejemplo el

Framework 3.5.

7.3.3 Microsoft .NET Framework versión 2.0 (x86).

59

Para esta aplicación fue seleccionado el Microsoft .NET Framework versión 2.0 (x86) esto debido principalmente a que Mono Framework 2.4

(Framework que implementa el estándar de la ECMA para máquinas virtuales multiplataforma equivalente a .Net 2.0 y superiores, para sistemas operativos

Linux, , MacOS, Sun Solares, Sparc, ARM, MIPS entre otros) soporta de manera estable aplicaciones desarrolladas para el Microsoft .NET Framework versión 2.0 no así para versiones más recientes de este. Al cliente le interesa que la aplicación quede portable al sistema operativo Linux, no obstante la aplicación está orientada principalmente al Framework .Net 2.0 de Microsoft.

6.3.4 Tecnología de desarrollo basadas Reflection de Plataforma .NET.

Otra de las tecnologías seleccionadas es Reflection de .Net, que está ubicada dentro del NameSpace “System.Reflection” del mismo. Este contiene clases e interfaces que proporcionan una vista administrada de los campos, los métodos y los tipos cargados, con la posibilidad de crear e invocar tipos dinámicamente.

Esta tecnología se usará debido a la naturaleza de la aplicación donde se requiere la ejecución de métodos en forma dinámica, ejecución de métodos de objetos específicos dentro de una colección genérica y además uno de los

60

requerimientos que se refiere a la generación de código fuente, con lo cual hace que esta tecnología sea indispensable para el desarrollo de esta aplicación.

7.3.5 Tecnología XML 1.0.

Para esta aplicación se necesita un método de respaldo y restauración de datos de lo diseñado con la aplicación, para esto se ha seleccionado la tecnología XML sigla en inglés de Extensible Markup Language («lenguaje de marcas ampliable»), es un metalenguaje extensible de etiquetas desarrollado por el World Wide Web Consortium (W3C). XML propone un estándar para el intercambio de información estructurada entre diferentes plataformas. Se puede usar en bases de datos, editores de texto, hojas de cálculo y casi cualquier cosa imaginable.

XML es una tecnología sencilla que tiene a su alrededor otras que la complementan y la hacen mucho más grande y con posibilidades mucho mayores. Tiene un papel muy importante en la actualidad ya que permite la compatibilidad entre sistemas para compartir la información de una manera segura, fiable y fácil.

61

7.3.6 Mono 2.4 y MonoDevelop 2.0.

Otra característica que esta aplicación implementó es que el código fuente generado debe ser multiplataforma y además se debió portar una versión de la aplicación a Mono Framework para el sistema operativo Linux, con lo cual para probar el código fuente, se uso FrameWork Mono 2.4 el cual es un proyecto liderado por la corporación informática Novell (antes de Ximian) para crear un estándar compatible con las especificaciones de la organización ECMA y un conjunto de herramientas .NET, incluye entre sus características un compilador del lenguaje C# y un entorno denominado CLR (Common Language

Runtime). Mono se puede ejecutar en Linux, BSD, Unix, Mac OS X, Solaris y sistemas operativos Microsoft Windows, además en un número muy amplio de otras arquitecturas como RISC, Sparc, Arm, entre otras.

Debemos hacer una distinción: Mono 2.4 es el FrameWork, por lo tanto para probar el código fuente se necesita un entorno de desarrollo, el cual es llamado “MonoDevelop”, diseñado primordialmente para C# y otros lenguajes

.NET como Nemerle, Boo, y Java (vía IKVM.NET). MonoDevelop originalmente fue una adaptación de SharpDevelop para Gtk#, pero desde entonces se ha desarrollado para las necesidades de los desarrolladores de Mono. El IDE incluye manejo de clases, ayuda incorporada, completación automática de

62

código, Stetic (diseñador de GUI para Gtk#), soporte para proyectos, y un depurador integrado. Para el desarrollo de la aplicación se utilizará la versión

2.0 de MonoDevelop.

7.4 Validación de Requerimientos

Para esta etapa se contempló reuniones iterativas para validar los requerimientos extraídos primordialmente desde los análisis de “casos de usos”.

Estas reuniones consistieron en presentaciones donde se fueron validando todos los casos de uso. Además se presentaron prototipos de la aplicación con algunas funcionalidades mínimas; estas reuniones se realizaron para validar los requerimientos y en base a esto ir mejorando el prototipo. Una vez validado este, se dió paso al diseño con la información sacada de esta etapa y de las anteriores etapas de la metodología.

63

8. Diseño de la Solución

En esta etapa de la metodología, XP enfatiza que no se puede establecer una definición temprana de una arquitectura definitiva para la aplicación, si no que dicha arquitectura va evolucionando a medida que se realizan las iteraciones de diseño, con la información que se obtuvo de las actividades anteriores se desarrollará una primera versión del diseño el cual irá evolucionando durante cada una de las iteraciones.

Basándose en el paradigma de la orientación a objeto, en el cual se desarrolló la aplicación, el diagrama de clases otorga una representación ideal para el diseño de ésta. Los productos que se quieren obtener de esta representación son los siguientes:

 Las clases de objetos de la aplicación.

 Las relaciones que existen entre estas clases.

 Una descripción en detalle de para qué sirve cada una de estas clases; esto

incluye descripción de sus miembros, propiedades y métodos.

 Descripción de Interfaces.

64

8.1 Diagrama de clases

El diagrama de clases es un tipo de diagrama estático que describe la estructura de un sistema o aplicación mostrando sus clases, atributos y las relaciones entre ellos [UML2007], a continuación se mostrará el diagrama de clases de la aplicación desarrollada, este se encuentra reducido mostrando los miembros y métodos más representativos de cada clase, no obstante el diagrama completo se encuentra en los anexos, además en capítulos posteriores se abordará el “diccionario de clases”, el cual describe los miembros y métodos en detalle del diagrama completo.

65

Diagrama de Clases Editor 3D y Desensamblador de Código.

8.2 Diccionario de clases de editor OpenGL

A continuación se describirá en detalle cada una de las clases de la aplicación, esto involucra una descripción de sus miembros propiedades y métodos en detalle, todo esto para comprender de mejor forma la función de cada una de las clases y las relaciones entre ellas.

66

8.2.1 Class World:

Es la clase encargada de inicializar la ventana Glut por la que se muestra el mundo y además despliega la escena donde están contenidos los objetos de tipo Entity, esta clase hereda de la clase XmlConverter con el fin de obtener comportamientos y métodos para guardar y restaurar las propiedades de los objetos de esta clase en un archivo XML. Además, esta clase posee los métodos suscritos a los callbacks de Glut para la captura de información del teclado y mouse.

8.2.1.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Fps 0

Frames por segundo en la ventana Glut

Private String xml_file

Directorio del archivo Xml donde se guarda la escena.

Private Int num_type_entity 15

Cantidad de tipos de objetos.

Private XmlNode Textura

Nodo Xml que servirá para guardar o restaurar una textura.

Private Trajectory camera_position

Posición de la cámara.

67

Private Vector camera_rotation

Rotación de la cámara.

Private Bool fps_enable False frames por segundo no visible(en la ventana glut)

Private Int View_mode 0

Tipo cámara.

Private Bool EjeXYZ True

Eje XYZ visible.

Private Bool PlaneX False

Plano X=0 no visible.

Private Bool PlaneY True

Plano y=0 visible.

Private Bool PlaneZ False

Plano z=0 no visible.

Private Bool traslate_mode_camera_in_z True

Modo de traslación de cámara con referencia al plano z=0 habilitado.

Private Bool traslate_mode_camera_in_x False

Modo de traslación de cámara con referencia al plano x=0 deshabilitado.

Private Bool traslate_mode_camera_in_y False

Modo de traslación de cámara con referencia al plano y=0 deshabilitado.

68

Private Bool rotate_mode_camera False

Modo de rotación de cámara deshabilitado.

Private Double traslate_factor_camera 1

Factor de traslación de la cámara.

Private Double Rotate_factor_camera 10

Factor de rotación de la cámara.

Private Bool traslate_mode_mouse True

Modo de traslación con el mouse.

Private Bool traslate_mode_mouse_in_x False

Modo de traslación con el mouse con referencia al plano X=0 habilitado. Modificador de Tipo Nombre Valor acceso Private Bool traslate_mode_mouse_in_y False

Modo de traslación con el mouse con referencia al plano Y=0 habilitado.

Private Bool traslate_mode_mouse_in_z True

Modo de traslación con el mouse con referencia al plano Z=0 habilitado.

Private Bool Rotate_mode_mouse False

Modo de Rotación con el mouse deshabilitado.

Private Bool Rotate_mode_mouse_in_x False

Modo de Rotación con el mouse con referencia al plano x=0 deshabilitado. Private Bool rotate_mode_mouse_in_y False

Modo de Rotación con el mouse con referencia al plano y=0 deshabilitado.

69

Private Bool rotate_mode_mouse_in_z True

Modo de Rotación con el mouse con referencia al plano z=0 habilitado.

Private Bool scale_mode_mouse False

Modo de Escalado con el mouse deshabilitado.

Private Bool scale_mode_mouse_in_x False

Modo de Escalado con el mouse con referencia al plano x=0 deshabilitado.

Private Bool scale_mode_mouse_in_y False

Modo de Escalado con el mouse con referencia al plano y=0 deshabilitado

Private Bool scale_mode_mouse_in_z True

Modo de Escalado con el mouse con referencia al plano z=0 habilitado.

Private Bool Selection_mode_Mouse True

Modo de selección con el mouse habilitado.

Private Bool BToggle

Variable utilizada para la animación.

Private Int Hits

Cantidad de veces que ha sido seleccionado un objeto determinado.

Private Int Glutwnd

Identificador ventana glut.

Private Int oldX,oldY

Variables auxiliares que hacen posible la edición dinámica de objetos con el mouse.

70

Private Int animation_interval 1

Intervalo de animación.

Private Bool Design_mode False

Modo de diseño deshabilitado.

Private Vector Size

Tamaño del mundo.

Private Int Width 812

Ancho ventana glut.

Private Int Height 540

Alto ventana glut.

Private Double Rotation True

Variable para la animación de la cámara (Rotación).

Private Int GlutWnd

Identificador ventana glut.

Private Type ClassObj

Variable de tipo type que será usada para aplicar reflection sobre esta clase.

Modificador de Tipo Nombre Valor acceso Private Int[] History_names

Arreglo que guarda historial de nombres.

Private Int Prkeyent

Clave del objeto seleccionado actualmente.

71

Private List Entities

Colección de objetos del mundo.

Private Bool Preview False

Anima la cámara para que rote por la escena.

Private Bool Render_mode True

Modo render habilitado.

8.2.1.2 Métodos:

Private void Init()

Descripción:

Inicializa la ventana Glut y sus manejadores.

Private void Show()

Descripción:

Despliega el mundo 3D en la ventana Glut e inicializa el buffer de profundidad, de colores, texturas y carga la matriz identidad.

Private void ReshapeHandler(int width, int height)

Descripción:

72

Método manejador que repinta la ventana Glut cada vez que es redimensionada.

Requiere los parámetros:

Width: Tipo Int, que contiene el nuevo ancho de la ventana por donde se visualiza la escena.

Height: Tipo Int, que contiene el nuevo alto de la ventana por donde se visualiza la escena.

Private void MouseHandler(int button, int estate, int x, int y)

Descripción:

Método manejador que captura las coordenadas xy cada vez que se hace un click en la ventana Glut.

Requiere los parámetros:

Button: Tipo Int, que contiene el botón del mouse que fue presionado.

Estate: Tipo Int, que contiene si e botón fue presionado o fue desprecionado. x: Tipo Int, que contiene la coordenada x del pixel de la ventana que fue clickeado con el mouse. y: Tipo Int, que contiene la coordenada y del pixel de la ventana que fue clickeado con el mouse.

73

Private void InitEntityFromXml():

Descripción:

Método encargado de crear los objetos del mundo desde el Xml, solo los inicializa no le asigna datos a sus propiedades.

Private void KeyboardHandler(byte key, int x, int y)

Descripción:

Método manejador que captura las teclas (mientras está en foco la ventana glut) cada vez que son presionadas.

Requiere los parámetros:

Key: Tipo byte, que contiene la tecla que fue presionada. x, y: Tipos int, que contienen las coordenadas x,y del pixel sobre el cual está el puntero del mouse al momento de presionar una tecla(teclado).

Private void KeyboardHandlerS(int key, int x, int y)

Descripción:

Método manejador que captura las teclas (mientras está en foco la ventana glut) especiales (down, left, rigth, up) cada vez que son presionadas.

Requiere los parámetros:

Key: Tipo int, que contiene la tecla que fue presionada.

74

x,y: Tipos int, que contienen las coordenadas x, y del pixel sobre el cual está el puntero del mouse al momento de presionar una tecla(teclado).

Private void Paint():

Descripción:

Método encargado de pintar la escena 3D que se muestra por la ventana en forma dinámica, cada cambio que se hace en la escena en tiempo de ejecución es mostrado gracias a este método.

Public override void SaveToXML(XmlElement parent):

Descripción:

Método encargado de guardar en el documento XML todas las propiedades de la clase World.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento XML padre.

Public override void LoadFromXML(XmlNode parent)

Descripción:

Método encargado de cargar desde el XML todas las propiedades de la clase

World.

Requiere los parámetros:

75

Parent: Tipo XmlNode, que contiene el nodo XML padre.

Public void ShowFps():

Descripción:

Método encargado de desplegar los frames por segundo que se están mostrando por la ventana que muestra la escena.

public virtual void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente del mundo.

Requiere los parámetros: writer: de tipo StreamWriter en cual la se escribirá el código del mundo (World).

public int SearchCode(string nameMethod)

Descripción:

Método que busca el código fuente de un método en particular dentro de la lista de métodos desensamblados (Methods de tipo List ) para construir el código del mundo.

Requiere los Parámetros: nameMethod: de tipo string que corresponde al nombre del método desensamblado al que se le desea ocupar el código.

76

public int SearchCodeField(string nameClass)

Descripción:

Método que busca las fields de una clase, esto dentro de la lista de Fields desensamblados (Fields de tipo List < DissasemblerClassField>) de la clase

World.

Requiere los Parámetros: nameClass: de tipo string, corresponde al nombre de la clase a la cual se quiere obtener el código de sus fields.

public string replaceVar(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase World por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.1.3 Propiedades:

Public String Name: establece u obtiene el nombre del mundo.

77

Public trajectory CameraPosition: establece u obtiene la posición de la cámara en el mundo.

Public Vector CameraRotation: establece u obtiene la rotación de la cámara en el mundo.

Public Entity Entities: establece u obtiene los objetos del mundo (objetos de tipo Entities).

Public bool TraslateModeMouse: Habilita o deshabilita el movimiento de traslación del objeto con el Mouse.

Public bool TraslateModeMouseX: Habilita o deshabilita el movimiento de traslación de objetos del mundo con el Mouse, usando como referencia el plano

YZ o X=0.

Public bool TraslateModeMouseY: Habilita o deshabilita el movimiento de traslación de objetos del mundo con el Mouse, usando como referencia el plano

XZ o Y=0.

78

Public bool TraslateModeMouseZ: Habilita o deshabilita el movimiento de traslación de objetos del mundo con el Mouse, usando como referencia el plano

XY o Z=0.

Public bool RotateModeMouse: Habilita o deshabilita el movimiento de

Rotación de los objeto del mundo con el Mouse.

Public bool RotateModeMouseX: Habilita o deshabilita el movimiento de

Rotación de los objeto del mundo con el Mouse, con referencia al plano YZ.

Public bool RotateModeMouseY: Habilita o deshabilita el movimiento de

Rotación de los objeto del mundo con el Mouse, con referencia al plano XZ.

Public bool RotateModeMouseZ: Habilita o deshabilita el movimiento de

Rotación de los objeto del mundo con el Mouse, con referencia al plano XY.

Public bool ScaleModeMouse: Habilita o deshabilita el escalamiento de los objetos del mundo con el Mouse.

Public bool ScaleModeMouseX: Habilita o deshabilita el escalamiento de los objetos del mundo con el Mouse, con referencia al plano YZ.

79

Public bool ScaleModeMouseY: Habilita o deshabilita el escalamiento de los objetos del mundo con el Mouse, con referencia al plano XZ.

Public bool ScaleModeMouseZ: Habilita o deshabilita el escalamiento de los objetos del mundo con el Mouse, con referencia al plano XY.

Public bool Histfig: establece u obtiene un arreglo que tiene un contador en cada posición del arreglo, de cada tipo de figura que ha sido creada en el mundo esta propiedad se utiliza para la construcción del nombre de los objetos tipo Entity.

Public dateTime Time: Obtiene o establece la fecha y hora del mundo.

Public Vector Size: Obtiene o establece el tamaño del mundo.

Public bool TraslateModeCameraX: Habilita o deshabilita el movimiento de traslación de la cámara en el mundo con el teclado, usando como referencia el plano YZ.

Public bool TraslateModeCameraY: Habilita o deshabilita el movimiento de traslación de la cámara en el mundo con el teclado, usando como referencia el plano XZ.

80

Public bool TraslateModeCameraZ: Habilita o deshabilita el movimiento de traslación de la cámara en el mundo con el teclado, usando como referencia el plano XY.

Public bool RotateModeCamera: Habilita o deshabilita el movimiento de

Rotación de la cámara con el teclado.

Public int RotateFactorCamera: Obtiene o establece la cantidad de rotación que se moverá la cámara.

Public int TraslateFactorCamera: Obtiene o establece la cantidad de traslación que se moverá la cámara.

Public int Prkeyent: Obtiene o establece el identificador del objeto que está seleccionado.

Public bool RenderMode: Obtiene o establece el modo de renderizado

(true=render false=wire) en que mostrará el mundo.

81

8.2.2 Class Entity:

Es la clase que reúne las características (métodos, propiedades y miembros) en común de todos los objetos (Entities) representables por el software.

8.2.2.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Trajectory Location

Posición de la entidad.

Private Vector Rotation

Rotación de la entidad.

Private Vector Scale

Escala de la entidad.

Private Bool plane_qutX False plano de corte en x.

Private Bool plane_qutY False plano de corte en y.

Private Bool plane_qutY False plano de corte en z.

Private List Entities

Lista de entidades que componen la entidad.

82

Private List Actions

Lista de acciones de la entidad.

Private List Inputs

Lista de entradas de la entidad.

Private List Outputs

Lista de salidas de la entidad.

Private System.Drawing.Image Textura

Textura entidad.

Private Vector Color Color de la entidad.

Private Bool on_Focus False

Foco entidad.

Private Int Slice

Detalle del modelo del Objeto 3D.

Private Int Stacks

Detalle del modelo del Objeto 3D.

8.2.2.2 Métodos: public virtual void NormalRender()

Descripción:

Método que muestra el objeto en modalidad render.

83

public virtual void DesignRender()

Descripción:

Método que muestra el objeto en modalidad design (diseño).

public virtual void SimulationRender()

Descripción:

Método que muestra el objeto en modalidad simulación.

public virtual void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Entity.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public double factor()

Descripción:

Calcula el factor de movimiento de los objetos para que se corresponda con el del mouse.

public override void SaveToXML(XmlElement parent)

Descripción:

84

Método que guarda las propiedades de los objetos en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public string replaceVar(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Entity por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.2.3 Propiedades:

85

Public string Name: Obtiene o establece el nombre objeto de tipo Entity.

Public Trajectory Location: Obtiene o establece la posición del objeto tipo

Entity en el mundo 3D.

Public vector Scale: Obtiene o establece la escala del objeto tipo Entity en el mundo 3D.

Public vector Rotation: Obtiene o establece la Rotación del objeto tipo Entity en el mundo 3D.

Public bool PlaneQutX: Obtiene o establece el plano de corte con referencia al plano X del objeto.

Public bool PlaneQutY: Obtiene o establece el plano de corte con referencia al plano Y del objeto.

Public bool PlaneQutZ: Obtiene o establece el plano de corte con referencia al plano Z del objeto.

Public int PrimaryKey: Obtiene o establece una llave primaria que identifica a un Objeto de tipo Entity.

86

Public System.Drawing.Image Texture: Obtiene o establece la textura de la entidad.

Public List Entities: Obtiene o establece las entidades que contienen la entidad.

Public List Actions: Obtiene o establece las acciones de la entidad.

Public Vector Color: Obtiene o establece el color de la entidad.

8.2.3 Class XMLConverter:

Es la encargada la guardar o cargar información de la escena además hereda comportamientos, a las clases que hereden de ella para guardar o cargar datos desde un Xml.

8.2.3.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private XmlNode Textura

Es un nodo Xml que guarda una textura.

8.2.3.2 Métodos:

87

public static XmlNode ImageToXMLNode(Image imagen)

Descripción:

Método que recibe una imagen, la codifica binariamente y la deja en un nodo

Xml.

Requiere los parámetros:

Imagen: de tipo Image, que contiene la imagen a codificar binariamente para ser guardada en un nodo Xml.

public static XmlNode ImageToXMLNode(System.Drawing.Image imagen, string nombre)

Descripción:(recarga)

Método que recibe una imagen, la codifica binariamente y la deja en un nodo

Xml.

Requiere los parámetros:

Imagen: de tipo Image, que contiene la imagen a codificar binariamente para ser guarda en un nodo Xml.

Nombre: de tipo string, que contiene el nombre de la textura a codificar, el cual igual se guardará en el Xml.

public static Image XMLNodeToImage(XmlNode Nodo)

Descripción:

88

Deserializa el XML y retorna la Imagen.

Requiere los parámetros:

Nodo: de tipo de XmlNode, que contiene la imagen deserializar.

public override void SaveToXML(XmlElement child,XmlElement parent,Entity entity)

Descripción:

Método que guarda las propiedades de los objetos hijos de un objeto tipo

Custom en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre. child: Tipo XmlElement, que contiene el elemento Xml hijo.

Entity: Tipo Entity, que contiene el objeto hijo al cual se le guardarán las propiedades en el Xml.

public void LoadFromXML(XmlNode xmlent, World world, Entity entity)

Descripción:

Método que carga las propiedades de los objetos hijos de un objeto tipo Custom en el Xml.

Requiere los parámetros: xmlent: Tipo XmlElement, que contiene el objeto hijo serializado.

89

world: Tipo World, que contiene los objetos del mundo.

Entity: Tipo Entity, que contiene el objeto hijo al cual se le cargarán las propiedades desde el Xml.

8.2.4 Class GlPrimitives:

GlPrimitives es la clase que proporciona métodos para dibujar primitivas

3D mediante llamadas OpenGL, además proporciona métodos para manipular las primitivas OpenGL.

8.2.4.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Glu.GLUquadric Quadric

Variable de tipo GLUquadric necesaria para construir primitivas de tipo Quádricas.

Private Bool Gotquadric False

Sirve para verificar si la variable quadric ha sido asociada a un objeto quádrico.

Private double[] clippingPlane1 { 1.0, 0.0, 0.0, 0.0} Arreglo que guarda la representación del plano de corte x=0.

Private double[] clippingPlane2 { 0.0, 1.0, 0.0, 0.0 } Arreglo que guarda la representación del plano de corte y=0.

90

Private double[] clippingPlane3 { 0.0, 0.0, 1.0, 0.0 } Arreglo que guarda la representación del plano de corte z=0.

8.2.4.2 Métodos: public static void RenderSphere(double Radius,int slice,int stacks)

Descripción:

Método que construye la primitiva OpenGL esfera sólida.

Requiere los parámetros:

Radius: de tipo double, es el radio de la esfera.

Slice: de tipo Int, establece calidad del modelo de la primitiva.

Stacks: de tipo Int, establece calidad del modelo de la primitiva.

public static void RenderSphereWire(double Radius,int slice,int stacks)

Descripción:

Método que construye la primitiva OpenGL esfera cableada.

Requiere los parámetros:

Radius: de tipo double, es el radio de la esfera.

Slice: de tipo Int, establece calidad del modelo de la primitiva

Stacks: de tipo Int, establece calidad del modelo de la primitiva.

91

public static void RenderCylinder(double baseRadius,double topRadius,double heigth, int slice, int stacks)

Descripción:

Método que construye la primitiva OpenGL cilindro sólido.

Requiere los parámetros: baseRadius: de tipo double, es el radio basal del cilindro. topRadius: de tipo double, es el radio superior del cilindro.

Heigth: de tipo double, es la altura del cilindro.

Slice: de tipo Int, establece calidad del modelo de la primitiva.

Stacks: de tipo Int, establece calidad del modelo de la primitiva.

public static void RenderCylinderWire(double baseRadius,double topRadius,double heigth, int slice, int stacks)

Descripción:

Método que construye la primitiva OpenGL cilindro cableado.

Requiere los parámetros: baseRadius: de tipo double, es el radio basal del cilindro. topRadius: de tipo double, es el radio superior del cilindro.

Heigth: de tipo double, es la altura del cilindro.

Slice: de tipo Int establece calidad del modelo de la primitiva.

Stacks: de tipo Int establece calidad del modelo de la primitiva.

92

public static void RenderDisk(double innerRadius,double outerRadius, int slice, int stacks)

Descripción:

Método que construye la primitiva OpenGL disco sólido.

Requiere los parámetros: innerRadius: de tipo double, es el radio interior del cilindro. outerRadius: de tipo double, es el radio externo del cilindro.

Slice: de tipo Int, establece calidad del modelo de la primitiva.

Stacks: de tipo Int, establece calidad del modelo de la primitiva.

public static void RenderDiskWire(double innerRadius,double outerRadius, int slice, int stacks)

Descripción:

Método que construye la primitiva OpenGL disco cableado.

Requiere los parámetros: innerRadius: de tipo double, es el radio interior del cilindro. outerRadius: de tipo double, es el radio externo del cilindro.

Slice: de tipo Int, establece calidad del modelo del Objeto 3D.

Stacks: de tipo Int, establece calidad del modelo del Objeto 3D.

93

public static void RenderCube(double x)

Descripción:

Método que construye la primitiva OpenGL cubo sólido.

Requiere los parámetros: x: de tipo double, es el tamaño del lado del cubo.

public static void RenderBox(double width, double height, double depth)

Descripción:

Método que construye la primitiva OpenGL Box sólido.

Requiere los parámetros:

Width: de tipo double, es el ancho de la caja.

Heigth: de tipo double, es la altura de la caja.

Depth: de tipo double, es el largo de la caja.

public static void RenderBoxWire(double width, double height, double depth)

Descripción:

Método que construye la primitiva OpenGL Box cableado.

Requiere los parámetros: width: de tipo double, es el ancho de la caja.

Heigth: de tipo double, es la altura de la caja.

Depth: de tipo double, es el largo de la caja.

94

public static void RenderSquare(double x)

Descripción:

Método que construye la primitiva OpenGL cuadrado sólido.

Requiere los parámetros: x: de tipo double, es el tamaño del lado del cuadrado.

public static void RenderSquareWire(double x)

Descripción:

Método que construye la primitiva OpenGL cuadrado cableado.

Requiere los parámetros: x: de tipo double, es el tamaño del lado del cuadrado.

public static void RenderTriangle(double Sizesides)

Descripción:

Método que construye la primitiva OpenGL triángulo sólido.

Requiere los parámetros:

Sizesidez: de tipo double, es el tamaño del lado del triángulo equilátero.

public static void RenderPyramid(double x)

Descripción:

Método que construye la primitiva OpenGL Pirámide sólida.

95

Requiere los parámetros: x: de tipo double, es la distancia del centro de la pirámide a sus vértices.

public static void RenderPyramidWire(double x)

Descripción:

Método que construye la primitiva OpenGL Pirámide cableado.

Requiere los parámetros: x: de tipo double, es la distancia del centro de la pirámide a sus vértices.

public static void RenderCircle(float radius)

Descripción:

Método que construye la primitiva OpenGL Círculo cableado.

Requiere los parámetros: radius: de tipo float, es el tamaño del radio del círculo.

public static void RenderCircleWire(float radius)

Descripción:

Método que construye la primitiva OpenGL Círculo cableado.

Requiere los parámetros: radius: de tipo float, es el tamaño del radio del círculo.

96

public static void RenderPoligon(double Sizesides,int sides)

Descripción:

Método que construye la primitiva OpenGL Polígono sólido.

Requiere los parámetros:

Sizesidez: de tipo double, es el tamaño del lado del polígono.

Sides: de tipo int, es la cantidad de lados del polígono.

public static void RenderPoligonWire(double Sizesides,int sides)

Descripción:

Método que construye la primitiva OpenGL Polígono cableado.

Requiere los parámetros:

Sizesidez: de tipo double, es el tamaño del lado del polígono.

Sides: de tipo int, es la cantidad de lados del polígono.

public static void RenderPcBot()

Descripción:

Método que construye la primitiva OpenGL Tanque.

97

public static void postredisplay()

Descripción:

Método que llama a un postRediplay OpenGL.

public static void PushMatrix()

Descripción:

Método que llama a un PushMatrix OpenGL.

public static void LoadName(int name)

Descripción:

Método que asocia un identificador a una primitiva OpenGL.

Requiere los parámetros: name:Tipo Int, contiene el identificador que se asociará a la primitiva.

public static void Traslate(double x,double y, double z)

Descripción:

Método que traslada las primitivas.

Requiere los parámetros: x: de tipo double, contiene lo que se trasladará la primitiva en x. y: de tipo double, contiene lo que se trasladará la primitiva en y. z: de tipo double, contiene lo que se trasladará la primitiva en z.

98

public static void Scale(double x, double y, double z)

Descripción:

Método que escala las primitivas.

Requiere los parámetros: x: de tipo double, contiene lo que se escalará la primitiva en x. y: de tipo double, contiene lo que se escalará la primitiva en y. z: de tipo double, contiene lo que se escalará la primitiva en z.

public static void Rotate(double x, double y, double z)

Descripción:

Método que rota las primitivas.

Requiere los parámetros: x: de tipo double, contiene lo que se rotará la primitiva en x. y: de tipo double, contiene lo que se rotará la primitiva en y. z: de tipo double, contiene lo que se rotará la primitiva en z.

public static void Color(double r, double g, double b)

Descripción:

Método que colorea las primitivas.

Requiere los parámetros: r: de tipo double, contiene el componente r del color de el objeto.

99

g: de tipo double, contiene el componente g del color del objeto. b: de tipo double, contiene el componente b del color de el objeto.

public static void Onfocus(string name,double x,double y,double z)

Descripción:

Método que le da foco a la primitiva OpenGL.

Requiere los parámetros:

Name: de tipo string, contiene el nombre del objeto (no de la primitiva). x: de tipo double, contiene la posición de la primitiva en x. y: de tipo double, contiene la posición de la primitiva en y. z: de tipo double, contiene la posición de la primitiva en z.

public static void plane()

Descripción:

Método que construye la primitiva OpenGL plano.

8.2.5 Class Sphere:

Clase que hereda de Entity la cual se encarga de construir un objeto de tipo Sphere y además ofrecer las propiedades referentes a este tipo de objetos.

100

8.2.5.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Radius 2

Radio de la esfera.

8.2.5.2 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Sphere en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Sphere en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos tipo Sphere en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

101

Descripción:

Método que carga las propiedades de los objetos tipo Sphere desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public virtual void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un objeto de tipo Sphere.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarSphere(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Sphere, por el valor que estas tienen en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

102

8.2.5.3 Propiedades:

public double Radius: establece u obtiene el radio de la esfera.

8.2.6 Class Box:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Box y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.6.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Width

Ancho de la caja.

Private Double Heigth

Altura de la caja.

Private Double Depth

Largo de la caja.

Private Int Text

Dirección de memoria de la textura que cubre a la caja.

8.2.6.2 Métodos: public override void NormalRender()

103

Descripción:

Método que muestra el objeto de tipo box en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo box en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades del objeto tipo Box en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades del objeto tipo Box desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

104

Método que escribe el código fuente de un Objeto 3D de tipo Box.

Requiere los parámetros: writer: de tipo StreamWriter en el cual se escribirá el código.

public string replaceVarBox(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Box por el valor que estas tienen en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.6.3 Propiedades: public double Width: propiedad que obtiene o establece el ancho de la caja.

public double Heigth: propiedad que obtiene o establece la altura de la caja.

public double Depth: propiedad que obtiene o establece el largo de la caja.

105

8.2.7 Class Cylinder:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Cylinder y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.7.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double baseRadius

Radio basal del cilindro.

Private Double topRadius

Radio superior del cilindro.

Private Double Heigth

Altura del cilindro.

Private Int Slice

Detalle de Modelo del cilindro.

Private Int Stacks

Detalle de Modelo del cilindro.

8.2.7.2 Métodos: public override void NormalRender()

Descripción:

106

Método que muestra el objeto de tipo Cylinder en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Cylinder en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo Cylinder en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Cylinder desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un objeto de tipo Cylinder.

107

Requiere los parámetros: writer: de tipo StreamWriter en cual la se escribirá el código.

public string replaceVarCylinder(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Cylinder por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.7.3 Propiedades: public double BaseRadius: propiedad que obtiene o establece el radio basal del cilindro.

public double TopRadius: propiedad que obtiene o establece el radio superior del cilindro.

public double Heigth: propiedad que obtiene o establece la altura del cilindro.

108

public int Slice: propiedad que obtiene o establece el detalle del modelo.

public int Stacks: propiedad que obtiene o establece el detalle del modelo.

8.2.8 Class Pyramid:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Pyramid y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.8.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Size

Distancia desde el centro de la pirámide a sus vértices.

8.2.8.2 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Pyramid en modalidad render.

public override void DesignRender()

Descripción:

109

Método que muestra el objeto de tipo Pyramid en modalidad design(diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo Pyramid en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Pyramid desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Pyramid.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

110

public string replaceVarPyramid(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Pyramid por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.8.3 Propiedades: public double Size: propiedad que obtiene o establece el tamaño de la

Pirámide.

8.2.9 Class Disk:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Disk y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.9.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double InnerRadius

Radio interior del disco.

111

Private Double OuterRadius

Radio exterior del disco.

Private Int Slice

Detalle de Modelo del Disco

Private Int Stacks

Detalle de Modelo del Disco.

8.2.9.2 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo disk en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo disk en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo “disk” en el Xml.

Requiere los parámetros:

112

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo disk desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo disk.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarDisk(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase “Disk” por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros:

113

body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.9.3 Propiedades: public double InnerRadius: propiedad que obtiene o establece el radio interno del disco.

public double OuterRadius: propiedad que obtiene o establece el radio exterior del disco.

public int Slice: propiedad que obtiene o establece el detalle del modelo.

public int Stacks: propiedad que obtiene o establece el detalle del modelo.

8.2.10 Class Square:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Square y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.10.1 Miembros:

Modificador de Tipo Nombre Valor acceso

114

Private Double Size

Tamaño del cuadrado.

8.2.10.2 Métodos. public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Square en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Square en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo square en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo square desde el Xml.

115

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Square.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarSquare(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Square por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.10.3 Propiedades: public double Size: propiedad que obtiene o establece el tamaño del Objeto

3D Square.

116

8.2.11 Class Circle:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Circle y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.11.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Radius

Radio del círculo.

8.2.11.2 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Circle en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Circle en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

117

Método que guarda las propiedades de los objetos de tipo Circle en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Circle desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Circle.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarCircle(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Circle por el valor constante que tienen estas en tiempo de ejecución.

118

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.11.3 Propiedades: public double Radius: propiedad que obtiene o establece el radio del Objeto

3D de tipo Circle.

8.2.12 Class Poligon:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Poligon y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.12.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Size

Tamaño del lado del polígono equilátero.

Private Int Sides

Cantidad de lados del polígono.

8.2.12.2 Métodos:

119

public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Poligon en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Poligon en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo Poligon en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Poligon desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

120

Descripción:

Método que escribe el código fuente de un objeto de tipo Poligon.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarPoligon(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Poligon por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.12.3 Propiedades: public double Size: Obtiene o establece el tamaño del lado del polígono equilátero.

Public int sizes: Obtiene o establece la cantidad de lados del polígono equilátero.

121

8.2.13 Class Triangle:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Triangle y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.13.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double Size

Tamaño del lado del triángulo equilátero.

8.2.13.2 Métodos:

Public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Triangle en modalidad render.

public override void DesignRender()

Descripción:

Método que muestra el objeto de tipo Triangle en modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

122

Descripción:

Método que guarda las propiedades de los objetos de tipo Triangle en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Triangle desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un objeto de tipo Triangle.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

public string replaceVarTriangle(string body)

Descripción:

123

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Triangle por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.13.3 Propiedades:

Public double Size: Obtiene o establece el tamaño del lado del triángulo equilátero.

8.2.14 Class Tank:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Tank y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.14.1 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Tank en modalidad render.

124

public override void DesignRender()

Descripción:

Método que muestra el objeto en de tipo Tank modalidad design (diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo Tank en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Tank desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un objeto de tipo Tank.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

125

public string replaceVarTank(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Tank por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.15 Class Ligth:

Clase que hereda de Entity la cual está encargada de construir una fuente de luz y además ofrecer las propiedades referentes a esta.

8.2.15 .1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Int Ligth

Variable que identifica una fuente de luz.

Private Vector lightAmbientVector

Vector que sirve para cambiar la luz ambiente de una fuente de luz dinámicamente.

Private Vector lightDiffuseVector

126

Vector que sirve para cambiar la difusión de una fuente de luz dinámicamente.

Private float[] LightAmbient { 0.0f, 0.0f, 0.0f, 0.0f } Ambiente de la fuente de luz.

Private float[] LightDiffuse { 1f, 1f, 1f, 1f }

Difusión de la fuente de luz.

8.2.15.2 Métodos: public override void NormalRender()

Descripción:

Método que muestra la luz sin mostrar la posición de la fuente.

public override void DesignRender()

Descripción:

Método que muestra la luz y la posición de la fuente.

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de la luz en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

127

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de la luz desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Ligth.

Requiere los parámetros: writer: de tipo StreamWriter en cual la se escribirá el código.

public string replaceVarLigth(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Ligth por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

128

8.2.15.3 Propiedades: public int Ligths: Obtiene o establece el identificador de la fuente de luz.

public Vector LightDiffuse: Obtiene o establece la difusión de la luz de una fuente.

public Vector LightAmbient: Obtiene o establece la luz ambiente de una fuente.

8.2.16 Class Custom:

Clase que hereda de Entity la cual está encargada de construir un objeto de tipo Custom (objeto compuesto) y además ofrecer las propiedades referentes a este tipo de objetos.

8.2.16.1 Métodos: public override void NormalRender()

Descripción:

Método que muestra el objeto de tipo Custom en modalidad render.

public override void DesignRender()

129

Descripción:

Método que muestra el objeto de tipo Custom en modalidad design(diseño).

public override void SaveToXML(XmlElement parent)

Descripción:

Método que guarda las propiedades de los objetos de tipo Custom en el Xml.

Requiere los parámetros:

Parent: Tipo XmlElement, que contiene el elemento Xml padre.

public override void LoadFromXML(XmlNode parent)

Descripción:

Método que carga las propiedades de los objetos de tipo Custom desde el Xml.

Requiere los parámetros:

Parent: Tipo XmlNode, que contiene el nodo Xml padre.

public override void ToSource(StreamWriter writer)

Descripción:

Método que escribe el código fuente de un Objeto 3D de tipo Custom.

Requiere los parámetros: writer: de tipo StreamWriter en cual se escribirá el código.

130

public string replaceVarCustom(string body)

Descripción:

Método que reemplaza las variables del código fuente desensamblado de un método o field de la clase Custom por el valor constante que tienen estas en tiempo de ejecución.

Requiere los Parámetros: body: de tipo string, es el código fuente de un método desensamblado al cual se le quiere reemplazar sus variables.

8.2.17 Class Action:

Clase encargada de construir una acción para un Objeto.

(Solo se propondrá una versión beta ya que el proyecto no contempla la funcionalidad de animación avanzada)

8.2.17.1 Miembros.

Modificador de Tipo Nombre Valor acceso Private Double target_x

Cantidad de movimiento x.

Private Double target_y

Cantidad de movimiento y.

Private Double target_z

131

Cantidad de movimiento z.

Private Int typeAction

Tipo de movimiento(traslación, rotación o escalamiento)

8.2.17.2 Propiedades: public double TargetX: obtiene o establece la cantidad en x que el objeto se moverá.

public double TargetY: obtiene o establece la cantidad en y que el objeto se moverá.

public double TargetZ: obtiene o establece la cantidad en z que el objeto se moverá.

public int TypeAction: obtiene o establece el tipo de acción.

8.2.18 Class Dissasembler:

Dissasembler es la clase encargada de desensamblar las clases del proyecto para obtener el código fuente de ellas.

132

8.2.18.1 Métodos: public static List DissasemblerC(String Assembly,ref

List Field)

Descripción:

Método que obtiene el código fuente de de todas la clases del proyecto y las devuelve por medio de dos listas de objetos de tipo DissasemblerMethod y

DissasemblerClassField.

Requiere los parámetros:

Assembly: de tipo string, que en este caso es la ruta (“path”, ubicación) donde está el proyecto al cual se le desensamblan sus clases.

Field: de tipo ref List que es una lista en donde se devolverán el código correspondiente a los campos de cada una de las clases del proyecto.

8.2.19 Class ZeroFxInterface:

Clase encargada de ofrecer una interfaz visual para la manipulación del mundo y sus objetos. Ofrece menús para cargar y guardar la escena; soporte básico para creación y edición de objetos mediante menús, soporte avanzado para manipulación de la cámara en la escena y configuraciones del Mundo 3D.

133

8.2.19.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private World World

Mundo 3D.

Private Engine Engine

Engine para manipular el mundo 3D.

Private XmlDocument Xml

Documento Xml usado para cargar o guardar la configuración de la interfaz visual del software.

Private (controles win forms) Controles winforms y los métodos de esta clase, no se describirán en detalle ya que sería muy extenso, el código se encuentra documentado igualmente.

8.2.20 SceneEditInterface:

Clase encargada de ofrecer una interfaz visual avanzada para la creación y edición de Objetos (Entities) y el Mundo. Ofrece una interface visual para la creación y edición de luces y ofrece una interface visual para la creación de objetos de tipo compuesto (Custom).

8.2.20.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private World World

134

Mundo 3D.

Private Engine Engine

Engine para manipular el mundo 3D.

Private (controles win forms) Controles winforms y los métodos de esta clase, no se describirán en detalle ya que sería muy extenso, el código se encuentra documentado igualmente.

8.2.21 Class Engine:

Engine es la clase encargada de proporcionar interfaces para manipular el mundo y sus objetos, tales como teclado y mouse, además provee métodos de creación de objetos y manipulación de cámaras.

8.2.21.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private List list_world

Lista de Mundos 3D.

Private Int Camera

Identificador de la cámara activa.

135

8.2.21.2 Métodos: public void CreateEntityWorld(World world, Entity entity, Double r, Double g,

Double b)

Descripción:

Método que agrega un objeto 3D a un mundo especificado.

Requiere los parámetros: world: objeto de tipo World, donde se agregará el objeto 3D. entity: objeto de tipo Entity, el cual se agregará al Mundo 3D (world). r,g,b: parámetros de tipo double,los cuales establecerán el color del Objeto 3D.

public Entity EntitySearch(string name,World world)

Descripción:

Método que busca un objeto en el mundo.

Requiere los parámetros: name: de tipo string, el cual es el nombre del objeto 3D a buscar. world : de tipo world, es el mundo 3D donde se buscará el objeto 3D.

public void AddEntityToEntity(Entity custom, Entity child)

Descripción:

Método que le agrega un objeto 3D hijo a un objeto Custom (padre).

Requiere los parámetros:

136

Custom: de tipo Entity, objeto padre.

Child: de tipo Entity, objeto hijo.

public void MouseEngine(int x, int y, int oldX, int oldY, int Prkeyent, World world)

Descripción:

Método encargado de editar (escala, posición, rotación) el objeto seleccionado mediante el mouse.

Requiere los parámetros: x: de tipo int, es la posición en x del mouse.

Y: de tipo int, es la posición en y del mouse. oldX: de tipo int, es la posición anterior en x del mouse. oldY: de tipo int, es la posición anterior en y del mouse.

Prkeyent: de tipo int, es el id del objeto seleccionado actualmente. world: de tipo World, el mundo 3D que está editando el mouse.

public void KeyboardEngine(int key,World world)

Descripción:

Método que está encargado de modificar el mundo y sus objetos mediante el teclado, incluye el manejo para teclas especiales.

Requiere los parámetros: key: de tipo entero, es el identificador de la tecla que ha sido presionada.

137

world: de tipo World, es el mundo que será manipulado con el teclado.

public void KeyboardEngine(byte key,World world) (sobrecarga)

Descripción:

Método que está encargado de modificar el mundo y sus objetos mediante el teclado.

Requiere los parámetros: key: de tipo byte, es el id de la tecla que ha sido presionada. world: de tipo World, es el mundo que será manipulado con el teclado.

public void SelectCamera(int camera,World world)

Descripción:

Método que está encargado de seleccionar la cámara.

Requiere los parámetros: camera: de tipo int, que identifica la cámara a seleccionar. world: de tipo World, es el mundo 3D al cual se le establecerá una cámara.

public void SaveProyect(SaveFileDialog saveFileDialog, World world,

XmlElement parent)

Descripción:

Método que está encargado de guardar el proyecto gráfico en un archivo XML.

138

Requiere los parámetros: saveFileDialog: de tipo SaveFileDialog, el cual captura el path donde se guardará el Xml del proyecto. world: de tipo World, es el mundo 3D el cual se guardará en el Xml.

public void LoadProyect(OpenFileDialog openFileDialog,World world,XmlElement parent)

Descripción:

Método que está encargado de restaurar el proyecto gráfico desde un archivo

XML.

Requiere los parámetros: openFileDialog: de tipo OpenFileDialog, el cual captura el path de donde se restaurará el documento XML del proyecto. world: de tipo World, es el mundo 3D el cual se restaurará desde el XML.

public void CreateEntityCustomWorld(World world,Entity custom,String Name)

Descripción:

Método que agrega un objeto 3D de tipo “Custom” a un mundo especificado.

Requiere los parámetros: world: objeto de tipo World donde se agregará el objeto 3D. custom: objeto de tipo Custom, el cual se agregará al Mundo 3D (world).

139

public void DetailModel(int detail,World world)

Descripción:

Método que está encargado de aplicar el detalle de modelo al mundo.

Requiere los parámetros: detail: de tipo int, que establece el grado de detalle.(mientras mayor más detalle del modelo) world: de tipo World, es el mundo 3D el cual se le aplicará el detalle de modelo.

8.2.21.3 Propiedades: public List ListWorld: obtiene o establece una lista de objetos de tipo

World.

public int Camera: obtiene o establece la cámara activa en el mundo.

8.2.22 Class LanguageWriterConfiguration:(clase de apoyo de

Dissasembler)

Es la clase encargada de configurar las partes de la clase que se

Desensamblarán.

140

8.2.23 Class CustomAssemblyResolver:(clase de apoyo de Dissasembler)

Es la clase encargada de cargar un ensamblado dado usando una librería “reflector.dll” que sirve como clase de apoyo al desensamblador.

8.2.24 Class DissasemblerClassField:

Clase encargada de guardar el código de los campos de una clase desensamblada.

8.2.24.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double class_name

Nombre de la clase.

Private Double Body

Código fuente de las fields de la clase.

8.2.24.2 Propiedades:

public string ClassName: obtiene o establece el nombre de la clase de donde se obtendrán los fields .

141

public string Body: obtiene o establece el código de los fields de una clase.

public int Parameter: obtiene o establece el número de parámetros del método desensamblado, sirve para distinguir métodos sobrecargados.

8.2.25 Class DissasemblerMethod:

Clase encargada de guardar el código de un método de una clase desensamblada.

8.2.25.1 Miembros:

Modificador de Tipo Nombre Valor acceso Private Double class_name

Nombre de la clase.

Private String Body

Código fuente del método desensamblado.

Private String Name

Nombre del método desensamblado.

Private Int Parameter

Número de parámetros del método desensamblado sirve para distinguir métodos sobrecargados.

142

8.2.25.2 Propiedades: public string Name: obtiene o establece el nombre del método desensamblado.

public string NameClass: obtiene o establece el nombre de la clase del método desensamblado.

public string Body: obtiene o establece el cuerpo del método desensamblado.

public int Parameter: obtiene o establece el número de parámetros del método desensamblado, sirve para distinguir métodos sobrecargados.

143

8.32 Casilla de Responsabilidades.

A continuación, se mostrará un diagrama resumen de la responsabilidad de cada clase con el fin mostrar una visión global del rol que cumple cada clase en el funcionamiento de la aplicación.

World Entity GlPrimitives Action -Es la clase encargada de inicializar y deplegar -Es la clase que reúne las características -Proporciona métodos -Es la encargada de definir acciones la ventana Glut por la que se muestra en común de todos los objetos representables para dibujar primitivas 3D para los objetos del mundo. el espacio 3D donde están contenidos por el software. mediante llamadas OpenGl. los objetos. -Proporciona métodos para Inputs -Prorporciona métodos y propiedades manipular las primitivas OpenGl para controlar y mostrar el mundo 3D. Engine -Es la encargada de definir Inputs para los objetos del mundo. -Contiene la colección de objetos presentes en el mundo. -Clase encargada de porporcionar métodos de mainipulación del mundo Outputs 3D y sus Objtos, proporciona un nivel Dissasembler más alto de abstracción que la clase World. -Es la encargada de definir Outputs XmlConverter para los objetos del mundo. -Es la encargada de obtener -Proporciona métodos de manipulación el código fuente de las clases -Es la clase encargada la guardar y cargar del mundo mediante el mouse y teclado. de la aplicación. información de la escena y heredar comportamientos para guardar o cargar CustomAssemblyResolver datos desde un xml. -Es la clase encargada de cargar un Asembly dado usando la dll reflector, sirve como clase de apoyo a dissasembler. WorldUserInterface

-Clase encargada de ofrecer una interfaz visual Sphere LanguageWriterConfiguration Cylinder para la manipulación del mundo 3D. -Sphere es la clase encargada -Es la clase encarda de configurar las partes de la clase que se -Cylinder es la clase encargada -Ofrece menus para cargar y guardar la escena. de constuir objetos 3D de desensamblaran. de construir y representar tipo esfera. un objeto 3D de tipo cylinder. -Soporte básico para creación y edición de objetos mediante menus.

Box -Soporte avanzado para manipulación de la Ligth cámara en la escena y configuraciones del Mundo 3D. DissasemblerMethod -Es la clase encargada de construir y representar -Ligth es la clase encargada -Clase encargada guardar el código de un método de una clase desensamblada. objetos 3d de tipo Box. de construir fuentes de luz. EntityUserInterface

-Clase encargada de ofrecer una interfaz visual DissasemblerClassField Pyramid Square Avanzada para para la creación y edición de Objetos(Entities). -Clase encargada guardar el código de los fileds de una clase desensamblada. -Es la encargada de construir -Es la encargada de construir y representar Objetos de y representar Objetos de -Ofrece una interface visual para la creación y tipo Pyramid. tipo Square. edición de fuentes de luz. -Ofrece una interface visual para la creación de objetos de tipo compuesto(custom). Circle Poligon

-Es la encargada de construir -Es la encargada de construir y representar Objetos de tipo y representar Objetos de tipo Circle. Poligon.

Custom Triangle Disk Tank -Es la encargada de construir -Es la encargada de construir -Es la encargada de construir -Es la encargada de construir y representar Objetos de tipo y representar Objetos de tipo y representar Objetos de tipo y representar Objetos de tipo custom los cuales están formados Triangle. Disk. Tank. a su vez por otros objetos. Fi

Diagramas Casilla de Responsabilidades

144

8.4 Diagrama de Procesos.

A continuación se mostrará el diagrama de flujo de algunos de los procesos más importantes de la aplicación, los cuales muestran la lógica de su funcionamiento, estos diagramas suministran como producto la base lógica de la programática de la aplicación.

8.4.1 Diagrama de Proceso Creación y edición de un Objeto 3D.

El siguiente diagrama (Figura 1) muestra la lógica con que se crea y edita un objeto 3D, este diagrama se ha abordado desde el punto de vista de un

Objeto 3D genérico.

145

El usuario usa las interfaces (Teclado o Formulario) para Se crea un objeto crear un Objeto. 3D.

Se agrega el Objeto 3D a la colección de objetos del mundo.

El usuario Selecciona como se mostrará el Objeto.

¿Que Modalidad El Objeto 3D se El Objeto 3D se de despliegue del muestra en muestra en Design Render Objeto 3D Render modalidad modalidad Design. o Design? Render.

Se Refresca la ventana por donde se muestra el El usuario mediante las mundo. interfaces (Teclado o Formulario) Eliminar un Objeto.

El usuario mediante El usuario mediante El usuario mediante las las interfaces (Teclado las interfaces interfaces (Teclado o o Formulario) (Teclado o El usuario mediante Formulario) habilita Selecciona una Formulario) agrega las interfaces (Teclado Traslación/Rotación/Escala textura para aplicar al el Objeto 3D a un o Formulario) aplica del Objeto 3D. Objeto 3D Objeto compuesto. Planos de Corte.

i El Objeto 3D es eliminado de la colección de Objetos del Se aplica los Mundo o de un planos de corte Traslada/Rota/ Objeto Se Aplica la seleccionados por Escala el Objeto textura Compuesto. el usuario al Se agrega el 3D como el seleccionada por Objeto 3D. Objeto 3D a un usuario requiera el usuario al Objeto mediante Mouse o Objeto 3D. compuesto. Teclado.

Figura 1

Como se puede observar en el diagrama anterior, se muestra la secuencia lógica para la creación y edición de un objeto, se puede observar además, que este diagrama de proceso no posee un estado final, esto debido a que después de que el usuario selecciona la modalidad de despliegue del objeto, este entra en un ciclo iterativo de edición.

146

8.4.2 Diagrama de Proceso Guardar escena.

El siguiente diagrama (Figura 2), muestra la lógica de cómo se guardará la escena en un archivo XML con el objetivo de guardar el trabajo realizado con el Editor 3D, para posteriormente ser retomado, básicamente la lógica programática se centra en la ejecución de un método llamado “SaveToXml” que guarda las propiedades de las instancias (Objetos) actuales del Editor 3D en un archivo Xml.

El usuario selecciona guardar escena en el menú principal de la aplicación.

Se ejecuta el método SaveToXml de todas las instancias que posean este método.

La escena es guardada en el Xml lista para ser cargada por la aplicación cuando el usuario lo requiera.

Figura 2

147

8.4.3 Diagrama de Proceso Cargar escena.

El siguiente diagrama (Figura 3), muestra la lógica de cómo se cargará la escena desde archivo Xml con el objetivo de retomar el trabajo hecho con el

Editor 3D, básicamente la lógica programática se centra en la ejecución de dos métodos llamados InitEntityFromXml y LoadFromXml, el primero se encarga de crear las instancias necesarias y el segundo es encargado de asignarle las propiedades a estas instancias, la información respecto a las instancias que se deben crear y las propiedades que se les deben asignar vienen en el archivo

Xml.

El usuario selecciona Cargar escena en el menú principal de la aplicación.

Se ejecuta el método InitEntityFromXml para crear las instancias necesarias según la información que trae el Xml.

Se ejecuta el método LoadFromXml para cargar las propiedades de las instancias creadas en el proceso anterior desde el Xml.

La escena es cargada por la aplicación y queda lista para seguir siendo editada por el usuario.

Figura 3

148

Finalmente, una vez ejecutados todos los pasos lógicos del diagrama, la escena queda restaurada totalmente lista para seguir siendo diseñada.

8.4.4 Diagrama de Proceso Generación código Fuente de la escena

Diseñada con el Editor 3D.

El siguiente diagrama (Figura 4) muestra la lógica de cómo se generará el código fuente a partir de lo diseñado con el Editor 3D.

149

El usuario selecciona Exportar a código C# la escena en el menú principal de la aplicación.

Se desensamblan las clases gráficas de Editor 3D.

Se ejecuta el método ToSource de todas las instancias que posean este método.

Se genera una clase C# que es capas de desplegar la escena diseñada anteriormente con el Editor 3D.

La clase C# es agregada a un proyecto Visual Studio.

El editor 3D ejecuta automáticamente Visual Studio con el proyecto ya cargado listo para compilar y ejecutarse.

Figura 4

8.4.5 Diagrama de Proceso de Selección de objetos Mediante el Mouse.

El siguiente diagrama (Figura 5) muestra los pasos lógicos para realizar la selección de objetos mediante el Mouse.

150

Cada vez que se crea un objeto se le asigna un nombre (número entero).

Se obtienen las coordenadas de donde se encuentra el cursor del Mouse en la ventana.

Se habilita el modo de selección de OpenGL.

Se define el área de selección de modo que sólo una pequeña

parte de la ventana sea tomada en cuenta, esta debe ser en

donde está el cursor del Mouse.

Se llama al método que despliega la escena a la cual se le seleccionaran los objetos.

Se debe salir del modo de selección e identificar los objetos que fueron presionados en esa pequeña parte de la pantalla.

Se establece en foco el objeto seleccionado más cercano a la cámara y se le cargan sus propiedades.

Figura 5

Este proceso (Figura 5), es uno de los más relevantes debido a que es muy necesario para el funcionamiento del Editor 3D.

151

9. Construcción del Software

En este capítulo se abordará la construcción de la aplicación para esto, se definieron dos versiones, una versión beta que tiene la funcionalidad de editor 3D y una versión final que tendrá además la funcionalidad de generación de código, por lo tanto la construcción se dividió en base a ésto, a continuación se describirá en detalle de como se construyó cada funcionalidad.

9.1 Construcción Aplicación versión Beta (solo Funcionalidad de Editor 3D).

Esta versión de la aplicación fue obtenida mediante la construcción de una lista de funcionalidades, éstas fueron construidas en base a los casos de uso, diagramas de procesos y de clases abordados en capítulos anteriores. A continuación se describirá la construcción de todas las funcionalidades más relevantes para el funcionamiento del Editor 3D.

9.1.1 Construir una ventana que despliegue un Objeto en el mundo.

Para esta funcionalidad, se debió codificar una primera versión de una clase llamada World que representa el mundo y además despliega la ventana por donde se visualizará. También se construyó una clase llamada Entity, la que

152

construye un objeto 3D y además reúne las características (Propiedades, métodos etc.) en común de todos los objetos 3D representables por el software, posteriormente se crearon especializaciones de la clase Entity tales como

Sphere, Box entre otras, el detalle de estas clases (cantidad y tipos) se abordarán más adelante dentro de la construcción de las clases especializadas de Entity. A continuación (Figura 6) se muestra la ventana que despliega la escena con una de las primeras versiones de la aplicación.

Figura 6

153

9.1.2 Capacidad de agregar en forma dinámica objetos al mundo y además que se desplieguen.

Para esta funcionalidad se debió crear una colección de objetos de tipo

Entity llamada Entities, ésta es un miembro de la clase “World”; es aquí donde los objetos se agregan en forma dinámica. Se usó una de las características de la tecnología Reflection, la cual nos permite invocar métodos de un objeto sólo sabiendo su tipo, y en este caso nos interesa llamar al método que muestra el objeto de tipo Entity o que hereda de este tipo.

9.1.3 Crear una clase que ofrezca Primitivas OpenGL personalizadas.

Para esta funcionalidad se creó una clase Estática que ofrece primitivas

OpenGL personalizadas, esta clase se llama GlPrimitives, la cual encapsula las llamadas nativas a OpenGL, además ofrece más de sesenta métodos para desplegar y manipular primitivas OpenGL, éstos métodos son los que finalmente se llaman en los métodos que despliegan los Objetos de tipo en

Entity y sus especializaciones. A continuación se presenta un método que despliega la Primitiva OpenGL Sphere.

154

//método que construye la primitiva OpenGl esfera sólida public static void RenderSphere(double Radius,int slice,int stacks) { CheckQuadric(); //se selecciona el estilo de despliegue. Glu.gluQuadricDrawStyle(quadric, Glu.GLU_FILL); //se despliega la primitiva sphere Glu.gluSphere(quadric, Radius, slice, stacks); }

Código Nº [1] Método que construye la primitiva OpenGL esfera sólida.

Como se puede apreciar en el método anterior, el cual está encargado de construir una esfera 3D, esto se logra mediante el uso de primitivas OpenGL como las que se ven en el trozo de código expuesto anteriormente.

9.1.4 Definir tipos Objetos que derivan de Entity.

Para la construcción de esta funcionalidad el cliente solicitó diez tipos de especializaciones de Entity (Tipos de Objetos 3D), finalmente se construyeron catorce con las cuales se puede construir escenarios de buena complejidad y detalle, para esta funcionalidad se construyeron clases que derivan de “Entity” las cuales son las siguientes:

 Sphere

 Box

155

 Cylinder

 Pyramid

 Disk

 Square

 Triangle

 Poligon

 Circle

 Camera

 Tank

 Custom

 Cone

 Ligth

Para más detalle, la descripción completa de estas clases se encuentra en el diccionario de clases en el capítulo de diseño.

9.1.5 Crear interfaz visual y lógica para creación de Objetos.

Para la construcción de esta funcionalidad, en la parte visual se agregó una paleta de objetos diseñada sobre un Formulario del tipo WinForm llamado

156

SceneEditInterface, con la cual mediante un click se crea un objeto en el mundo.

Figura 7

En cuanto a la parte lógica para esta funcionalidad, se creó la clase

Engine con el método AddEntity, el cual agrega un Objeto de tipo Entity o que hereda de Entity a un Objeto World.

A continuación se muestra un trozo de código, donde se crea un Objeto de tipo Sphere y se agrega a un Objeto de tipo World.

Sphere sphere = new Sphere(); engine.AddEntity(world, sphere, colorR, colorG, colorB);

157

Se debe tomar en cuenta el método AddEntity sólo puede agregar objetos de tipo Entity o que hereden de Entity a un objeto de tipo World.

9.1.6 Exhibir las propiedades del mundo y objetos en una paleta de propiedades.

Para la construcción de esta funcionalidad se agregó un control de tipo

PropertyGrid a un formulario de tipo WinForm, este control se incluyó con el objetivo de editar de forma dinámica las propiedades del mundo (World) y sus

Objetos, de manera que estas se visualicen inmediatamente en la ventana que muestra el mundo, la paleta de propiedades sólo ofrece las propiedades del objeto que está seleccionado o el mundo como se muestra en la Figura 8.

158

Figura 8

9.1.7 Seleccionar el mundo o los objetos desplegados en la ventana mediante el Mouse.

Para esta funcionalidad se debió poner especial interés ya que fue una de las más solicitadas por el cliente y ésta se obtuvo mediante las siguientes consideraciones.

La API de OpenGL proporciona un mecanismo de selección de objetos en una escena 3D para detectar los objetos que están bajo el Mouse en una

159

parte o región de la ventana. Los pasos involucrados en la selección de objetos mediante el Mouse son los siguientes:

1. Obtener las coordenadas de donde se encuentra el puntero del Mouse en la ventana.

2. Habilitar el modo de selección de OpenGL.

3. Definir el área de selección de modo que sólo una pequeña parte de la ventana sea tomada en cuenta, ésta debe ser en donde está el cursor del

Mouse.

4. Llamar al método que despliega la escena a la cual se le seleccionaran los objetos.

5. Se debe salir del modo de selección e identificar los objetos que fueron presionados en esa pequeña parte de la pantalla.

Con el fin de identificar los objetos seleccionados utilizando la API de

OpenGL, se debe asignar un nombre a cada objeto en la escena, para esto la

API permite dar nombres a las primitivas o conjuntos de primitivas (objetos). El modo de selección es un modo especial de la API OpenGL. En lugar de retornar los nombres de los objetos, al seleccionarlos OpenGL devuelve la información de selección en una matriz, la cual contiene información de todos los objetos que fueron seleccionados.

160

Usando la terminología de OpenGL, cada vez que se presiona sobre una primitiva en el modo de selección, el buffer de selección es modificado. Al salir del modo de selección, OpenGL vuelve al modo normal, devolviendo en una matriz la información del búffer de selección, OpenGL proporciona información detallada acerca del objeto seleccionado, como por ejemplo a qué distancia se encuentra de la cámara, lo cual se utiliza principalmente cuando dos objetos se encuentran en el área de selección y se requiere seleccionar uno de los dos, generalmente es elegido el más cercano a la cámara.

Los nombres que se asignaron a los objetos se almacenan en una pila, los que en realidad no son nombres (cadena de texto) sino un número que representa un identificador de la primitiva, a continuación se muestra el método que despliega un objeto de tipo Sphere (Código Nº [2]) y se destacará en donde se le asignó el nombre al objeto.

161

//método que muestra en modo render el Objeto tipo Sphere public virtual void NormalRender(){ //se aplican las propiedades al objeto GlPrimitives.PushMatrix(); GlPrimitives.Traslate(Location.Target.X, Location.Target.Y, Location.Target.Z); GlPrimitives.Traslate(Location.Position.X, Location.Position.Y, Location.Position.Z); GlPrimitives.Rotate(Rotation.X, Rotation.Y, Rotation.Z); GlPrimitives.Scale(Scale.X, Scale.Y, Scale.Z); //se le asigna el nombre para la selección OpenGL Gl.glLoadName(PrimariKey); GlPrimitives.Color(Color.X, Color.Y, Color.Z); //se le asigna los planos de corte a la esfera. GlPrimitives.Cutfigures(PlaneQutX, PlaneQutY, PlaneQutZ); //se llama a la primitiva OpenGl RenderSphere GlPrimitives.RenderSphere(Radius,Slice,Stacks, ITexture, Texture); GlPrimitives.PopMatrix(); }

Código Nº [2] Método que Despliega un Objeto de Tipo Entity.

Como se explicó anteriormente se le asignó un nombre al Objeto, ahora corresponde detectar cuando el objeto sea seleccionado con el mouse. A continuación un trozo de código (Código Nº [3]) que realiza esta tarea.

162

//método que sirve para seleccionar los objetos //presentes en el mundo mediante el uso del mouse private void gl_select(int x, int y) { int[] buff = new int[1000]; float[] projection = new float[16];

int[] view = new int[4]; /* designamos un array en el que OpenGl nos devuelva la información de selección. */ Gl.glSelectBuffer(128, buff); /* Recuperamos informción con el siguiente método acerca del wiew port que será requerido más adelante. */ Gl.glGetIntegerv(Gl.GL_VIEWPORT, view); /* Para realizar una selección se le debe indicar a OpenGl que se trabajará en modo SELECT. */ Gl.glRenderMode(Gl.GL_SELECT); /* Inicialisamos la pila de nombres. */ Gl.glInitNames(); /* Inicialisamos la pila de nombres en 0. */ Gl.glPushName(0); /* Fijamos la tranformación de proyección. */ Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glPushMatrix(); Gl.glLoadIdentity(); /* Restringimos el área de selección a la posición del cursor con el siguiente método.

*/ Glu.gluPickMatrix(x, y, 1.0, 1.0, view); Glu.gluPerspective(60, Aspect, 1, 2000); /* Redibujamos nuevamente los objetos en pantalla. */ Gl.glMatrixMode(Gl.GL_MODELVIEW); Glut.glutSwapBuffers(); /* LLamamos al método que está asociado al manejador DisplayCallback ya que sólo este nos devuelve información del bufer de selección. */ show(); /* Preparamos para volver al Modo Render con las siguientes sentencias. */ Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glPopMatrix(); /* La siguiente sentencia obtiene la cantidad de objetos que se seleccionó y además vuelve al modo RENDER. */ hits = Gl.glRenderMode(Gl.GL_RENDER);

163

/* procedemos a recorrer el arreglo que tiene los datos del bufer de selección, en la posición 0 de este arreglo está el valor con que inicialisamos la pila, en la 1 y 2 información no relevante para la selección y en la posición 3 el nombre del objeto seleccionado, esto es en el caso que bajo el puntero del mouse se encuentre solo un objeto, en caso contrario se deben revisar todos lo objetos selecionados en las posiciones (2*i)+1 del bufer,para esta implementación trabajaremos con el objeto que se encuentra más cercano a la cámara, esta información se obtendrá de los elementos (2*i)+2 y (2*i)+3 del bufer, una vez encontrado el objeto más cercano a la cámara se asigna el valor(nombre) a la posición 3 del bufer, para no cambiar el código respecto al caso de si se huviera seleccionado un solo objeto. Posteriormente se busca el nombre que se encuentra en el bufer (buff[3]) en la colección de objetos de tipo Entity del objeto World, mediante la propiedad primarykey de los objetos de tipo Entity, ya que con este nombre(el valor de la propiedad primarykey) fue guardado en la pila de nombres, una vez encontrado el objeto de nombre buff[3] dentro de la colección de objetos de tipo Entity del Mundo(World), la propiedad onfocus del objeto se establece en true y posteriormente se cargan sus propiedades en el propertygrid. */

int i = 1; if (hits > 1) { while (i < hits) { if (buff[i * 4 - 3] < buff[(i + 1) * 4 - 3]) { buff[3] = buff[i * 4 - 1]; } else {

buff[3] = buff[(i + 1) * 4 - 1]; }

if (buff[3] == 1024) { buff[3] = buff[(i + 1) * 4 - 1];

}

i++; } } //se procede a la busqueda del objeto mediante el nombre devuelto por la //pila de nombres,una vez encontrado,se procede dando foco al objeto //seleccionado y carga de sus propiedade en el propertygrid. foreach (Entity entity in Entities) { if (string.Compare(entity.PrimariKey.ToString(), buff[3].ToString()) == 0) { entity.Onfocus = true; selected_object = buff[3]; PropertyInterface.Show(); PropertyInterface.comboBoxObject.Text = entity.Name; PropertyInterface.propertyGridObject.SelectedObject = entity; Refresh(); } else { entity.Onfocus = false; } }

Gl.glMatrixMode(Gl.GL_MODELVIEW); }

164

Código Nº [3] Método que Selecciona un Objeto el Mundo mediante el

Mouse.

Finalmente teniendo esta funcionalidad se puede editar el mundo o los objetos sólo haciendo un click sobre ellos.

9.1.8 Trasladar/Rotar/Escalar objetos en forma dinámica mediante el

Mouse y Paleta de Propiedades.

Para esta funcionalidad se debió crear un método manejador especial llamado MouseEngine, el cual cumple la función de Trasladar, Rotar y Escalar los objetos mediante el Mouse, éste se ubica en la clase Engine, la cual es la clase encargada de proporcionar interfaces para manipular el mundo y sus objetos, tales como teclado y mouse, además provee métodos de creación de objetos y manipulación de cámaras.

El método manejador antes nombrado, recibe como parámetros las coordenadas actuales del cursor del Mouse cuando el botón izquierdo del

Mouse se encuentra presionado, para obtener estos datos se usó el Callback

Motion de Glut, por tanto debemos suscribirnos a el de la siguiente forma.

Glut.glutMotionFunc(new Glut.MotionCallback(Motion));

165

La línea anterior suscribe el método Motion al MotionCallback de Glut con el cual se obtiene la posición actual del cursor del Mouse mientras esté presionado algún botón de éste.

Se definió el método Motion en la clase World con el objetivo de suministrar los datos que necesita el método MouseEngine para editar los objetos dinámicamente.

private void Motion(int x, int y) { //se suministran los parámatros al método MouseEngine para poder mover //objetos dinámicamente mediante el Mouse. engine.MouseEngine(x, y, oldX, oldY, selected_object, this); }

Código Nº [4] Método Motion que captura la posición del Mouse mientras el botón izquierdo del Mouse está presionado.

166

public void MouseEngine(int x, int y, int oldX, int oldY, int selected_object, World world) {

if (world.Entities.Count > selected_object) { Entity Entity = world.Entities[selected_object]; if (world.Lockworld == false) { //Si world está en modo de traslación el objeto seleccionado //se moverá en concordancia con el Mouse. if (world.TraslateModeMouse) { //Si world está en modo de traslación en el plano Z=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano Z=0. if (world.TraslateModeMouseInZ) { Entity.Location.Position.X += (x - oldX) * Entity.factor(); b Entity.Location.Position.Y += (y - oldY) * -Entity.factor(); } //Si world está en modo de traslación en el plano Y=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano Y=0. if (world.TraslateModeMouseInY) { Entity.Location.Position.X += (x - oldX) * Entity.factor(); Entity.Location.Position.Z += (y - oldY) * 0.03; } //Si world está en modo de traslación en el plano X=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano X=0. if (world.TraslateModeMouseInX) { Entity.Location.Position.Z += (x - oldX) * Entity.factor(); Entity.Location.Position.Y += (y - oldY) * -0.03; } world.OldX = x; world.OldY = y; Glut.glutPostRedisplay(); } }

Código Nº [5] sección del Método MouseEngine que traslada el objeto mediante el Mouse.

En el código anterior (Código Nº [5]), se puede apreciar una pequeña parte del método MouseEngine, específicamente la parte que traslada el objeto seleccionado mediante el Mouse, este método también posee la lógica

167

programática para escalar y rotar objetos además trasladar y rotar la cámara.

Como se puede observar también, los parámetros recibidos por el método

MouseEngine modifican la posición del objeto seleccionado, no obstante esta también depende de la función llamada Factor la cual calcula un factor de movimiento del objeto esto dependiendo de la posición que tiene el objeto con referencia a la cámara.

Por último se debió agregar al método base de la clase Entity que despliega los objetos de tipo Entity, la lógica para que el objeto responda al

Mouse cuando éste se mueva ya sea trasladando, rotando o escalando.

A continuación el código (Código Nº [6]) del método que despliega una entidad con la lógica antes descrita destacada, cabe mencionar que se conjugó la lógica del método base que está en la clase Entity con el método que reescribe de la clase derivada Sphere para que sea más entendible en el ejemplo. En este método se puede apreciar como las propiedades Location,

Rotation y Scale de la clase Entity son aplicadas a la primitiva RenderSphere no olvidar que estas mismas fueron modificadas en el método MouseEngine.

168

//método que muestra en modo render el Objeto tipo Sphere public virtual void NormalRender(){ //se aplican las propiedades al objeto GlPrimitives.PushMatrix(); GlPrimitives.Traslate(Location.Target.X, Location.Target.Y, Location.Target.Z); GlPrimitives.Traslate(Location.Position.X, Location.Position.Y, Location.Position.Z); GlPrimitives.Rotate(Rotation.X, Rotation.Y, Rotation.Z); GlPrimitives.Scale(Scale.X, Scale.Y, Scale.Z); //se le asigna el nombre para la selección OpenGL Gl.glLoadName(PrimariKey); GlPrimitives.Color(Color.X, Color.Y, Color.Z); //se le asigna los planos de corte a la esfera. GlPrimitives.Cutfigures(PlaneQutX, PlaneQutY, PlaneQutZ); //se llama a la primitiva OpenGl RenderSphere GlPrimitives.RenderSphere(Radius,Slice,Stacks, ITexture, Texture); GlPrimitives.PopMatrix(); }

Código Nº [6] Método que Despliega un Objeto de Tipo Sphere que hereda de Entity.

9.1.9 Trasladar/Rotar la cámara en forma dinámica mediante el Mouse y

Paleta de Propiedades.

Para esta funcionalidad se debió agregar código al método manejador para Trasladar, Rotar, Escalar objetos mediante el Mouse mencionado en la funcionalidad anterior (MouseEngine), sólo que ahora se le agregó código para que en lugar de trasladar un objeto lo realice con la cámara. Por último se debió agregar al método que despliega el mundo de la clase World, la lógica para que la cámara se Traslade o rote dinámicamente al mover el Mouse.

169

public void MouseEngine(int x, int y, int oldX, int oldY, int selected_object, World world) { b //Se pregunta si el mundo está seleccionado. if (selected_object == World.selected_world) { if (world.TraslateModeMouse) { //Si world está en modo de traslación de cámara en el plano Z=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano Z=0. if (world.TraslateModeMouseInZ) { world.CameraPosition.Position.X += (x - oldX)*0.03 ; world.CameraPosition.Position.Y -= (y - oldY)*0.03; } //Si world está en modo de traslación de cámara en el plano Y=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano Y=0. if (world.TraslateModeMouseInY) { world.CameraPosition.Position.X += (x - oldX) *0.03 ; world.CameraPosition.Position.Z += (y - oldY) * 0.03; } //Si world está en modo de traslación de cámara en el plano X=0 // el objeto seleccionado se moverá en concordancia // con el Mouse pero con referencia al plano X=0. if (world.TraslateModeMouseInX) { world.CameraPosition.Position.Z += (x - oldX) * 0.03; world.CameraPosition.Position.Y += (y - oldY) * -0.03; } } world.OldX = x; world.OldY = y; Glut.glutPostRedisplay(); }

Código Nº [7] sección del Método MouseEngine que traslada la cámara mediante el Mouse.

9.1.10 Selección de cámaras.

Independiente de que la cámara se pueda trasladar o rotar mediante la funcionalidad anterior, la aplicación igual debe ofrecer la funcionalidad de mover la cámara a posiciones predeterminadas, para esto se construyó la lógica para

170

que el usuario pueda seleccionar cinco tipos o perspectivas de cámara las cuales son:

a. Plano X=0.

b. Plano Y=0.

c. Plano Z=0.

. Perspectiva.

e. Multi Cámaras.

En el caso de los tres primeros tipos de cámaras, la cámara está orientada al plano coordenado mencionado en el nombre, en el caso de la cámara de tipo Perspectiva, es aquella en que se distinguen todos los planos coordenados, por último la cámara de tipo Multi Cámaras muestra todas las cámaras anteriores en la misma ventana. Cabe mencionar que toda la lógica respecto a la manipulación de cámaras se encuentra en la clase Engine.

9.1.11 Crear una interfaz visual para la aplicación.

Para esta funcionalidad se construyó dos formularios de tipo WinForm que se agregan a la ventana Glut ya existente, uno para la creación y edición del mundo (SceneEditInterface) y sus objetos y el otro para contener el menú principal de la aplicación y accesos directos a los elementos más usados

171

(ZeroFxInterface), para el diseño de estos formularios se tomó en cuenta el diseño de otras aplicaciones tales como 3D Studio Max y Maya.

Las interfaces visuales fueron creadas de manera que al usuario le resulte intuitivo y fácil manipular la aplicación, una de las características que se construyó para facilitar la manipulación de los objetos y el mundo, es la configuración automática de traslación, rotación y escalado según la cámara seleccionada por el usuario, esto ayuda a que la traslación, rotación y escalado coincida con el movimiento del Mouse cualquiera sea la cámara seleccionada.

A continuación la pantalla (Figura 9) principal de la aplicación la cual muestra una escena en modalidad Design.

172

Figura 9

Otra característica que se mencionó anteriormente es el uso de cámaras, un ejemplo de esto es la misma escena de la figura anterior, pero visto desde la cámara Y=0 que no es otra cosa que una cámara orientada hacia ese plano

(plano azul en la imagen Figura 10).

173

Figura 10

Otra de las características de la interfaz visual es la posibilidad elegir la modalidad de despliegue de la escena. En las figuras anteriores se desplegó

ésta en modalidad Design. A continuación una escena (Figura 11) en modalidad

Render.

174

Figura 11

Como se puede observar en la Figura 11, los planos coordenados en la modalidad Render han desaparecido y los objetos son sólidos (no cableados) como en la modalidad Design.

Otra de las características de la interfaz visual es la posibilidad elegir la modalidad multi cámaras como se muestra en la Figura 12, esta funcionalidad se refiere a desplegar las cuatro cámaras que ofrece el Editor 3D al mismo

175

tiempo por la ventana de la escena, esto sirve para facilitar la visión espacial de la escena.

Figura 12

Finalmente, hay otras funcionalidades que se encuentran en el menú de la interfaz visual, tales como configuración de la creación y edición de objetos, configuración de cámaras, configuración del detalle del modelo de la escena, cargar y guardar una escena y generar código fuente de la escena.

176

9.1.12 Aplicar Texturas a Objetos de tipo Entity.

Para esta funcionalidad se construyó un método que carga una textura en una posición de memoria (Código Nº [8]), posteriormente en el método que despliega un objeto de tipo Entity se agregan las líneas de código necesarias para asociar la textura a un Objeto de Tipo Entity en específico (Código Nº

[9]).

/// Método encargado de cargar una textura desde un archivo /// y devuelve la posición de memoria donde se encuentra public static int LoadTexture(string file,ref Bitmap bitmap) { int AuxTexture; /// se crea un objeto bitmap cargado desde la ruta file bitmap = new Bitmap(file); bitmap.RotateFlip(RotateFlipType.Rotate270FlipX); Rectangle Rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); /// se mapea la textura en un rectángulo BitmapData BitmapData = bitmap.LockBits(Rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); //Generamos el id de la textura en el contexto de OpenGL Gl.glGenTextures(1, out AuxTexture); Gl.glBindTexture(Gl.GL_TEXTURE_2D, AuxTexture); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB8, BitmapData.Width, BitmapData.Height, 0, Gl.GL_BGR_EXT, Gl.GL_UNSIGNED_BYTE, BitmapData.Scan0); bitmap.UnlockBits(BitmapData); //retornamos el id de la textura. return (AuxTexture); }

Código Nº [8] Método que carga una Textura en una posición de memoria.

177

//Seleccionamos la textura 0 para limpiar cualquier textura //seleccionada anteriormente Gl.glBindTexture(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE0); // Seleccionamos nuestra nueva textura Gl.glBindTexture(Gl.GL_TEXTURE_2D, ITexture); //le asignamos el color blanco a nuestra primitiva para // que la textura se vea en forma adecuada. GlPrimitives.Color(1, 1, 1); GlPrimitives.RenderBox(Width, Heigth, Depth); Gl.glBindTexture(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE0);

Código Nº [9] Trozo de código que asocia la Textura cargada a un objeto

Entity en especifico.

En el trozo de código (Código Nº [9]) mostrado anteriormente, se puede apreciar como la textura cargada en una posición de memoria es asociada a un objeto de tipo Entity, la primera línea de código desasocia cualquier textura que podría estar asociada anteriormente, la segunda línea asocia la textura a cualquier primitiva OpenGL que se llame después de esta línea, en este caso la primitiva llamada RenderBox, en la tercera línea le asignamos el color blanco a la primitiva OpenGL de manera que esta primitiva despliegue la textura asociada a ella de buena manera y no de un color que no corresponda a la textura original, esto se valida principalmente debido a que el Objeto de tipo

Entity que se le asigna una textura puede tener un color asociado, la línea cinco llama a la primitiva RenderBox a la cual se le asociará la textura, finalmente en la última línea de código se desasocia la textura para que no tenga efecto sobre ninguna primitiva que sea llamada posteriormente.

178

Finalmente, como producto de esta funcionalidad se puede ver como en la pantalla del editor 3D (Figura 13) se visualiza un cubo con una textura.

Figura 13

179

9.1.13 Construir funcionalidad que permita crear Objetos Entity compuestos de Otros.

Esta funcionalidad se llevó a cabo mediante la construcción de una clase derivada de Entity llamada Custom, la cual permite que uno o más objetos pertenezcan a un objeto Custom, con lo cual todos los objetos pertenecientes a este objeto se trasladarán, rotarán y escalarán al mismo tiempo, como si se tratara de un solo objeto. También fue necesario definir una colección de objetos de tipo Entity en la clase Entity la cual permite que un objeto de tipo

Entity pueda tener objetos Entity hijos.

A continuación en la imagen (Figura 14) se puede apreciar el lugar

(elipse en la imagen) que ocupa la interfaz para crear objetos compuestos, mediante un click del mouse se pueden agregar o quitar objetos de uno compuesto. Una vez seleccionados los objetos que compondrán nuestro objeto compuesto debemos presionar el botón “Create Custom Object” con el cual es creado el objeto compuesto, el cual estará conformado por las tres esferas de la imagen.

180

Figura 14

9.1.14 Construir Funcionalidad que permita aplicar planos de corte a objetos de tipo Entity.

Esta funcionalidad se llevó a cabo mediante construcción de un método que aplica planos de corte a un objeto en particular, para esto se definieron tres planos de corte, Plano de Corte X=0, Y=0 y Z=0. Como parte de la implementación de esta funcionalidad se definieron tres propiedades en la clase

181

Entity, que habilitan o deshabilitan los planos de corte antes mencionados para un Objeto de tipo Entity en específico.

A continuación un ejemplo de la funcionalidad de planos de corte aplicada al Editor 3D, se puede ver en la imagen (Figura 15) un disco con dos planos de corte aplicados y una esfera con todos los planos de corte posible aplicados, con lo cual la esfera queda reducida a una cuarta parte de lo que era.

Figura 15

182

9.1.15 Construir funcionalidad que permita crear y editar fuentes de Luz.

Esta funcionalidad se llevó a cabo mediante la construcción de una clase derivada de Entity llamada Ligth, la cual proporciona mecanismos para crear y editar Fuentes de luz, para esta clase se definieron propiedades tales como

LightDiffuse la cual configura la componente Difusa de la fuente de luz,

LightAmbient la cual configura la componente Ambiente de la fuente de luz, estas componentes de una fuente de luz se tratan de lo siguiente;

Componente Difusa:

 La luz viene de una dirección, pero cuando golpea una superficie se

esparce igualmente en todas las direcciones.

 Una luz que proviene de una posición particular tiene una

componente difusa.

Componente Ambiente:

 Es luz que ha sido esparcida por todo el ambiente y es imposible de

determinar su origen.

 Cuando golpea una superficie se esparce igualmente en todas

direcciones.

 Una sala iluminada tiene una gran componente ambiente.

183

Por lo anterior si el usuario quiere iluminar una parte de la escena con una luz direccional se debe usar la componente Difusa, no obstante si se quiere iluminar de forma homogénea toda la escena es necesario usar la componente ambiente, cabe mencionar que también se puede usar una combinación de las dos componentes.

Una característica de OpenGL con respecto al manejo de luces es que soporta un máximo de ocho luces simultáneas en una escena, con lo cual la aplicación soportará esta cantidad de luces como máximo.

Otra característica que incluye la construcción de esta funcionalidad es la capacidad de trasladar dinámicamente una fuente de luz mediante el Mouse, para esta característica se trató a la fuente de luz como un objeto Entity, más aun Ligth es una clase que hereda de Entity y dentro de las características que hereda Ligth de Entity es la propiedad que hace referencia a la posición, por lo tanto ocupa el mismo método manejador que usan los Objetos de tipo Entity para moverse, rotar y escalar mediante el Mouse. No obstante el objeto de tipo light solo ocupa la característica de traslación.

En la siguiente imagen (Figura 16) se puede apreciar un ejemplo de una luz con componente difusa, la cual viene de la posición de una pequeña esfera

184

de color naranja, la posición de la luz sólo es visible en modalidad design ya que en modalidad render sólo se ve su efecto en la escena.

Figura 16

En la siguiente imagen (Figura 17) se puede apreciar un ejemplo de una luz con componente Ambiente la cual tiene una posición, (pequeña esfera de color naranja), el efecto de la luz en la escena es homogénea, por lo tanto no distingue la posición, con lo cual, la posición de la luz no tiene mayor incidencia en la iluminación de ésta.

185

Figura 17

Por último, cabe mencionar que para efecto de configuración inicial se creó una luz por defecto, la cual está ubicada en el origen del sistema y además tiene una mezcla de componentes difusa y ambiente, ya que de no ser por esta luz la escena se vería opaca y obscura, no obstante al desplegarse la primera luz creada por el usuario el efecto de esta luz por defecto desaparece.

9.1.16 Construir funcionalidad que permita editar el mundo y sus Objetos mediante el teclado.

186

Para esta funcionalidad se creó un método llamado KeyboardHandler, el cual recibe como parámetros las teclas que fueron presionadas, este método se ubica en la clase Engine, y alguna de sus características y sus funcionalidades especificas son:

 Presionado [CTRL+E] se crea objeto de tipo Sphere.

 Presionado [CTRL+Q] se habilita el traslado del objeto seleccionado.

 Presionado [CTRL+R] se habilita el rotado del objeto seleccionado.

 Presionado [CTRL+S] se habilita el escalado del objeto seleccionado.

 Presionado [Supr] se elimina el objeto seleccionado.

 Presionado las teclas direccionales se traslada la cámara.

Esta funcionalidad proporciona más de cuarenta accesos personalizados por teclado, con lo cual involucra casi la mayoría de acciones sobre el mundo y sus objetos pueden realizarse mediante teclado.

Para capturar las teclas presionadas por el usuario hay suscribirse al

KeyboardCallback de Glut mediante el siguiente código.

Glut.glutKeyboardFunc(new Glut.KeyboardCallback(KeyboardHandler));

187

Una vez suscritos al KeyboardCallback se creó un método manejador en la clase World que se llamó KeyboardHandler el cual debió cumplir con una firma preestablecida para poder suscribirse al KeyboardCallback de Glut; con esto ya se puede realizar la captura de las teclas presionadas por el usuario.

Estas teclas serán manejadas en el método KeyboardHandler de la clase

Engine que no es el mismo método usado para capturar las teclas (de la clase

World) presionadas, ya que KeyboardHandler de la clase Engine realiza la lógica que se desencadena al presionar el teclado, por ejemplo crear, editar eliminar objetos y muchas otras acciones.

// Método que está encargado de capturar las teclas presiondas. private void KeyboardHandler(byte key, int x, int y) { // se llama al método KeyboardHandler de la clase Engine // la cual realiza la lógica cuando se presionan las teclas. engine.KeyboardHandler(key,this); e.Rotate = RotateModeMouse; e.Traslate = TraslateModeMouse; e.Scale = ScaleModeMouse; worldChanged(this, e); Glut.glutPostRedisplay(); }

Código Nº [10] Método suscrito al KeyboardCallback de Glut que captura las teclas presionadas.

188

// Método que está encargado de modificar el mundo y sus objetos mediante el //teclado. public void KeyboardHandler(byte key,World world) {

switch (key) { case 3: //key "ctlr+C" crear Cylinder Cylinder cylinder = new Cylinder(); AddEntity(world,cylinder , 200, 100, 0); break; case 5: //key "ctlr+E" crear Sphere Sphere sphere = new Sphere(); AddEntity(world, sphere, 200, 100, 0); break; case 2: //key "ctlr+B" crear Box Box box = new Box(); AddEntity(world, box, 200, 100, 0); break; case 16: //key "ctlr+P" crear Pyramid Pyramid pyramid = new Pyramid(); AddEntity(world, pyramid, 200, 100, 0); break; case 9: //key "ctlr+I" crear Circle Circle circle = new Circle(); AddEntity(world, circle, 200, 100, 0); break; case 21: //key "ctlr+U" crear Square Square square = new Square(); AddEntity(world, square, 200, 100, 0); break; case 15: //key "ctlr+O" crear Poligon Poligon poligon = new Poligon(); AddEntity(world, poligon, 200, 100, 0); break; case 20: //key "ctlr+T" crear Triangle Triangle triangle = new Triangle(); AddEntity(world, triangle, 200, 100, 0); }

}

Código Nº [11] Trozo del método KeyboardHandler de la clase Engine.

En resumen, existen dos métodos con el mismo nombre pero de distintas clases, uno de la clase World que está encargado sólo de capturar las teclas que fueron presionadas y el otro de la clase Engine el cual toma los valores entregados por el método de la clase World y ejecuta la lógica correspondiente,

189

por ejemplo crear una esfera, aplicar escala, rotación y muchas otras funcionalidades.

9.1.17 Construir funcionalidad que permita revisar la escena mediante una animación Básica que rote la cámara por la escena.

Para esta funcionalidad se creó un método llamado

AnimationTimerEventHandler, el cual se encuentra en la clase World. Este método despliega una animación básica la cual consiste en una rotación de la cámara por toda la escena en 360 grados. A continuación, se mostrará el método (Código [12]) manejador de la animación éste se encuentra en la clase

World y para activar la animación sólo basta cambiar la propiedad de la clase

World llamada Preview a True.

private void AnimationTimerEventHandler(object o, ElapsedEventArgs args) { //lógiga de animación de la cámara para la revisión de la escena(rotación en 360 //grados por la escena) if (Preview) { Rotation = Rotation + 0.5; }

Glut.glutPostRedisplay(); }

Código Nº [12] Método manejador que se encarga de la animación Básica.

190

9.1.18 Construir funcionalidad que permita guardar y cargar la escena mediante el uso de la Tecnología Xml.

Para esta funcionalidad se creó una clase abstracta llamada

XmlConverter, la cual exige que todas las clases que heredan de ella implementen los métodos SaveToXML y LoadFromXml. Además, la clase posee métodos estáticos para guardar o cargar una imagen en el Xml, a continuación el código fuente (Código Nº [13]) que implementa los métodos

SaveToXML y LoadFromXml de la la Clase Sphere.

// Método que guarda las propiedades de los objetos de tipo Sphere en el Xml. public override void SaveToXML(XmlElement parent) { parent.SetAttribute("Radius", Radius.ToString()); } // Método que carga las propiedades de los objetos de tipo Sphere desde el Xml. public override void LoadFromXML(XmlNode parent) { Radius = double.Parse(parent.Attributes["Radius"].Value); }

Código Nº [13] Métodos que cargan y guardan la propiedad especializada

Radius de la clase Sphere.

Para esta funcionalidad, además se construyó una interfaz de clase llamada XMLstruct, la cual exige que las clases que firmen un contrato con ella deben implementar los métodos SaveToXml y LoadFromXml, una de las clases que están suscritas a este contrato es Entity, con lo cual se exige que Entity y

191

todas las clases que hereden de ésta deben implementar los métodos antes nombrados.

El archivo Xml que guardará la escena tiene una estructura análoga al diseño de clases del Editor 3D, a continuación se mostrara un archivo generado por el Editor 3d el cual al cargarlo muestra la escena con un cubo y una esfera.

192

0 False False False True 2 -3,03 -20 0 0 0 False True False World 1 0 -4,214 0,172 0 1 1 1 0 0 0 0,784313725490196 0,392156862745098 0 False False False 2 1 3,87 -0,043 0 1 1 1 0 0 0 0,784313725490196 0,392156862745098 0 False False False

Código Nº [14] sección de archivo Xml del Editor 3D.

193

En la sección archivo anterior también se pueden ver otras etiquetas como por ejemplo “textura”, la cual guarda una textura en forma binaria, esta codificación binaria se realizó mediante un método llamado ImageToXMLNode de la clase XMLConverter, la cual básicamente toma una imagen y la codifica en forma binaria usando el formato de codificación UTF8 y por último guarda esta codificación en un nodo XML. A continuación, se mostrará el código

(Código Nº [15]) que realiza esta tarea.

194

//método que transforma una imagen en un nodo Xml public static XmlNode ImageToXMLNode(Image imagen) { System.IO.MemoryStream oStream = new System.IO.MemoryStream(); XmlDocument oDom = new XmlDocument(); System.IO.MemoryStream mResult = new System.IO.MemoryStream(); long LenData = 0; byte[] Buffer; System.IO.BinaryReader oBinaryReader; XmlTextWriter oXMLTextWriter; System.IO.StreamReader oStreamReader; string StrResult; //Verifico si existe imagen a serializar if ((imagen != null)) { //Se graba en Stream para almacenar la imagen en formato //binario se conserva el formato de la imagen System.Drawing.Imaging.ImageFormat imgF; imgF = ImageFormat.Png; imagen.Save(oStream, imgF); oStream.Position = 0; LenData = oStream.Length - 1; //Verifico la longitud de datos a serializar if (LenData > 0) { Buffer = new byte[Convert.ToInt32(LenData) + 1]; //Genero Buffer y leo los datos binarios oBinaryReader = new System.IO.BinaryReader(oStream, System.Text.Encoding.UTF8); oBinaryReader.Read(Buffer, 0, Buffer.Length); //Creo XMLTextWriter y agrego nodo con la imagen oXMLTextWriter = new XmlTextWriter(mResult, System.Text.Encoding.UTF8); oXMLTextWriter.WriteStartDocument(); oXMLTextWriter.WriteStartElement("BinaryTexture"); oXMLTextWriter.WriteBase64(Buffer, 0, Buffer.Length); oXMLTextWriter.WriteEndElement(); oXMLTextWriter.WriteEndDocument(); oXMLTextWriter.Flush();

Código Nº [15] parte 1

195

//posiciono en 0 el resultado mResult.Position = 0; //Pasa el Stream a String y retorna oStreamReader = new System.IO.StreamReader(mResult, System.Text.Encoding.UTF8); StrResult = oStreamReader.ReadToEnd(); oStreamReader.Close(); //Agrego Nuevo Nodo con imagen oDom.LoadXml(StrResult); return oDom.DocumentElement;

} else { //En caso de no existir datos retorno el XML con //formato vacio oDom.LoadXml(""); return oDom.DocumentElement.CloneNode(true); } } else { //no hay imagen devuelvo el XML Vacio oDom.LoadXml(""); return oDom.DocumentElement.CloneNode(true); } }

Código Nº [15] parte 2

Para interpretar la información binaria que se encuentra en la etiqueta texture y transformarla nuevamente en una imagen, se construyó un método llamado XMLNodeToImage presente en la clase XMLConverter. A continuación el código del método (Código Nº [16]).

196

//Método que recibe un nodo Xml y retorna una Imágen. public static Image XMLNodeToImage(XmlNode Nodo) { int IntResult = 0; int IntPosition = 0; int LenBytes = 1024 * 1024; //1024KB - 1MB Lee bloques de 1MB byte[] myBytes = new byte[LenBytes]; System.IO.MemoryStream oMem = new System.IO.MemoryStream(); System.Xml.XmlTextReader oXMLTextReader; bool NodeFound = false; //Dim oStreamReader As IO.StreamReader System.IO.StreamWriter oStreamWriter; System.IO.MemoryStream oTempMem = new System.IO.MemoryStream(); string nombre = ""; try { //Cargo nodo de texto en Memory Stream para almacenar //la imagen temporalmente en bytes oStreamWriter = new System.IO.StreamWriter(oTempMem, System.Text.Encoding.UTF8); oStreamWriter.Write(Nodo.OuterXml); oStreamWriter.Flush(); oTempMem.Position = 0; //Cargo un xmlReader con el Memory Stream para //leer la imágen almacenada oXMLTextReader = new System.Xml.XmlTextReader(oTempMem); //Busco el Nodo en Binario while (oXMLTextReader.Read()) { if (oXMLTextReader.Name == "BinaryTexture") { NodeFound = true; break; } NodeFound = true; }

Código Nº [16] parte 1

197

//Verifico si se encontró el Nodo con la imagen if (NodeFound) { if (oXMLTextReader.HasAttributes) { nombre = oXMLTextReader.GetAttribute("Nombre"); } //Lo encontro, me muevo a la Posicion Inicial //del Stream para leerlo IntPosition = 0; //Intento Leer IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes); while (IntResult > 0) { //Escribe datos oMem.Write(myBytes, 0, IntResult); //Limpio el array Array.Clear(myBytes, 0, LenBytes); //Leo nuevamente IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes); } try { //Intento crear la Imagen y retornarla //si no devuelvo Nothing Image img; img = Bitmap.FromStream(oMem, true, true); if ((nombre != null) && (nombre.Length > 0)) { img.Tag = nombre; } return img; } catch { return null; } } else { //No encontró el nodo de imágen return null; } } catch (Exception ex) { //Ocurrio un error no contemplado Retorno Nothing return null; } }

Código Nº [16] parte 2

198

Finalmente, la función antes descrita devuelve la imagen lista para ser cargada por objeto de tipo Entity que lo requiera. Con los métodos antes descritos se cumple una de la característica de guardar y cargar imágenes desde el Xml completando así la funcionalidad total.

9.1.19 Integración de funcionalidades.

La construcción de esta funcionalidad se refiere a la reestructuración de algunas de éstas con el objetivo de que funcionen correctamente al ir siendo integradas a las demás, esta tarea se realizó recurrentemente debido a la naturaleza del proyecto, una vez terminada las funcionalidades e iteraciones de integración, se obtuvo como producto final el Editor 3D. A continuación una imagen(Figura 18 y 19) mostrando la interfaz visual final del Editor 3D aplicando algunas funcionalidades descritas anteriormente, como por ejemplo mostrar la escena en modalidad Design o Render y también otras como aplicación de

Texturas y luces .

199

Figura 18(Escena en modalidad Render).

200

Figura 19(Escena en modalidad Design).

Las dos figuras (Figura 18 y 19) mostradas anteriormente son de la interfaz gráfica de la aplicación final. Esta se ejecutó sobre la plataforma de software y hardware mencionada en el capítulo de Hardware y Software.

201

9.2 Construcción aplicación versión Final (Editor 3D + Generador de código Fuente).

Esta versión de la aplicación fue construida una vez terminado el editor 3D y consiste en la construcción de una funcionalidad que genera el código fuente en lenguaje C# de lo diseñado con el editor 3D, para que posteriormente sea utilizado en lo que el usuario de la aplicación estime conveniente, esta funcionalidad fue construida en varias subfuncionalidades tales como:

 Generador de Clase C# que despliegue la escena.

 Generador de Proyecto .Net con la Clase C# antes nombrada ya cargada

en el Proyecto.

 Generador de Proyecto .Net con la Clase C# antes nombrada ya cargada

en el Proyecto, además levantando automáticamente Visual Studio.

A continuación el detalle de la construcción de la implementación.

9.2.1 Generador de clase que despliegue la escena diseñada con la aplicación.

Para esta funcionalidad se construyó una clase llamada Dissasembler, la cual implementa un método llamado DissasemblerC, el que desensambla el código fuente de todas las clases de la aplicación y lo devuelve en forma de dos

202

tipos de objetos (DissasemblerClassField y DissasemblerMethod), en uno se devuelven las field/campos de las clases y en el otro los métodos. La clase

Dissasembler se basó en el uso una librería llamada Reflector, que es una implementación de la tecnología de .Net Reflection. La librería reflector es en realidad una especialización de la clase Reflection de .Net, posee las mismas funcionalidades de Reflection la cual es principalmente una vista administrada de los campos, los métodos y los tipos cargados, con la posibilidad de crear e invocar tipos dinámicamente, dentro de estas funcionalidades (de Reflection) está la de obtener los métodos y tipos cargados, lo cual supone la solución de esta funcionalidad, no obstante cabe mencionar que en el caso de la visualización de métodos (obtener código fuente del método), sólo es capaz de obtener el equivalente binario, es aquí donde reflector hace la diferencia, ya que esta librería es capaz de llegar más allá, y es capaz de obtener el código MSIL del método y además proporciona métodos adicionales para traducir lenguaje

MSIL al lenguaje administrado que se requiera, para el caso de esta funcionalidad C#. A continuación un trozo de código (Código Nº [17]) que usa reflector para la obtención del código de un método.

203

foreach (IMethodDeclaration methodDeclaration in typeDeclaration.Methods) { //se crea un método desensamblado IMethodDeclaration methodDeclaration2 = translatorManager.CreateDisassembler(null,_ null).TranslateMethodDeclaration(methodDeclaration); eventReflection(CountTypesDissasembler); //se crea un objeto de tipo DissasemblerMethod para guardar //el método desensamblado DissasemblerMethod method = new DissasemblerMethod(); //Se guarda el nombre,cuerpo, nombre de la clase // y número de parámetros method.Name = methodDeclaration2.Name; method.Body = methodDeclaration2.Body.ToString(); method.NameClass=typeDeclaration.Name; method.Parameter = methodDeclaration2.Parameters.Count; //se agrega a la colección de métodos desensamblados. Methods.Add(method);

}

Código Nº [17] Trozo de código del método DissaseblerC.

El trozo de código antes expuesto (Código Nº [17]) el cual obtiene el código fuente de un método y lo guarda dentro de un objeto de tipo

DissasemblerMethod, además se almacena el nombre del método, nombre de la clase y número de parámetros.

Con la librería Reflector como se abordó anteriormente, se puede obtener el código de la mayor parte de una clase, pero éste código no es utilizable directamente, ya que viene con algunos pequeños problemas de sintaxis y nombres de variables cambiadas respecto al código original, y además se deben aplicar el valor de la propiedades de cada uno de los objetos

204

3D desplegados actualmente por la aplicación, por lo tanto se crearon métodos para la preparación de código fuente, a continuación se explicará paso a paso como se obtuvo el código fuente de una escena diseñada con la aplicación.

Como primer paso se desensambló en su totalidad las clases que inciden en el despliegue gráfico de la aplicación, posteriormente se construyó dos clases para poder albergar el código fuente desensamblado, las cuales son

DissasemblerMethod y DissasemblerClassField, la primera es la encargada de albergar el código fuente de los métodos de las clases desensambladas y la segunda los field/campos de cada clase, posteriormente la clase Entity y todas las clases que heredan de ella se les construyó el método llamado “ToSource”, el cual construye el código fuente necesario para desplegar un objeto 3D o el mundo, en esta oportunidad se abordará el caso de un objeto de tipo esfera que hereda de la clase Entity, a continuación se creó un método en la clase Entity que busca la posición del código fuente de un método dentro de la colección de métodos desensamblados. Una vez encontrada esta posición, se hace referencia a la colección con el índice encontrado, el cual posee un objeto de tipo DissasemblerMethod. Este, posee como propiedades el nombre de la clase, nombre del método y el cuerpo del método, teniendo el código del método, se procedió a construir un método llamado ReplaceGlConst que aplica las constantes OpenGL, ya que éstas se perdieron al ser desensambladas, un ejemplo de esto a continuación.

205

//método que construye la primitiva OpenGl cilindro sólido public static void RenderCylinder(double baseRadius, double topRadius,double heigth, int slice, int stacks) { GlPrimitives.PushMatrix(); CheckQuadric(); Glu.gluQuadricDrawStyle(quadric, Glu.GLU_FILL); //método OpenGL que despliega la primitiva Cylinder Glu.gluCylinder(quadric, baseRadius,topRadius,heigth,slice,stacks); GlPrimitives.PopMatrix(); }

//método que construye la primitiva OpenGl cilindro sólido //(desensamblado) public static void RenderCylinder(double baseRadius, double topRadius,double heigth, int slice, int stacks) { GlPrimitives.PushMatrix(); CheckQuadric(); //linea de código desensamblada, la constante // GLU_FILL fue devuelta en forma del número 6914 Glu.gluQuadricDrawStyle(quadric, 6914); //método OpenGL que despliega la primitiva Cylinder Glu.gluCylinder(quadric, baseRadius,topRadius,heigth,slice,stacks); GlPrimitives.PopMatrix(); }

Código Nº [18] Trozo de código que muestra la diferencia entre el código original y el desensamblado por la aplicación.

Como se pudo observar, el desensamblado devolvió la constante

Glu.GLU_FILL como un numero 6914, lo cual desde el punto de vista de la compilación está correcto, no obstante para el programador que retome el código es inentendible, por lo cual se construyó un método estático llamado

ReplaceGlConst de la clase GlConst, el cual toma las constantes tales como

6914 y los sustituye por su constante OpenGL en este caso Glu.GLU_FILL.

206

Una vez arreglado el código, se procedió a construir una función en la clase Entity y World llamada ReplaceVar, la cual se preocupa de aplicar las propiedades actuales de la clase World y Entity al código desensamblado, además de aplicar indentación al código y algunas normas básicas de programación.

Un ejemplo programático de la aplicación de los métodos antes descritos sería el siguiente.

ReplaceVar(GlConst.ReplaceGlConst(Methods[SearchCode("RenderSphere", 5)].Body)));

Código Nº [19] Trozo de código que busca y configura un fuente desensamblado de un método.

Finalmente, se aplica el método ToSource a todas las instancias actuales de la aplicación que posean este método, con lo cual se obtiene una clase C# que es capaz de desplegar la escena tal cual como se ve en el Editor 3D. El código fuente obtenido está listo para ser utilizado en la implementación que el desarrollador estime conveniente.

9.2.2 Generador de Proyecto .Net que despliegue la escena diseñada con la aplicación.

207

Para esta funcionalidad se tomó la clase C# generada en la funcionalidad anterior y se agregó a un proyecto .Net. El detalle de esta implementación a continuación.

En primer lugar se creó un proyecto plantilla, el cual posee las librerías necesarias ya cargadas, después se copia el proyecto desde esta platilla donde el usuario señale, posteriormente se agrega la clase C# antes nombrada al proyecto .Net mediante las siguientes líneas de código (Código Nº [20]).

//cargamos el archivo del proyecto y le agregamos nuestra clase xml.Load("C:/GlApplication/GlApplication.csproj"); XmlNode xmlm = xml.DocumentElement["ItemGroup"]; //Codigo que agrega clase(desensamblada) generada a un proyecto Vs2008. XmlElement csElement = xml.CreateElement("Compile"); csElement =xml.CreateElement("Compile", _ "http://schemas.microsoft.com/developer/msbuild/2003"); csElement.SetAttribute("Include","OpenGl.cs"); if (xmlm.ChildNodes.Count == 9) { //cargamos xmlm.AppendChild(csElement); el archivo del proyecto y le agregamos nuestra clase. } xml.Save("C:/GlApplication/GlApplication.csproj");

Código Nº [20] Trozo de código que agrega la clase desensamblada en proyecto .Net.

Una vez cargada la clase al proyecto, éste se encuentra listo para compilar y ejecutarse.

208

10. Pruebas

En este capítulo se describirán las pruebas que se realizaron a las distintas funcionalidades desarrolladas, ya sea en conjunto o modularizado, esto con el fin de encontrar o detectar diferencias entre las condiciones requeridas y las reales (fallas o defectos), y finalmente evaluar las características de la aplicación.

10.1 Conceptos generales de las pruebas realizadas.

10.1.1 Pruebas de Unidad.

Las pruebas de unidad se realizaron sobre cada una de las funcionalidades codificadas en la etapa de construcción de forma independiente. Con esto se consigue comprobar que las funcionalidades, vistas como unidades funcionales de programas autónomos están correctamente codificadas.

Dichas funcionalidades fueron “testeadas”, bajo la técnica de prueba llamada “caja blanca”.

10.1.2 Pruebas de Integración.

209

Estas pruebas se realizaron de forma incremental, es decir, a medida que se desarrollaban las funcionalidades de la aplicación, se comprobara el funcionamiento de la aplicación en su totalidad, cabe señalar que sólo al final del último ciclo del proyecto se pudo comprobar que la aplicación funcionaba de forma correcta y con la prestación necesaria para satisfacer los requerimientos solicitados por el cliente.

10.1.3 Pruebas de Sistema y Evaluación.

Las pruebas de caja negra, se utilizaron para comprobar el comportamiento de la aplicación. Este tipo de pruebas se utilizaron para el ingreso de valores máximos y mínimos para los dominios permitidos como entradas. Bajo este análisis se pueden aplicar varios casos de pruebas tales como:

 Ingreso de valores máximos a propiedades del mundo y Objetos3D.

 Creación de la máxima cantidad de Objetos en la escena antes de que

se vuelva inestable la aplicación.

Por último, las pruebas estéticas fueron evaluadas por el cliente, mediante prototipos y versiones betas que fueron presentados en cada una de las reuniones que se realizaron, en donde el cliente entregó su percepción de la

210

aplicación. Los comentarios y recomendaciones fueron recabados e implementados en las interfaces que componen la aplicación.

10.2 Plan de pruebas.

Con los antecedentes mencionados anteriormente se crea un plan de pruebas que permite definir las actividades, planificar y estimar los esfuerzos, condiciones y tiempos involucrados para la ejecución de las pruebas de la aplicación. A continuación, se describe el plan de pruebas de forma general, de acuerdo a los siguientes objetivos:

 Identificar la información generada por el proyecto y los componentes de

software que deberán ser probados.

 Establecer las actividades de prueba a ser realizadas.

 Recomendar y describir la estrategia de pruebas a utilizar.

10.2.1 Pruebas Funcionales.

En este plan de Test se aplicarán técnicas de “Caja Negra”, las que tendrán como objetivo principal verificar el comportamiento de la aplicación, comparando el resultado esperado detallado en el caso de uso contra el resultado obtenido en la ejecución de las pruebas.

211

Los datos de entrada serán los utilizados por las operaciones o uso normal de la aplicación. Cada argumento de entrada puede seleccionar uno de los siguientes datos de pruebas, dependiendo éste del resultado que se desea obtener (esperado), verificando así el comportamiento del componente a testear, usando los siguientes valores de entrada:

 Valores normales para cada una de las propiedades de los objetos y el

mundo.

 Valores límites para cada una de las propiedades de los objetos y el

mundo.

 Cantidad normal de objetos (1 a 30 objetos).

 Cantidad alta de objetos (31 -200).

 Cargar archivos de Texturas inválidos y validos.

 Cargar archivos de respaldo de la escena (Xml) inválidos y validos.

10.2.2 Estrategias de las Pruebas.

Las pruebas serán realizadas por funcionalidades, en la medida que

éstas sean entregadas al proceso de prueba, cada funcionalidad está asociada a un caso de uso en particular por ende las pruebas velarán por que la funcionalidad cumpla con el caso de uso.

212

10.2.3 Tipos de Pruebas.

Las pruebas funcionales se realizaron de acuerdo a la siguiente tabla.

Objetivo del Test: Asegurar la funcionalidad del conjunto de casos de prueba. Que la navegación a través de los casos de prueba refleje apropiadamente los resultados esperados. Que los objetos de las ventanas y sus características, tales como menús, tamaño, posición, estados y el foco, estén de acuerdo a los estándares. Técnica a Utilizar: Ejecutar cada Caso de Pruebas, su flujo y funcionalidad usando tanto datos válidos como inválidos para verificar lo siguiente:  Resultados esperados ocurren cuando los datos válidos son utilizados.  El mensaje de error es el apropiado cuando se utilizan datos inválidos. Criterio de Verificación:  Que todas las pruebas planificadas se ejecuten correctamente y en forma empírica, con lo cual este criterio de verificación se encasilla dentro del tipo fuerte.

Tabla Nº [1]: Descripción de las Pruebas Funcionales.

213

Todas las pruebas mencionadas en este capítulo, tuvieron resultados satisfactorios y cubren todos los requerimientos establecidos en la etapa de análisis del proyecto.

Con estos antecedentes se puede asegurar que la aplicación ofrece una prestación bastante aceptable y que cumple completamente lo requerido para el proyecto.

214

11. Conclusiones y Recomendaciones

Una de la conclusiones que se obtuvo con la construcción de este tipo aplicaciones, es que un buen diseño y construcción es especialmente perceptible en el desempeño final de este tipo de aplicaciones, esto en base a que las primeras versiones de la aplicación soportaba de 10 a 15 primitivas sin texturas, a lo largo de las iteraciones de diseño y construcción como lo permite la metodología Xp, las cantidades de primitivas fueron subiendo hasta llegar a las 300 primitivas con texturas, aún cuando esto puede aumentar o disminuir dependiendo del Computador usado.

Otro punto importante dentro del desarrollo de este seminario fue la elección de la metodología de desarrollo, en un primer momento se estudiaron diversas metodologías con el fin de obtener una variable aplicabilidad al proyecto, se estudiaron algunas como Rup y Aup que si bien están consideradas dentro las metodologías ágiles, éstas no consideran natural el cambio de requisitos sobre la marcha, por contraparte XP propone que los cambios de requisitos sobre la marcha son un aspecto natural, inevitable e incluso deseable del desarrollo de proyectos, por otra parte XP ofrece un soporte óptimo a juicio del alumno tesista, ya que el desarrollo de esta aplicación tuvo un alto riesgo técnico y muchas veces se incurrió en desarrollar

215

desde cero algunas funcionalidades, ya que no cumplían a cabalidad los requisitos o no cumplían algunas características de integración con el resto de la aplicación.

Otra conclusión que se pudo obtener de la construcción de la aplicación es que si bien la CPU de la computadora es parte importante en el rendimiento de la aplicación, es más importante aún, la tarjeta gráfica del computador, a continuación un benchmark (Prueba estática de rendimiento) de la aplicación en el cual se basa esta conclusión, estas pruebas se realizaron con tres configuraciones de hardware y software distintas las cuales son las siguientes.

Equipo 1: Hardware  CPU AMD Turion X2 de 2 GHZ.  1 GB de RAM.  Video 64 MB ATI X1200 DDR3 (Integrada).  Disco duro de 120 GB. Software  Visual Studio 2005 ó 2008 bajo Windows XP y lenguaje C#.  Librerías OpenGL en sistemas operativos Windows y Linux.  Estándar XML versión 1.2.  Mono/MonoDevelop en Linux para pruebas de códigos fuentes generados por la aplicación.

Equipo 2: Hardware  CPU Intel Core 2 DUO 2.2 GHZ.  1 GB de RAM.  Video 256 MB Intel series DDR3 (Integrada).

216

 Disco duro de 320 GB. Software  Visual Studio 2005 ó 2008 bajo Windows Vista y lenguaje C#.  Librerías OpenGL en sistemas operativos Windows y Linux.  Estándar XML versión 1.2.  Mono/MonoDevelop en Linux para pruebas de códigos fuentes generados por la aplicación.

Equipo 3: Hardware  CPU Intel Core 2 Duo 2,2 GHZ.  1 GB de RAM.  512 MB Nvidia. 8600 GTS (Dedicada).  Disco duro de 120 GB. Software  Visual Studio 2005 ó 2008 bajo Windows Vista y lenguaje C#.  Librerías OpenGL en sistemas operativos Windows y Linux.  Estándar XML versión 1.2.  Mono/MonoDevelop en Linux para pruebas de códigos fuentes generados por la aplicación.

Para esta prueba se tomó en cuenta la cantidad de frames por segundo con una carga de 30 objetos, los parámetros de entrada son los siguientes:

 30 objetos en modalidad Render sin texturas.

 30 objetos en modalidad Render con texturas.

 30 objetos en modalidad Render con texturas, más una Luz con una

componente difusa.

217

350 300 250 200 Frames / 150 Segundo 100 50 0 30 objetos sin 30 objetos con 30 objetos con Texturas. Texturas. Texturas más una Luz. Equipo 1 Equipo 2 Equipo 3

Con lo anterior se puede concluir además, que para el uso de aplicaciones gráficas se hace fundamental un Computador con una tarjeta gráfica dedicada (no integrada).

El desarrollo de esta aplicación proporcionó como producto un entorno de diseño de escenarios en tres dimensiones, el cual puede ser utilizado en entornos matemáticos, robótica y propósito general, con el cual el desarrollador puede sin ser experto en OpenGL, diseñar modelos complejos, que sin la ayuda de esta herramienta le sería muy arduo.

218

Otra conclusión que se obtuvo de la etapa de “Selección de Tecnologías para el Desarrollo” es el caso especifico de la selección de la librería FreeGlut la cual básicamente está encargada de la gestión de ventanas y de comunicación del contexto OpenGL con periféricos tales como mouse y teclado, esta librería no es la más actual ni la más desarrollada para realizar el trabajo antes descrito, existen otras más actuales y ampliamente desarrolladas, tales como Sdl entre otras, no obstante para este proyecto se requirió la generación de código fuente y ésta se realiza mediante el uso de los fuentes de la aplicación, con lo cual haber usado por ejemplo Sdl, el código fuente OpenGl devuelto ya no hubiera sido puro, como si lo es con el uso de FreeGlut, ya que esta librería es considerada como complemento natural de OpenGl no así Sdl, con lo cual se puede concluir que la “Selección de Tecnologías para el

Desarrollo” es parte fundamental del desarrollo de una aplicación y se debe tener en cuenta claramente el problema que desea solucionar y que el uso de la herramienta ofrezca las características para solucionar este problema.

Otro producto obtenido del desarrollo de esta aplicación, fue encapsulación de la dificultad del trabajo con OpenGL, ya que parte de esta aplicación dió como producto una biblioteca de clases llamada ZeroFxCore, la cual permite crear desde escenarios simples hasta complejos, esto sin necesidad de usar la aplicación propiamente tal. Además, con el uso de biblioteca antes mencionada, el diseño de las escenas en forma programática

219

reduce drásticamente la cantidad de líneas de código, a continuación se expone el código que despliega una pirámide usando la biblioteca de Clases

ZeroFxCore (Código Nº [21]) y otro usando directamente la API OpenGL

(Código Nº [22]).

//Código que construye la primitiva OpenGl pirámide sólida usando la //Biblioteca de Clases ZeroFxCore

Pyramid pyramid = new Pyramid(); engine.AddEntity(world, pyramid, colorR, colorG, colorB);

Código Nº [21]

220

//método que construye la primitiva OpenGl pirámide sólida usando //OpenGL public static void RenderPyramid(double x) { //triángulo 1 Gl.glBegin(Gl.GL_TRIANGLES); Gl.glTexCoord2d(1, 0.5); Gl.glNormal3d(0f, x, 0f); Gl.glVertex3d(0, x, 0); Gl.glTexCoord2d(0, 1); Gl.glNormal3d(-x, -x, x); Gl.glVertex3d(-x, -x, x); Gl.glTexCoord2d(0, 0); Gl.glNormal3d(x, -x, x); Gl.glVertex3d(x, -x, x); //triángulo 2 Gl.glTexCoord2d(1, 0.5); Gl.glNormal3d(0, x, 0); Gl.glVertex3d(0, x, 0); Gl.glTexCoord2d(0, 1); Gl.glNormal3d(x, -x, x); Gl.glVertex3d(x, -x, x); Gl.glTexCoord2d(0, 0); Gl.glNormal3d(x, -x, -x); Gl.glVertex3d(x, -x, -x); //triángulo 3 Gl.glTexCoord2d(1, 0.5); Gl.glNormal3d(0, x,0); Gl.glVertex3d(0, x,0); Gl.glTexCoord2d(0, 1); Gl.glNormal3d(x, -x, -x); Gl.glVertex3d(x, -x, -x); Gl.glTexCoord2d(0, 0); Gl.glNormal3d(-x, -x, -x); Gl.glVertex3d(-x, -x, -x); //triángulo 4 Gl.glTexCoord2d(1, 0.5); Gl.glNormal3d(0, x, 0); Gl.glVertex3d(0, x, 0); Gl.glTexCoord2d(0, 1); Gl.glNormal3d(-x, -x, -x); Gl.glVertex3d(-x, -x, -x); Gl.glTexCoord2d(0, 0); Gl.glNormal3d(-x, -x, x); Gl.glVertex3d(-x, -x, x); Gl.glEnd(); }

Código Nº [22].

221

Se puede concluir, que el uso de la librería ZeroFxCore dá como resultado una disminución del código necesario para desplegar una primitiva, en una escala promedio de 5 es a 1.

Otra conclusión que se puede obtener, es referente al uso de Reflection de .Net, el cual básicamente es un mecanismo para examinar, manipular y crear objetos en tiempo de ejecución, lo cual fue ampliamente utilizado para el desarrollo de la aplicación, ya sea usado directamente para la generación de entornos dinámicos o por medio de una implementación (Reflector) usada para la generación de código fuente, con lo cual se puede concluir que la tecnología reflection fue uno los pilares programáticos de la implementación de la aplicación desarrollada.

Otra conclusión que puede obtener, es que si bien la aplicación es portable a Linux, ésta no funciona completamente en forma adecuada, esto principalmente a la diferencia en el esquema de trabajo con hilos que tiene

Linux con Windows, además los WinForms utilizados en la aplicación no son completamente compatibles con Mono, con lo cual la aplicación funciona en

Linux de manera aceptable, pero en ningún caso como lo hace en Windows, no obstante el código fuente generado por la aplicación es totalmente portable entre Linux y Windows, con lo cual se puede concluir que la portabilidad de esta aplicación no es total, lo cual no quiere decir que esta no pueda ser mejorada

222

en un futuro, esto en base a que la plataforma Mono de Linux avanza rápidamente en la implementación análoga de la tecnologías .Net.

Junto con lo anterior, se puede establecer que los requerimientos y/o funcionalidades esperados para esta aplicación se han cumplido satisfactoriamente de acuerdo a lo esperado por el cliente.

Finalmente, relacionada con la extensibilidad de la aplicación, queda totalmente abierta agregar nuevas funcionalidades tales como aplicación de

Físicas, Animaciones avanzadas, aplicación de motor de partículas entre otras muchas funcionalidades aplicables, por lo cual a juicio del alumno tesista es un muy buen tema a retomar como parte una nueva tesis.

223

12. Bibliografía

[Autodesk2008] Autodesk, 3ds MAX Overview. Disponible en http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=5659305

[Bateman2004] The Maya Exporter Factfile. Disponible en http://www.robthebloke.org/research/index.htm

[CrytekGames2008] CrytekGames CrisisEngine2 Features. Disponible en http://www.crytek.com/ .abril 2008

[EpicGames2008] EpicGames UnrealEngine3 Features. Disponible en http://www.unrealtechnology.com/ .abril 2008

[Sinclair2008] GDC '08: Final Fantasy XIII powered by Crystal Tools. Disponible en http://www.gamespot.com/news/6186627.html 22 .febrero 2008

[Edge2007] 3 Vs CryEngine 2.Disponible en http://www.next- gen.biz/index.php?option=com_content&task=view&id=6049&Itemid=2&li mit=1&limitstart=0 .18 junio 2007

[Kyprianidis2007] Jan Eric Kyprianidis Lib3ds Features. Disponible en http://lib3ds.sourceforge.net/

[Ogre3d2008] Ogre3d Feature, documentation. Disponible en http://www.ogre3d.org/

224

[SerranoLobo2007] Iván Lobo y Francisco A. Serrano. Star Wars: The Force Unleashed avance. Disponible en http://www.meristation.com/v3/des_avances.php?pic=360&id=cw47c653f5 7508 1&idj=cw45d4689b5bed2&idp=&tipo=art&c=1&pos=0 .febrero 2008

[XtremePrograming2007] Xtreme Programing. XP Leasson. Disponible en Http://www.extremeprogramming.org

[Flower2003] Martin Flower, La nueva Metodología. Disponible en http://www.programacionextrema.org/articulos/newMethodology.es.html febrero 2003

[UML2007] Tutorial de UML Diagrama de clases. http://www.dcc.uchile.cl/~psalinas/uml/modelo.html

225

13. Anexo

Diagrama de clases Editor 3D

226