Professional Documents
Culture Documents
Desarrollo de un sistema de edicin de escenas basado en una librera grfica de alto nivel: OpenSceneGraph.
INGENIERA INFORMATICA ESCUELA TECNICA SUPERIOR DE INGENIERA
Septiembre 2006
PARTE II ................................................................................................... 13
2.1 Informtica grfica en tiempo real. ................................................................................... 17 2.1.1 Introduccin. .................................................................................................................. 17 2.1.2 Orientacin hacia el Hardware Grfico 3D. Libreras grficas de bajo nivel. ............... 18 2.1.2.1 OpenGl. ................................................................................................................... 19 2.1.2.2 Representacin poligonal de los objetos. ................................................................ 20 2.1.2.3 Modelos de Sombreado. Sombreado Local............................................................. 21 2.1.2.4 Primitivas de dibujado............................................................................................. 21 2.1.2.5 Pilas de Matrices. .................................................................................................... 22 2.1.2.6 Empleo de Texturas................................................................................................. 22 2.1.2.7 Depth buffer. ........................................................................................................... 23 2.1.2.8 Shaders. ................................................................................................................... 23 2.1.3 Libreras grficas de Alto Nivel. Grafos de escena........................................................ 24 2.1.3.1 Grafos de Escena. Generalidades. ........................................................................... 24 2.1.3.2 Tipos bsicos de Nodos........................................................................................... 25 2.1.3.3 Proceso de seleccin de niveles de detalle. ............................................................. 26 2.1.3.4 Proceso de culling. .................................................................................................. 28 2.1.3.5 Multiproceso............................................................................................................ 30 2.1.3.5.1 Procesamiento Paralelo. ................................................................................... 30 2.1.3.5.2 Procesamiento Serie o en Pipeline. .................................................................. 31 2.1.4 Revisin de Grafos de Escena. ....................................................................................... 31 2.1.4.1 OpenGl Performer. .................................................................................................. 32 2.1.4.2 Open Inventor.......................................................................................................... 33 2.1.4.3 VRML ...................................................................................................................... 35 2.1.4.4 OpenSceneGraph..................................................................................................... 36 2.1.4.5 Otras libreras graficas de alto nivel........................................................................ 38 2.1.5 Motores de Videojuegos................................................................................................. 38 2.1.5.1 Motores de Visualizacin........................................................................................ 38 2.1.5.1.1 3D GameStudio ................................................................................................ 38 2.1.5.1.2 Crystal Space.................................................................................................... 39 2.1.5.1.3 Genesis3D ........................................................................................................ 39 2.1.5.1.4 The Nebula Device........................................................................................... 40 2.1.5.1.5 OGRE ............................................................................................................... 40 2.1.5.1.6 Shark3D............................................................................................................ 40 2.1.5.1.7 The Torque Game Engine ................................................................................ 41 2.1.5.1.8 CDX Game Development Kit .......................................................................... 41 2.1.5.1.9 Artist................................................................................................................. 41 2.1.6.2 Motores de Videojuegos.......................................................................................... 42 2.1.6.2.1 Fly3D................................................................................................................ 42 2.1.6.3 Videojuegos Completos .......................................................................................... 43 2.1.6.3.1 Doom................................................................................................................ 43 2.1.6.3.2 Quake ............................................................................................................... 44 2.1.6.3.3 Unreal Tournament .......................................................................................... 45 2.1.6.3.4 Source Engine ................................................................................................. 46 2.1.7 Editores 3D................................................................................................................. 49 2.1.7.1 Maya.................................................................................................................... 51 2.1.7.2 3D Studio Max .................................................................................................... 54
2.1.7.3 LightWave 3D ..................................................................................................... 56 2.1.7.4 SoftImage XSI..................................................................................................... 57 2.1.7.5 Multigen Creator ................................................................................................. 57 2.1.7.6 OSGEdit .............................................................................................................. 58 2.1.7.7 Valve Hammer Editor ......................................................................................... 59 2.1.7.8 UnrealED............................................................................................................. 60 2.2 Arquitectura de Plugins..................................................................................................... 61 2.3 Bibliotecas de enlace dinmico ......................................................................................... 63 2.3.1 Desarrollo de Plugins en 3D Studio Max....................................................................... 74 2.3.1.1 Funciones que debe implementar un plugin en 3ds Max .................................... 74 2.3.1.2 La funcion DllMain() .......................................................................................... 74 2.3.1.3 LibNumberClasses .............................................................................................. 75 2.3.1.4 LibClassDesc....................................................................................................... 75 2.3.1.5 LibDescription..................................................................................................... 75 2.3.1.6 LibVersion() ........................................................................................................ 75 2.3.1.7 Descriptores de clases ......................................................................................... 76 2.3.1.8 Mapas de parmetros........................................................................................... 79 2.4 Conclusiones. .................................................................................................................... 79
PARTE III.................................................................................................. 81
3.1 Metodologa ...................................................................................................................... 84 3.2 Materiales .......................................................................................................................... 84 3.3 Planificacin temporal....................................................................................................... 84 3.3.1 Diagrama de Gant....................................................................................................... 85
PARTE IV .................................................................................................. 89
4.1 Introduccin ...................................................................................................................... 94 4.2 Anlisis de Requisitos. ...................................................................................................... 95 4.2.1 Requisitos generales del sistema. ............................................................................... 95 4.2.2 Requisitos de la representacin del grafo de escena .................................................. 95 4.2.3 Requisitos de la representacin de tipos de datos en el interfaz................................ 96 4.2.4 Requisitos de la manipulacin sobre la representacin 3D del grafo......................... 96 4.2.5 Requisitos del sistema de deshacer / rehacer.............................................................. 97 4.2.5 Requisitos del sistema de plugins............................................................................... 97 4.2.6 Requisitos del Manejador de Vista Activa ................................................................. 97 4.3 Anlisis.............................................................................................................................. 98 4.3.1 Anlisis de la representacin de los datos del grafo en el interfaz ............................. 98 4.3.1.1 Grupos de parmetros.......................................................................................... 99 4.3.1.2 Descriptores de parmetros ................................................................................. 99 4.3.1.3 El gestor de parmetros ....................................................................................... 99 4.3.1.4 Objects, Nodes, y AttributeTypes en OpenSceneGraph ................................... 103 4.3.1.5. El Gestor de ObjectTypes, NodeTypes y AttributeTypes. ............................... 104 4.3.2 Anlisis de la representacin del grafo de escena .................................................... 104 4.3.2.1 Crear un rbol a partir de un grafo .................................................................... 105 4.3.2.2 Mostrar el grafo en mltiples vistas de rbol .................................................... 106 4.3.2.3 Acciones sobre el rbol ..................................................................................... 107 4.3.2.4 Mostrar la informacin de un nodo del grafo.................................................... 108 4.3.3 Anlisis de la interaccin con el visor del editor...................................................... 108 4.3.3.1 El gestor de seleccin ........................................................................................ 109 4.3.3.2 El eje manipulador ............................................................................................ 109 4.3.3.3 Creacin automtica de Matrices de Transformacin ....................................... 110 4.3.3.4 Traslacin de objetos usando el eje manipulador.............................................. 111 4.3.3.5 Representacin de objetos independientes a la escena del editor...................... 112 4.3.4 Anlisis del sistema deshacer / rehacer. ................................................................... 113
4.2.7 Anlisis del sistema de plugins. ............................................................................... 114 4.2.8 Anlisis del Manejador de Vista Activa................................................................... 115 4.4 Casos de uso .................................................................................................................... 117 4.4.1 Funciones del sistema............................................................................................... 117 4.4.2 Descripcin de alto nivel de los Casos de Uso......................................................... 119 Iniciar la aplicacin. ...................................................................................................... 119 Iniciar Barras. ................................................................................................................ 119 Crear barra de paneles de comandos. ............................................................................ 119 Iniciar tipos de objeto.................................................................................................... 120 Registrar un TabOutput................................................................................................. 120 Registrar un ObjectType. .............................................................................................. 120 Mapear los grupos de parmetros de un TabOutput...................................................... 120 Cargar Plugins. .............................................................................................................. 121 Cerrar aplicacin. .......................................................................................................... 121 Cerrar treebar ................................................................................................................ 122 Cerrar escena. ................................................................................................................ 122 Cargar escena. ............................................................................................................... 122 Establecer un grafo sobre un elemento del rbol. ......................................................... 123 Replicar una escena de una TreeBar a otra. .................................................................. 123 Clonar un TreeCtrl a partir de otro................................................................................ 124 Nueva escena................................................................................................................. 124 Crear grafo por defecto. ................................................................................................ 124 Nuevo rbol................................................................................................................... 125 Insertar fichero. ............................................................................................................. 125 Cambiar escena activa................................................................................................... 125 Deshacer. ....................................................................................................................... 126 Rehacer.......................................................................................................................... 126 Crear Nodo. ................................................................................................................... 126 Crear un nodo segn el nombre de su NodeType. ........................................................ 126 Crear una nueva instancia de un nodo segn su nombre............................................... 127 Seleccionar elemento en rbol....................................................................................... 127 Seleccionar todas las instancias de un elemento. .......................................................... 128 Seleccionar todos los mirrors de un elemento. .......................................................... 128 Mostrar la informacin de un nodo ............................................................................... 128 Crear los dilogos de un TabOutput.............................................................................. 129 Crear un dilogo a partir de un grupo de parmetros .................................................... 129 Generar el contenido de un TabOutput ......................................................................... 130 Vaciar el contenido de un TabOutput............................................................................ 130 Notificar fin de seleccin de un ObjectType................................................................. 130 Mostrar los datos de un TabOutput ............................................................................... 131 Seleccionar nodo en el visor.......................................................................................... 131 Agregar nodo a la seleccin del visor ........................................................................... 131 Crear Matriz de Transformacin como padre de un nodo............................................. 132 Actualizar la seleccin. ................................................................................................. 132 Actualizar el eje manipulador. ...................................................................................... 132 Copiar nodo................................................................................................................... 133 Replicar seleccin. ........................................................................................................ 133 Mover nodo. .................................................................................................................. 133 Duplicar Nodo. .............................................................................................................. 134 Duplicar Seleccion. ....................................................................................................... 134 Eliminar nodo................................................................................................................ 134 Activar modo seleccin................................................................................................. 135 Activar modo traslacin de objetos............................................................................... 135 Activar modo escalado de objetos................................................................................. 135 Activar modo rotacin de objetos. ................................................................................ 136
Activar modo rotar vista................................................................................................ 136 Activar modo trasladar vista. ........................................................................................ 136 Escalar seleccin. .......................................................................................................... 136 Comenzar escalado de seleccin. .................................................................................. 137 Realizar escalado de seleccin. ..................................................................................... 137 Finalizar escalado de seleccin. .................................................................................... 138 Rotar seleccin. ............................................................................................................. 138 Comenzar rotacin de seleccin.................................................................................... 138 Realizar rotacin de seleccin....................................................................................... 139 Finalizar rotacin de seleccin...................................................................................... 139 Trasladar seleccin........................................................................................................ 139 Comenzar traslacin de seleccin. ................................................................................ 140 Realizar traslacin de seleccin. ................................................................................... 140 Finalizar traslacin de seleccin. .................................................................................. 140 Centrar la vista en la seleccin...................................................................................... 141 Modificar el zoom de la vista. ....................................................................................... 141 Aadir un StateAttribute a un StateSet.......................................................................... 141 Eliminar un StateAttibute de un StateSet. ..................................................................... 142 Aadir un Modo a un StateSet. ..................................................................................... 142 Eliminar un Modo de un StateSet. ................................................................................ 142 Modificar un Modo de un StateSet. .............................................................................. 142 Modificar el parmetro de un control del panel de comandos. ..................................... 143 Establecer el valor de un parmetro. ............................................................................. 143 Establecer el valor de un parmetro. ............................................................................. 143 Establecer el contenido del portapapeles....................................................................... 144 Pegar el contenido del portapapeles. ............................................................................. 144 Visualizar escena en modo de alambre. ........................................................................ 144 Visualizar escena en modo de relleno. .......................................................................... 145 Visualizar sombreado en modo plano. .......................................................................... 145 Visualizar sombreado en modo suavizado. ................................................................... 145 Mostrar vista superior de la escena. .............................................................................. 145 Mostrar vista inferior de la escena. ............................................................................... 145 Mostrar vista anterior de la escena. ............................................................................... 146 Mostrar vista posterior de la escena. ............................................................................. 146 Mostrar vista lateral izquierda de la escena................................................................... 146 Mostrar vista lateral derecha de la escena. .................................................................... 146 4.4.3 Casos de Uso siguiendo la notacin UML. .............................................................. 147
5.3.13 Copiar elemento de rbol ....................................................................................... 179 5.3.14 Copiar tem de un nico rbol. ............................................................................... 179 5.3.15 SelectAllInstances .................................................................................................. 180 5.3.16 SelectAllMirrors..................................................................................................... 180 5.3.17 CreateParentMatrixTransform ............................................................................... 181 5.3.18 StartTranslation ...................................................................................................... 181 5.3.19 DoTranslate ............................................................................................................ 182 5.3.20 EndTranslate........................................................................................................... 182 5.3.21 RemoveSceneTree.................................................................................................. 183 5.3.22 Exec........................................................................................................................ 183 5.3.23 RecursiveCreateDialogs ......................................................................................... 184 5.3.24 CreateDialogs. ........................................................................................................ 184 5.3.25 CreateDialogFromGroup........................................................................................ 185 5.3.26 RegisterTabOutput (TabOutputManager) .............................................................. 186 5.3.27 RegisterType (ObjectTypeManager)...................................................................... 186 5.3.28 NewInstance ........................................................................................................... 187 5.3.29 CreateTreeNode ..................................................................................................... 187 5.3.30 CargarPlugins ......................................................................................................... 188 5.3.31 Update (Selection)................................................................................................. 188 5.3.32 UpdateAxis............................................................................................................. 189 5.3.33 MapIOControls....................................................................................................... 190 5.3.34 RecursiveOnEndSelection...................................................................................... 190 5.3.35 RecursiveGenerateRollupContent (ObjectType).................................................... 191 5.3.36 RecursiveClearRollupContent (ObjectType) ......................................................... 191 5.3.37 GenerateRollupContent (TabOutput) ..................................................................... 192 5.3.38 ClearRollupContent (TabOutput)........................................................................... 192 5.3.39 GetParamValue (TabOutput) ................................................................................. 193 5.3.40 SetParamValue (TabOutput) .................................................................................. 193 5.3.41 LookAtSelection..................................................................................................... 194 5.3.42 SetRootNode (ActiveViewHandler)....................................................................... 194 5.3.43 SetRootNode (MultiTreeBar)................................................................................. 195 5.3.44 ReplicateSceneTree (MultiTreeBar) ...................................................................... 196 5.3.45 CloneFrom (OSGTreeCtrl) .................................................................................... 196 5.3.46 DeleteNode (OSGTreeCtrl).................................................................................... 197 5.3.47 ActDeleteMultiItem (Action) ................................................................................. 197 5.3.48 DeleteNode (ActiveViewHandler) ......................................................................... 198 5.3.49 Cambiar escena activa............................................................................................ 199 5.4. Diagrama de estados del sistema.................................................................................... 199 5.4.1 Estado del cursor ...................................................................................................... 199
6.3.3 La clase CEditTreeCtrlEx ........................................................................................ 222 6.3.4 La clase COSGTreeCtrl ........................................................................................... 223 6.3.5 CTreeBar y CMultiTreeBar. .................................................................................... 224 6.4 Interaccin con el visor 3D ............................................................................................. 226 6.4.1 La clase OSGSelection............................................................................................. 226 6.4.2 La clase OSGAxisManipulator ............................................................................... 231 6.4.3 La clase MFCKeyboardMouseCallback .................................................................. 233 6.5 El sistema de deshacer / rehacer...................................................................................... 234 6.5.1 La clase OSGAction................................................................................................. 234 6.5.2 La clase OSGHistory................................................................................................ 235 6.6 El sistema gestor de plugins ............................................................................................ 236 6.6.1 El plugin Cartoon ..................................................................................................... 236 6.6.2 La clase OSGPluginManager ................................................................................... 237 6.6.3 La clase OutPlugins.................................................................................................. 239 6.7 El manejador de la vista activa y las clases MFC ........................................................... 241 6.7.1 La clase OSGActiveViewHandler............................................................................ 241 6.7.2 La clase COSGWorldView ...................................................................................... 246 6.8 Problemas y tips de implementacin. .......................................................................... 249 6.8.1 La actualizacin de OpenSceneGraph 0.9 a 1.0. ...................................................... 249 6.8.2 La clase RefParticle.................................................................................................. 249 6.8.3 La funcin clone....................................................................................................... 250 6.8.4 La funcin DoFrame().............................................................................................. 250 6.8.5 Eliminar un nodo, deshacer y rehacer. ..................................................................... 251
PARTE I
INTRODUCCIN
INDICE
10
1.1 Introduccin.
En el mundo de los grficos por ordenador, existen dos lneas de investigacin que se encuentran en estados muy avanzados, pero han seguido caminos divergentes: de un lado la Animacin 3D que ha centrado toda su atencin en la calidad visual de las imgenes, y de otro, la Realidad Virtual o Informtica Grfica en Tiempo Real, que ha intentando conseguir la mayor calidad posible, pero dando prioridad a la rapidez en la generacin de imgenes. La realidad virtual puede ser de dos tipos: inmersiva y no inmersiva. Los mtodos inmersivos de realidad virtual con frecuencia se ligan a un ambiente tridimensional creado por un ordenador, el cual se manipula a travs de cascos, guantes u otros dispositivos que capturan la posicin y rotacin de diferentes partes del cuerpo humano. La realidad virtual no inmersiva utiliza medios como el que actualmente nos ofrece Internet, en el cual podemos interactuar en tiempo real con diferentes personas en espacios y ambientes que en realidad no existen sin la necesidad de dispositivos adicionales al ordenador. La realidad virtual no inmersiva ofrece un nuevo mundo a travs de una ventana de escritorio. Este enfoque no inmersivo tiene varias ventajas sobre el enfoque inmersivo como son el bajo coste y fcil y rpida aceptacin de los usuarios. Los dispositivos inmersivos son de alto coste y generalmente el usuario prefiere manipular el ambiente virtual por medio de dispositivos familiares como son el teclado y el ratn que por medio de cascos pesados o guantes. Pero tanto la Animacin 3D como la Informtica Grfica en Tiempo Real siempre han estado complementadas por herramientas especficas o interfaces de edicin. Estas herramientas grficas han facilitado al desarrollador de entornos o animaciones la tarea de modelar objetos o generar escenarios, o realizar secuencias de movimientos de manera manual, mediante series de comandos o introduciendo las posiciones de la geometra manualmente. Estas herramientas tambin han ido evolucionando al mismo tiempo que lo han ido haciendo los motores grficos, permitiendo en algunas de ellas una visualizacin en tiempo real del resultado final de la imagen. Adems, gracias a la modularidad de estas aplicaciones, cada vez son ms las aplicaciones que admiten extensiones, desarrollables por terceras personas, que se pueden ir aadiendo a las mismas para mejorar su capacidad y flexibilidad. Gran parte de los motores grficos de simulacin actuales definen una escena mediante el uso de un Grafo de Escena (Scene Graph), el cual es una estructura en forma de grafo, formado por diversos tipos de nodos que ejercen distintos tipos de influencias sobre sus nodos hijos, bien sea estableciendo una agrupacin, introduciendo algn tipo de poda o aplicando alguna transformacin afn. Los nodos hijos de estas estructuras suelen ser los objetos geomtricos a representar. Aunque hasta hoy los grafos de escena han estado principalmente orientados a la representacin de entornos estticos, u objetos relativamente simples, cada vez ms se pueden encontrar grafos de escena que permiten realizar animaciones ms complejas y dinmicas, incluso que soportan sistemas de partculas. La motivacin de este proyecto radica en proporcionar una herramienta de edicin para uno de los ltimos grafos de escena disponibles en cdigo abierto: OpenSceneGraph, dada la carencia de potentes herramientas de edicin para este grafo de escena. Esta librera est siendo ampliamente utilizada por el Instituto de Robtica de la Universidad de Valencia, debido a la antigedad de OpenGL Performer (el motor grfico de SGI basado tambin en grafo de escena). Para ello, ser necesario analizar las carencias de las actuales herramientas existentes, as como las necesidades del Instituto de Robtica para as proponer soluciones que permitan llegar a construir una aplicacin a la altura de sus exigencias.
11
1.2 Objetivos.
En este proyecto se pretende construir una aplicacin que permita construir y manipular un grafo de escena de la librera OpenSceneGraph, proporcionando un interfaz sencillo e intuitivo, pero a la vez potente, ampliable, y que no requiera apenas conocimientos de programacin. Concretamente vamos a enumerar los siguientes objetivos: Crear un interfaz sencillo, flexible y dinmico pero a la vez potente, proporcionando al usuario acciones que faciliten algunas de las tareas ms tediosas. Se tomar en cuenta el interfaz y el manejo de 3d Studio Max, puesto que es una herramienta muy utilizada por el Instituto de Robtica, y ser una de las aplicaciones que complementen con la aplicacin desarrollada en este proyecto. Dotar a la aplicacin de un mecanismo de visualizacin y manipulacin de la estructura del grafo de escena. Del mismo modo, realizar una parametrizacin de los datos del grafo de escena en el interfaz grfico para permitir la manipulacin de los datos, de la manera ms intuitiva posible y que aporte la mayor informacin al usuario. Disponer de un sistema de historia, para poder deshacer y rehacer cualquier tipo de accin sobre el grafo. Visualizar el estado del grafo de escena en tiempo real, permitiendo una interaccin del usuario con la escena, sin necesidad de hacerlo manipulando directamente el rbol. Que sea un sistema ampliable, mediante una arquitectura de plugins. De este modo se podrn desarrollar nuevas funcionalidades en la aplicacin, sin necesidad de modificar su ncleo. Por tanto se deber proporcionar un conjunto de clases y libreras disponibles para el desarrollador de plugins.
Todos estos objetivos se debern cumplir siempre siguiendo las tcnicas de desarrollo aprendidas en las asignaturas de Ingeniera del Software, pudiendo obtener, de este modo, unas aplicaciones de buena calidad.
12
PARTE II
13
14
INDICE
PARTE II .......................................................................................................
2.1 Informtica grfica en tiempo real. ................................... Error! Marcador no definido. 2.1.1 Introduccin. .................................................................. Error! Marcador no definido. 2.1.2 Orientacin hacia el Hardware Grfico 3D. Libreras grficas de bajo nivel. .......Error! Marcador no definido. 2.1.2.1 OpenGl. ................................................................... Error! Marcador no definido. 2.1.2.2 Representacin poligonal de los objetos. ................ Error! Marcador no definido. 2.1.2.3 Modelos de Sombreado. Sombreado Local............. Error! Marcador no definido. 2.1.2.4 Primitivas de dibujado............................................. Error! Marcador no definido. 2.1.2.5 Pilas de Matrices. .................................................... Error! Marcador no definido. 2.1.2.6 Empleo de Texturas................................................. Error! Marcador no definido. 2.1.2.7 Depth buffer. ........................................................... Error! Marcador no definido. 2.1.2.8 Shaders. ................................................................... Error! Marcador no definido. 2.1.3 Libreras grficas de Alto Nivel. Grafos de escena........ Error! Marcador no definido. 2.1.3.1 Grafos de Escena. Generalidades. ........................... Error! Marcador no definido. 2.1.3.2 Tipos bsicos de Nodos........................................... Error! Marcador no definido. 2.1.3.3 Proceso de seleccin de niveles de detalle. ............. Error! Marcador no definido. 2.1.3.4 Proceso de culling. .................................................. Error! Marcador no definido. 2.1.3.5 Multiproceso............................................................ Error! Marcador no definido. 2.1.3.5.1 Procesamiento Paralelo. ................................... Error! Marcador no definido. 2.1.3.5.2 Procesamiento Serie o en Pipeline. .................. Error! Marcador no definido. 2.1.4 Revisin de Grafos de Escena. ....................................... Error! Marcador no definido. 2.1.4.1 OpenGl Performer. .................................................. Error! Marcador no definido. 2.1.4.2 Open Inventor.......................................................... Error! Marcador no definido. 2.1.4.3 VRML ...................................................................... Error! Marcador no definido. 2.1.4.4 OpenSceneGraph..................................................... Error! Marcador no definido. 2.1.4.5 Otras libreras graficas de alto nivel........................ Error! Marcador no definido. 2.1.5 Motores de Videojuegos................................................. Error! Marcador no definido. 2.1.5.1 Motores de Visualizacin........................................ Error! Marcador no definido. 2.1.5.1.1 3D GameStudio ................................................ Error! Marcador no definido. 2.1.5.1.2 Crystal Space.................................................... Error! Marcador no definido. 2.1.5.1.3 Genesis3D ........................................................ Error! Marcador no definido. 2.1.5.1.4 The Nebula Device........................................... Error! Marcador no definido. 2.1.5.1.5 OGRE ............................................................... Error! Marcador no definido. 2.1.5.1.6 Shark3D............................................................ Error! Marcador no definido. 2.1.5.1.7 The Torque Game Engine ................................ Error! Marcador no definido. 2.1.5.1.8 CDX Game Development Kit .......................... Error! Marcador no definido. 2.1.5.1.9 Artist................................................................. Error! Marcador no definido. 2.1.6.2 Motores de Videojuegos.......................................... Error! Marcador no definido. 2.1.6.2.1 Fly3D................................................................ Error! Marcador no definido. 2.1.6.3 Videojuegos Completos .......................................... Error! Marcador no definido. 2.1.6.3.1 Doom................................................................ Error! Marcador no definido. 2.1.6.3.2 Quake ............................................................... Error! Marcador no definido. 2.1.6.3.3 Unreal Tournament .......................................... Error! Marcador no definido. 2.1.6.3.4 Source Engine ................................................. Error! Marcador no definido. 2.1.7 Editores 3D................................................................. Error! Marcador no definido. 2.1.7.1 Maya.................................................................... Error! Marcador no definido. 2.1.7.2 3D Studio Max .................................................... Error! Marcador no definido. 2.1.7.3 LightWave 3D ..................................................... Error! Marcador no definido.
15
2.1.7.4 SoftImage XSI..................................................... Error! Marcador no definido. 2.1.7.5 Multigen Creator ................................................. Error! Marcador no definido. 2.1.7.6 OSGEdit .............................................................. Error! Marcador no definido. 2.1.7.7 Valve Hammer Editor ......................................... Error! Marcador no definido. 2.1.7.8 UnrealED............................................................. Error! Marcador no definido. 2.2 Arquitectura de Plugins..................................................... Error! Marcador no definido. 2.3 Bibliotecas de enlace dinmico ......................................... Error! Marcador no definido. 2.3.1 Desarrollo de Plugins en 3D Studio Max....................... Error! Marcador no definido. 2.3.1.1 Funciones que debe implementar un plugin en 3ds Max .... Error! Marcador no definido. 2.3.1.2 La funcion DllMain() .......................................... Error! Marcador no definido. 2.3.1.3 LibNumberClasses .............................................. Error! Marcador no definido. 2.3.1.4 LibClassDesc....................................................... Error! Marcador no definido. 2.3.1.5 LibDescription..................................................... Error! Marcador no definido. 2.3.1.6 LibVersion() ........................................................ Error! Marcador no definido. 2.3.1.7 Descriptores de clases ......................................... Error! Marcador no definido. 2.3.1.8 Mapas de parmetros........................................... Error! Marcador no definido. 2.4 Conclusiones. .................................................................... Error! Marcador no definido.
16
17
grficos relevantes por medio de una estructura jerrquica de dibujado conocida con el nombre de grafo de escena (scene graph). Estas estructuras son rboles formados por un conjunto de nodos organizados de tal modo que cada uno de ellos ejerce una determinada influencia sobre sus ramas hijas. Los nodos hoja de este rbol usualmente estn formados usualmente por primitivas de dibujado. El empleo de grafos de escena tambin facilita enormemente la organizacin lgica de la escena, y el control por parte del usuario. En los siguientes apartados se muestra un estado del arte sobre el hardware grfico, descrito a travs de las funcionalidades de las libreras grficas de bajo nivel empleadas para su manejo, se muestran las funcionalidades de las libreras grficas de alto nivel y sus grafos de escena, y por ltimo se realiza una revisin de los grafos de escena actuales.
2.1.2 Orientacin hacia el Hardware Grfico 3D. Libreras grficas de bajo nivel.
El objetivo bsico en la generacin de imgenes 3D interactivas es alcanzar unas velocidades de refresco elevadas. El hecho de renderizar una escena 3D de una complejidad media varias veces por segundo, implica una inmensa cantidad de clculos que suele sobrepasar la capacidad de la CPU del ordenador. Por ello, es norma comn recurrir a la utilizacin de hardware grfico especialmente diseado para esta tarea, y, como consecuencia de un API (Application Programmer's Interface) que proporcione un acceso eficiente a sus capacidades. Adems, es deseable que dicho API proporcione una interfaz comn entre los diferentes tipos de hardware grfico existentes. En la actualidad hay varios sistemas que proporcionan un API para renderizado de grficos 3D, pero no todos ellos resultan adecuados para su utilizacin en tiempo real. Uno de los ms conocidos es PHIGS (Programmers's Hierarchical Interactive Graphics System) . PHIGS est basado en GKS (Graphic Kernel System) y es un estndar ANS que permite manipular y dibujar escenas 3D encapsulando descripciones de objetos y atributos en display list, esta caracterstica es especialmente til si existen objetos complejos que pueden ser definidos una sola vez y dibujados varias veces, o tambin si la escena va a ser transmitida por red. Uno de sus principales inconvenientes es que no resulta adecuada si los objetos necesitan estar actualizndose continuamente, y tambin que no soporta algunas caractersticas actualmente bsicas tales como el mapeado de texturas. PEXlib es otro API, basado originalmente en PHIGS, pero que a diferencia de ste, permite el renderizado en modo inmediato, es decir, los objetos son dibujados a medida que son descritos, sin necesidad de emplear una display list intermedia. PEXlib presenta como inconveniente que tampoco dispone de algunas caractersticas avanzadas de rendering y que tan slo funciona en sistemas basados en X. Otro API muy conocido es Renderman, a diferencia de los anteriores, proporciona un lenguaje de programacin para realizar las descripciones de los objetos y sus propiedades, esta caracterstica permite generar imgenes de un nivel de acabado muy elevado, pero es muy difcil disear un hardware grfico que lo soporte. Los tres sistemas anteriores constituyen los sistemas estndar de generacin de imgenes histricamente ms conocidos, pero presentan algunas carencias importantes a la hora de ser empleados en la generacin de imgenes en tiempo real. OpenGl es un API desarrollado a partir de IrisGL, una librera creada por Silicon Graphics en 1982. OpenGl tiene unas funcionalidades similares a PEXlib, pero es independiente de X, siendo en la actualidad soportado por casi la totalidad de sistemas operativos y de hardwares grficos. Una alternativa a OpenGl en sistemas Windows, es el API Direct3D, el cual es un subconjunto de DirectX, una librera que adems de la parte grfica da soporte de audio, vdeo, gestin de perifricos y gestin de red. Desde sus orgenes Direct3D ha sido considerada de inferior calidad que OpenGl (incluso en sistemas Windows), esta visin est cambiando debido a las
18
ltimos mejoras en su API que lo han hecho ms estable y potente. Sin embargo, Direct3D no es un standard abierto, solamente funciona en sistemas Windows, y es ms que dudoso que Microsoft tenga intencin de hacer que DirectX est disponible en otras plataformas.
2.1.2.1 OpenGl.
OpenGl fue introducida en 1992, y es en la actualidad un estndar industrial cuya especificacin es llevada a cabo por el ARB (OpenGL Architecture Review Board), un organismo del que son socios 3DLabs, ATI, Compaq, Evans&Sutherland, Hewlett-Packard, IBM, Intel, NVidia, Microsoft, y SGI. OpenGl es multiplataforma, independiente de vendedor y abierta, lo que le permite adaptarse a las nuevas innovaciones del hardware. Soporta primitivas grficas bsicas tales como puntos, lneas, polgonos e imgenes, y operaciones tales como la aplicacin de transformaciones afines o proyecciones, clculos de iluminacin, ocultacin entre objetos o mapeado de texturas. En la actualidad existen gran cantidad de tarjetas grficas desarrolladas para cumplir la especificacin de OpenGl. Los drivers de OpenGl encapsulan la informacin sobre el hardware grfico al que van destinados, liberando al desarrollador de aplicaciones, de tener que hacer desarrollos adaptados a las caractersticas de los diferentes tipos de tarjetas grficas. El funcionamiento bsico de la OpenGl puede ser observado en la Figura 2-1. Los comandos de OpenGl son recibidos desde la parte izquierda del diagrama, la informacin que se enva es bsicamente relativa a vrtices de la geometra (Geometry Path) o a imgenes (Imaging Path). Existe la posibilidad de acumular estos comandos en display list para procesarlos en un instante posterior, de otro modo, los comandos son enviados directamente al pipeline de procesado.
Tanto la informacin de vrtices como de imagen puede llegar en un formato compactado, siendo en este caso descomprimido dentro de la propia pipeline. Puede que la informacin referente a la geometra est indicada en forma curvas o superficies paramtricas, en tal caso se evalan y transforman en una descripcin basada en vrtices. En la siguiente etapa, se realizan operaciones sobre primitivas formadas de vrtices (puntos, segmentos de lneas y polgonos), los vrtices son transformados e iluminados, y las primitivas son ensambladas y recortadas por la pirmide de visin. Tambin se realizan operaciones sobre las imgenes, y algunas de ellas se almacenan sobre la memoria de texturas, listas para ser aplicadas sobre la geometra 3D. En la etapa de Rasterizacin, se utilizan los resultados de la fase anterior para generar una serie de direcciones y valores del framebuffer mediante la utilizacin de una descripcin 2D basada en puntos, lneas o polgonos. Por ltimo, el contenido del framebuffer es actualizado teniendo en cuenta la informacin anterior, y un conjunto de operaciones tales como comprobaciones de zbuffer, operaciones de mezcla con los actuales colores de framebuffer, operaciones de enmascaramiento etc. OpenGl ofrece acceso a un conjunto de operaciones grficas del nivel ms bajo posible, y como consecuencia no proporciona mecanismos directos para realizar la descripcin de objetos
19
geomtricos complejos (como por ejemplo un cubo o una esfera). Estos han de ser ensamblados mediante la utilizacin de mltiples comandos de OpenGl.
El hecho de emplear una representacin de este tipo hace que el proceso de dibujado de una escena pueda ser considerado como el procesado de un conjunto ms o menos grande de tringulos. Las actuales tarjetas grficas 3D incorporan hardware capaz de procesar dichos tringulos y transformarlos en su representacin correspondiente en pxeles de pantalla. Las libreras grficas de bajo nivel proporcionan mtodos para realizar descripciones de este tipo de objetos poligonales y emplear de forma adecuada el hardware grfico. La forma bsica de descripcin de un objeto en OpenGl consiste en la definicin de las coordenadas que especifican vrtices entre un par de comandos glBegin/glEnd, as, por ejemplo, para definir un tringulo formado por los vrtices en (0,0,0) (0,1,0) y (1,0,1) seria necesaria la siguiente secuencia de cdigo.
Cada vrtice es especificado con dos o tres coordenadas. Adicionalmente se pueden definir una normal, coordenadas de textura y color que sern utilizados en el procesamiento del vrtice. La normal se utiliza en los clculos de iluminacin y es especificada por medio de un vector de 3 componentes. El color proporciona informacin sobre las componentes Roja, Verde, Azul y de Alfa del vrtice. Las coordenadas de textura indican la forma en la que imagen que define la textura es mapeada sobre la primitiva. En una fase previa al dibujado del tringulo se pueden haber definido otras caractersticas que afectaran a la forma en la que ser dibujado, tales como las caractersticas del material empleado, la posicin y caractersticas de las luces que le afectan, la presencia de niebla, etc.
20
21
En arquitecturas en las cuales las transformaciones geomtricas e iluminacin son realizadas por software, se pueden emplear estructuras indexadas en las que los vrtices pueden ser procesados y almacenados una sola vez, y los tringulos se generan en una fase posterior accediendo de forma indexada a estos vrtices ya procesados. Sin embargo, por razones de compatibilidad con el hardware grfico, los APIs actuales no suelen explotar esta posibilidad.
22
La incorporacin de esta capacidad en los sistemas de generacin de imgenes en tiempo real supuso un enorme incremento en el realismo de las imgenes obtenidas (ver Figura 2-4).
Desde hace un par de aos es comn que el hardware grfico pueda aplicar varias texturas simultneamente sobre el mismo objeto, esta capacidad (multitexturing) ha contribuido a incrementar an ms la calidad de la imagen final.
2.1.2.8 Shaders.
En los ltimos aos, los fabricantes de hardware grfico han centrado parte de sus esfuerzos en flexibilizar la forma en la que acta la OpenGl, permitiendo que algunas de las partes de la pipeline grfica (hasta ahora totalmente fija) puedan ser reemplazadas por unidades de cdigo definibles por el usuario. Estas unidades son descritas en un lenguaje de alto nivel basado en un ANS C extendido de tal modo que es capaz de realizar operaciones con vectores y matrices, y que proporciona funciones especialmente diseadas para su utilizacin en grficos 3D. Un
Figura 2-5. Imagen generada con la ayuda de shaders
23
Shader es una unidad compilable independientemente que ha sido definida mediante este lenguaje.
24
alguna transformacin afn o realizando algn tipo de seleccin sobre alguna de sus ramas hijas. El proceso de dibujado consiste en realizar un recorrido de dicho grafo, aplicando las operaciones indicadas por cada tipo de nodo. El Grafo de Escena tiene como funciones principales: Contribuir a establecer una organizacin lgica de la escena. Establecer dependencias jerrquicas entre distintos sistemas de referencia. Posibilitar el proceso de seleccin entre mltiples niveles de detalle. Posibilitar el proceso automtico de Culling (eliminacin automtica de los objetos que se encuentran fuera del campo de visin). Facilitar el control de la escena por parte del usuario. Hacer ms cmodo el acceso a las libreras grficas de bajo nivel (OpenGl en este caso). En la siguiente imagen (Figura 2-5) se puede apreciar la descomposicin de un objeto en sus diferentes componentes, de manera agrupada, lo cual sera una aproximacin al grafo de escena que lo definira.
25
Nodo Grupo. Se emplean para agrupar varios nodos hijos, bien sea a nivel meramente organizativo, o para facilitar el proceso de culling jerrquico. Nodo Nivel de Detalle. Usualmente llamados nodos LOD (Level of Detail). Seleccionan uno de sus hijos, basndose en la distancia entre el objeto con mltiples niveles de detalle y el punto de vista. Nodo de Transformacin Afn. Permite aplicar una matriz de transformacin que afectara a ubicacin espacial de sus nodos hijos. Son necesarios para la definicin de objetos mviles y tambin para la creacin de estructuras articuladas. Nodo de Switch. Permiten realizar una seleccin entre sus nodos hijos.
Tambin es usual que el usuario tenga cierta capacidad para personalizar el comportamiento de los nodos, para ello los nodos suelen tener la capacidad de almacenar datos genricos que necesite el usuario, y tambin rutinas de callback escritas por el usuario que son invocadas junto con el cdigo interno de gestin del nodo.
26
los efectos indeseables de las transiciones entre niveles de detalle, unas de ellas consisten en seleccionar el punto adecuado de transicin, otras, en la creacin de muchos niveles de detalle distintos, de tal forma que las diferencias entre dos niveles de detalle consecutivos sean mnimas, y otras hacen que los saltos no se produzcan de forma brusca, sino mediante transiciones suaves entre las representaciones, no existiendo una distancia a la cual un modelo es directamente sustituido por otro, sino un rango de distancias, o bien, un rango temporal en el cual se realiza una transicin progresiva entre las dos representaciones: La tcnica de Fading produce un fundido suave entre las imgenes correspondientes a dos niveles de detalle consecutivos, pero, presenta como inconveniente que incrementa temporalmente la carga en el periodo en el que los dos modelos estn siendo dibujados simultneamente; la tcnica de Morphing, hace que los vrtices de la geometra de uno de los modelos se modifiquen suavemente, hasta adoptar la posicin de los vrtices del otro modelo. Esto requiere que algunos vrtices sean creados o destruidos en tiempo real, y, por tanto, obliga a que existan fuertes dependencias entre los modelos que representan los distintos niveles de detalle. Durante los periodos de transicin la CPU consume un tiempo adicional en la gestin del morphing. Es el mtodo que presenta mejores resultados tanto a nivel visual como computacional, sin embargo, el hecho de que existan dependencias tan fuertes entre los distintos niveles de detalle, hace que dichos modelos sean muy difciles de generar, y que en la prctica, sea muy poco usado. Para tener una referencia de la magnitud de la reduccin de clculos que supone la utilizacin de niveles de detalle, se puede indicar que la representacin poligonal de una persona de una calidad aceptable requiere unos 2250 polgonos, mientras que el nivel de detalle ms bajo puede ser resuelto con tan slo 38. En la Figura 2-6 se pueden apreciar los diferentes niveles de detalles empleados en la representacin del busto de una persona.
En la figura anterior, la representacin de ms calidad tiene aproximadamente unos 60.000 caras, la que aparece en tercer lugar presenta aproximadamente 600 caras, y por ltimo la ms sencilla, est formada por tan slo 60 caras. Esto evidencia que con la utilizacin adecuada de niveles de detalle se obtienen unas tasas de reduccin de su coste computacional que se mueven en dos ordenes de magnitud. En la Figura 2-7 se ha realizado una representacin conjunta de las geometras que representan el tercer y cuarto nivel de detalle, situndolas a distancias de la cmara cada vez mayores, es fcil comprobar que a medida que la distancia va aumentando las diferencias entre ellos se vuelven prcticamente imperceptibles.
27
Figura 2-8. Evidencia de que la capacidad de percepcin de detalles disminuye con la distancia del objeto.
Existe un gran nmero de investigaciones relativas al desarrollo de tcnicas de simplificacin geomtrica que pueden ser empleadas para la generacin de niveles de detalle.
presenta corno inconveniente principal, el hecho de que las intersecciones han de ser calculadas en tiempo de ejecucin. Los algoritmos que realizan este tipo de culling han de ser capaces de establecer un balance entre la carga que producen sobre la CPU, y el ahorro de trabajo que producen sobre el hardware grfico. La utilizacin de bounding volumes resulta especialmente adecuada para las bases de datos organizadas en forma de Grafo de Escena, ya que su estructura puede ser aprovechada para definir una organizacin jerrquica de bounding volumes. Cada nodo tiene asociado un bounding volume que engloba al nodo en s, y a todos sus hijos. La librera que gestiona el scene graph, tiene capacidad para recalcular automticamente la forma de esas envolventes cada vez que existe una modificacin en la topologa de la base de datos. Es usual que cada nodo tenga una lista que contiene referencias a sus nodos padre, de modo que cuando el bounding volume de un nodo es modificado, esa modificacin es propagada hacia sus padres. De este modo la jerarqua de bounding volumes permanece continuamente actualizada. Es bastante comn emplear como envolventes paraleleppedos alineados con los ejes (tambin conocidos como bounding boxes), o esferas (bounding spheres). Este tipo de envolventes son aproximaciones de la forma original, y, por tanto, puede ocurrir que el bounding volume de un objeto est intersectando con la pirmide de visin, y, sin embargo, no ocurra lo mismo con el objeto en s. Por esta razn, es adecuado que la envolvente se adapte lo mximo posible a la forma real del objeto. Analizado desde esta ptica, las bounding boxes son una mejor aproximacin, sin embargo, la actualizacin, transformacin y testeado mediante bounding spheres es mucho ms rpida. Algunas libreras como OpenGl Performer emplean sistemas mixtos, en los que las geometras finales del grafo de escena se procesan mediante bounding boxes y los nodos intermedios mediante bounding spheres. El mtodo de procesado de una escena con este tipo de culling jerrquico consiste en hacer un recorrido recursivo del grafo de escena, comprobando para cada nodo la forma en la que su envolvente intersecta con la pirmide de visin, tomando las siguientes decisiones: El bounding volume est completamente fuera de la pirmide de visin: ni este nodo ni sus hijos han de ser dibujados. El recorrido del scene graph contina sin entrar en esta rama. El bounding volume est completamente dentro de la pirmide de visin: este nodo y sus hijos han de ser dibujados. En esta rama ya no es necesario realizar ms comprobaciones de cull. El bounding volume intersecta con la pirmide de visin: se contina realizando el proceso de cull sobre los nodos hijos. En el caso de que sea un nodo final, se procede a su dibujado. En el caso de emplear este tipo de culling es muy conveniente tener una buena organizacin jerrquica de la escena, de tal modo que los objetos con una ubicacin espacial prxima aparezcan agrupados debajo de un mismo nodo. As por ejemplo, supongamos en el caso del tornillo que forma parte de una lmpara, la cual se encuentra en el saln de una casa que forma parte de un pueblo; si esta escena tuviese una organizacin jerrquica adecuada en la que hubiese sucesivos nodos tomillo->lmpara->saln->casa->pueblo, bastara con comprobar que la casa est fuera de la pirmide de visin para descartar su dibujado y las comprobaciones de culling con todos los objetos que se encuentran en su interior. En siguiente diagrama (Figura 2-8) se muestra de forma grfica una situacin similar en la que se representa una escena sencilla formada por seis objetos que aparecen agrupados mediante distintos nodos intermedios, as como sus correspondientes bounding spheres. Se puede observar claramente la relacin entre la organizacin jerrquica de los nodos del grafo de escena y las bounding spheres correspondientes a cada nodo.
29
Existen mtodos de culling que tambin tienen en cuenta las condiciones de visibilidad debidas a las condiciones atmosfricas (bien sea niebla, lluvia, etc.). Un objeto que normalmente es visible a una determinada distancia puede, que a la misma distancia, deje de serlo en el caso de que exista una niebla densa.
2.1.3.5 Multiproceso.
Las aplicaciones de grficos en tiempo real suelen consumir gran cantidad de recursos, por ello es habitual que en algunos casos sea necesario recurrir al empleo de ordenadores con varios procesadores. Hay dos formas posibles de emplear de forma conjunta varios procesadores: La organizacin en paralelo y la organizacin en serie o pipeline. La primera de ellas presenta como ventaja que tiene poca latencia, pero es de difcil implementacin, pues encontrar la forma en la que paralelizar procesos encierra bastante complejidad. La organizacin en pipeline, presenta como inconveniente que tiene ms latencia que la anterior, pero, por el contrario, resulta de una implementacin mucho ms sencilla. Tambin es posible definir estructuras mixtas, pero es un rea que no ha sido muy investigada.
30
La generacin de una imagen en tiempo real puede ser considerada como constituida por una serie de etapas que se realizan en cascada. La forma tradicional de emplear varios procesadores en una aplicacin de grficos en tiempo real consiste en dividirla en tres etapas: APP, CULL y DRAW. El procesado de la escena se realiza en el proceso de APP, y consiste en la actualizacin de los valores de los nodos con los valores provenientes de algn mecanismo de gestin del comportamiento de la escena. El procesado visual consiste en la realizacin de las operaciones de culling y dibujado (CULL y DRAW). Es habitual que los procesos de culling y draw sean realizados de forma automtica. La misin de cada una de estas etapas es la siguiente: APP. Lee valores de los perifricos de entrada, realiza la simulacin de los objetos que se mueven, actualiza la base de datos visual e interacciona con otras posibles simulaciones conectadas a travs de la red. CULL. Aplica el culling jerrquico determinando que porciones de la escena son potencialmente visibles, realiza una seleccin de los niveles de detalle, realiza una ordenacin de la geometra por su estado grfico, ordena los objetos transparentes por distancia para su correcto dibujado, y finalmente, crea una lista con los objetos que han de ser dibujados. DRAW. Se encarga de alimentar al hardware grfico con la lista de los objetos que han quedado de la fase anterior. Algunas libreras grficas como OpenGl Performer incluyen en la pipeline de procesado de la escena otros procesos: ISECT. Realiza clculos de interseccin entre segmentos de lnea y la geometra del grafo de escena, lo cual se puede emplear para deteccin de colisiones. COMPUTE. Realiza clculos complejos de forma asncrona. DBASE. Gestiona de forma asncrona la base de datos que define la escena. Dependiendo del nmero de CPUs disponibles y del tipo de aplicacin se pueden emplear distintos modelos de multiproceso, as, en el caso de disponer de slo un nico procesador las tres etapas seran ejecutadas en la misma CPU. En el caso de disponer de dos, los procesos de APP y CULL pueden ser ejecutada en una y el DRAW en la otra, o bien se ejecutara la etapa de APP en una CPU y las de CULL y DRAW en las otra. En el caso de existir 3 procesadores, uno podra estar dedicado al APP, otro al CULL y otro al DRAW. En sistemas de simulacin complejos con dos o ms salidas grficas, es comn encontrar estructuras mixtas formadas por 8 o ms CPUs.
31
grfica y un grafo de escena muy flexibles que facilitan la creacin y manipulacin interactiva de una escena 3D; VRML, un formato de fichero que describe un grafo de escena y que tiene la intencin de ser el estndar para la navegacin en espacios tridimensionales a travs de Internet ; y por ltimo se profundizara en OpenSceneGraph, que es la que hemos utilizado en el presente proyecto, una librera basada en OpenGl, y con gran similitud con OpenGl Performer, con la principal diferencia de que es de codigo abierto, y por tanto totalmente gratuita. En los siguientes apartados se detallaran las propiedades bsicas de estos grafos de escena, y se har una descripcin de cuales son los nodos que los constituyen y caractersticas. En un ltimo apartado se muestran de forma rpida otros grafos de escena existentes en la actualidad.
hardware grfico. Es una librera muy orientada al mercado de la simulacin visual, siendo su mayor prioridad la obtencin de tasas de refresco muy altas, llegando a mantener tasas constantes de 50 frames/segundo. Proporciona soporte para multiproceso, permitiendo dividir el trabajo entre mltiples CPUs, gestionando su sincronizacin y transferencia de informacin. Adems, proporciona algunas caractersticas avanzadas tales como la deteccin de intersecciones, la gestin de terrenos, morphing geomtrico o incluso una pequea interfaz de usuario. Los nodos utilizados por la librera Performer son los siguientes: Nodo Geode: Es un nodo hoja que almacena la informacin geomtrica de un objeto (Geometry node). Est formado por una lista de estructuras llamadas pfGeoSet que encapsulan caractersticas de bajo nivel referentes a primitivas de dibujado y su apariencia grfica, y que almacenan la informacin en un formato muy prximo a la OpenGl. Nodo Grupo: Sirve para agrupar varios nodos hijos. Nodo Scene: Acta como nodo padre de todo el grafo de escena. Se utiliza tambin para almacenar informaciones visuales comunes a toda la escena, tales como condiciones de iluminacin, modos de dibujado, condicin de niebla, etc. Nodo SCS: Permite definir un sistema de coordenadas que no pueden ser modificados durante la simulacin (Static Coordnate System), se utilizan para ubicar objetos en distintas posiciones de la escena Nodo DCS: Permite definir un sistema de coordenadas que puede ser modificado durante la simulacin (Dynamic Coordnate System). Se utiliza para implementar objetos articulados u objetos que se desplacen por la escena. Nodo FCS: (Flux Coordnate System). Es de caractersticas similares al DCS, pero presenta caractersticas especiales para su utilizacin en multiproceso. Nodo Switch: Es un nodo que puede tener varios hijos y permite que el usuario seleccione cuales de ellos quiere que sean dibujados. Nodo Secuence: Es un nodo que puede tener varios hijos, los cuales va mostrando de forma secuencial. Se utiliza para representar secuencias animadas. Una secuencia consiste en una lista ordenada de hijos, cada uno de los cuales con una duracin asignada. Es posible hacer que la secuencia se ejecute de inicio a fin, de fin a inicio, que se repita cclicamente, etc. Nodo LOD: Se emplea para gestionar distintos niveles de detalle de un objeto. Nodo Layer: Es un nodo hoja, que permite establecer un orden de dibujado en el caso de geometra coplanar. Nodo LighSource: Contiene la especificacin de una fuente de luz.
32
Nodo BillBoard: Rota una geometra de modo que siempre aparezca orientada hacia el punto de vista. Es especialmente til para representar objetos que tienen una simetra axial, como pueden ser rboles, farolas, etc. Nodo Partition: Particiona la geometra para realizar intersecciones eficientes. Nodo Text: Es tambin un nodo hoja que se utiliza para renderizar textos tridimensionales. Nodo ASD: Permite realizar transiciones suaves entre superficies complejas tales como grandes superficies de terreno (Active Surface Definition).
Las principales caractersticas de Open Inventor son: Facilita la organizacin de escenas 3D. Por tener una estructura de grafo de escena, permite organizar jerrquicamente la informacin de forma sencilla. Proporciona estructuras grficas predefinidas. Las formas bsicas proporcionadas por Inventor son cajas, conos, esferas y cilindros, adems, permite definir textos 2D y 3D. Proporciona utilidades grficas ya definidas, por ejemplo rutinas para manejar matrices. Tiene mecanismos muy flexibles de descripcin de formas y objetos. Permite definir objetos a partir de curvas y superficies de tipo NURBS, y tambin a partir de mallas de tringulos. Tiene capacidades de rendering sofisticadas. Permite seleccionar entre distintos modos de renderizado. Se pueden seleccionar distintas cmaras y distintos modos de visualizacin interactiva. Proporciona un mtodo integrado de seleccin y manipulacin interactiva de objetos. Es extensible de tal modo que es posible crear nuevos tipos de primitivas y objetos. Tiene un formato de fichero 3D con descripciones de alto nivel. Permite incorporar animaciones, teniendo nodos especialmente diseados para ese propsito. No est diseado para soportar multiproceso. Inventor es un grafo de escena en el que las propiedades de cada nodo afectan a los nodos que estn por debajo de l y tambin a los nodos colocados a su derecha. Cada nodo puede ser una forma, una propiedad de su apariencia, una transformacin, una cmara o una luz. Algunos de los tipos nodos que Open Inventor emplea son los siguientes: Nodo Shape: Representa un objeto 3D o 2D como puede ser una esfera o un cubo. Nodo Transform: Representa transformacin afn, como por ejemplo una traslacin o una rotacin. Nodo Appearance: Modifica la apariencia de los objetos que le siguen en el grafo. Nodo Light: Aplica una iluminacin a los nodos que le siguen. Nodo Camera: Visualiza los nodos que le siguen.
33
Nodo Separator: Separa el efecto de los nodos que hay por debajo de l de tal modo que no afecte a los nodos que hay a su derecha. Nodo Units: Especifica el tipo de unidades medida del mundo real que se corresponde a los nodos que le siguen (como por ejemplo centmetros, pulgadas o metros), y aplica un factor de escala en el caso que sea distinto de los nodos que le precedan. Nodo Sensor: Detecta el momento en el que ocurre un determinado evento, como por ejemplo que un timer llegue a su final, o que un nodo haya sido seleccionado por el usuario, y lanza una llamada a una rutina de callback definida previamente. Nodo Manpulator: Asigna a los objetos una interfaz 3D que permite de modificar su posicin, su tamao y orientacin de un modo muy sencillo. Nodo Complexity: Permite controlar la calidad con la que se quieren dibujar los nodos que le siguen. Nodo Texture: Especifica una textura para los nodos que le siguen. Nodo Environment: Define efectos atmosfricos, como por ejemplo niebla. Nodo Normals: Es utilizado para realizar clculos de iluminacin.
En la Figura 2-9 se puede apreciar el aspecto de un Grafo de Escena de Inventor. Todos los grafos de escena comienzan con un nodo que acta como raz, y usualmente existe una cmara en la parte izquierda del grafo que es el que permite visualizar el resto de la escena. El siguiente nodo es de tipo Light, que sirve para iluminar a los objetos que le siguen, si ese nodo estuviese puesto despus de la primera esfera, sta no estara iluminada. El resto son los objetos de la escena. Cada uno de ellos tiene su propio subgrafo que comienza por un nodo Separator que hace que lo que ocurra en el subgrafo no afecte al resto de los nodos. A cada nodo Shape le precede un nodo Transform, que permite colocar cada objeto con la posicin y orientacin deseada.
Una de las objetivos principales de Inventor es definir escenas 3D interactivas. Inventor gestiona automticamente la seleccin y manipulacin de objetos 3D, as como el movimiento del usuario por la por la escena 3D o en torno a los objetos 3D. Tambin permite asociar animaciones automticas a los objetos.
34
2.1.4.3 VRML
VRML (Virtual Reality Modeling Language) es un formato de fichero de texto que sirve para realizar descripciones de objetos 3D y entornos interactivos en Internet. Permite la incorporacin de textos, imgenes y secuencias de audio y vdeo. Es posible hacer que un entorno VRML, conecte con otro entorno VRML en otro lugar de la red de dos formas posibles: puede que un objeto 3D de una escena, por ejemplo un mueble, se est cargando de una direccin en Internet diferente de la de la habitacin principal, o puede que al seleccionar la puerta de dicha habitacin accedamos a una habitacin que est en otro servidor dentro de la red. Adems, VRML ha sido diseado para trabajar interactuando con Java y JavaScript. Concebido como una extensin de Inventor, sufre de sus mismos problemas de rendimiento. El formato VRML se encuentra en su versin 2.0. Su primera versin (VRML 1.0) slo permita crear y visualizar mundos 3D estticos. En la versin VRML 2.0 incorpora elementos que permiten hacer que los objetos 3D se modifiquen automticamente y sean capaces de responder a la accin del usuario. En la Figura 2-10 se muestra un esquema con los definidos por VRML, gran cantidad de ellos (Group, switch, LOD...) ya son conocidos de grafos de escena como Performer o Inventor.
Grouping nodes
Anchor Billboard Collision Group Transform
Sensors
CylinderSensor PlaneSensor ProximitySensor SphereSensor TimeSensor TouchSensor VisibilitySensor
Appearance
Appearance FontStyle ImageTexture Material MovieTexture PixelTexture TextureTransform
Special Groups
Inline LOD Switch
Geometry
Box Cone Cylinder ElevationGrid Extrusion IndexedFaceSet IndexedLineSet PointSet Sphere Text
Interpolators
ColorInterpolator CoordinateInterpolator NormalInterpolator OrientationInterpolator PositionInterpolator ScalarInterpolator
Common Nodes
AudioClip DirectionalLight PointLight Script Shape Sound SpotLight WorldInfo
Bindable Nodes
Background Fog NavigationInfo Viewpoint
Geometric Properties
Color Coordinate Normal TextureCoordinate
Tabla 2-1. Nodos de VRML 2.0.
Llama la atencin de existencia de nodos muy especializados como el Background que permite aadir imgenes de fondo, lo que permite representar por ejemplo montaas lejanas y un cielo, o de un tipo de nodo para crear fcilmente terrenos irregulares (nodo ElevationGrid). Tambin existen nodos como el Collision que permiten hacer que un objeto reaccione como si fuese slido de tal modo que el usuario no puede atravesarlo pero si caminar sobre l. Existe un grupo de nodos que actan como sensores (de un modo similar a como hacia inventor) y que permiten que la escena reaccione a las acciones del usuario. Los distintos nodos de tipo interpolator permiten crear animaciones predefinidas que pueden ser ejecutadas cuando sea necesario. Con este tipo de nodos se pueden definir modificaciones dinmicas sobre los objetos de la escena, 35
as es posible definir un objeto que presente un morphing geomtrico, una puerta de apertura automtica o un objeto que varia cclicamente su color o que recorre una trayectoria determinada. El nodo Sound permite incorporar sonidos con una ubicacin espacial tridimensional. Uno de los nodos ms importantes en VRML es el nodo Script, el cual bsicamente contiene un programa que recibe eventos de entrada, los procesa y genera eventos nuevos, mediante la utilizacin de este tipo de nodos se puede hacer que la escena y sus objetos presenten comportamientos muy sofisticados. Tambin resulta muy interesante la capacidad que tiene el usuario para definir nodos PROTO los cuales pueden contener en su interior ms nodos VRML, campos y scripts. Un desarrollador puede definir un nodo PROTO con unas determinadas caractersticas, de tal modo que puede ser utilizado, modificado o ampliado por un segundo desarrollador. En general se puede establecer una clasificacin similar en nodos grupo y nodos hoja similar a la de Performer o Inventor. Pero la gran cantidad de nodos (Figura 2-10), y las interdependencias que se establecen entre ellos, hacen VRML resulte mucho ms confuso que los grafos de escena anteriores.
2.1.4.4 OpenSceneGraph.
OpenSceneGraph (OSG) es un toolkit grfico de alto nivel y portable para el desarrollo de aplicaciones grficas de alto rendimiento tales como simuladores de vuelo, juegos, realidad virtual o visualizacin cientfica. Est orientado a objetos y construido a partir de la librera grfica OpenGL, esto libera al desarrollador de implementar y optimizar llamadas grficas de bajo nivel, y provee muchas utilidades adicionales para un rpido desarrollo de aplicaciones grficas. El corazn del grafo de escena ha sido diseado para tener mnimas dependencias de una plataforma especfica, requiriendo poco ms que C++ estndar y OpenGL. Esto ha permitido al grafo de escena ser rpidamente portado a un gran nmero de plataformas (originalmente desarrollado en IRIX, portado a Linux, Windows, FreeBSD, Mac OSX, Solares, HP-UX e incluso PlayStation2).
Todo el cdigo de OpenSceneGraph esta publicado bajo la OpenSceneGraph Public License (permite a proyectos de cdigo abierto y cerrado utilizarla, modificarla y distribuirla libremente). Open Scene Graph soporta view frustum culling, occlusion culling, small feature culling, nodos con nivel de detalle (LOD), clasificacin de estado, vertex arrays y listas de dibujado como parte del corazn del grafo de escena. OpenSceneGraph es uno de los grafos de escena disponibles de mayor rendimiento. Este rendimiento iguala a otros grafos de escena como OpenGL Performer o Vega Scene Graph. Open Scene Graph opta por soluciones muy parecidas a OpenGL Performer. Por contra, no soporta multiproceso, caracterstica que soporta OpenGL Performer. Open Scene Graph esta formado por los siguientes espacios de nombres:
osg : Es el ncleo de la librera OSG, y proporciona las clases bsicas del grafo de
escena tales como Nodes, Status, y Drawables, as como clases matemticas y otras.
36
proporcionando un framework para plugins y clases para manejo de ficheros. osgFX : Es una extensin del ncleo del grafo de escena para proporcionar un framework de efectos especiales. osgGA : osgGA (osg GUI Abstraction) proporciona herramientas para ayudar a los desarrolladores para trabajar con distintos sistemas de ventanas. osgIntrospection : Proporciona un entorno de programacin que permite la consulta en tiempo de ejecucin de las propiedades y los mtodos relacionados con las librerias OSG. osgParticle : osgParticle amplia el ncleo del grafo de escena para soportar efectos de partculas. osgProducer : Es una librera de utilidades que integra OpenProducer para proporcionar clases de viewer de propsito general. osgSim : osgSim extiende el ncleo del grafo de escena para soportar Nodes y Drawables que especifiquen la simulacin visual, tales como soporte para un punto de luz navegacional y transformaciones de grados de libertado del estilo OpenFlight. osgTerrain : Librera de utilidades que proporciona soporte para la generacin de bases de datos de terreno. osgText : Extiende el ncleo del grafo de escena para dar soporte a texto de alta calidad. osgUtil : Proporciona clases de utilidad de propsito general, tales como recorridos de update, cull, y/o Draw, operadores de grafo de escena como son optimisation, tri stripping, y tessellation. osgUtx : osgUtx es un entorno de programacion para la evaluacion de aplicaciones.
OpenSceneGraph emplea los siguientes tipos bsicos de nodos: Node : La clase base para todas la clases que derivan de Node. Group : Agrupa varios nodos hijos. Transform : Clase base para aplicar una transformacin al subgrafo. MatrixTransform : Transformacin de una matriz 4x4. PositionAttitudeTransform : Transformacin que usa un Vector de tres coordenadas (Vec3) para la posicin, y una rotacin de Cuaternion (Quat) para la actitud, y un Vec3 para el pivote. DOFTransform : Nodo de transformacin de grados de libertad. Geode : Es un nodo hoja que almacena la informacin geomtrica de un objeto. Billboard : Rota una geometra de modo que siempre aparezca orientada hacia el punto de vista. Es especialmente til para representar objetos que tienen una simetra axial, como pueden ser rboles, farolas, etc. LOD : Se emplea para gestionar distintos niveles de detalle de un objeto Impostor : aade soporte para el cacheado jerrquico de imgenes. Switch : Es un nodo que puede tener varios hijos y permite que el usuario seleccione cuales de ellos quiere que sean dibujados. Sequence : Es un nodo que puede tener varios hijos, los cuales va mostrando de forma secuencial. Se utiliza para representar secuencias animadas. Una secuencia consiste en una lista ordenada de hijos, cada uno de los cuales con una duracin asignada. Es posible hacer que la secuencia se ejecute de inicio a fin, de fin a inicio, que se repita cclicamente, etc. LightSource : Posicin un objeto Light en la escena ClipNode : Posiciona un objeto ClipPlane en la escena Projection : Sobrecarga la matriz de proyeccin. OccluderNode : Permite colocar en la escena planos y cajas para definir oclusiones entre objetos.
37
Es un entorno de desarrollo OpenSource, empleado para implementar aplicaciones 3D en sistemas Unix/X11 y Win32, puede trabajar con varios threads.
OpenSG. (http://www.opensg.org)
Es una librera basada en C++ y OpenGl que contiene un grafo de escena. Es distribuido bajo los principios de Open Source, es multi-thread, multiplataforma (Linux, Irix, Windows), y fcilmente extensible. Es mantenido por varias empresas y centros de investigacin.
PLIB/SSG. (http://plib.sf.nef).
PLib es un conjunto de libreras multiplataforma diseadas para ayudar a los desarrolladores de aplicaciones 3D interactivas. Es tambin distribuida bajo los principios de OpenSource. SSG (Simple Scene Graph) es uno de sus mdulos que proporciona un grafo de escena implementado sobre la base de OpenGl y C++.
RMScenegraph. (http://www.r3vis.com/RMSSceneGraph)-
Es un grafo de escena basado en OpenGl, actualmente disponible para Unix, Linux y Win32.
SGI OpenGL Optimizer. (http://www.sgi.com/software/optimizer).
Es un conjunto de herramientas orientadas al mercado del CAD/CAM. Optimizer en s mismo no es un grafo de escena, pero emplea internamente un grafo de escena (similar a VRML) especialmente optimizado para manejar modelos voluminosos.
SGL. (http://sgl.sf.net).
Es un conjunto de libreras multiplataforma desarrolladas en C++ y que operan sobre OpenGl, gestiona de forma adecuada la seleccin de objetos y clculo de intersecciones, permite cargar distintos tipos de formatos de imagen, y dispone de varios mtodos de culling.
Sun's Java 3D. (http://java.sun.com/products/java-media/3D).
El API de Java3D proporciona un conjunto de interfaces orientados a objetos, que permiten a los desarrolladores definir una escena de 3D y su comportamiento, de una forma independiente de plataforma. Internamente dispone de un grafo de escena que introduce algunos conceptos comnmente no considerados como parte del entorno de simulacin tales como sonido espacial 3D.
motor de iluminacin que soporta sombras verdaderas y fuentes de luz en movimiento. El principal objetivo que esta aplicacin persigue es que el desarrollador del juego no necesite ser un programador experimentado. Se reduce al mximo el esfuerzo de desarrollo a costa de perder flexibilidad en el diseo del juego. La ltima versin (v5) es de marzo de 2002. Ofrece tres posibilidades para crear un juego: 1) Juegos diseados a base nicamente de controles, para usuarios con pocos conocimientos de programacin. 2) Juegos o efectos diseados con algo de programacin utilizando C-scripts. 3) Juegos o efectos programados en C++ o Delphi, para programadores con experiencia. Incorpora un ncleo de videojuegos, llamado A5. Pero lo que aqu se entiende por ncleo es un sistema de desarrollo que se encarga de generar efectos 3D y controlar la inteligencia artificial del juego.
Figura 2-12. Captura del editor de 3D Gamestudio.
2.1.5.1.3 Genesis3D
Genesis3D es un motor de cdigo libre para la visualizacin de escenas tridimensionales en tiempo real y que permite construir aplicaciones graficas 3D de altas prestaciones. Ha sido diseado principalmente para la visualizacin de escenas de interior logrando una elevada tasa de fotogramas por segundo siempre y cuando estn compuestas por una cantidad moderada de polgonos. Tambin puede ser utilizado para escenas de exterior si el diseo de las escenas se realiza tomando ciertas precauciones. Sus principales caractersticas son la deteccin rpida de colisiones, iluminacin precalculada y chequeo de la visibilidad. Su principal inconveniente es la visualizacin de escenarios exteriores sin imponer algn tipo de restriccin o lmite al tamao de la escena.
39
La versin actual es la v1.1 (noviembre de 1999), se va enriqueciendo mediante las contribuciones o comentarios que realizan los usuarios. No incluye rutinas de gestin de eventos.
Independencia de la plataforma. Gestin de la base de datos del juego: jerarquas 3D, texturas, materiales, luces, sonidos, animaciones, estados y sus relaciones. Proporcionar herramientas bsicas de trabajo en equipo para el desarrollo del juego.
El servidor de entrada gestiona los eventos de entrada de usuario utilizando una lista de eventos. Se utiliza un mecanismo de paso de mensajes para el tratamiento de los jugadores en red.
2.1.5.1.5 OGRE
OGRE (Object-Oriented Graphics Rendering Engine) es un motor escrito en C++ flexible, orientado a escenas, y diseado para hacer ms simple e intuitiva a los desarrolladores la produccin de juegos utilizando hardware de aceleracin 3D. La librera de clases permite abstraer los detalles asociados a las libreras de bajo nivel (OpenGL o Direct3D), proporcionando una interfaz basada en objetos.
2.1.5.1.6 Shark3D
Shark3D es un kit de desarrollo de alto nivel para aplicaciones 3D en tiempo real. Esta orientado
a juegos, aplicaciones de realidad virtual y visualizacin. Optimizado para aplicaciones multiusuario a travs de una red de computadores o internet. Distribuido. Contiene un servidor de mltiples escenas. Incluye gestin de eventos de usuario y paso de mensajes para comunicacin en red y como comunicacin entre los diferentes elementos de su arquitectura.
40
utilidades para la creacin de terrenos, superficies acuticas, interiores estilo portal y sistemas de partculas. Tambin incluye soporte multiplataforma (Windows, Mac OS y Linux), soporte para red, creacin de interfaces de usuario y lenguaje de script estilo C++. Permite importar objetos desde 3D Studio MAX y dispone de libreras matemticas, de deteccin de colisiones, de fsica de vehculos y una base de datos espacial. Incluye gestin de eventos de usuario y paso de mensajes para comunicacin en red.
2.1.5.1.9 Artist
Artist (Animation Package for Real-Time Simulation) es un paquete de animacin de bajo coste
para el desarrollo de aplicaciones 3D complejas e interactivas en tiempo real: juegos, simulacin y realidad virtual. Artist permite generar grficos con velocidad optimizada y aspectos de comportamiento de los objetos en un juego, simulaciones o aplicaciones de realidad virtual. Consigue enlazar ambos aspectos de forma eficiente y sencilla, generando el cdigo necesario para ejecutar la simulacin del comportamiento. Puede generar bases de datos graficas optimizadas para mejorar la velocidad de visualizacin que permite maximizar el uso del hardware grafico disponible. Estas estructuras jerrquicas permitirn mantener una frecuencia de cuadro uniforme, sobre los 30 fps, consiguiendo la continuidad visual necesaria en el juego. Incluye las siguientes herramientas: Modelador de objetos geomtricos de propsito general. Base de datos jerrquica grafica. Conversores de fichero desde los formatos grficos usuales. 41
Interfaz 3D para aadir objetos interactivos en las escenas de los juegos. Editor de jerarqua grafica para la configuracin de los parmetros de la gestin de la base de datos y la incorporacin de descripciones de comportamiento a los objetos geomtricos de la base de datos. Descripcin de alto nivel orientada a objeto del comportamiento de los objetos y las caractersticas del juego.
2.1.6.2.1 Fly3D
Fly3D es un motor de juegos gratuito que acompaa al libro 3D Games de Alan Watt y Fabio
Policarpo. El motor se encuentra actualmente en la segunda versin v2.0 (disponible en el segundo volumen del libro). Es un ncleo de videojuegos de reciente creacin, altamente estructurado y comentado y orientado a objetos. Ambas versiones estn desarrolladas en C++ y todo el cdigo especfico del juego se encuentra desarrollado con DLLs plugins (se incluye una herramienta para crear plugins). Contiene una amplia gama de herramientas y utilidades que facilitan el proceso de desarrollo del juego. El motor permite crear videojuegos y aplicaciones graficas en tiempo real de forma fcil y sencilla. Para ello se crean nuevos plugins que se enlazan con la aplicacin, sin necesidad de recompilar el ncleo y permitiendo un desarrollo modular. Se pueden implementar mltiples aplicaciones sin necesidad de replicar el ncleo. La implementacin del comportamiento visual y dinmico esta tambin modularizada, debiendo implementar para cada objeto una funcin especfica de visualizacin y otra de comportamiento (simulacin). Para conseguir que los objetos del juego se comporten de forma uniforme, heredan de un objeto base de Fly3D. El objeto base contiene una serie de funciones virtuales que los objetos del juego deben redefinir. Es un motor de cdigo libre y los videojuegos creados usando Fly3D v.1 pueden incluso comercializarse.
42
2.1.6.3.1 Doom
Doom es un juego de laberintos en primera persona creado por John Carmack en 1993. Es un
juego 2D, aunque simula cierta profundidad. La nica versin del juego liberada es la v1.1 para Linux (Idsw). Utiliza como entidades bsicas las estructuras things, que definen elementos del juego como monstruos, armas, llaves o posiciones de inicio de un jugador. El tipo de datos thing incluye nicamente informacin sobre la parte fsica de la entidad, como posicin de la entidad o tipo. Las entidades no incluyen informacin sobre los eventos del sistema.
43
Para gestionar los eventos se utiliza una lista doblemente enlazada con un nico puntero a cabeza. Cada evento contiene tres funciones que definen las acciones a realizar cuando suceda el evento. Los eventos se ejecutan comenzando por la cabeza de la lista hasta alcanzar la cola, ejecutando para cada evento las acciones asociadas. Los eventos no tienen tiempos asociados, se ejecutan todos y en el orden en que aparecen en la lista. La lista de eventos se recorre desde la cabeza hasta la cola. Todos los eventos son evolucionados obligatoriamente a la mxima velocidad que el sistema pueda obtener. El sistema analiza desde el ltimo estado, cual es el nuevo estado en el que se debe encontrar el sistema en funcin del tiempo transcurrido. Este esquema de simulacin obliga a que un objeto nunca pueda programar eventos situados a varios intervalos de muestreo. Por ejemplo, en Doom no existe la bomba de relojera. Para que una granada estalle, esta debe ser disparada y estallara cuando colisione con el suelo, una pared u otro personaje. La gestin de eventos discretos debe realizarse de forma explcita por el programador al margen del ncleo del videojuego y cada objeto debe gestionarla de forma independiente. La ordenacin de los eventos en la lista no es cronolgica sino que depender del orden en que se gestione el sistema. La insercin de nuevos eventos se realiza en cabeza de la lista, por ello, los nuevos eventos se trataran siempre en el siguiente ciclo, independientemente de que algn evento corresponda al ciclo actual. Cualquier evento que se produzca con una frecuencia superior a la frecuencia de muestreo, es sencillamente obviado.
2.1.6.3.2 Quake
Quake es un juego de arcade de laberintos en primera persona creado por John Carmack en
1996. Es el primer juego realmente 3D. La versin objeto de este estudio ha sido la v2.3. El elemento bsico de Quake para la gestin del comportamiento de los personajes y objetos es la entidad. Las entidades son partes independientes del entorno virtual, como monstruos, jugadores, objetos o posiciones en el espacio. Una entidad especial es world, que define el entorno esttico por el que se mueven los personajes. En la entidad confluyen una serie de propiedades fsicas y otras propiedades que determinan sus reglas de comportamiento. Al comportamiento de las entidades se le denomina dentro del juego inteligencia artificial, aunque no utilicen tcnicas propiamente de inteligencia artificial. La inteligencia artificial utiliza tres propiedades de la entidad para gestionar los eventos: Tiempo en el que debe suceder el siguiente evento relacionado con la entidad, momento en el que cambiara de algn modo su comportamiento. Funcin que define el comportamiento justo antes de modificar fsicamente la entidad (como moverla o hacer que dispare). Funcin que define el comportamiento de la entidad despus de modificar su parte fsica.
La descripcin de la escena esta constituida por un vector de entidades. El vector se recorre en orden, comenzando por la entidad world (primera posicin del vector), y se comprueba si cada
44
una de las entidades tiene que modificar su comportamiento en el instante actual, comprobando si el tiempo asociado al evento vencer en el prximo intervalo de tiempo. Este intervalo lo predefine el programador.
Figura 2-17. Captura del juego Unreal Tournament 2007. Define un lenguaje de script: UnrealScript, que es un lenguaje semicompilado para acceder a la lgica del juego y usar el potencial del motor grafico. Permite trabajar con una interfaz de alto nivel para controlar los objetos en un juego.
45
El desarrollo de juegos y herramientas que hacen uso del editor de mapas UnrealED. La orientacin a objetos de Unreal permite aadir nuevos objetos y funcionalidades una vez terminado el desarrollo. La maquina virtual de Unreal esta compuesta de: servidor, cliente, motor de visualizacin y motor de soporte de cdigo. El servidor controla el juego y las interacciones entre los jugadores y los actores. Cada actor en el mapa puede estar bajo control de un jugador o el control de un script. El script define completamente como el actor se mueve e interacciona con otros actores. El bucle de actualizacin sigue los siguientes pasos: 1. El servidor comunica el estado del juego a los clientes. El estado del juego es el conjunto de estados de sus elementos. 2. Cada cliente enva al servidor la peticin de movimiento. El servidor le contesta con el nuevo estado del juego. El cliente comienza el proceso de visualizacin de su escena. 3. El cliente realiza la operacin de actualizacion (Tick()) del estado del juego, tomando en consideracin el tiempo desde la ultima actualizacin (ultima llamada a la funcin Tick()). Para gestionar el tiempo, Unreal divide cada segundo del juego en ticks. El estado del videojuego se actualiza con cada tick. Un tick es la menor unidad de tiempo con la cual el actor puede ser actualizado. Normalmente la frecuencia de ticks suele estar entre 10 y 100 veces por segundo, aunque este valor depende de la potencia de la CPU. Las funciones que necesitan mas de un tick para su ejecucin se llaman funciones latentes (como Sleep, FisnishAnim o MoveTo). Mientras un actor esta ejecutando una funcin latente, la ejecucin del actor se paraliza hasta que termina de ejecutarse. Sin embargo, otros actores o la maquina virtual puede seguir ejecutndose. Cada actor tiene su propio hilo de ejecucin. Pero, estos hilos son virtuales. Unreal simula la utilizacin de hilos. Los scripts se ejecutan en paralelo. En la operacin de actualizacin de los actores, se les informa de los eventos pendientes, ejecutando el cdigo del script asociado. Todo el cdigo asociado a la actualizacin de los actores se disea para que el tiempo que ha pasado desde la ultima actualizacin pueda ser variable (igual que en Fly3D, pero diferente a Doom y Quake, quienes actualizan el sistema suponiendo que el intervalo desde la ultima actualizacin es fijo). La clase Actor es la clase padre de todos los objetos de un juego en Unreal. La clase Actor contiene todas las funcionalidades necesarias para que el actor se mueva, interacciones con otros actores, afecte al entorno y se relacione con los objetos del juego. Pawn es la clase padre de todas las criaturas y jugadores en Unreal, las cuales son capaces de tener un control a alto nivel definido por su inteligencia artificial o por el control del jugador.
46
Source est diseado ascendentemente para ser altamente modular. Esto permite una fcil actualizacin y modificacin de ciertos aspectos sin tener que romper otras reas del motor, o romper la continuidad del motor. Una de las tecnologas desarrolladas para la versin de Xbox de Half Life 2 fue el File Streaming, consistente en cargar los recursos de un mapa al tiempo que el jugador se mueve por l, en lugar de realizar una carga nica antes de jugar. Con este sistema se redujo el tiempo de carga a tan solo 15 segundos. Este sistema era una expansin del sistema de cacheado, ya implementado. Source Engine utiliza un sistema de cacheado, a travs del cual la carga de ciertos recursos est manejada y administrada al vuelo, en lugar de una nica operacin mediante la tpica pantalla de carga. Los datos de texturas y sonidos son las principales reas donde esto ocurre. Las texturas se cargan en memoria, pero solo se mueven a la tarjeta grafica del sistema cuando son necesarias, y los ficheros de sonido son cargados con un inusual sistema de cacheado de sonido: solo los primeros 0.125 segundos de cada fichero son pre-cacheados.
Ambos sistemas mantienen los datos en la pila hasta que no hay ms espacio y los recursos antiguos se liberan, y cuando est atascado o ralentizado, el motor se queda parado o entra en un bucle hasta que los datos llegan. El resultado de estas pausas es una especie de molesto tartamudeo del juego. Mientras que este tartamudeo puede ser causado por un mal rendimiento del sistema, se ha observado tambin en algunas configuraciones de hardware que deberan ser lo suficiente potentes para manejar esta tasa de datos, y a pesar de muchas teoras , la causa precisa continua siendo desconocida al publico, incluso dos aos despus del debut del motor. La mayor parte de
47
las soluciones encontradas apuntan a evitar el sistema de cacheado, ya que no puede ser deshabilitado directamente. En Febrero de 2006, se introdujeron unos cambios en el motor Source, con el objetivo de reducir el problema. Esta actualizacin se caracteriz por una implementacin limitada del sistema de file streaming, y la respuesta fue bastante positiva. Renderer Shaders versin 2.0, bump mapping, LOD sobre modelos y el mundo. Author Shaders con HLSL. Cube mapping y enviroment mapping. Luces dinmicas, vertex lighting y light maps, muchos tipos de luces incluyendo parpadeantes, de pulso, etc. Iluminacin de alto rango dinmico. Agua con refraccin y efectos. Avanzado sistema de partculas que puede emitir sprites o modelos. Proyeccin de sombras permisible por gran numero de personajes por escena. Entornos abiertos/cerrados. o Terreno deformable. o Materiales dinmicamente renderizados (csped, rboles). Superficies de subdivisin, bump maps difuso y especular. Iluminacin por radiosidad en tiempo real. Efectos de partculas, destellos, humo, rayos, sangre, y efectos ambientales como niebla o lluvia. Escalabilidad.
Sistema de Materiales En lugar de usar las tradicionales texturas, Source define conjuntos de materiales que especifican de que est hecho el objeto y la textura usada para ese objeto. Un material especifica como se romper un objeto al ser golpeado, como sonar al romperse o al ser arrojado sobre otra superficie, y cual es la masa y la flotabilidad de este objeto. Este sistema es mucho ms flexible que cualquier otro sistema basado nicamente en texturas. Los materiales pueden interactuar con objetos o NPCs como barro o hielo sobre vehculos.
Personajes Personajes detallados. Ojos realistas. o Enfocado automtico sobre el jugador. o Brillo en los ojos Musculatura simulada proporciona emociones, habla, y lenguaje corporal. Habla independiente del lenguaje, los personajes pueden hablar naturalmente en distintos lenguajes. Sistema de animacin basado en esqueletos. El sistema de animacin basado en capas puede sintetizar complejas animaciones de varias partes.
Fsica
48
Mundo ms receptivo con interacciones realistas. Sonidos y grficos enlazados con la fsica. La IA de los personajes puede interactuar con los objetos simulados fsicamente. Cuerdas/cables, maquinas, sistemas de restriccin. Controladores de procedimientos fsico personalizados. Vehculos. o Las ruedas resbalan y patinan. o Suspensin realista en cada rueda. o Inclinacin realista en aceleraciones/deceleraciones y giros. o Parmetros configurables individualmente tales como caballos de potencia, velocidad, aceleracin, material de los neumticos, friccin de los neumticos, tensin de la amortiguacin, etc.
Programacin Todo el cdigo est escrito en C/C++ usando Visual Studio 6.0. Se pueden derivar nuevas entidades de manera fcil y rpida desde las clases base existentes. Sistema de monitorizacin interno. Herramientas de medida del rendimiento grfico. El diseo modular del cdigo (mediante DLLs) permite intercambiar componentes del ncleo para una fcil actualizacin o reemplazamiento de cdigo. Shaders de DirectX9 escritos en HLSL. Exportadores XSI, Max y Maya .smd para exportar modelos 3D.
2.1.7 Editores 3D
El proceso de creacin de grficos 3D por computador puede ser dividido en estas tres fases bsicas: Modelado Composicin de la escena Rnder (creacin de la imagen final)
Modelado La etapa de modelado consiste en ir dando forma a objetos individuales que luego sern usados en la escena. Existen diversas tcnicas de modelado; Constructive Solid Geometry, modelado con NURBS y modelado poligonal son algunos ejemplos. Los procesos de modelado puede incluir la edicin de la superficie del objeto o las propiedades del material (por ejemplo, color, luminosidad, difusin, especularidad, caractersticas de reflexin, transparencia u opacidad, o el ndice de refraccin), agregar texturas, mapas de relieve (bump-maps) y otras caractersticas. El proceso de modelado puede incluir algunas actividades relacionadas con la preparacin del modelo 3D para su posterior animacin. A los objetos se les puede asignar un esqueleto, una estructura central con la capacidad de afectar la forma y movimientos de ese objeto. Esto ayuda al proceso de animacin, en el cual el movimiento del esqueleto automticamente afectara las porciones correspondientes del modelo. Vase tambin animacin por Cinemtica Directa (Forward Kinematic animation) y animacin por Cinemtica Inversa (Inverse Kinematic animation). El modelado puede ser realizado por programas dedicados (como Lightwave 3D, Rhinoceros 3D o Moray), un componente de una aplicacin (Shaper, Lofter en 3D Studio) o por un lenguaje de descripcin de escenas (como en POV-Ray). En algunos casos, no hay una distincin estricta 49
entre estas fases; en dichos casos, el modelado es slo una parte del proceso de creacin de escenas (por ejemplo, con Caligari trueSpace).
Composicin de la escena Esta etapa involucra la distribucin de objetos, luces, cmaras y otras entidades en una escena que ser utilizada para producir una imagen esttica o una animacin. Si se utiliza para Animacin, esta fase, en general, hace uso de una tcnica llamada Keyframing, que facilita la creacin de movimientos complicados en la escena. Con la ayuda de la tcnica de keyframing, en lugar de tener que corregir la posicin de un objeto, su rotacin o tamao en cada cuadro de la animacin, solo se necesita marcar algunos cuadros clave (keyframes). Los cuadros entre keyframes son generados automticamente, lo que se conoce como 'Interpolacin'. La iluminacin es un aspecto importante de la composicin de la escena. Como en la realidad, la iluminacin es un factor importante que contribuye al resultado esttico y a la calidad visual del trabajo terminado. Por eso, puede ser un arte difcil de dominar. Los efectos de iluminacin pueden contribuir en gran medida al humor y la respuesta emocional generada por la escena, algo que es bien conocido por fotgrafos y tcnicos de iluminacin teatral. Renderizado Se llama Render al proceso final de generar la imagen 2D o animacin a partir de la escena creada. Esto puede ser comparado a tomar una foto o en el caso de la animacin, a filmar una escena de la vida real. Generalmente se buscan imgenes de calidad fotorrealista, y para este fin se han desarrollado muchos mtodos especiales. Las tcnicas van desde las ms sencillas, como el rnder de alambre (wireframe rendering), pasando por el rnder basado en polgonos, hasta las tcnicas ms modernas como el Scanline Rendering, el Raytracing, la radiosidad o el Mapeado de fotones. El software de rnder puede simular efectos cinematogrficos como el lens flare, la profundidad de campo, o el motion blur (desenfoque de movimiento). Estos artefactos son, en realidad, un producto de las imperfecciones mecnicas de la fotografa fsica, pero como el ojo humano est acostumbrado a su presencia, la simulacin de dichos efectos aportan un elemento de realismo a la escena. Se han desarrollado tcnicas con el propsito de simular otros efectos de origen natural, como la interaccin de la luz con la atmsfera o el humo. Ejemplos de estas tcnicas incluyen los sistemas de partculas que pueden simular lluvia, humo o fuego, el muestreo volumtrico para simular niebla, polvo y otros efectos atmosfricos, y las custicas para simular el efecto de la luz al atravesar superficies refractantes. El proceso de rnder necesita una gran capacidad de clculo, pues requiere simular gran cantidad de procesos fsicos complejos. La capacidad de clculo se ha incrementado rpidamente a travs de los aos, permitiendo un grado superior de realismo en los rnders. Estudios de cine que producen animaciones generadas por ordenador hacen uso, en general, de lo que se conoce como render farm (granja de rnder) para acelerar la produccin de fotogramas. A pesar de haber muchos paquetes de modelado y animacin 3D, solo nombraremos los ms importantes, o aquellos que as lo requieran por su similitud o relacin con el actual proyecto.
50
2.1.7.1 Maya
Maya es la culminacin de 3 lneas de software 3D: Wavefront's The Advanced Visualizer (en California), Thomson Digital Image Explore (en Francia) y Alias Power Animator (en Canad). En 1993 Wavefront adquiri TDI, y en 1995 Silicon Graphics Incorporated (SGI) adquiri Alias y Wavefront(debido a la presin de Microsoft por adquirir Softimage ese mismo ao) y las combin en una sola compaa, produciendo un nico paquete de sus dos fuentes. A mediados de los 90, la pipeline ms popular en las pelculas de Hollywood era una combinacin de herramientas: Alias Studio para el modelado, Softimage para la animacin y Photorealistic RenderMan para el rendering. Esta combinacin se us en numerosas pelculas, tales como Jurassic Park, The Abyss y Terminator 2: El juicio final. A la compaa resultante de combinar Alias y Wavefront le llev mas de dos aos lanzar Maya. Maya es un paquete de modelado 3D, creado originalmente por Alias Systems Corporation, pero adquirido actualmente por Autodesk bajo su divisin Media and Entertainment. Autodesk adquiri el software en Octubre de 2005 tras adquirir Alias. Normalmente se usa en la industria cinematogrfica y de la TV, as como en los videojuegos. Maya, es usado en la mayor parte de las pelculas de hoy da. Esta disponible en dos versiones Maya Complete (el paquete menos potente) y Maya Unlimited. Maya Unlimited tiene hoy en da un precio similar a cualquier otro paquete 3D, pero sola ser considerablemente ms caro. Maya Personal Learning Edition (PLE) est disponible para uso no comercial, totalmente gratuito. Las imgenes generadas por esta versin contienen una marca de agua. Maya fue desarrollado por Alias y lanzado para Microsoft Windows, Linux, IRIX, y Mac OS X. La ultima versin de Maya, versin 8.0, fue lanzada en agosto de 2006. La versin 6.5 fue la ltima versin que soport IRIX, debido a la cada de popularidad de dicha plataforma en los ltimos aos. En la adquisicin, la preocupacin de los usuarios de Maya era si Autodesk fusionara Maya con su software 3D Studio Max, creando alguna especie de hbrido llamado Mayax. En subsecuentes entrevistas se clarific que se mantendran separados : Maya para soluciones 3D de alta fidelidad, y max para baja fidelidad. La adquisicin se complet en Enero de 2006.
51
La caracterstica mas importante de Maya es su posibilidad de software de terceros, que puede hacer que cambien su apariencia estndar y, usando solo el ncleo de Maya, puede transformarlo en un software altamente personalizable. Aparte de su intrnseca potencia y flexibilidad, esta caracterstica en s ha hecho que Maya atraiga a grandes estudios que tienden bastante a escribir cdigo personalizado para sus producciones usando el SDK proporcionado. Tambin cabe destacar de Maya su lenguaje de Script potente e independiente de la plataforma llamado Maya Embedded Language (MEL), similar a Tcl. No se proporciona nicamente como lenguaje Script, sino tambin para personalizar la funcionalidad de su ncleo (muchos de los entornos de Maya y herramientas estn escritas en este lenguaje). Adicionalmente, las interacciones de usuario estn implementadas y guardadas como scripts MEL, que los usuarios pueden ver y arrastrar a una barra de herramientas donde pueden crear nuevas macros instantneamente. Esto proporciona a los animadores el poder de aadir funcionalidad a Maya sin tener experiencia en programacin C o C++ ni sus compiladores, aunque esta opcin est incluida con el SDK. Los ficheros, que incluyen todos los datos de geometra, se guardan como secuencias de operaciones MEL, que pueden ser guardados opcionalmente como ficheros legibles (.ma, para Maya ASCII), editables en cualquier fichero de texto externo al entorno Maya, y permite un tremendo nivel de flexibilidad al trabajar con herramientas externas. Tambin pueden ser editados para permitir al fichero ser abierto por versiones anteriores del software. Caractersticas de modelado: NURBS. Modelado Poligonal. SubDivision Surface Modeling. Es una manera sencilla de crear objetos complicados tales como manos humanas. Combina las mejores caractersticas de las nurbs con el modelado poligonal. Subdivision surfaces permite usar una sola superficie para modelar formas complejas. Una nica superficie de subdivisin puede tener diferentes niveles de detalles en sus diferentes regiones. Esto es, una regin que tiene una forma compleja puede tener mas puntos de control para permitir un mayor detalle, mientras que una regin simple o plana necesita muchos menos puntos de control. Ventajas de las Subdivision Surfaces : o Permiten mayor nivel de control sobre formas que sobre polgonos. o Permiten usar geometra compleja nicamente en las regiones complejas del modelo. o Permiten pliegues y topologa arbitraria. o La continuidad de las Subdivision Surfaces elimina muchos de los problemas que pueden ocurrir en las uniones al animar usando NURBS. o Se pueden enlazar Subdivision Surfaces a esqueletos en nivel grueso y los efectos se traducirn suavemente a los niveles ms finos.
Caractersticas de animacin, configuracin de personajes y deformadores: Animacin basada en Keyframes (Fotogramas clave) o Animacin no lineal. Tras animar un personaje con Keyframes o motion Capture, se puede muestrear su animacin en una secuencia editable llamada clip de animacin. o Animacin de camino (Path Animation). Este tipo de animacin controla la posicin y rotacin de un objeto a lo largo de una curva. Se debe de asociar el objeto a la curva. Animacin de captura de movimiento.
52
o o
o o
Animacin con Esqueletos. Los esqueletos son estructuras articuladas jerarquizadas que permite posicionar y animar objetos vinculados. Un esqueleto proporciona un modelo deformable del mismo modo que el esqueleto humano lo hace con el cuerpo humano. Tal como en el cuerpo humano, la ubicacin de las uniones (joints) y el nmero de uniones a aadir al esqueleto determina como se mover el modelo. Cuando se enlaza un modelo a un esqueleto, se le denomina Skinning. Existen varios mtodos de animacin: Cinemtica Directa Cinemtica Inversa Full body IK Solver Skinning. Es el proceso de configurar un personaje o modelo de manera que pueda ser deformado por un esqueleto. Restricciones. Posibilitan aadir restricciones a la posicin, orientacin o escalado de un objeto respecto de otros. Adems, con restricciones se pueden imponer lmites especficos a los objetos y automatizar el proceso de animacin. Character Sets. Es un nodo que contiene un conjunto de atributos que se pueden aplicar a distintos objetos a los que quieras aplicar la misma animacin. Deformers. Son herramientas de alto nivel que se pueden usar para manipular (al modelar) o llevar (al animar) los componentes de bajo nivel de cierta geometra. Los Deformers, son conocidos en otro tipo de paquetes como Modifiers.
Caractersticas sobre dinmica y simulacin: Partculas: se pueden animar y visualizar movimiento de partculas con varias tcnicas. Campos: el movimiento de fuerzas naturales se puede simular con campos dinmicos. Simulacin de Cuerpo Blando: se puede recrear un objeto geomtrico como un objeto flexible llamado cuerpo blando. Simulacin de Cuerpo Rgido: un cuerpo rgido es una superficie poligonal o NURBS convertida en una forma. A diferencia de las superficies convencionales, los cuerpos rgidos colisionan entre si en lugar de atravesarse durante una animacin. Para animar un cuerpo rgido, se usan campos, claves, expresiones, restricciones de cuerpo rgido, o colisiones con partculas. Efectos: Lo efectos en Maya son mdulos que facilitan crear efectos de animacin complejos tales como humo o fuego. Cada efecto de Maya ofrece gran nmero de opciones y atributos para modificar los resultados. Caractersticas de rendering : Shading(sombreado): en Maya, la apariencia de una superficie est definida por como est sombreada. El sombreado de una superficie es una combinacin del material bsico de un objeto y las texturas aplicadas al mismo. En Maya, los materiales (tambin llamados Shaders), definen la sustancia del objeto. Algunos de los atributos ms bsicos de materiales incluyen color, transparencia y brillo. Toon Shading: da una apariencia 2D o de animacin cartoon usando modelos 3D. Iluminacion: en el mundo real, cuando la luz brilla sobre una superficie, las partes de la superficie que estn encaradas hacia el foco de luz aparecen iluminadas, y las partes de la superficie contrarias aparecen oscuras. PaintEffects : componente de Maya usado para pintar trazos de pincel y efectos de partculas en una superficie 2D o sobre geometra 3D en el entorno 3D. Mental Ray : Mental Ray renderer. RenderMan for Maya : Renderer de Pixar para Maya.
53
Caractersticas adicionales de la versin Unlimited : Maya Fluid : simulador de fluidos, efectos atmosfricos, pirotcnicos, de viscosidad y ocenicos. Maya Cloth: Simulacin de ropa y telas, cualquier objeto textil, incluidas velas, forros, tiendas, cortinas y ropa de cama. Usado el la pelcula Spiderman 2. Maya Fur: Simulacin de piel animal, vello, lana y hierba en superficies NURBS, de subdivisin o modelos poligonales. Maya Hair: Simulacin para cabello humano, cabellos totalmente dinmicos en objetos poligonales y NURBS. Maya Live: Combina la accin en vivo 2D con elementos 3D. Proporciona un secuenciador 2D integrado y un solver de fotograma raz interactivo. Tambin permite reconstruir elementos de grabaciones en vivo como geometra 3D, adems de generar la salida a aplicaciones externas.
54
3ds Max venia normalmente con distintos emisores de partculas. Como en su version 8, existen 6 emisores de partculas bsicos, mostrando comportamientos especficos. Los emisores de partculas tradicionales son Spray, Nieve, Ventisca, PArray, PCloud, y Super Spray. Particle Flow es un sistema de partculas sofisticado, no lineal, basado en eventos, desarrollado por Oleg Bayborodin como uno de los siete emisores de partculas de MAX. A diferencia de la mayoria de sistemas de partculas disponibles en los paquetes 3D, Particle Flow permite al usuario disear el comportamiento de la partcula basado en una serie de eventos definidos por el usuario (Procedimientos), usando un GUI intuitivo. 3ds Max incluye un motor fsico, llamado Reactor, originalmente creado por Havok. Reactor puede simular cuerpos rigidos, cuerpos blandos, ropa, gravedad, y otras fuerzas. Como muchos motores fsicos, Reactor utiliza un envoltorio convexo simplificado, pero puede ser personalizado para usar todos los vrtices. Existen varios renderers para generar imgenes, estos son: Scanline rendering. Es el renderer por defecto. Es bastante robusto, soporta iluminacin global, radiosidad y ray tracing. Mental ray. Es un renderer de calidad desarrollado por Metal Images. Mental Ray est integrado en las ultimas versiones de MAX y es una potente herramienta de render, con bucket rendering (similar al Satelling Rendering de Maya) que distribuye la carga del render entre distintas maquinas mas eficientemente. Mental Ray tambin viene con cantidad de herramientas que permiten gran nmero de efectos para ser creados con relativa facilidad. RenderMan. Herramienta de conexin a la pipeline Renderman para aquellos que necesiten integrar Max con renders de Renderman.
55
2.1.7.3 LightWave 3D
LightWave 3D es un programa para el modelado 3D, render y animacin. Aunque el programa se origin en el Commodore Amiga, ha sido migrado para funcionar en Mac OS X, Windows, Sgi IRIX, y el motor de render tambin ha sido portado a Linux. Actualmente desarrollado completamente por NewTek. LightWave ha sido durante tiempo bien conocido por su excelente capacidad para el render y su inusual interfaz de usuario (por ejemplo, no se usan iconos; en su lugar se usan funciones con su titulo descriptivo). Como muchos otros paquetes 3D, Lightwave est compuesto por dos partes, un entorno de modelado de objetos donde los modelos o las mallas se crean y un entorno de animacin donde los modelos se preparan y animan para el render. A diferencia de otros paquetes, estas dos partes son programas independientes. Tambin existe una aplicacin independiente para el render, que puede ser ejecutada en mltiples mquinas. Algunas funciones de LightWave son multi-hilo, lo cual significa que pueden usar hasta ocho procesadores al mismo tiempo en la misma maquina al renderizar una imagen. Los programadores pueden ampliar las caractersticas de LightWave usando un SDK que se incluye con el paquete, as como un lenguaje especial de Script llamado LScript. Este SDK est basado en el lenguaje C, y se puede crear casi cualquier cosa, desde un shader personalizado hasta distintos formatos de exportadores de escena. LightWave en si incluye docenas de plugins gratuitos y se pueden obtener muchos mas de distintos desarrolladores de todo el mundo. En 1988, Allen Hastings cre un programa de render y animacin llamado Videoscape, y su amigo Stuart Ferguson cre un programa de modelado 3D complementario llamado Aegis Modeler. Estos dos programas seran lo que actualmente se conoce como LightWave 3D. Newtek planeaba incorporar Videoscape y Aegis en su paquete de edicin de video, Video Toaster. Segn Hastings, Newtek pretenda originalmente llamar a este nuevo software 3D Newtek 3D Animation System for the Amiga. Mas tarde, en Diciembre de 1989, a Hastings se le ocurri el nombre LightWave 3D, inspitado por los paquetes 3D de aquel entonces: Intelligent Light y Wavefront. En 1990, se lanz el paquete Video Toaster, incorporando Lightwave 3D, listo para ejecutar en el Commodore Amiga.
56
LightWave 3D ha estado disponible como una aplicacin independiente desde 1994, y la version 9.0 ahora corre bajo Max OS X y cualquier PC con Windows. LightWave gan fama como el programa usado para crear efectos especiales para las series de ciencia ficcion Babylon 5 y Seaquest DSV; El programa tambin se utiliz en la produccin de pelculas como Titanic, y las recientes Sin City y Star Wars. En 2001, se origin un problema entre el mantenimiento de NewTek y un grupo dirigido por el videpresidente de desarrollo 3D, Brad Peebler, entre los que figuraban desarrolladores como Allen Hastings o Stuart Ferguson. Por segunda vez en su historia NewTek sufri un importante abandono de ingenieros y programadores. Tras meses de confusin, este grupo form una nueva compaa, Luxology. Fue entonces cuando lanzaron su propio paquete 3D, Modo. NewTek y LightWave has sido galardonados con premios Emmy desde 1993 y ganaron sus 10 y 11 galardones en 2004. En 2003 NewTek fue galardonado con un Emmy por la tecnologa que tuvo mayor impacto en televisin. Ahora en su novena versin, su mercado abarca desde los aficionados (dado su bajo precio), hasta el desarrollo de alto nivel como videojuegos, televisin y cine. La compaa recientemente lanz su versin para 64 bit de LightWave 3D. Esta versin incluye nuevas caractersticas como un editor se superficie basado en nodos Subdivision Adaptativa de Pixel (APS) que permite a la malla variar su complejidad dependiendo de los criterios definidos por el usuario, incluyendo la distancia a la cmara, maximizando la eficiencia de render.
57
bordes, etc. Tiene capacidad para detectar lneas de costa, cabos, y valles para una representacin exacta y eficiente. Las herramientas de mapeado de texturas (Texture Mapping) posibilitan a los usuarios a aplicar colores, texturas y materiales de manera automtica e interactiva. El editor de texturas esta integrado con una Paleta personalizable. Durante el proceso de construccin de la base de datos se mantiene doble precisin interna. La opcin Terrain es compatible con las herramientas Poblar y Dispersar (Poblate and Scatter), que permiten a los usuarios colocar modelos de manera aleatoria y automtica sobre el terreno. Creador puede importar ficheros DXF, 3Ds y OBJ. Para abrir ficheros SHP en Creador, el usuario tiene tres opciones: Usar la API OpenFlight para escribir un conversor propio; Usar Multigen Paradigms SiteBuilder3D para trabajar con los datos en ArcView, y luego exportarlos a OpenFlight; Usar el software FME para convertir ficheros SHP a DFD. Creator incluye FlightViewer, un plug-in para previsualizacion. FlightViewer posibilita el modo de vuelo en tiempo real o modo de rotacin, visualiza modelos con texturas, materiales, luces y sombras, carga de puntos de vista guardados en Creador ,vista en diferentes modos (wireframe, solido y puntos), actualizacin constante de la estadsticas de render, tales como tringulos por segundo o fotogramas por segundo (FPS). Los productos Multigen-Paradigm estn siendo usados para proporcionar una base de datos 3D en tiempo real en un proyecto de una autopista de California. Creador se usa para modelado 3D, RoadPro se usa para construir carreteras en 3D, y Vega se usa para realizar aplicaciones de visualizacin 3D interactivas. Creador tambin se ha usado para desarrollar un modelo 3D del desarrollo de proyecto de lnea de costa en Vallejo, CA. El modelo inclua tiendas, hoteles, terreno y calles. MultiGen-Paradigms Urban Simulation Services Group entreg un modelo 3D en tiempo real para el Centennial Center a la ciudad de Las Vegas. La base de datos 3D comprenda 160 acres y fue hecha a partir de planos, datos de elevaciones, imgenes digitales y datos de sistemas de informacin geogrfica (GIS). Sitebuilder 3D se uso para convertir mapas digitales 3D y fotografas areas en elementos 3D como carreteras, caminos, edificios y campos. Creador se uso para renders de edificios y mejorar detalles. Por ultimo, Vega se uso para proporcionar un interfaz personalizado para visualizar e interactuar con el modelo.
2.1.7.6 OSGEdit
OSGEdit comenz en 2002, apoyado por el hosting de Source Forge y el respaldo de la comunidad OpenSceneGraph (OSG). De entre sus caractersticas, debera permitir montar escenas, hacer pequeos ajustes, y ejecutar procesos tpicos de un grafo de escena. Aunque la idea evolucion en cierto modo, el desarrollo contina enfocndose en hacer un compositor de escenas, no una herramienta completa de creacin de contenidos con modelado, animacin, etc., puesto que ya existen bastantes herramientas de este tipo en el mundo. El diseo de OSGEdit ha evolucionado bastante desde su nacimiento, desde un interfaz rgido hecho completamente a mano hasta el actual, generado dinmicamente casi en su totalidad. Cada paso del diseo fue hecho con la ayuda de Ricardo Rodrguez y la contribucin de gente repartida por todo el mundo, como es usual en este tipo de proyectos de cdigo abierto.
58
La generacin del GUI est automatizada, ya que esta es la nica manera de soportar cualquier caracterstica de OSG en un tiempo razonable de tiempo. No obstante, esta caracterstica del interfaz se ve penalizada con un incremento de la inestabilidad del programa. La generacin automtica de la GUI se realiza utilizando una descripcin XML proporcionando meta-datos sobre las clases OSG. Los meta-datos separan los detalles OSG del interfaz de usuario, proporcionando un mecanismo genrico para conocer los atributos de cada clase, y las caractersticas de dichos atributos. El interfaz de usuario se genera a partir de estos meta-datos, as como las acciones que actualizan el grafo de escena, relacionadas con la opcin undo/redo del programa. Desde la versin 0.6.0, tanto la barra de men como la barra de herramientas se generan automticamente desde una descripcin XML. Esto reduce el coste de desarrollo al aadir nuevas herramientas al GUI, ya que no necesitar escribir, compilar y depurar cdigo fuente. Otra de las novedades de esta ultima versin es la implementacin tanto para entorno X como para Win32 utilizando la librera GTK+.
Figura 2-24. Captura del programa OSGEdit.
Caractersticas de OSGEdit : El grafo de escena se representa mediante un rbol donde se pueden seleccionar los nodos para cualquier operacin. Este rbol es realmente un grafo, un mismo nodo puede colgar de distintas ramas, aunque realmente represente un nodo compartido, no una copia. Cada tipo de nodo tiene un dialogo de propiedades integrado en la ventana (la mayora soportadas). Se pueden manipular las transformaciones visualmente, hay herramientas para mover, escalar, y rotar nodos de transformacin visualmente con el ratn. Todas las operaciones excepto new/open/save y zoom se pueden deshacer y rehacer sin lmite. Se pueden crear nodos tipo Group/Transform/Switch/LOD unicamente. Se pueden abrir todos los formatos que soporta OSG as como guardar en todos los formatos que soporta OSG. Se pueden unir ficheros, aadindolos como nodos hijo. Se pueden copiar, cortar y pegar nodos.
59
Actualmente la versin oficial de este software de la desarrolladora Valve es la 4.0. Esta versin ya si es de "pago", se adquiere cuando se compra una copia original de los siguientes videojuegos: Half-Life 2, Counter-Strike Source, Day of Defeat Source. Cuando adquirimos uno o varios de estos productos, estamos obligados a registrarlos en la plataforma Online Steam de la propia compaa desarrolladora del Half-Life, Valve. Una vez registrada nuestra copia de software en dicha plataforma se nos dara la posibilidad para acceder al Kit de desarrollo de mods para el Source Engine. La herramienta se llama Source SDK (Software Development Kit) donde dispondremos de las siguientes herramientas: Valve Hammer Editor 4.0 HL2 Model Viewer HL2 Face Poser
2.1.7.8 UnrealED
UnreadED, es el software editor de niveles usado para crear niveles para Unreal, otros juegos de Unreal series , y juegos basados en el motor Unreal, como puede ser Deus Ex. Este tipo de juegos utilizan su propia versin del mismo programa. Todos los juegos Unreal en PC tenan en editor de niveles incluido de manera gratuita, y algunos otros juegos que usaban su motor hicieron lo mismo con una versin mas especifica del mismo. Esto extendi la longevidad de los juegos. Los diseadores amateur podan ahora crear contenidos adicionales para el juego. Adems, el lenguaje Script llamado UnrealScript permita a los editores personalizar el contenido del juego. UnrealED tiene un interfaz de usuario personalizable, pero lo mas comn son las cuatro vistas, con la vista superior en la parte superior izquierda, y en sentido de las agujas del reloj la vista frontal, la vista lateral, y una vista en perspectiva. Tiene una fila de botones con distintas opciones de salvado, guardado, as como para funciones de editado. Han existido varias versiones de UnrealED, la primera en aparecer fue la versin 1.0, la cual ya visualizaba la barra de herramientas con sus 4 vistas. Esta versin era extremadamente inestable, particularmente al reconstruir mapas. En la actualizacin a la versin 2.0, se mejor su aspecto visual con unos botones ms coloridos y un interfaz ms atractivo. Se aadieron nuevas herramientas y caractersticas (tales como opciones de bsqueda, y un nuevo editor de formas 2D), y experiment una actualizacin significante de escalabilidad, y aunque el editor continuaba con sus extraa inestabilidad, no lo era tanto como la versin 1.0. Junto con Unreal Tournament 2003 estaba UnrealED 3.0, mucho mas estable q los anteriores. Mantena los colores de su interfaz, y el aspecto de su versin 2.0. Al editor se aadi un navegador de mallas estticas para soportar mallas estticas, y combinado con varios navegadores en un nico navegador con pestaas para alternar entre texturas, mallas, actores, etc Esta es la versin actual de UnrealED.
UnrealED opera con el concepto de brush (pincel). Los brushes pueden ser formas primitivas (tales como cubos, esferas y conoces), formas predefinidas (como escaleras), o formas
60
personalizadas (como prismas y otros poliedros). Usando operaciones CSG (Constructive Solid Geometry), se pueden crear objetos y habitaciones complejas aadiendo, sustrayendo e intersectando brushes entre si. Los brushes aditivos pueden ser slidos, semislidos o no-slidos. UnrealED trata el mundo como una masa gigante. Para crear espacio, los brushes son sustrados de la masa, de modo que se crea un espacio hueco por donde pasar. Inversamente, la adicin de masa crea espacio slido dentro del espacio hueco. Un nivel se construye con una mezcla de suma y resta de brushes. Estos brushes se usan para compilar un nivel en un rbol BSP (Binary Space Partitioning) para render y deteccin de colisiones. Desafortunadamente, a medida que los niveles se complican, ms propensos a error son los BSP, dando como resultado errores de visualizacin y de colisiones. De aqu el uso de Mallas Estticas introducido en la versin 2.0 del motor. Las mallas estticas son geometra pre-renderizada, creada con algn software como Maya o 3D Studio Max, que puede ser importada y posicionada dentro de los niveles. Aunque los niveles se construyen con brushes, las mallas estaticas se pueden usar para crear edificios y formas complejas que los brushes tienen difcil para emular. Puesto que las mallas estticas solo se cargan en memoria una vez, aunque sean usadas mltiples veces en la escena, son una mejor forma de usar recursos. Algunos diseadores de edificios, para poder proporcionar una visita en tiempo real de sus creaciones, con gravedad y deteccin de colisiones, han comenzado a construir modelos usando UnreadED, y asi poner en practica sus ideas. Permitir al pblico visitar un edificio antes de su construccin puede desarrollar un mejor resultado previo a la construccin del mismo. El problema es la conversin de medidas desde programas de diseo tales como Autocad y 3D Studio Max a UnrealED.
La aplicacin principal proporciona los servicios que permite a los plugins usar, incluyendo la manera en que los plugins se registran a s mismos en la aplicacin principal, y el protocolo por el cual los datos se intercambian con el plugin. Los plugins son dependientes de estos servicios que proporciona la aplicacin principal, y no suelen funcionar por s solos. En cambio, la aplicacin principal es independiente de los plugins, haciendo posible que los plugins se aadan o se actualicen dinmicamente sin que sea necesario hacer cambios en la aplicacin principal. Los plugins sin ligeramente diferentes de las extensiones, que modifican o aaden funcionalidad. La principal diferencia es que los plugins generalmente dependen del interfaz de usuario de la aplicacin principal, y tienen bien definidos los lmites para su conjunto de acciones. Las extensiones generalmente tienen menos restricciones en sus acciones, y pueden proporcionar sus propias interfaces. Algunas veces se usan para decrementar el tamao de la aplicacin principal, y ofrecer funciones adicionales.
61
Quiz el primer software en incluir la funcin de plugin fue HyperCard y QuarkXPress (Macintosh), ambos lanzados en 1987. En 1988, Silicon Beach Software incluy la funcionalidad de plugin en Digital Darkroom y SuperPaint. Por aquellos tiempos, los plugins eran implementados como libreras compartidas, que deban instalarse en una ruta indicada en la aplicacin principal. Las APIs de cdigo abierto suelen proporcionar un interfaz estndar, permitiendo a otros desarrolladores crear plugins que interacten con la aplicacin principal. Un API estable permite que los plugins de otros desarrolladores funcionen perfectamente aunque la versin original cambie, y prolonga el ciclo de vida de las aplicaciones obsoletas. Adobe Photoshop y el API de plugins After Effects se han convertido en un estndar y se ha adoptado hasta cierto punto por aplicaciones de su competencia.
Los Plugins le dan a una aplicacin la capacidad de agregar funcionalidades nuevas en tiempo de ejecucin. De entre sus ventajas podemos destacar: Hace posible el personalizar la aplicacin de maneras no pensadas por el autor, o que al menos no tena la intencin de hacer. Da la posibilidad de difundir la responsabilidad. Mucha gente trabaja en proyectos de software abierto ya que ser autor de una pieza de cdigo les brinda cierta satisfaccin personal. Utilizando plugins, una persona puede desarrollar un plugin, y reclamar su autora. Es posible compartir cdigo entre aplicaciones sin mucho que ver entre ellas si estas comparten una infraestructura de plugins entre si. Un ejemplo seran los visores de imgenes. Existen muchos visores. Teniendo una infraestructura de plugins en comn, sera posible desarrollar plugins que funcionen en cada uno de estos visores. Finalmente, hace posible que slo cierta funcionalidad este disponible si alguna librera de o aplicacin de terceros no est disponible en el sistema.
Existen dos tipos de plugins: El primer tipo de plugins implementa una interfaz especificada por la aplicacin padre (la aplicacin principal). Esto es similar a implementar una clase virtual pura, con la excepcin de que la clase se encuentra en una biblioteca compartida cargable en tiempo de ejecucin. Este tipo de plugins tambin se les llama mdulos cargables. Ejemplos de mdulos cargables son mdulos de soporte para nuevos formatos de imgenes, destacadores de sintaxis, y mdulos para importar y/o exportar datos a diferentes formatos. Las ventajas de este tipo de plugins es que terceros fabricantes pueden aadir nuevos formatos a la aplicacin. Ej: Un editor para programadores puede destacar cdigo escrito en lenguaje VDM-SL, an cuando el autor del editor no tiene idea que ese lenguaje siquiera existe. El segundo tipo de plugins brinda nueva funcionalidad y acciones para la barra de mens y la barra de herramientas. Ejemplos para este tipo de plugins sera la clsica opcin para exportar una galera HTML desde un visor de imgenes (an cuando este no tena esta funcionalidad anteriormente), verificacin y correccin de ortografa en un editor, validacin de pginas Web en un navegador Web. La ventaja de este tipo de plugins es que nueva funcionalidad puede ser aadida por terceros, con las consecuencias descritas anteriormente.
62
Creacin de una biblioteca de enlace dinamico A menudo es ms sencillo crear una biblioteca de enlace dinmico que crear una aplicacin. La razn es que habitualmente una DLL consta de un conjunto de funciones autnomas que pueden ser utilizadas por cualquier aplicacin. Lo normal es que en las DLLs no haya cdigo que se encargue del procesamiento de bucles de mensaje o de la creacin de ventanas. Una biblioteca de enlace dinmico es simplemente un conjunto de mdulos de cdigo fuente, cada uno de los cuales contiene un conjunto de funciones. Estas funciones se escriben con la esperanza de que les llame una aplicacin (archivo EXE) u otra DLL. Despus de compilar todos los archivos de cdigo fuente, se enlazan igual que el archivo EXE de una aplicacin. Sin embargo, para una DLL se debe especificar al enlazador la opcin /DLL. Esta opcin provoca que el enlazador genere una informacin ligeramente diferente en la imagen del archivo DLL resultante, de manera que el cargador del sistema operativo reconozca que la imagen del archivo es una DLL y no una aplicacin. Para que una aplicacin (u otra DLL) llame a las funciones contenidas en una DLL, primero se debe proyectar la imagen del archivo DLL en el espacio de direcciones del proceso llamante. Esto se puede llevar a cabo de dos maneras: con enlazado implcito en tiempo de carga o con enlazado explcito en tiempo de ejecucin. Una vez se ha proyectado la imagen de un archivo DLL en el espacio de direcciones del proceso llamante, las funciones de la DLL estn disponibles para todos los hilos que se ejecutan en el proceso. De hecho, la DLL pierde casi toda su identidad como DLL: para todos los hilos del proceso, el cdigo y los datos de la DLL simplemente parecen cdigo y datos adicionales que estn en el espacio de direcciones del proceso. Cuando un hilo llama a cualquier funcin de la DLL, esta funcin toma los parmetros que le han pasado en la pila del hilo y tambin utiliza esta pila para guardar las variables locales que pudiera necesitar. Adems, el hilo o proceso llamante posee todos los objetos creados por el cdigo de las funciones de la DLL: una DLL nunca posee nada en Win32. Por ejemplo, si una funcin de una DLL llama a VirtualAlloc, la regin se reserva en el espacio de direcciones del proceso del hilo llamante. Si ms adelante se elimina la proyeccin de la DLL del espacio de direcciones del proceso, la regin del espacio de direcciones permanece
63
reservada porque el sistema no es consciente del hecho de que una funcin de la DLL ha reservado la regin. La regin reservada la posee el proceso y slo ser liberada si un hilo llama a la funcin VirtualFree o si termina el proceso. Como ya sabemos, las variables globales y estticas de un archivo EXE no se comparten entre los mltiples ejemplares en ejecucin del mismo EXE. Cuando un proceso proyecta una imagen de archivo DLL en su espacio de direcciones, el sistema crea tambin ejemplares de las variables globales y estticas. Existe una tcnica que permite que una DLL comparta sus variables globales y estticas entre mltiples proyecciones de la DLL. Sin embargo, esta tcnica no es la que se aplica por defecto en Win32 (se deben realizar algunas acciones adicionales para conseguir este comportamiento).
Proyectar una DLL en el espacio de direcciones de un proceso Para que un hilo llame a una funcin de una DLL, se debe proyectar la imagen del archivo DLL en el espacio de direcciones del proceso del hilo llamante. Se puede conseguir esto de dos maneras: enlazando implcitamente las funciones de la DLL y cargando explcitamente la DLL. Enlazado implcito El enlazado implcito es el mtodo ms habitual de proyectar la imagen de un archivo DLL en el espacio de direcciones del proceso. Cuando se enlaza una aplicacin, se debe especificar un conjunto de archivos LIB al enlazador. Cada archivo LIB contiene la lista de las funciones a las que el archivo de DLL permite que llame una aplicacin (u otra DLL). Cuando el enlazador ve que la aplicacin llama a una funcin incluida en el archivo LIB de una DLL, incrusta informacin en la imagen del archivo EXE resultante que indica el nombre de la DLL que contiene las funciones que requiere el EXE Cuando el sistema operativo carga un archivo EXE, el sistema examina el contenido de la imagen del archivo EXE para ver qu DLLs deben estar cargadas para que la aplicacin se ejecute. Entonces, el sistema intenta proyectar las imgenes de archivo DLL requeridas en el espacio de direcciones del proceso. Cuando busca el archivo DLL, el sistema examina los siguientes directorios: 1. 2. 3. 4. 5. El directorio que contiene la imagen del archivo EXE. El directorio actual del proceso. El directorio de sistema de Windows. El directorio de Windows. Los directorios enumerados en la variable de entorno PATH.
Si no se puede encontrar el archivo DLL, el sistema operativo muestra un cuadro de mensaje y termina inmediatamente el proceso completo. Cuando se utiliza este mtodo, no se elimina la proyeccin de todas las imgenes de archivo DLL proyectadas en el espacio de direcciones del proceso hasta que se termina el proceso.
Enlazado explcito La imagen de un archivo DLL se puede proyectar explcitamente en el espacio de direcciones de un proceso cuando uno de los hilos del proceso llama a la funcin LoadLibra-ry o LoadLibraryEx:
HINSTANCE LoadLibrary(LPCTSTR IpszLibFile); HINSTANCE LoadLibraryEx(LPCTSTR IpszLibFile, HANDLE hFile, DWORD dwFlags);
Estas dos funciones localizan una imagen de archivo en el sistema del usuario (utilizando el orden de bsqueda mencionado anteriormente) e intentan proyectar la imagen del archivo DLL
64
en el espacio de direcciones del proceso llamante. El valor HINSTANCE que devuelven estas funciones identifica la direccin de memoria virtual en la que se proyect la imagen de archivo. Si no se puede proyectar la DLL en el espacio de direcciones del proceso, las funciones devuelven NULL. Podemos observar que la funcin LoadLibraryEx tiene dos parmetros adicionales: hFile y dwFlags. El parmetro hFile est reservado para una utilizacin futura y por el momento debe ser NULL. Para el parmetro dwFlags, se debe especificar un 0 o una combinacin de DONT_RESOLVE_DLL_REFERENCES, LOAD_LIBRARY_AS_DATAFILE y LOAD_WITH_ALTERED_SEARCH_PATH. Estos flags se tratan brevemente a continuacin. DONT_RESOLVE_DLL_REFERENCES: Al especificar este flag se le indica al sistema que proyecte la DLL en el espacio de direcciones del proceso llamante. Normalmente, cuando se proyecta una DLL en el espacio de direcciones de un proceso, el sistema llama a una funcin especial de la DLL, que se llama habitualmente DllMain, y que se utiliza para inicializar la DLL. Si se especifica este flag, el sistema simplemente proyecta la imagen de archivo sin llamar a la funcin DllMain. Adems, una DLL podra importar las funciones contenidas en otra DLL. Cuando el sistema proyecta una DLL en el espacio de direcciones del proceso, el sistema tambin comprueba si la DLL requiere otras DLLs y tambin las carga automticamente. Cuando se especifica el flag DONT_RESOLVE_DLL_REFERENCES, el sistema no carga automticamente ninguna de estas DLLs adicionales en el espacio de direcciones del proceso. LOAD_LIBRARY_AS_DATAFILE: Este flag es muy similar al anterior; es decir, el sistema simplemente proyecta la DLL en el espacio de direcciones del proceso como si fuera un archivo de datos. El sistema no pierde ms tiempo en prepararse para ejecutar el cdigo del archivo. Por ejemplo, cuando una DLL se proyecta en el espacio de direcciones del proceso, el sistema examina la informacin de la DLL para determinar qu atributos de proteccin de pgina se deberan asignar a las diferentes secciones del archivo. Cuando no se especifica este flag, el sistema establece los atributos de proteccin de pgina como si fuese a ejecutar el cdigo de ese archivo. Este flag es til por varias razones: Si tenemos una DLL que contiene slo recursos y ninguna funcin, es preferible especificar este flag. Al hacerlo, se proyecta la imagen de archivo de la DLL en el espacio de direcciones del proceso y se puede utilizar entonces el valor HINSTANCE que devuelve LoadLibraryEx en las llamadas a las funciones que cargan los recursos. Tambin se puede utilizar este flag si se desean utilizar recursos que estn contenidos en un archivo EXE. Normalmente, al cargar un archivo EXE se inicia un nuevo proceso, pero tambin se puede utilizar la funcin LoadLibraryEx para proyectar una imagen de archivo EXE en un espacio de direcciones de proceso. De nuevo, una vez se ha asignado el valor HINSTANCE del EXE, se puede acceder a los recursos contenidos en l. Dado que un archivo EXE no tiene la funcin DllMain, hay que especificar este flag cuando se llama a LoadLibraryEx para que cargue un archivo EXE. LOAD_WITH_ALTERED_SEARCH_PATH: Al especificar este flag se cambia el orden de bsqueda que utiliza LoadLibraryEx para localizar el archivo de DLL especificado. Normalmente, LoadLibraryEx busca los archivos en el orden mencionado anteriormente. Sin embargo, si se especifica el este flag, LoadLibraryEx busca el archivo utilizando el siguiente orden: 1. 2. 3. 4. El directorio especificado en el parmetro lpszLibFile. El directorio actual del proceso. El directorio de sistema de Windows. El directorio de Windows.
65
5.
Cuando se carga explcitamente una DLL, la imagen de archivo se puede eliminar explcitamente la proyeccin del espacio de direcciones del proceso en cualquier momento llamando a la funcin FreeLibrary:
BOOL FreeLibrary(HINSTANCE hinstDll);
Cuando se llama a FreeLibrary, se le debe pasar el valor HINSTANCE que identifica a la DLL que se desea liberar. Este valor es el que devolvi una llamada anterior a LoadLibrary o LoadLibraryEx. En realidad, las funciones LoadLibrary y LoadLibraryEx incrementan un contador de utilizacin asociado a la biblioteca especificada, y la funcin FreeLibrary decrementa dicho contador. Por ejemplo, la primera vez que se llama a LoadLibrary para que cargue una DLL, el sistema proyecta la imagen del archivo DLL en el espacio de direcciones del proceso llamante y asocia a la DLL un contador de utilizacin con un valor 1. Si un hilo del mismo proceso llama ms tarde a LoadLibrary para que cargue la misma imagen del archivo DLL, el sistema no la proyecta por segunda vez en el espacio de direcciones del proceso. En su lugar, el sistema simplemente incrementa el contador de utilizacin asociado a la DLL. Para que se elimine la proyeccin de la imagen del archivo DLL del espacio de direcciones del proceso, los hilos del proceso deben llamar a FreeLibrary dos veces (la primera llamada a FreeLibrary simplemente decrementa el contador de utilizacin de la DLL a 1, y la segunda llamada lo decrementa a 0). Cuando el sistema ve que el contador de utilizacin de una DLL ha llegado a O, elimina la proyeccin de la imagen del archivo DLL del espacio de direcciones del proceso. Despus de eliminar la proyeccin de la imagen de archivo, si un hilo intenta llamar a una funcin de la DLL, provocar una violacin de acceso porque el cdigo de la direccin especificada ya no est proyectado en el espacio de direcciones del proceso. El sistema mantiene un contador de utilizacin de una DLL para cada proceso. Es decir, si un hilo de un Proceso A realiza la llamada
HINSTANCE hinstDll = LoadLibrary("MiLib.DLL");
y despus un hilo del Proceso B realiza la misma llamada, se proyecta MILIB.DLL en los espacios de direcciones de ambos procesos (el contador de utilizacin de la DLL en el Proceso A y en el Proceso B es 1 en ambos). Si un hilo del proceso B llama ms tarde a
FreeLibrary(hinstDll);
el contador de utilizacin de la DLL con respecto al Proceso B se hace 0, y se elimina la proyeccin de la DLL del espacio de direcciones del Proceso B. Sin embargo, la proyeccin de la DLL en el espacio de direcciones del Proceso A no se ve afectada, y el contador de utilizacin de la DLL asociado al Proceso A sigue valiendo 1. Un hilo puede llamar a la funcin GetModuleHandle
HINSTANCE GetModuleHandle(LPCTSTR IpszModuleName);
para determinar si una DLL est proyectada en el espacio de direcciones de su proceso. Por ejemplo, el cdigo siguiente carga MILIB.DLL slo si no est ya proyectada en el espacio de direcciones del proceso:
HINSTANCE hinstDll; hinstDll = GetModuleHandle("MiLib"); if (hinstDll == NULL) { hinstDll = LoadLibrary("MiLib"); } // se asume la extensin DLL // se asume la extensin DLL
66
Tambin se puede determinar el nombre de trayecto completo de una DLL (o EXE) si todo lo que se tiene es el valor HINSTANCE de la DLL. Para ello, se utiliza la funcin GetModuleFileName:
DWORD GetModuleFileName(HINSTANCE hinstModule, LPTSTR IpszPath, DWORD cchPath);
El primer parmetro es el HINSTANCE de la DLL (o EXE). El segundo, IpszPath, es la direccin del bfer en el que la funcin pondr el nombre de trayecto completo de la imagen de archivo. El tercer y ltimo parmetro, cchPath, especifica el tamao del bfer en caracteres. Hay otra funcin de Win32 que se puede utilizar para decrementar el contador de utilizacin de una DLL:
VOID FreeLibraryAndExitThread (HINSTANCE hinstDll, DWORD dwExitCode);
Supongamos que escribimos una DLL que crea un hilo cuando se proyecta por primera vez en el espacio de direcciones de un proceso. Cuando el hilo termina de realizar su trabajo, puede eliminar la proyeccin de la DLL del espacio de direcciones del proceso. Para que el hilo elimine la proyeccin de la DLL debe llamar a FreeLibrary y despus inmediatamente a ExitThread. Pero si el hilo llama a FreeLibrary y a ExitThread individualmente, se produce un error muy serio. El problema, claro est, es que la llamada a FreeLibrary elimina inmediatamente la proyeccin de la DLL del espacio de direcciones del proceso. En el mo-ment en que vuelve la llamada a FreeLibrary, el cdigo que contiene la llamada a ExitThread ya no est disponible y el hilo no intentar ejecutar nada. Esto provocar que se lance una violacin de acceso y que termine el proceso completo! Sin embargo, si el hilo llama a FreeLibraryAndExitThread, esta funcin llama a FreeLibrary, provocando que se elimina la proyeccin de la DLL inmediatamente. La siguiente instruccin que se ejecuta se encuentra en KERNEL32.DLL, no en la DLL que se acaba de eliminar. Esto significa que el hilo puede continuar ejecutndose y que puede llamar a ExitThread. ExitThread provocar que el hilo termine y no volver.
La funcion de entrada/salida de la DLL Una DLL de Win32 puede, opcionalmente, tener una sola funcin de entrada/salida. El sistema llama a esta funcin en varias ocasiones que veremos ms adelante. Estas llamadas son informativas y habitualmente son utilizadas por una DLL para realizar tareas de inicializacin y liberacin para cada proceso o cada hilo. Si la DLL no necesita estas notificaciones, no es necesario implementar esta funcin en el cdigo fuente de la DLL. Por ejemplo, si creamos una DLL que slo contiene recursos, no es necesario implementar esta funcin. Si existe esta funcin de entrada/salida, debe ser como sta:
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID flmpLoad) { switch (fdwReason) { case DLL_PROCESS_ATTACH: // La DLL se proyecta en el espacio de // direcciones del proceso break; case DLL_THREAD_ATTACH: // Se crea un hilo break; case DLL_THREAD_DETACH: // Un hilo termina sin problemas break; case DLL_PROCESS_DETTACH:
67
El sistema operativo llama a esta funcin de entrada/salida en varios momentos. Cuando se llama a esta funcin, el parmetro hinstDll contiene el descriptor del ejemplar de la DLL. Como el parmetro hinstExe para WinMain, este valor identifica la direccin de memoria virtual en la que se proyect la imagen del archivo DLL en el espacio de direcciones del proceso. Habitualmente, se guardar este parmetro en una variable global para poder utilizarlo en las llamadas que cargan recursos, como DialogBox y LoadString. El ltimo parmetro, flmpLoad, es un valor distinto de cero si la DLL se carga implcitamente o cero si se carga explcitamente. El parmetro fdwReason indica la razn por la que el sistema llama a la funcin. Este parmetro puede ser uno de estos cuatro valores: DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH o DLL_THREAD_DETACH. DLL_PROCESS_ATTACH Cuando se proyecta por primera vez una DLL en el espacio de direcciones del proceso, el sistema llama a la funcin DllMain de la DLL, pasando el valor DLL_PROCESS_ATTACH como parmetro fdwReason. Esto slo sucede cuando se proyecta por primera vez la imagen del archivo DLL. Si un hilo llama despus a LoadLibrary o LoadLibraryEx para una DLL que ya est proyectada en el espacio de direcciones del proceso, el sistema operativo simplemente incrementa el contador de utilizacin de la DLL; no llama de nuevo a la funcin DllMain de la DLL con el valor DLL_PROCESS_ATTACH. Cuando procesa DLL_PROCESS_ATTACH, una DLL debera realizar todas las inicializaciones relativas al proceso que necesiten las funciones contenidas en la DLL. Por ejemplo, la DLL podra contener funciones que tengan que utilizar su propio Heap (creado en el espacio de direcciones del proceso). La funcin DllMain de la DLL podra crear este Heap llamando a HeapCreate durante el procesamiento de la notificacin DLL_PROCESS_ATTACH. El descriptor del Heap creado se podra guardar en una variable global a la que tuviesen acceso las funciones de la DLL. Cuando DllMain est procesando la notificacin DLL_PROCESS_ATTACH, el valor de retorno de DllMain indica si la inicializacin de la DLL ha tenido xito. Por ejemplo, si la llamada a HeapCreate ha tenido xito, DllMain debera devolver TRUE. Si no se ha podido crear el Heap, devuelve FALSE. Para cualquiera de los otros valores de fdwReason (DLL_PROCESS_DETACH, DLL_THREAD_ATTACH y DLL_THREAD_DETACH) el sistema ignora el valor que devuelve DllMain. Obviamente, debe haber algn hilo en el sistema que sea el responsable de ejecutar el cdigo de la funcin DllMain. Cuando se crea un nuevo proceso, el sistema proyecta el espacio de direcciones del proceso y despus proyecta la imagen del archivo EXE y todas las imgenes de archivo DLL requeridas en el espacio de direcciones del proceso. A continuacin, el sistema crea el hilo primario del proceso y utiliza este hilo para llamar a cada una de las funciones DllMain de DLL con un valor DLL_PROCESS_ATTACH. Despus de que todas las DLLs proyectadas hayan respondido a esta notificacin, el sistema provoca que el hilo primario del proceso comience a ejecutar el cdigo de inicio en tiempo de ejecucin de C del EXE, seguido de la funcin WinMain del EXE. Si alguna de las funciones DllMain de DLL devuelven FALSE, indicando que la inicializacin no ha tenido xito, el sistema termina todo el proceso, eliminando todas las imgenes de archivo de su espacio de direcciones y mostrando un cuadro de mensaje al usuario que indica que no ha podido comenzar el proceso. Cuando un hilo de un proceso llama a LoadLibrary o LoadLibraryEx, el sistema localiza la DLL especificada y proyecta la DLL en el espacio de direcciones del proceso. Despus, el sistema llama a la funcin DllMain de la DLL con el valor DLL_PROCESS_ATTACH,
68
utilizando el hilo que realiz la llamada a LoadLibrary o LoadLibraryEx. Despus de que la funcin DllMain de la DLL haya procesado la notificacin, el sistema permite que vuelva la llamada a LoadLibrary o LoadLibraryEx, y el hilo contina su procesamiento con normalidad. Si la funcin DllMain devuelve FALSE, indicando que la inicializacin no tuvo xito, el sistema elimina automticamente la proyeccin de la imagen del archivo DLL del espacio de direcciones del proceso y la llamada a LoadLibrary o LoadLibraryEx devuelve NULL. DLL_PROCESS_DETACH Cuando se elimina la proyeccin de una DLL del espacio de direcciones de un proceso, el sistema llama a la funcin DllMain de la DLL, pasando DLL_PROCESS_DETACH como valor fdwReason. Una DLL debera realizar todas las liberaciones relativas al proceso cuando procese este valor. Por ejemplo, una DLL podra llamar a HeapDestroy para destruir un Heap que ha creado durante la notificacin DLL_PROCESS_ATTACH. Si se llama a la funcin DllMain de una DLL con un valor fdwReason igual a DLL_PROCESS_ATTACH y DllMain devuelve FALSE, indicando que la inicializacin no ha tenido xito, el sistema no dejar de llamar a DllMain con el valor DLL_PROCESS_DETACH. Por esta razn, debe asegurarse de que no intenta liberar nada que no se haya inicializado con xito. Si se est eliminando la proyeccin de la DLL porque el proceso est terminando, el hilo que llama a ExitProcess es el responsable de ejecutar el cdigo de la funcin DllMain. Bajo circunstancias normales, ste es el hilo primario de la aplicacin. Cuando la funcin DllMain vuelve al cdigo de inicio de la biblioteca de tiempo de ejecucin de C, este cdigo llama explcitamente a la funcin ExitProcess para terminar el proceso. Si se est eliminando la proyeccin de la DLL porque un hilo del proceso ha llamado a FreeLibrary, este hilo ejecuta el cdigo de la funcin DllMain. La llamada a Fre-eLibrary no volver hasta que la funcin DllMain haya terminado de ejecutarse. Si un proceso termina porque algn hilo del sistema llama a TerminateProcess, el sistema no llama a la funcin DllMain de la DLL con el valor DLL_PROCESS_DETACH. Esto significa que las DLLs proyectadas en el espacio de direcciones del proceso no tendrn la oportunidad de realizar ninguna liberacin antes de que el proceso termine. Esto podra provocar la prdida de datos. Slo se debera utilizar la funcin TerminateProcess como ltimo recurso.
69
Figura 2-26. Los pasos que lleva a cabo el sistema cuando un hilo llama a LoadLibrary.
70
La Figura 2-27. Los pasos que se lleva a cabo el sistema cuando un hilo llama a FreeLibrary.
DLL_THREAD_ATTACH Cuando se crea un hilo en un proceso, el sistema examina todas las imgenes de archivo DLL proyectadas actualmente en el espacio de direcciones del proceso y llama a cada una de las funciones DllMain de estas DLLs con el valor DLL_THREAD_ATTACH. Esta notificacin indica a todas las DLLs que realicen todas las inicializaciones de cada hilo. Por ejemplo, la versin DLL de la biblioteca de tiempo de ejecucin de C asigna un bloque de datos para que una aplicacin multihilo pueda utilizar de forma segura las funciones contenidas en la biblioteca de tiempo de ejecucin de C. El hilo recin creado es el responsable de ejecutar el cdigo de todas las funciones DllMain de la DLL. Slo despus de que todas las DLLs hayan tenido la oportunidad de procesar esta notificacin, permitir el sistema que el nuevo hilo comience a ejecutar la funcin de su hilo. Si un proceso ya tiene varios hilos ejecutndose en l cuando se proyecta una nueva DLL en su espacio de direcciones, el sistema no llama a la funcin DllMain de la DLL con el valor DLL_THREAD_ATTACH para ninguno de los hilos ya existentes. El sistema llama a la funcin DllMain de la DLL con un valor DLL_THREAD_ATTACH slo si la DLL est proyectada en el espacio de direcciones del proceso en el momento en que se crea el hilo nuevo. Observe tambin que el sistema no llama a ninguna de las funciones DllMain con un valor DLL_THREAD_ATTACH para el hilo primario del proceso. Todas las DLLs que estn proyectadas en el espacio de direcciones del proceso cuando se llama al proceso por primera vez reciben la notificacin DLL_PROCESS_ATTACH, pero no la DLL_THREAD_ATTACH.
71
DLL_THREAD_DETACH Cuando un hilo termina llamando a ExitThread, el sistema examina todas las imgenes de archivo de DLL proyectadas actualmente en el espacio de direcciones del proceso y llama a todas las funciones DllMain de la DLL con un valor DLL_THREAD_DETACH. Esta notificacin les indica a todas las DLLs que realicen todas las liberaciones correspondientes al hilo. Por ejemplo, la versin de DLL de la biblioteca de tiempo de ejecucin de C libera el bloque de datos que utiliza para gestionar las aplicaciones multihilo. Importante Si un hilo termina porque llama a TerminateThread, el sistema no llama a todas las funciones DllMain de la DLL con un valor DLL_THREAD_DETACH. Esto significa que todas las DLLs proyectadas en el espacio de direcciones del proceso no tendrn la oportunidad de realizar ninguna liberacin antes de que termine el hilo. Esto podra provocar que se perdiesen datos. Igual que TerminateProcess, solo se debe utilizar TerminateThread como ltimo recurso. Si se est ejecutando algn hilo cuando se elimina la proyeccin de la DLL, no se llama a DllMain con DLL_THREAD_DETACH para ninguno de los hilos. Se podra comprobar esto en el procesamiento de DLL_PROCESS_DETACH para realizar cualquier liberacin que resulte necesaria.
Exportar funciones y variables de una DLL Cuando se crea una DLL, se crea un conjunto de funciones a las que se desea que un EXE u otras DLLs sean capaces de llamar. Cuando una funcin de DLL pasa a estar disponible para un archivo EXE o de otra DLL, se dice que la funcin est exportada. Win32 hace posible que se exporten variables de datos globales adems de funciones. Ahora veremos los pasos que se deben seguir para exportar las funciones y variables globales de una DLL. El cdigo siguiente (tomado de un archivo fuente de DLL) muestra cmo exportar una funcin llamada Ada y una variable entera global llamada g_nUsageCount desde una DLL:
_declspec(dllexport) int Add (int nLeft, int nRight) { return (nLeft + nRight); } _declspec(dllexport) int g_nUsageCount = O ;
En su mayor parte, nada de este cdigo debera resultarle nuevo a excepcin de _declspec(dllexport). El compilador de Microsoft C/C++ la reconoce como una nueva palabra clave. Cuando el compilador compila la funcin Add y la variable g_nUsageCount, incrusta alguna informacin adicional en el archivo .OBJ resultante. El objeto de esta informacin es que el enlazador la analice sintcticamente y la procese cuando enlaza todos los objetos OBJ de la DLL. Cuando se enlaza la DLL, el enlazador detecta esta informacin incrustada acerca de la funcin y de la variable exportada, y genera automticamente un archivo LIB que contiene la lista de smbolos exportados por la DLL. Este archivo LIB, claro est, se necesitar para enlazar cualquier EXE que llame a las funciones exportadas de la DLL. Adems de crear el archivo LIB, el enlazador incrusta una tabla de nombres exportados de funcin o de variable y la direccin en la cual est situada la funcin o variable dentro de la imagen de archivo DLL. El enlazador asegura que la lista est ordenada alfabticamente en funcin del nombre de smbolo.
Importar funciones y variables de una DLL Cuando se desea que un EXE llame a las funciones o acceda a las variables contenidas en una DLL, se le debe indicar al compilador que las funciones o variables a las que se desea acceder
72
estn contenidas en una DLL. Por ejemplo, el fragmento de cdigo siguiente muestra cmo importar la funcin Ada y la variable g_nUsageCount exportadas por la DLL que hemos visto en el apartado anterior:
_declspec(dllimport) int Add (int nLeft, int nRight); _declspec(dllimport) int g_nUsageCount;
Como _declspec(dllexport), _declspec(dllimport) es una palabra clave reconocida por el compilador de Microsoft C/C++. Esta palabra clave le indica al compilador que la funcin Add y la variable g_nUsageCount estn contenidas en una DLL a la que el EXE tendr acceso cuando se cargue. Esto provoca que el compilador genere cdigo especial para estos smbolos importados. Cuando se desea importar un smbolo, no se tiene que utilizar la palabra clave _declspec(dllimport). En su lugar, basta con utilizar la palabra clave extern estndar de C. Sin embargo, el compilador es capaz de generar un cdigo ligeramente ms eficiente si conoce por adelantado que el smbolo al que se hace referencia va a ser importado desde el archivo LIB de una DLL. Por tanto, le recomiendo que utilice la palabra clave _declspec(dllimport) para los smbolos de funciones y de datos importados. Un hilo puede obtener la direccin de la funcin o variable exportada por una DLL llamando a la funcin GetProcAddress:
FARPROC GetProcAddress (HINSTANCE hinstDll, LPCSTR IpszProc);
El parmetro hinstDll especifica el descriptor de la DLL. El valor que devuelve LoadLibrary o LoadLibraryEx identifica este valor de descriptor. El parmetro IpszProc puede tomar dos formas. En primer lugar, puede ser la direccin de una cadena terminada en cero que contiene el nombre de la funcin cuya direccin deseamos:
Ipfn = GetProcAddress (hinstDll, "AlgunaFuncEnDll");
Observe que el parmetro IpszProc aparece en el prototipo como LPCSTR, en vez de LPCTSTR. Esto significa que la funcin GetProcAddress slo aceptar cadenas ANS no se le puede pasar una cadena Unicode a esta funcin. La razn es que los smbolos de funcin y variable se almacenan siempre como cadenas ANS en la tabla de exportaciones de la DLL. La segunda forma del parmetro IpszProc indica el nmero ordinal de la funcin cuya direccin deseamos:
Ipfn = GetProcAddress (hinstDll, MAKEINTRESOURCE(2));
Esta utilizacin asume que conocemos que el creador de la DLL le ha asignado a la funcin AlgunaFuncEnDll el valor ordinal 2. Los dos mtodos proporcionan la direccin de la funcin AlgunaFuncEnDll contenida en la DLL. Si no se puede encontrar la funcin, GetProcAddress devuelve NULL.
Archivo de cabecera de una DLL Habitualmente, cuando se crea una DLL, tambin se crea un archivo de cabecera. Este archivo tiene los prototipos de todas las funciones y variables que la DLL est exportando. Cuando se compilan los archivos de cdigo fuente del EXE, se incluir este archivo de cabecera. A menudo tambin desearemos incluir este archivo de cabecera cuando se compilen los archivos de cdigo fuente de la DLL.
73
74
Hay que tener en cuenta que la llamada a DllMain() puede realizarse mas de una vez, por lo que hay q controlar que los controles no se inicialicen mas de una vez.
2.3.1.3 LibNumberClasses
Cuando 3ds max arranca, busca DLLs para cargarlas. Cuando encuentra una, necesita determinar el nmero de clases tipo plugin dentro de la DLL. El programador proporciona esta informacin a 3ds max definiendo la funcin LibNumberClasses(). Por ejemplo:
__declspec(dllexport) int LibNumberClasses() { return 1; }
El desarrollador debe devolver el numero de clases de plugin que hay implementado dentro de la DLL.
2.3.1.4 LibClassDesc
El plugin debe proporcionar al sistema algn mecanismo para obtener los Descriptores de Clases definidos por el plugin. Los Descriptores de Clases proporcionan al sistema de la informacin sobre las clases plugin en el DLL. La funcin LibClassDesc(i) permite al sistema acceder a los Descriptores de Clases. Una DLL puede tener varios Descriptores de Clases, uno para cada clase plugin. La funcin debe devolver un puntero al i-simo descriptor de clase. Por ejemplo:
__declspec(dllexport) ClassDesc *LibClassDesc(int i) { switch(i) { case 0: return &MeltCD; case 1: return &CrumpleCD; default: return 0; } }
Este ejemplo devuelve un puntero al descriptor de la clase Melt, o al descriptor de la clase Crumple.
2.3.1.5 LibDescription
Devuelve un texto que contenga el nombre descriptivo de la DLL.
__declspec( dllexport ) const TCHAR *LibDescription() { return _T("Melt Modifier. Call 1-800-PLUG-INS to obtain a copy"); }
2.3.1.6 LibVersion()
Los desarrolladores deben implementar una funcin que permita al sistema tratar con versiones obsoletas de plugins. Debido que la arquitectura de 3ds max mantiene una relacin muy estrecha con sus plugins, el sistema puede en algn punto evitar cargar algunos plugins demasiado antiguos. Para permitir que 3ds max cumpla esto, la DLL debe implementar una
75
funcin llamada LibVersion(). Esta funcin simplemente devuelve una constante indicando la versin del sistema bajo la cual fue compilada. Las versiones futuras de 3ds max podran actualizar esta constante, incluso las DLLs mas antiguas siempre devolvern el valor. Con esta funcin el sistema puede comprobar si se est cargando una DLL ya obsoleta, y en ese caso mostrar un mensaje de aviso.
__declspec( dllexport ) ULONG LibVersion() { return VERSION_3DSMAX; }
El significado de VERSION_MAX ha sido mejorado en la versin 2 para incluir informacin sobre la versin actual de max, as como el numero de la versin actual de la API y el numero de versin del 3ds max SDK. La palabra ms alta contiene el nmero de la versin de 3ds max multiplicado por 100, y la palabra baja es el nmero de API y la revisin del SDK. 3ds max solo cargar DLLs que tengan el numero de API actual.
#define VERSION_3DSMAX ((MAX_RELEASE<<16)+(MAX_API_NUM<<8)+MAX_SDK_REV)
MAX_RELEASE Numero de versin de 3ds max multiplicado por 1000. MAX_API_NUM Numero de API de 3ds max. Cuando un cambio en la API requiere ser recompilada, este numero se incrementa y MAX_SDK_REV se pone a 0. Esto har que todas las DLLs con el MAX_API_NUM antiguo dejen de poder cargarse. MAX_SDK_REV Esto indica la revisin del SDK para una API dada. Este numero se incrementa cuando la funcionalidad del SDK cambia de manera significante (por ejemplo se aade un nuevo valor de retorno de la funcin GetProperty() ), pero las cabeceras no han cambiado. Un desarrollador puede acceder a este valor usando
DWORD Get3DSMAXVersion();
76
Este mtodo devuelve un booleano, si el plugin es accesible por el usuario, como suele ser normal, devuelve TRUE. Ciertos plugins pueden ser usados de manera privada por otros plugins, implementados en la misma DLL y no debera aparecer en listas para que los usuarios los elijan. Estos plugins devolvern FALSE.
Create(BOOL loading=false)
3ds max llama esta funcin cuando necesita un puntero a una nueva instancia de la clase plugin. Por ejemplo, si 3ds max est cargando un fichero de disco conteniendo un plugin anteriormente utilizado, llamar a la funcin Create() del plugin. El plugin responder reservando una nueva instancia de su clase plugin. Como en el ejemplo del descriptor de clase anterior, tan solo implica el uso del operador new. El parmetro opcional de la funcin Create(), es un flag indicando si la clase a crear va a ser cargada de un fichero de disco. Si el flag es TRUE, el plugin probablemente no tenga que realizar ninguna inicializacin del objeto ya que el proceso de carga se encajar de ello. Cuando el sistema necesita eliminar una instancia de una clase plugin, usualmente llama al mtodo DeleteThis(). Los desarrolladores de plugins tambin deben implementar este mtodo. Puesto que un desarrollador usa el operador new para reservar memoria, deber usar el operador delete para liberarla. Por ejemplo, el desarrollador podra implementar DeleteThis() de esta manera :
void DeleteThis() { delete this; }
This method returns the name of the class. This name appears in the button for the plug-in in the 3ds max user interface.
SuperClassID()
Este mtodo devuelve la constante definida por el sistema describiendo la clase de la cual deriva este plugin. Por ejemplo, el plugin Bend revuelve OSM_CLASS_ID. Este ID se usa por todos los modificadores de objetos.
ClassID()
Este mtodo debe devolver el ID nico para el objeto plugin. El SDK proporciona un programa para generar este ClassID, es importante usar este programa para no provocar ningn conflicto de IDs.
Category()
Indica la categora del plugin. De esta manera el plugin se mostrar en una u otra lista de categoras del interfaz de usuario. Si la categora no existe, se crea una nueva.
77
La clase de bloque de parmetros proporciona un mecanismo para almacenar valores para los parmetros de los plugins. Cuando se crea un bloque de parmetros, el desarrollador especifica el nmero de parmetros y el tipo de cada parmetro. El tipo de cada parmetro consiste en un rango de tipos predefinidos como entonces, coma flotante, punto 3D, y color. Para acceder a los valores del bloque de parmetros, el desarrolladores usan los mtodos GetValue() y SetValue(). Un descriptor de bloque de parmetros se usa para describir cada parmetro. Se inicializa pasando tres argumentos por parmetro.
class ParamBlockDesc { public: ParamType type; UserType *user; BOOL animatable; };
Los valores que puede tomar ParamType son : TYPE_INT valores enteros TYPE_FLOAT valores en coma flotante TYPE_POINT3 Puntos en el espacio 3D TYPE_RGBA Valores de color TYPE_BOOL Valores booleanos
Cuando un desarrollador necesita obtener un valor del bloque de parmetros, se usa la funcin GetValue(). Existe una funcin sobrecargada para cada tipo de valor a obtener (int, float, point y RGBA). Cada mtodo tiene cuatro parmetros. A continuacin se muestra la funcin para el tipo float:
BOOL GetValue( int i, TimeValue t, float &v, Interval &ivalid );
Cuando un desarrollador necesita almacenar un valor en el bloque de parmetros, se usa la funcin SetValue(). Igual que en GetValue(), existe una funcin sobrecargada para cada tipo de dato.
BOOL SetValue( int i, TimeValue t, float v );
Puesto que los bloques de parmetros derivan de ReferenceTarget, los plugins pueden crear referencias a ellos. Creando una referencia a un bloque de parmetros, el plugin puede ser notificado siempre que alguno de sus parmetros tome un nuevo valor. Cuando cambia un valor del bloque de parmetros, el plugin necesita ser informado. Esta notificacin la hace el mtodo NotifyDependents() de la clase ReferenceMaker. Hay dos mtodos que se invocan cuando un usuario comienza y termina de modificar los parmetros de un elemento. Estos son BeginEditParams() y EndEditParams().
78
2.4 Conclusiones.
En este captulo se han mostrado las diferencias entre la informtica grfica tradicional y la informtica grfica en tiempo real, mostrando la necesidad de utilizacin de hardware especializado en la generacin de imgenes, y en consecuencia, de libreras de bajo nivel que proporcionen control sobre dicho hardware. En este sentido, se ha realizado un recorrido histrico por las distintas libreras que proporcionan un API para el renderizado de grficos 3D, finalizando con la librera OpenGl, un standard empleado por la gran mayora de los sistemas grficos actuales. Se ha presentado de forma abreviada los principales aspectos que definen la forma de funcionamiento de la librera OpenGl, realizando tambin una introduccin sobre la forma en la que opera con las matrices de transformacin. Se ha descrito como las libreras de bajo nivel proporcionan buenos mtodos para controlar las capacidades del hardware grfico, pero resultan demasiado elementales si se desea implementar una escena de simulacin compleja, siendo en este caso necesaria la utilizacin de una librera grfica de alto nivel basada en la utilizacin de un Grafo de Escena. Los grafos de escena estn diseados para optimizar el proceso de dibujado y contribuir a la organizacin de la base de datos, resultando de especial importancia sus procesos de culling y seleccin de nivel de detalle, y su capacidad para actuar como soporte para la aplicacin jerrquica de transformaciones afines. Se han presentado los tipos de nodos bsicos empleados en la definicin de estos grafos, y tambin la forma en la que estas libreras de alto nivel actan en el caso de disponer de un sistema con varios procesadores. Tambin se ha realizado un recorrido por los grafos de escena actuales, profundizando en aquellos que han tenido una mayor influencia en la evolucin de esta rama de la informtica grfica (OpenGl Performer, Open Inventor y VRML). El resto de los grafos de escena presentan 79
unas caractersticas bsicas similares, siendo destacable que alguno de ellos presenta carencias a la hora de proporcionar un buen rendimiento en tiempo real, que muchos de ellos reproducen el comportamiento de OpenGl Performer, y que algunos de ellos estn siendo distribuidos como cdigo abierto, como es el caso de OpenSceneGraph. Hemos hecho del mismo modo un recorrido sobre los distintos editores 3D y su importancia en el mundo de la informtica grafica, la simulacin, realidad virtual, videojuegos etc., y hemos visto como la mayor parte de los motores de videojuegos son o bien motores de visualizacin o bien motores completos, siendo cada vez mas estandarizados. La simulacin y la visualizacin estn fuertemente acopladas, y en las aplicaciones de realidad virtual existe una fuerte componente de simulacin y exigencias elevadas de velocidad interaccin con el usuario. De las aplicaciones vistas, tan solo permiten trabajar en tiempo real UnrealED y Hammer Editor. Las libreras de enlace dinmico permiten el desarrollo de plugins en las aplicaciones, las cuales nos proporcionan una mayor personalizacin, modularidad, mantenibilidad y flexibilidad, incluso puede prolongar la vida de nuestro software. Como ejemplo de aplicacin basada en el uso de plugins hemos estudiado a 3D Studio Max, el cual hemos tomado como referencia este tipo de arquitectura para este proyecto.
80
PARTE III
TECNOLOGIA Y MATERIALES
81
82
INDICE
PARTE III......................................................................................................
3.1 Metodologa ...................................................................... Error! Marcador no definido. 3.2 Materiales .......................................................................... Error! Marcador no definido. 3.3 Planificacin temporal....................................................... Error! Marcador no definido. 3.3.1 Diagrama de Gant....................................................... Error! Marcador no definido.
83
3.1 Metodologa
El primer paso en todo proyecto es la investigacin del estado de las tecnologas implicadas en el mismo, con el objetivo de adquirir un conocimiento sobre la tarea a realizar, encontrar otros estudios o aplicaciones existentes que estn relacionados con el mismo campo. Tras este estudio, documentado detalladamente en la parte II de este proyecto, es momento de planificar en detalle las tareas que se van a realizar dentro del proyecto.
3.2 Materiales
El recurso ms importante para el desarrollo de este proyecto ser un PC convencional. En dicho PC ser necesaria la instalacin de un compilador de C++. Se ha elegido para esta ocasin el compilador Microsoft Visual Studio .NET, versin 7.1 ya que su versin anterior presentaba distintas incompatibilidades con la librera OpenSceneGraph necesaria para el desarrollo del proyecto. La licencia de uso de esta plataforma de desarrollo de aplicaciones ha sido adquirida por la Universidad de Valencia, por lo que no ha sido necesaria su compra, puesto que la universidad lo utiliza como apoyo para la docencia en las distintas asignaturas de programacin de la carrera. Una vez instalado dicho compilador no queda ms que instalar la librera OpenSceneGraph en el sistema operativo as como configurar el compilador adecuadamente para compilar adecuadamente sus fuentes. El software generado ser dependiente del sistema operativo (en este caso Microsoft windows), ya que se har uso de las MFCs (Microsoft Foundation Classes). Debido al motivo de uso del compilador de Microsoft el uso del software generado deber correr bajo sistemas operativos de Microsoft.
84
codificar el sistema convenientemente, teniendo en cuenta no solo los apartados de anlisis y diseo realizados con anterioridad, sino tambin las decisiones tomadas en cuanto al lenguaje de programacin, comunicaciones, etc. 5) Pruebas. En esta parte se comprueba que todo el trabajo desarrollado es correcto, realizando pruebas de diferentes tipos, especificas para cada parte concreta del proyecto. 6) Redaccin. Es la ltima parte del proyecto, pero esto no indica que se realice en ltimo lugar. La redaccin del proyecto es un proceso creciente y continuo desde el comienzo del proyecto, redactando en cada momento los detalles y aspectos de inters que han aparecido en el transcurso del proyecto. Esta es la parte ms tediosa del proyecto, en la que la prioridad es poder comunicar a cualquier lector interesado, el trabajo realizado, la forma en que se ha llevado a cabo, y los resultados obtenidos.
nov '05
dic '05
ene '06
feb '06
mar '06
abr '06
may '06
jun '06
jul '06
ago '06
sep '06
oct '06
Documentacin bibliografica 15 das Analisis del sistema de informacion 15 das Diseo del sistema 115 das 20 das Diseo interfaz de usuario 14 das Generacion automatica de controles 35 das Control del grafo de escena multiple 20 das Interaccion escena/usuario 15 das Sistema undo/redo 10 das Soporte de plugins 12 das Pruebas y depuracion 24 das Redaccion Implementacin
85
Los materiales necesarios para el proyecto y sus costes son los siguientes:
PC Pentium 4 con 1GB de memoria RAM, tarjeta grfica aceleradora GeForce MX y tarjeta de red utilizado durante la elaboracin del proyecto Sistema Operativo Windows XP (cedido por el Instituto de Robtica). Herramientas de desarrollo Visual Studio .NET (cedido por el Instituto de Robtica). Licencia de Visual .NET Conexin a Internet, utilizando para ello la red de la Universidad de Valencia. Librera grafica OpenSceneGraph (open source).
700.00 -
96.15 0
Todo este proyecto se engloba en la nueva lnea de investigacin del grupo ARTEC acerca de la recreacin y simulacin de escenarios virtuales, para simulaciones en tiempo real. Por tanto, todo el material arriba mencionado, se utilizar posteriormente en otros proyectos, amortizando dicho coste en un corto periodo de tiempo. Por tanto, el coste amortizado se calcular en 24 meses, habiendo utilizado para este proyecto 11 meses.
CONCEPTO IMPORTE
PC Pentium 4, 1GB RAM, Ge-Force MX, tarjeta red, etc. Licencia Visual .NET Base imponible IVA 16% TOTAL: Coste amortizado = (923.54 / 24) * 11 = 423.28
A estos costes es necesario aadir el sueldo de un Ingeniero Informtico. Suponiendo un sueldo de 24,050.00 , se obtiene un salario de 2,004.00 al mes. Habiendo trabajado durante 11 meses: Sueldo = 2,004.00 * 11 = 22,044.00 Precio = Coste amort. + Sueldo = 923,54 + 20,040 = 22,967.54 Si ha este precio aadimos un 10 % para cubrir posibles imprevistos, obtenemos una cantidad final: TOTAL = Precio + 10 % = 25,264.3
86
87
88
PARTE IV
ANALISIS
89
INDICE
PARTE IV ......................................................................................................
4.1 Introduccin ...................................................................... Error! Marcador no definido. 4.2 Anlisis de Requisitos. ...................................................... Error! Marcador no definido. 4.2.1 Requisitos generales del sistema. ............................... Error! Marcador no definido. 4.2.2 Requisitos de la representacin del grafo de escena .. Error! Marcador no definido. 4.2.3 Requisitos de la representacin de tipos de datos en el interfaz..... Error! Marcador no definido. 4.2.4 Requisitos de la manipulacin sobre la representacin 3D del grafo.................Error! Marcador no definido. 4.2.5 Requisitos del sistema de deshacer / rehacer.............. Error! Marcador no definido. 4.2.5 Requisitos del sistema de plugins............................... Error! Marcador no definido.
90
4.2.6 Requisitos del Manejador de Vista Activa ................. Error! Marcador no definido. 4.3 Anlisis.............................................................................. Error! Marcador no definido. 4.3.1 Anlisis de la representacin de los datos del grafo en el interfaz .. Error! Marcador no definido. 4.3.1.1 Grupos de parmetros.......................................... Error! Marcador no definido. 4.3.1.2 Descriptores de parmetros ................................. Error! Marcador no definido. 4.3.1.3 El gestor de parmetros ....................................... Error! Marcador no definido. 4.3.1.4 Objects, Nodes, y AttributeTypes en OpenSceneGraph ..... Error! Marcador no definido. 4.3.1.5. El Gestor de ObjectTypes, NodeTypes y AttributeTypes. . Error! Marcador no definido. 4.3.2 Anlisis de la representacin del grafo de escena ...... Error! Marcador no definido. 4.3.2.1 Crear un rbol a partir de un grafo ...................... Error! Marcador no definido. 4.3.2.2 Mostrar el grafo en mltiples vistas de rbol ...... Error! Marcador no definido. 4.3.2.3 Acciones sobre el rbol ....................................... Error! Marcador no definido. 4.3.2.4 Mostrar la informacin de un nodo del grafo...... Error! Marcador no definido. 4.3.3 Anlisis de la interaccin con el visor del editor........ Error! Marcador no definido. 4.3.3.1 El gestor de seleccin .......................................... Error! Marcador no definido. 4.3.3.2 El eje manipulador .............................................. Error! Marcador no definido. 4.3.3.3 Creacin automtica de Matrices de Transformacin ......... Error! Marcador no definido. 4.3.3.4 Traslacin de objetos usando el eje manipulador Error! Marcador no definido. 4.3.3.5 Representacin de objetos independientes a la escena del editor................Error! Marcador no definido. 4.3.4 Anlisis del sistema deshacer / rehacer. ..................... Error! Marcador no definido. 4.2.7 Anlisis del sistema de plugins. ................................. Error! Marcador no definido. 4.2.8 Anlisis del Manejador de Vista Activa..................... Error! Marcador no definido. 4.4 Casos de uso ...................................................................... Error! Marcador no definido. 4.4.1 Funciones del sistema................................................. Error! Marcador no definido. 4.4.2 Descripcin de alto nivel de los Casos de Uso........... Error! Marcador no definido. Iniciar la aplicacin. ........................................................ Error! Marcador no definido. Iniciar Barras. .................................................................. Error! Marcador no definido. Crear barra de paneles de comandos. .............................. Error! Marcador no definido. Iniciar tipos de objeto...................................................... Error! Marcador no definido. Registrar un TabOutput................................................... Error! Marcador no definido. Registrar un ObjectType. ................................................ Error! Marcador no definido. Mapear los grupos de parmetros de un TabOutput........ Error! Marcador no definido. Cargar Plugins. ................................................................ Error! Marcador no definido. Cerrar aplicacin. ............................................................ Error! Marcador no definido. Cerrar treebar .................................................................. Error! Marcador no definido. Cerrar escena. .................................................................. Error! Marcador no definido. Cargar escena. ................................................................. Error! Marcador no definido. Establecer un grafo sobre un elemento del rbol. ........... Error! Marcador no definido. Replicar una escena de una TreeBar a otra. .................... Error! Marcador no definido. Clonar un TreeCtrl a partir de otro.................................. Error! Marcador no definido. Nueva escena................................................................... Error! Marcador no definido. Crear grafo por defecto. .................................................. Error! Marcador no definido. Nuevo rbol..................................................................... Error! Marcador no definido. Insertar fichero. ............................................................... Error! Marcador no definido. Cambiar escena activa..................................................... Error! Marcador no definido. Deshacer. ......................................................................... Error! Marcador no definido. Rehacer............................................................................ Error! Marcador no definido. Crear Nodo. ..................................................................... Error! Marcador no definido. Crear un nodo segn el nombre de su NodeType. .......... Error! Marcador no definido. Crear una nueva instancia de un nodo segn su nombre. Error! Marcador no definido.
91
Seleccionar elemento en rbol......................................... Error! Marcador no definido. Seleccionar todas las instancias de un elemento. ............ Error! Marcador no definido. Seleccionar todos los mirrors de un elemento. ............ Error! Marcador no definido. Mostrar la informacin de un nodo ................................. Error! Marcador no definido. Crear los dilogos de un TabOutput................................ Error! Marcador no definido. Crear un dilogo a partir de un grupo de parmetros ...... Error! Marcador no definido. Generar el contenido de un TabOutput ........................... Error! Marcador no definido. Vaciar el contenido de un TabOutput.............................. Error! Marcador no definido. Notificar fin de seleccin de un ObjectType................... Error! Marcador no definido. Mostrar los datos de un TabOutput ................................. Error! Marcador no definido. Seleccionar nodo en el visor............................................ Error! Marcador no definido. Agregar nodo a la seleccin del visor ............................. Error! Marcador no definido. Crear Matriz de Transformacin como padre de un nodo............... Error! Marcador no definido. Actualizar la seleccin. ................................................... Error! Marcador no definido. Actualizar el eje manipulador. ........................................ Error! Marcador no definido. Copiar nodo..................................................................... Error! Marcador no definido. Replicar seleccin. .......................................................... Error! Marcador no definido. Mover nodo. .................................................................... Error! Marcador no definido. Duplicar Nodo. ................................................................ Error! Marcador no definido. Duplicar Seleccion. ......................................................... Error! Marcador no definido. Eliminar nodo.................................................................. Error! Marcador no definido. Activar modo seleccin. .................................................. Error! Marcador no definido. Activar modo traslacin de objetos................................. Error! Marcador no definido. Activar modo escalado de objetos................................... Error! Marcador no definido. Activar modo rotacin de objetos. .................................. Error! Marcador no definido. Activar modo rotar vista.................................................. Error! Marcador no definido. Activar modo trasladar vista. .......................................... Error! Marcador no definido. Escalar seleccin. ............................................................ Error! Marcador no definido. Comenzar escalado de seleccin. .................................... Error! Marcador no definido. Realizar escalado de seleccin. ....................................... Error! Marcador no definido. Finalizar escalado de seleccin. ...................................... Error! Marcador no definido. Rotar seleccin. ............................................................... Error! Marcador no definido. Comenzar rotacin de seleccin...................................... Error! Marcador no definido. Realizar rotacin de seleccin......................................... Error! Marcador no definido. Finalizar rotacin de seleccin........................................ Error! Marcador no definido. Trasladar seleccin.......................................................... Error! Marcador no definido. Comenzar traslacin de seleccin. .................................. Error! Marcador no definido. Realizar traslacin de seleccin. ..................................... Error! Marcador no definido. Finalizar traslacin de seleccin. .................................... Error! Marcador no definido. Centrar la vista en la seleccin........................................ Error! Marcador no definido. Modificar el zoom de la vista. ......................................... Error! Marcador no definido. Aadir un StateAttribute a un StateSet............................ Error! Marcador no definido. Eliminar un StateAttibute de un StateSet. ....................... Error! Marcador no definido. Aadir un Modo a un StateSet. ....................................... Error! Marcador no definido. Eliminar un Modo de un StateSet. .................................. Error! Marcador no definido. Modificar un Modo de un StateSet. ................................ Error! Marcador no definido. Modificar el parmetro de un control del panel de comandos. ....... Error! Marcador no definido. Establecer el valor de un parmetro. ............................... Error! Marcador no definido. Establecer el valor de un parmetro. ............................... Error! Marcador no definido. Establecer el contenido del portapapeles......................... Error! Marcador no definido. Pegar el contenido del portapapeles. ............................... Error! Marcador no definido. Visualizar escena en modo de alambre. .......................... Error! Marcador no definido. Visualizar escena en modo de relleno. ............................ Error! Marcador no definido.
92
Visualizar sombreado en modo plano. ............................ Error! Marcador no definido. Visualizar sombreado en modo suavizado. ..................... Error! Marcador no definido. Mostrar vista superior de la escena. ................................ Error! Marcador no definido. Mostrar vista inferior de la escena. ................................. Error! Marcador no definido. Mostrar vista anterior de la escena. ................................. Error! Marcador no definido. Mostrar vista posterior de la escena. ............................... Error! Marcador no definido. Mostrar vista lateral izquierda de la escena..................... Error! Marcador no definido. Mostrar vista lateral derecha de la escena. ...................... Error! Marcador no definido. 4.4.3 Casos de Uso siguiendo la notacin UML. ................ Error! Marcador no definido.
93
4.1 Introduccin
Cualquier trabajo que requiere de un proceso de Ingeniera del Software, requiere una fase de anlisis del problema a resolver, de forma que se obtengan todas las caractersticas del sistema que se analiza.
94
En primer lugar se realizar un anlisis general del sistema, describiendo el problema y las necesidades o requerimientos del sistema global, gracias a lo cual conoceremos qu debe hacerse para solucionarlo. Esto no implica definir la solucin al problema, sino simplemente la forma de abordarlo. Al analizar el sistema en conjunto, se puede realizar una divisin para desglosar el sistema en distintas partes bien definidas: 1. Por una parte, analizaremos como plasmar la informacin de un grafo acclico en una estructura manejable desde el interfaz de usuario. 2. En segundo lugar, estudiaremos un sistema que nos permita generar automticamente controles para mostrar la informacin de los tipos de datos del grafo, entre otros. 3. Deberemos definir las acciones que vamos a permitir al usuario sobre la representacin 3D de la escena. 4. Continuaremos viendo un sistema de historia de las acciones, conocido comnmente como deshacer / rehacer. 5. Veremos como podemos dotar a nuestro software de un sistema de plugins. 6. Por ltimo, tendremos que hacer que todo esto funcione mediante un sistema que centralice todos los subsistemas anteriores que llamaremos Manejador de Vista Activa. En este caso, se centrar la atencin en realizar un anlisis dentro de la perspectiva de los objetos, para posteriormente implementarlos en un lenguaje de programacin orientado a objetos (C++). Se utilizara UML ya que rene una coleccin de las mejores practicas en la ingeniera que han sido utilizadas hasta el momento, es trata de la unificacin de los diversos sistemas que haba hasta el momento, con las mejores caractersticas de cada uno de ellos.
95
El grafo de escena deber estar representado en nuestro programa. Esto implica construir una estructura de datos y una imagen del grafo que permita manejar el grafo de escena de OpenSceneGraph, asociando cada uno de nuestros propios nodos con el nodo correspondiente en el grafo de escena. Otro aspecto muy importante ser la posibilidad de mostrar mltiples vistas del control en el interfaz de usuario, para aquellos casos en los que trabajemos con grafos muy grandes, y necesitemos trabajar simultneamente con distintas zonas del mismo. El rbol deber permitir que el usuario realice distintas acciones sobre l : Crear nodos. Copiar nodos (instanciarlos). Duplicar nodos. Mover nodos. Eliminar nodos. Arrastrar nodos. Mover / Copiar / Duplicar nodos entre distintas vistas del rbol. Posibilidad de copiar/mover/duplicar como: o Hijo. o Hermano superior. o Hermano inferior. Renombrar nodos.
Tambin tendremos que tener cuidado a la hora de manipular el grafo, evitando que el usuario pueda generar bucles o colgar nodos de otros donde no est permitido.
96
Deberemos intentar proporcionar al usuario las herramientas que mayor comodidad y flexibilidad puedan darle.
Necesitamos un sistema que nos permita cargar estos fragmentos de cdigo en la memoria de nuestro programa en tiempo de ejecucin. Para ello necesitaremos un interfaz comn que permita comunicarse a la aplicacin con todas estos plugins.
97
4.3 Anlisis.
98
Para el anlisis de este problema nos hemos basado en los Parameter Blocks (bloques de parmetros) que hemos explicado anteriormente que utiliza 3ds max, y los hemos adoptado, aunque de manera modificada y adaptada mas concretamente a nuestras necesidades.
Puesto que estamos trabajando con estructuras de datos relacionadas con la informtica grfica, deberemos dar soporte a los tipos bsicos de datos y adems otros ms especficos de este campo. Estos son: Entero Coma flotante Texto Booleano Enumeraciones Matrices Color Vector XYZ Vector XYZW Rango de Enteros Rango en coma flotante
99
Identificar de manera unvoca cada uno de los controles que se asocia a cada parmetro. Adems, este gestor ser el que se encargue de procesar los mensajes que genere Windows al manipular cada uno de los controles, y los pase a quien proceda.
En la figura 4.4 podemos apreciar en qu consistira el proceso de plasmar una estructura de datos Material , que contendra informacin sobre un material (tipo de color, color ambiental, difuso, especular y de emisin), en un grupo de parmetros utilizando descriptores de parmetros para obtener la salida por el interfaz de usuario.
Figura 4-2. Ejemplo de un proceso de parametrizacin de una estructura de datos mediante el gestor de parmetros.
Ya tenemos analizado un sistema que nos convierte automticamente grupos de parmetros en controles, y nos gestiona incluso su paso de mensajes. En la figura 4.4 anterior hemos parametrizado una estructura de datos Material, no obstante, no existe todava ningn mecanismo mediante el cual estos parmetros se modifiquen al modificarse en el interfaz o nos permitan consultar el valor de estos datos. Tenemos que relacionar ambas cosas de alguna manera. Aqu es donde surge el concepto de TabOutput, esta clase ser una clase virtual pura, que se deber implementar para cada tipo de dato que queramos poder parametrizar. Las funciones que deberemos implementar sern: Crear controles: en esta funcin deberemos indicar los grupos de parmetros que vamos a utilizar. Mostrar datos de la clase: Podremos establecer los valores de nuestra estructura de datos en los controles del interfaz.
100
Notificacin de evento modificado: Se invocar a esta funcin cuando un valor del interfaz sea modificado, de esta manera podremos actualizar los datos de nuestra estructura de datos.
Adems, nos deber proporcionar funciones para intercambiar datos con los controles. Estas funciones de asignar u obtener valores debern estar sobrecagadas para cada tipo de dato que soporten los Descriptores de parmetros. De esta manera, el proceso de la figura anterior quedara como se muestra en la figura 4.5.
Figura 4.3 Proceso de parametrizacin y utilizacin del gestor de parmetros para establecer y obtener valores, as como para su paso de mensajes.
Pero con esta estructura de datos TabOutput tan solo podemos indicar qu parmetros queremos que tenga nuestro descriptor de grupo para un tipo de datos en concreto, y podemos obtener notificacin de que los controles han sido manipulados, y obtener el valor actual del control manipulado, as como establecer su valor, pero todava no tenemos ninguna relacin que asocie automticamente todos estos controles con una instancia en particular del tipo de dato, para as actualizar su valor. En OpenSceneGraph existen 3 clases base que nos interesa diferenciar. Estas son: Object: Cualquier tipo de dato que no es ni Node ni StateAttribute. Node: Son los nodos que pertenecen al rbol. StateAttribute: Son los atributos que pueden tener los nodos y otros tipos de datos.
As pues, vamos a derivar 3 tipos de TabOutput: ObjectType, NodeType y AttributeType uno para cada tipo de clase respectivamente. Partiremos de ObjectType, puesto que Object es la clase base para todo objeto en OpenSceneGraph. Esta distincin nos interesa para poder asociar un objeto a los eventos al TabOutput, y tratar los datos en el interfaz de usuario de manera distinta, incluso para manejar algun tipo de evento concreto.
101
As por ejemplo, ObjectType nos servir para parametrizar objetos del tipo Object de OpenSceneGraph. Esta estructura tendr diferentes particularidades respecto a su predecesor TabOutput, estas son: Posibilidad de identificar su tipo de clase padre en el rbol de herencia. Esto permitir tan solo tener que parametrizar los elementos de una clase sin tener en cuenta su rbol de herencia. Si su padre est registrado como ObjectType y est parametrizado, entonces se mostrarn sus parmetros en la salida de interfaz de usuario, y as de manera recursiva hasta que no exista ms herencia. Esto nos ahorrar memoria, y mucho trabajo a la hora de implementar todos y cada uno de los tipos de Nodo, Atributo y Objeto, puesto que nos evitar tener que parametrizar de nuevo aquellos elementos de clases que ya hemos implementado anteriormente, por el hecho de tener parientes en comn. Posibilidad de vincular / desvincular otro ObjectType para poder tener acceso a sus datos y a su paso de eventos, de esta manera podremos manipular otros tipos de dato que pertenecen a un dato concreto. Podremos mostrar u ocultar la salida del ObjectType cuando nos convenga. Esto implica recibir notificaciones de eventos del ObjectType vinculado. Crear una nueva instancia del tipo de dato que estamos manejando. Esta caracterstica nos ofrecer gran flexibilidad a la hora de manipular datos de manera abstracta, y sin necesidad de tener que saber el tipo de objeto con el que estamos tratando. Notificacion de Fin de Seleccin: Esta nueva notificacin le llega al ObjectType que est siendo editado para indicar que el objeto va a dejar de ser mostrado, para mostrar en su lugar otro ObjectType distinto. Esto permite realizar ajustes de reset en la clase antes de que se muestre otra.
La clase NodeType y AttributeType solo diferirn de ObjectType en su constructor (para indicar que es un objeto tipo NodeType o AttributeType respectivamente). La clase AttributeType permite adems asignar el tipo de StateAttribute con el que estamos tratando. Ahora, cuando obtengamos una notificacin de que un parmetro ha sido modificado, obtendremos tambin un puntero a la instancia del elemento que estamos modificando, para que nosotros actualicemos el valor en funcin de nuestros requisitos. Esto no permitir desarrollar los tipos de objeto de una manera mucho ms rpida, y nos facilitar el posterior proceso de adaptacin a la arquitectura de plugins de la aplicacin.
102
StateAttributes : BlendFunc Fog FragmentProgram Light Material TexEnv TexGen Texture Texture2D
Objects necesarios, utilizados por los Nodes y StateAttributes: ConstantRateCounter Counter Drawable StateSet Geometry Particle ParticleSystem RandomRateCounter ShapeDrawable Text VariableRateCounter
103
Figura 4-5. Herencia de clases de una clase tipo Object, Node y StateAttribute de OpenSceneGraph.
Viendo la figura 4.7 muestra un ejemplo de la herencia de objetos en OpenSceneGraph. A la izquierda podemos ver por ejemplo la clase Geometry de OpenSceneGraph, que clasificaremos como ObjectType dentro de nuestro editor, que deriva de la clase Drawable. Si ahora queremos parametrizar esta clase, tan solo tendremos que hacerlo con los parametros propios de Geometry, e indicaremos en el constructor del ObjectType que el nombre de la clase padre es Drawable. Aqu entra en juego el gestor de ObjectTypes, comprobando que existe ya este tipo de objeto registrado y realizar una llamada a la funcin de mostrar datos al mostrar los de la clase Geometry.
104
La principal diferencia entre el rbol y el grafo de escena es que un nodo puede tener ms de un padre, la solucin a esto es representar el nodo en un rbol duplicando estas ramas tantas veces como padres tenga. Por tanto, deberemos indicar de alguna manera al usuario en el interfaz de usuario que un nodo est instanciado de manera mltiple.
Puesto que cada uno de los nodos del grafo puede estar representado en varios elementos del rbol (aunque solo est identificado con un solo nodo del grafo) necesitamos tener el grafo duplicado en nuestro editor, usando nuestra propia estructura de datos Nodo, que llamaremos TreeNodeInfo, y que contendr: Enlaces a sus padres y a sus hijos Enlaces a los distintos elementos del rbol (sus mltiples instancias). De esta manera sabremos inmediatamente las distintas instancias de un mismo nodo. Enlace a su nodo equivalente en el grafo de escena de OpenSceneGraph. Enlace al NodeType correspondiente a ese tipo de nodo.
Del mismo modo, cada elemento del rbol mantendr un puntero a su nodo del grafo del editor. Esto lo podemos ver reflejado en la figura 4.3.
Ya hemos analizado las estructuras de datos adecuadas para tener nuestro grafo de escena clonado y relacionado con su representacin de rbol, ahora necesitamos un mtodo que construya dicho grafo y dicho rbol. OpenSceneGraph define la clase NodeVisitor que nos permite recorrer completamente un grafo siguiendo ciertos criterios. En nuestro caso construiremos un NodeVisitor que recorra absolutamente todos los nodos del grafo es escena, guardando un vector con la informacin de cada uno de los nodos que hemos encontrado encapsulados en nuestra propia estructura de datos, y su relacin de sus padres e hijos. 1. Recorrer el grafo completamente y obtener informacin de todos sus nodos usando un NodeVisitor a la vez que vamos insertando elementos en el arbol. Esto es posible gracias a que NodeVisitor realiza un recorrido recursivo, siguiendo el orden de los nodos. 2. A partir de este vector de elementos obtenido asignamos los punteros apropiados a los padres y a los hijos, obteniendo asi una estructura de grafo (nuestro grafo clonado).
Figura 4-8. Diagrama de clases relacionado con la vista mltiple del grafo
MultiTreeBar nos debe permitir : Crear (clonar) una nueva imagen del rbol (TreeBar). Establecer y obtener el TreeBar activo. Establecer y obtener la escena activa. Obtener el nmero de TreeBar de cada rbol. Obtener el nmero de escenas de cada rbol. Copiar al portapapeles una rama de cualquier TreeBar. Pegar del portapapeles una rama de cualquier TreeBar sobre un nodo de cualquier otro.
Cabe aclarar una cosa, y es que tenemos que diferenciar entre escenas y TreeBars. Una escena identifica un grafo de escena, equivaldra a un TreeCtrl. Un TreeBar identifica un conjunto de 106
escenas, que, en caso de haber ms de una, sera imgenes clonadas las escenas de otra TreeBar. As pues, una escena puede estar clonada en varios TreeBars.
Figura 4-9. Ejemplo de MultiTreeBar para con dos escenas y tres vistas simultneas.
La figura 4.9 Muestra un grfico explicando la relacin de MultiTreeBar con TreeBar y las distintas escenas que puede contener en el editor.
Debemos aqu introducir dos conceptos que ya hemos utilizado: Nodo instanciado: Consiste en aadir un nodo a mltiples padres. Cuando un nodo tiene dos o ms padres lo denominaremos instanciado compartido. Si un nodo est instanciado, todo su subgrafo lo estar tambin. Puesto que cada padre comparte el mismo nodo, cualquier cambio hecho al nodo, ser apreciable del mismo modo por todos sus padres.
107
Nodo duplicado: consiste en duplicar el contenido del nodo, de manera que sea asignado a un solo padre. El contenido de cada uno de estos nodos duplicados ser independiente de los dems.
108
Enfocar a un objeto. Mover / Rotar la cmara usando el ratn. Mostrar la vista anterior y posterior de una escena. Mostrar la vista superior e inferior de una escena. Mostrar la vista izquierda y derecha de una escena. Mostrar una representacin en alambre de la escena. Mostrar una representacin slida de lo objetos. Mostrar un sombreado plano de la escena. Mostrar un sombreado suavizado de la escena.
Puesto que un objeto puede identificarse como mltiples instancias en un mismo nodo del grafo de escena, los objetos de la seleccin vendrn identificados por los distintos elementos del rbol que ocupen. Cuando pulsemos en pantalla para seleccionar un objeto, tendremos que hallar el nodo seleccionado del grafo. La clase IntersectVisitor de OpenSceneGraph nos da la posibilidad de hallar la interseccin de una linea con los distintos objetos de la escena. Esta clase nos devuelve una lista de los NodePath objetos intersectados en orden de proximidad al observador. Un NodePath es un vector de nodos, representando el camino que se ha seguido por el grafo desde la raz hasta llegar al un nodo descendiente, en este caso un nodo hoja. El NodePath es la manera que tiene OpenSceneGraph de identificar de manera nica un nodo instanciado. Por tanto, tendremos q crear un mtodo por el cual obtengamos un elemento del rbol a partir del NodePath del grafo de escena.
109
De esta manera se agiliza a la hora de realizar transformaciones sobre uno o dos ejes simultneamente. Este eje se mostrar siempre en el centro de la seleccin, y ser el gestor de seleccin el encargado de actualizarlo.
Figura 4-11. Eje manipulador en 3ds max (conocido como translate guizmo).
110
Figura 4-12. Creacin automatica de la Matriz de Transformacin para la seleccin de objetos. 1. Tenemos dos objetos sin nimguna matriz de transformacion. 2. Seleccionamos la piramide, entonces se crear una matriz de transformacion como su padre (MT1). 3. Copiamos el cubo como hijo de este nodo MT1. 4. Al seleccionar el cubo, comprobamos que existe una Matriz de Transformacion como padre del mismo, pero no es el nico hijo, por tanto repetimos la misma operacin que en el paso 2. Y lo mismo ocurrir cuando seleccionemos la pirmide.
1. Partimos de un punto de la pantalla que representa la posicin actual del puntero del ratn, este punto representar el punto donde queremos desplazar el objeto. 2. Debemos convertir ese punto en una lnea en el espacio 3D 3. Hallamos un plano imaginario en funcin de los ejes que estamos modificando, que pase por el centro del objeto que queremos modificar.
111
4. Hallaremos la interseccin de esa lnea con el plano imaginario que acabamos de calcular, obteniendo un punto en el espacio 3D. 5. Moveremos el objeto seleccionado hasta ese punto. De esta manera el usuario tendr la sensacin de estar moviendo el objeto exactamente donde quiere. En la figura 4-13 podemos ver una imagen que representa visualmente el algoritmo explicado.
Figura 4-13. Clculo de la posicin 3D de un objeto en el plano ZY en funcin de las coordenadas de pantalla.
112
Adems, todas las funciones de copiado de nodos, que se realizan de manera recursiva, tendrian que ser modificadas, complicandose bastante. La otra solucin que ser la que adoptemos, consistir en dividir la raiz del grafo de escena en dos grupos, el primero ser el grupo de datos auxiliares, de donde colgar toda la informacin que necesitemos para representar datos auxiliares, y en otro grupo que ser l grafo de escena que el usuario ver. Por tanto, el editor, en lugar de mostrar el grafo entero en la vista del rbol, mostrar solo el nodo de la escena, que ser el que contenga todos los datos que est manipulando el usuario. La figura 4-14 muestra la estructura que tomar el grafo para esta segunda solucin.
Usaremos este trmino para referirnos al conjunto de comandos o modificaciones en los datos de nuestra aplicacin que se realizan agrupados como uno solo, es decir, de manera nica e indivisible. Por ejemplo, mover un objeto puede ser una accin, pero mover 15 objetos simultneamente es tambin una accin indivisible, aunque internamente implique realizar 15 movimientos de distintos objetos. Sabiendo esto, crearemos una clase virtual pura con las siguientes funciones virtuales puras: Ejecutar: Aqu ir el cdigo que ejecute de manera indivisible la accin. Obtener el nombre de la accin: devolver una cadena con el nombre representativo de la accin. Deshacer: Aqu ir el cdigo que invierta la accin ejecutada.
113
El gestor de Historia
Ser el encargado de almacenar las acciones, ejecutarlas, deshacerlas y/o rehacerlas. Esta clase deber mantener un puntero a la posicin actual de la historia.
LibNumClasses(): Devuelve el numero de clases que hay implementadas dentro del plugin. LibClassInstance(i): Devuelve una instancia de la clase i-sima que hemos implementado. LibDescription(): Devuelve una cadena descriptiva sobre la DLL. LibVersion(): Constante que identifique la version del editor sobre la que se ha realizado el plugin, esto permitir al editor identificar plugins obsoletos. Aqu no necesitamos implementar la funcion DllMain() que usaba 3ds max, puesto que estamos creando DLLs de MFC y esta se realiza internamente.
El gestor de plugins
Es el encargado de cargar los plugins del directorio de plugins. Se encarga de establecer la comunicacin con la DLL, comprobar su versin, y obtener una instancia de cada una de las clases implementadas, almacenandola segn su nombre, y guardando una asociacion al manejador de la DLL de la cual proviene, y procesndolas para mandarlas al Gestor del tipo de clase apropiado segn su tipo. La figura 4-15 ilustra grficamente el funcionamiento del gestor de plugins.
114
115
o o o o o o o o
Inicializar los ObjectTypes, Nodetypes y AttributeTypes iniciales en la aplicacin. Inicializar los plugins. Inicializar las ventanas dockables de la aplicacin. Inicializar el rbol. Insertar nodos en el arbol Copiar nodos del arbol Ejecutar una accin Mostrar la informacin de un Nodo del grafo.
En la figura 4-16 se puede ver un dibujo que representa la funcionalidad del manejador de vista activa (Active View Handler).
116
Nombre funcin
Iniciar aplicacin Iniciar Barras Crear barra de paneles de comandos Iniciar Tipos de objeto Registrar un TabOutput Registrar un ObjectType Mapear los grupos de parmetros de un TabOutput Cargar Plugins Cerrar aplicacin Cerrar TreeBar Cerrar Escena Cargar Escena Establecer un grafo sobre un elemento del rbol Replicar una escena de una TreeBar a otra Clonar un TreeCtrl a partir de otro Nueva Escena Crear grafo por defecto Nuevo rbol Insertar fichero Cambiar escena activa Deshacer Rehacer Crear Nodo Crear un nodo segn el nombre de su NodeType Crear nueva instancia de un nodo segn su nombre Seleccionar elemento en rbol Seleccionar todas las instancias de un elemento Seleccionar todos los mirrors de un elemento Mostrar la informacin de un nodo Crear los dilogos de un TabOutput Crear un dialogo a partir de un grupo de parmetros Generar el contenido de un TabOutput Vaciar el contenido de un TabOutput Notificar fin de seleccin de un ObjectType Mostrar los datos de un TabOutput Seleccionar nodo en visor Agregar nodo a la seleccin del visor Crear Matriz de Transformacin como padre de un nodo
Categora
Evidente Oculta Oculta Oculta Oculta Oculta Oculta Oculta Evidente Evidente Evidente Evidente Oculta Oculta Oculta Evidente Oculta Evidente Evidente Evidente Evidente Evidente Evidente Oculta Oculta Evidente Oculta Oculta Evidente Oculta Oculta Oculta Oculta Oculta Oculta Evidente Evidente Oculta
F.1 F.1.1 F.1.2 F.1.3 F.1.4 F.1.5 F.1.6 F.1.7 F.2 F.2.1 F.3 F.4 F.4.1 F.4.2 F.4.3 F.5 F.5.1 F.6 F.7 F.8 F.9 F.10 F.11 F.11.1 F.11.2 F.12 F.12.1 F.12.2 F.12.3 F.12.4 F.12.5 F.12.6 F.12.7 F.12.8 F.12.9 F.13 F.13.1 F.13.2
117
F.13.3 F.13.4 F.14 F.14.1 F.15 F.16 F.16 F.17 F.18 F.19 F.20 F.21 F.22 F.23 F.24 F.24.1 F.24.2 F.24.3 F.25 F.25.1 F.25.2 F.25.3 F.26 F.26.1 F.26.2 F.26.3 F.27 F.28 F.29 F.30 F.31 F.32 F.33 F.34 F.34.1 F.34.2 F.35 F.36 F.37 F.38 F.39 F.40 F.41 F.42 F.43 F.44 F.45 F.46
Actualizar la seleccin Actualizar el eje manipulador Copiar nodo Replicar seleccin Mover nodo Duplicar nodo Duplicar seleccin Eliminar nodo Activar modo seleccin Activar modo traslacin de objetos Activar modo escalado de objetos Activar modo rotacin objetos Activar modo rotar vista Activar modo trasladar vista Escalar seleccin Comenzar escalado de seleccin Realizar escalado de seleccin Finalizar escalado de seleccin Rotar seleccin Comenzar rotacin de seleccin Realizar rotacin de seleccin Finalizar rotacin de seleccin Trasladar seleccin Comenzar traslacin de seleccin Realizar traslacin de seleccin Finalizar traslacin de seleccin Centrar vista en seleccin Modificar el zoom de la vista Aadir StateAttribute a StateSet Eliminar un StateAttribute de un StateSet Aadir un Modo a un StateSet Eliminar un Modo de un StateSet Modificar un Modo de un StateSet Modificar parmetro de un control del panel de comandos Establecer el valor de un parmetro Obtener el valor de un parmetro Establecer el contenido del portapapeles Pegar el contenido del portapapeles Visualizar escena en modo de alambre Visualizar escena en modo relleno Visualizar sombreado en modo plano Visualizar sombreado en modo suavizado Mostrar vista superior de la escena Mostrar vista inferior de la escena Mostrar vista anterior de la escena Mostrar vista posterior de la escena Mostrar vista lateral izquierda de la escena Mostrar vista lateral derecha de la escena
Oculta Oculta Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Oculta Oculta Oculta Evidente Oculta Oculta Oculta Evidente Oculta Oculta Oculta Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Oculta Oculta Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente Evidente
118
F.1
Caso de uso: Actores: Tipo: Descripcin:
Iniciar la aplicacin. Inicio Usuario. Evidente. Se realiza esta funcin o secuencia de funciones, cuando el usuario arranca la aplicacin, la cual iniciar el nico objeto global de la aplicacin (ActiveViewHandler), y generar una vista vaca, la cual iniciar los datos del grafo por defecto. Cuando el ActiveViewHandler arranque iniciar todos los gestores de la aplicacin, se crearan las barras de herramientas (la principal y la de creacin de nodos) iniciar la barra principal de paneles de comandos y el rbol que contendr la representacin del grafo, y adems iniciar los tipos de datos que soporta la aplicacin aadindolos a sus respectivos gestores. Es en esta fase donde se realizar tambin la carga de los plugins.
F.1.1
Caso de uso: Actores: Tipo: Descripcin:
Iniciar Barras. Inicio Usuario. Oculta. Esta es la funcin que invoca al iniciar la aplicacin, crea la barra principal que contiene los paneles de comandos, la barra de depuracin, y el rbol del grafo de escena.
F.1.2
Caso de uso: Actores: Tipo: Descripcin:
Crear barra de paneles de comandos. Inicio Usuario. Oculta. Esta funcin es invocada por la funcin de iniciar las barras. En concreto inicia el panel principal de comandos que consta de cinco pestaas, cada una con una funcionalidad caracterstica en la aplicacin, asignando un icono representativo a cada una de ellas. Inicialmente el contenido de estas pginas ser propertysheets vacos,
119
que mas adelante sern rellenados con dilogos desplegables q sern los que contendrn los controles.
F.1.3
Caso de uso: Actores: Tipo: Descripcin:
Iniciar tipos de objeto. Inicio Usuario. Oculta. En esta funcin se crean las instancias de los TabOutput iniciales, entre los que se encuentra el panel de plugins, los cuales se cargan al iniciarse, as como los tipos de objeto soportados por el editor, los tipos de nodo y los StateAttributes.
F.1.4
Caso de uso: Actores: Tipo: Descripcin:
Registrar un TabOutput. Inicio Usuario. Oculta. Esta funcin registra un objeto tipo TabOutput en la aplicacin. Esta funcin aade a sus tablas internas la referencia a esta nueva instancia a registrar, y la indexa por su nombre, y por ultimo realiza una llamada a la funcin de mapeo de los grupos de parmetros que tenga el objeto.
F.1.5
Caso de uso: Actores: Tipo: Descripcin:
Registrar un ObjectType. Inicio Usuario. Oculta. Esta funcin registra un objeto tipo ObjectType en la aplicacin. Aade a sus tablas internas la referencia a esta nueva instancia a registrar, y la indexa por su nombre, adems averigua el ObjectType de su padre (si lo tiene) y le asigna el enlace pertinente. Por ultimo realiza una llamada a la funcin de mapeo de los grupos de parmetros que tenga el objeto.
F.1.6
Caso de uso:
120
Usuario. Oculta. Esta funcin se invoca al registrar un TabOutput, ObjectType, NodeType o AtributeType. Realiza la llamada a la creacin de los grupos de parmetros del TabOutput en cuestin. Una vez hecha, se mapea en la tablas hash el id de cada uno de sus descriptores de los grupos de parmetros asociando como clave en descriptor en s. De esta manera tenemos una tabla hash que asocia Ids de parmetros con sus respectivos descriptores.
F.1.7
Caso de uso: Actores: Tipo: Descripcin:
Cargar Plugins. Inicio Usuario. Oculta. Al iniciar la aplicacin se realiza una llamada a Iniciar los tipos de objeto, entre ellos los TabOutput con los que cuenta la aplicacin inicialmente. Uno de ellos es el creador de nodos, disponible en la primera pestaa, y otro es la pestaa de visualizacin de plugins. Este TabOutput es quien, al iniciar, realiza el escaneo del directorio de plugins, el gestor de plugins los guarda en sus tablas y se encarga de cargarlos en memoria, una vez cargados, los objetos que contiene cada plugin las distribuye entre sus distintos gestores de elementos, segn su tipo.
F.2
Caso de uso: Actores: Tipo: Descripcin:
Cerrar aplicacin. Cerrar aplicacin Usuario. Evidente. Al cerrar la aplicacin se realizan llamadas a Cerrar para todos los TreeBar del programa. Puesto que cada TreeBar contiene el rbol del grafo de escena de una o varias escenas, se cierran estas escenas, que implican liberar sus recursos, as como se vaca toda la historia de todas las escenas. Del mismo modo, se liberan todos los recursos adquiridos por la librera OpenSceneGraph.
121
F.2.1
Caso de uso: Actores: Tipo: Descripcin:
Cerrar treebar Cerrar aplicacin Usuario. Oculta Al cerrar un nico TreeBar tendremos que liberar tan solo la memoria referente a los mirror de las escenas actuales. Dado que la TreeBar que estamos cerrando no es ms que una copia de la original, todas sus escenas lo son, por tanto, deberemos eliminar tan solo las referencias que contiene cada nodo del grafo de la aplicacin a los HTREEITEMS correspondientes, puesto que ya no van a existir ms. Por ultimo, deberemos eliminarla de la lista de MultiTreeBar
F.3
Caso de uso: Actores: Tipo: Descripcin:
Cerrar escena. Cerrar escena Usuario. Evidente. Esta funcin se invoca al cerrar una vista de la escena. Por tanto, deberemos vaciar la seleccin actual, liberar los recursos de la escena de OpenSceneGraph que todava queden sin liberar, vaciar la historia de esta escena (cada escena tiene su propia historia). Al cerrar la escena se debern eliminar todos los rboles de esta escena pertenecientes a cada una de las TreeBar, as como limpiar cualquier informacin de el ltimo nodo que se seleccion y pueda estar representado en pantalla para evitar que el usuario intente modificarlo despus de haberse liberado de la memoria.
F.4
Caso de uso: Actores: Tipo: Descripcin:
Cargar escena. Cargar escena Usuario. Evidente. Cargar una escena implica seleccionar un fichero del disco duro. Una vez hecho, se realizar la carga del fichero mediante las funciones que proporciona OpenSceneGraph de carga de ficheros. Seguidamente se iniciar un grafo por defecto para colgar esta informacin. El grafo no deber ser el fichero en s, puesto que el editor necesita ms elementos para visualizar de manera axiliar. Por tanto, el grafo inicial estar dividido en dos ramas principales, la primera ser la escena donde colgaremos el fichero que acabamos de cargar, y en la segunda
122
almacenaremos aquellos nodos que nos sern tiles en el editor para manipular otros nodos, como puede ser el eje manipulador, las cajas de seleccin de objetos, e incluso la rejilla. Una vez hecho esto, deberemos aadir una nueva escena al editor, esto implica crear nuestro propio grafo de escena (copia del de OpenSceneGraph), y aadir un nuevo control de rbol en cada una de las TreeBar, clonando su contenido tantas veces como sea necesario. Tambin aqu ser donde inicialicemos los datos de la seleccin, y el StateSet global, que nos servir para cambiar el modo de visualizacin de la escena.
F.4.1
Caso de uso: Actores: Tipo: Descripcin:
Establecer un grafo sobre un elemento del rbol. Cargar escena Usuario. Oculta. Permite establecer un grafo colgando de un elemento de un rbol. Este elemento puede ser la raz del rbol, por lo que el rbol no debe necesariamente contener algn elemento. Esta funcin internamente establece el grafo de escena sobre una de las vistas del rbol (suponiendo que haya varias simultneas) y realiza rplicas del mismo sobre las dems. Para recorrer el grafo y construir el rbol se utiliza la estructura NodeVisitor proporcionada por OpenSceneGraph que nos permite seguir un orden en los nodos del grafo, de esta manera iremos construyendo el subrbol sobre el rbol que queremos y completando nuestro grafo interno. Esta funcin solo permitir insertar nodos dentro del elemento que queramos, si este elemento pertenece a un nodo derivado de la clase Group de OpenSceneGraph.
F.4.2
Caso de uso: Actores: Tipo: Descripcin:
Replicar una escena de una TreeBar a otra. Cargar escena Usuario. Oculta. Una escena identifica un grafo de escena. En una sola TreeBar puede haber varias escenas distintas, cada una de ellas esta representada mediante un rbol. Por tanto, replicar una escena desde un TreeBar a otro consistir en clonar el rbol. A la vez que se clona el contenido del rbol, se deber de aadir la informacin necesaria al grafo de escena del editor para identificar los elementos del rbol por sus nodos. Esto se realizar con la ayuda de un NodeVisitor.
123
F.4.3
Caso de uso: Actores: Tipo: Descripcin:
Clonar un TreeCtrl a partir de otro. Cargar escena Usuario. Oculta. Esta funcin clona un rbol a partir de otro. Este rbol puede ser clonado solo a partir de una rama del rbol origen, en cuyo caso, su padre deber existir en el rbol destino como tem equivalente o mirror. La replica o clonacin se realiza elemento a elemento, respetando el orden de los nodos, y actualizando los datos de los nodos del grafo del editor, puesto que el grafo del editor contiene enlaces a los tems de las distintas instancias del nodo en el rbol, as como sus distintos mirrors.
F.5
Caso de uso: Actores: Tipo: Descripcin:
Nueva escena. Nueva escena Usuario. Evidente. Cuando el usuario desea crear una nueva escena vaca puede pulsar sobre el botn de nueva escena o acceder al men y crear una nueva escena. Es entonces cuando se inician las estructuras de datos necesarias para una escena (al igual que al cargar una escena). Se iniciar un grafo por defecto para colgar esta informacin. Una vez hecho esto, deberemos aadir una nueva escena al editor. Esto implica crear nuestro propio grafo de escena (copia del de OpenSceneGraph), y aadir un nuevo control de rbol en cada una de las TreeBar, clonando su contenido tantas veces como sea necesario. Tambin aqu ser donde inicialicemos los datos de la seleccin, y el StateSet global, que nos servir para cambiar el modo de visualizacin de la escena.
F.5.1
Caso de uso: Actores: Tipo: Descripcin:
Crear grafo por defecto. Nueva escena Usuario. Oculto. El grafo no deber ser la escena en s, puesto que el editor necesita ms elementos para visualizar de manera axiliar. Por tanto, el grafo inicial (raz) estar dividido en dos ramas principales, la primera ser la escena que vamos a crear, y en la segunda colgaremos aquellos nodos que nos
124
sern tiles en el editor para manipular otros nodos, como puede ser el eje manipulador, las cajas de seleccin de objetos, e incluso la rejilla.
F.6
Caso de uso: Actores: Tipo: Descripcin:
Nuevo rbol. Nuevo rbol Usuario. Evidente. Esta funcin se invoca cuando el usuario desea crear una nueva vista de rbol que representa el grafo de escena. Lo que esta funcin hace es crear una nueva TreeBar, inicialmente vaca, y replicar todos y cada uno de las escenas que contiene esta TreeBar en la que acabamos de crear. La funcin para replicar esto ya la hemos analizado en F.4.2.
F.7
Caso de uso: Actores: Tipo: Descripcin:
Insertar fichero. Insertar Fichero Usuario. Evidente. Cuando el usuario desea colgar de una rama un grafo completo, almacenado en el disco duro, entonces se invocar esta funcin. El usuario seleccionar del disco duro un fichero compatible con la aplicacin, que dar paso a un sub-grafo de escena, que colgar del nodo seleccionado actualmente en el rbol. Esto se consigue con una simple llamada a F4.1 ya que nos permite establecer un grafo sobre cualquier elemento de un rbol.
F.8
Caso de uso: Actores: Tipo: Descripcin:
Cambiar escena activa. Cambiar Escena Activa Usuario. Evidente. Se produce esta llamada a esta funcin cuando el usuario realiza un cambio de la escena activa, ya sea mediante alguna combinacin del teclado o usando el men de seleccin de ventanas. Al cambiar de escena activa se deben de actualizar las referencias la superficie de render, la historia actual, el grafo de escena y los datos de la seleccin, puesto que son independientes en cada escena, y cada escena tiene las suyas.
125
F.9
Caso de uso: Actores: Tipo: Descripcin:
Deshacer. Deshacer Usuario. Evidente. El usuario realiza esta accin cuando quiere deshacer la ltima accin ejecutada. El gestor de historia ser en encargado de realizar la llamada a deshacer sobre la ltima accin y de retroceder el cursor de posicin sobre la historia.
F.10
Caso de uso: Actores: Tipo: Descripcin:
Rehacer. Rehacer Usuario. Evidente. El usuario realiza esta accin cuando quiere rehacer la ltima accin deshecha. El gestor de historia ser en encargado de realizar la llamada a rehacer sobre la ltima accin y de avanzar el cursor de posicin sobre la historia.
F.11
Caso de uso: Actores: Tipo: Descripcin:
Crear Nodo. Crear Nodo Usuario. Evidente. El usuario podr crear un nodo sobre el elemento que est actualmente seleccionado en el rbol del grafo de escena, seleccionndolo desde una lista de nodos del panel de comandos, o pulsando un botn en forma de icono que identifica tal nodo.
F.11.1
Caso de uso: Actores:
126
Tipo: Descripcin:
Oculta. Esta funcin se invoca desde el caso de uso anterior. Al seleccionar el tipo de nodo, el Gestor de nodos busca un NodeType con el nombre especificado, y llama a la funcin que devuelva una nueva instancia del tipo de nodo que devuelve en NodeType en cuestin. Este nodo deberemos aadirlo al grafo de escena del editor y de OpenSceneGraph, as como aadirlo a todas las vistas que haya abiertas en el editor y aadir la informacin necesaria en las tablas de ndices de las estructuras de datos del grafo y de los rboles.
F.11.2
Caso de uso: Actores: Tipo: Descripcin:
Crear una nueva instancia de un nodo segn su nombre. Crear Nodo Usuario. Oculta. Cada NodeType debe de tener implementada la funcin NewInstance, que debe de devolver una nueva instancia del tipo de nodo que est representando. Cuando el gestor de NodeTypes quiere obtener una nueva instancia de un tipo de nodo a partir de su nombre (por ejemplo cuando el usuario quiere crear un tipo de nodo al seleccionarlo de la lista, por su nombre), busca entre sus ndices si existe el NodeType segn el nombre, y en ese caso, invoca a la funcin NewInstance, que devolver el objeto deseado.
F.12
Caso de uso: Actores: Tipo: Descripcin:
Seleccionar elemento en rbol. Seleccionar elemento en rbol Usuario. Evidente. Un usuario puede seleccionar un tem del rbol tan solo pulsando sobre l para mostrar sus propiedades. Al seleccionar un elemento del rbol el editor tiene acceso directamente al tem del rbol seleccionado. Puesto que el rbol mantiene una correspondencia de cada tem con su nodo del grafo del editor, podremos saber qu nodo, y en consecuencia qu tipo de nodo (NodeType) hemos seleccionado. Es entonces cuando marcaremos en cierto color todas las instancias de ese mismo nodo, y en rojo las equivalencias de esas mismas instancias en los dems TreeBars. Adems, ya disponiendo del tipo de nodo que estamos tratando, pasaremos a visualizar en el panel de comandos, todos los grupos de parmetros asociados a ese tipo de nodo, ocultando previamente los del nodo anteriormente seleccionado, y rellenaremos la informacin de salida con la informacin del nodo en cuestin.
127
F.12.1
Caso de uso: Actores: Tipo: Descripcin:
Seleccionar todas las instancias de un elemento. Seleccionar elemento en rbol Usuario. Evidente. Esta funcion simplemente sirve como ayuda visual para que el usuario pueda identificar de una manera sencilla e intuitiva las distintas instancias del rbol que pertenecen a un mismo nodo. De esta manera el usuario ser consciente de que cualquier parmetro que modifique de este elemento del rbol, afectar a todas sus instancias, que podr apreciar marcadas de distinto color.
F.12.2
Caso de uso: Actores: Tipo: Descripcin:
Seleccionar todos los mirrors de un elemento. Seleccionar elemento en rbol Usuario. Evidente. Esta funcin simplemente sirve como ayuda visual para que el usuario pueda identificar de una manera sencilla e intuitiva la correspondencia de un elemento de un rbol con su equivalente en las dems vistas del mismo rbol.
F.12.3
Caso de uso: Actores: Tipo: Descripcin:
Mostrar la informacin de un nodo Seleccionar elemento en rbol Usuario. Evidente. Esta funcin se invoca cuando hemos seleccionado un nodo del rbol. Para mostrar la informacin de un nodo necesitamos su NodeType. Una vez adquiridos ambos, podemos comenzar a mostrar la salida. Si es la primera vez que un NodeType se muestra, se realiza la llamada a generar sus dilogos en tiempo real. Esto se hace para intentar ahorrar recursos y no crear aquellos dilogos que no se lleguen a utilizar durante la ejecucin del programa. Si exista algn NodeType anterior mostrado, y distinto al actual, entonces lo ocultamos y mostramos el nuestro. Al mostrar el NodeType mostraremos de manera recursiva el contenido de los controles de este, y el de su padre, de manera que el pare siempre se muestre por encima de su hijo. Del mismo nodo, si hemos cambiado el NodeType deberemos lanzar una notificacin de fin
128
de seleccin, y por ltimo, rellenaremos los controles con los datos del nodo que queremos mostrar.
F.12.4
Caso de uso: Actores: Tipo: Descripcin:
Crear los dilogos de un TabOutput Seleccionar elemento en rbol Usuario. Oculta. Como hemos comentado en F12.3 la primera vez que se llama a mostrar un NodeType se crean dinmicamente los dilogos que contendrn los controles que mostrarn los datos del nodo. Esta funcin es recursiva y se llamar del mismo modo sobre su tipo padre, si as lo requiere. Para ello, se accede al vector del grupo de parmetros que debe de contener el NodeType por la funcin 1.6. Este vector contiene informacin de los distintos grupos o agrupaciones de parmetros que puede tener un nodo. Normalmente solo tendr un grupo, podr indicar de manera opcional en que pestaa del panel de comandos aparecer, y cada grupo estar compuesto por un conjunto de descriptores de parmetros. Por tanto, para cada grupo crearemos un dilogo que ir contenido dentro de lo que llamaremos una pgina desplegable (o Rollup Page, puesto que tendr un botn que permitir plegar o desplegar el contenido del dilogo) que se mostrar en alguna de las pestaas del panel de comandos.
F.12.5
Caso de uso: Actores: Tipo: Descripcin:
Crear un dilogo a partir de un grupo de parmetros Seleccionar elemento en rbol Usuario. Oculta. Esta funcin se invoca al crear los dilogos de un TabOutput. Cada uno de los grupos de parmetros que forman un TabOutput est formado a su vez por un conjunto de descriptores de parmetros. Cada uno de estos descriptores contendr informacin sobre cada uno de los controles que deber contener el dilogo que se va a construir dinmicamente. Entre esta informacin encontraremos, el nombre del control, el tipo de control, y si es editable o no, por ejemplo. Por tanto, en cada tipo de descriptor realizaremos una llamada distinta para crear un tipo de control distinto. Por ltimo, realizaremos una ltimos ajustes a los controles, como por ejemplo ajustar el numero mximo de caracteres en los campos de texto, o si deshabilitaremos el control inicialmente en caso de que as lo indique el descriptor.
129
F.12.6
Caso de uso: Actores: Tipo: Descripcin:
Generar el contenido de un TabOutput Seleccionar elemento en rbol Usuario. Oculta. Esta funcin es invocada directamente por la funcin de mostrar un TabOutput. Cuando hablamos del contenido, hablamos del contenido final que aparecer en el interfaz, mas concretamente sobre el panel de comandos. Consiste en generar una pgina desplegable o Rollup a partir de un dilogo ya generado. Una vez hecho esto, el dilogo estar contenido en un deplegable que el usuario podr plegar siempre que quiera tan solo pulsando un botn, para ahorrar espacio en el interfaz, y desplegar cuando quiera mostrar su contenido de nuevo.
F.12.7
Caso de uso: Actores: Tipo: Descripcin:
Vaciar el contenido de un TabOutput Seleccionar elemento en rbol Usuario. Oculta. Es la funcin inversa a la anterior. Suele invocarse cuando queremos limpiar la salida del panel de comandos, bien para dejarlo vaco, bien para dar paso a generar el contenido de otro TabOutput. Esta llamada desvincula el dilogo que identifica en grupo de parmetros del Rollup en el que est contenido, pero no destruye en dilogo que hemos creado de la memoria.
F.12.8
Caso de uso: Actores: Tipo: Descripcin:
Notificar fin de seleccin de un ObjectType Seleccionar elemento en rbol Usuario. Oculta. El ObjectType tiene la particularidad de que es notificado cuando su contenido que est actualmente siendo mostrado por pantalla va a ser eliminado y sustituido por otro, ya sea del mismo tipo o de un tipo distinto, pero de contenido distinto. Esta funcin se invoca de manera recursiva, de modo que la notificacin llegar tanto el ObjectType como a sus precedentes en la jerarqua de herencia que se haya establecido. Esta notificacin se realiza para que el desarrollador de ObjectTypes pueda realizar los ajustes que crea convenientes al ser consciente de que el objeto va a dejar de editarse.
130
F.12.9
Caso de uso: Actores: Tipo: Descripcin:
Mostrar los datos de un TabOutput Seleccionar elemento en rbol Usuario. Oculta. Esta es la funcin culminante en el proceso de mostrar el contenido de un nodo. Al igual que las anteriores, si se trata de un ObjectType se realiza de manera recursiva en caso de tener un tipo de padre. Esta funcin es la que realizar la llamada a la funcin que implemente el desarrollador para mostrar los datos del nodo. El comportamiento de tal funcin depender de la implementacin que el desarrollador haya dado al TabOutput o el ObjectType.
F.13
Caso de uso: Actores: Tipo: Descripcin:
Seleccionar nodo en el visor Seleccionar nodo en el visor Usuario. Evidente. Se llama a esta funcin cuando queremos seleccionar un nodo en el visor. Este nodo, generalmente un Geode, se puede seleccionar pulsando directamente sobre el elemento en la pantalla, o seleccionndolo en el rbol e indicando explcitamente que queremos seleccionarlo en el visor. Al seleccionar un objeto del visor tendremos que generar una informacin del objeto seleccionado, y crear una caja de seleccin que nos indique la posicin del objeto y el rea que ocupa. Este objeto que contiene informacin de seleccin se aadir a una lista, que consistir en una lista de las informaciones de todos los objetos seleccionados. Puesto que se trata de una seleccin nica, deberemos previamente vaciar la seleccin existente.
F.13.1
Caso de uso: Actores: Tipo: Descripcin:
Agregar nodo a la seleccin del visor Seleccionar nodo en el visor Usuario. Evidente. Esta funcin es equivalente a la anterior, solo que en este caso, en lugar de seleccionar solo el elemento que queremos, lo aadiremos a la seleccin actual.
131
F.13.2
Caso de uso: Actores: Tipo: Descripcin:
Crear Matriz de Transformacin como padre de un nodo. Seleccionar nodo en el visor Usuario. Oculta. Esta funcin se llama automticamente al seleccionar un objeto. La razn de ello es que al seleccionar un objeto, el usuario est indicando en cierto modo su intencin de aplicarle alguna transformacin. Esta transformacin solo se puede llevar a cabo sobre una Matriz de Transformacin que contenga al nodo como uno de sus descendientes. Por tanto, lo que har esta funcin ser comprobar si existe una matriz de transformacin como padre del nodo, y adems, que esa transformacin solo tenga a ese nodo como hijo. En caso contrario, creamos un nuevo nodo tipo Matriz de Transformacin y lo intercalamos entre el nodo que queremos transformar y su padre actual.
F.13.3
Caso de uso: Actores: Tipo: Descripcin:
Actualizar la seleccin. Seleccionar nodo en el visor Usuario. Oculta. Lo que esta funcin hace realmente es actualizar el cursor segn su posicin, o el eje manipulador, adems del estado del cursor. El estado del cursor define si el cursor est encima de algn objeto, o encima de algn otro elemento, como puede ser el eje manipulador. En primer lugar se comprueba si existe algn objeto seleccionado en la escena, en ese caso sabremos que el eje manipulador estar mostrado por tanto obtenemos si existe alguna colisin del cursor con tal eje. Si el cursor no esta encima de ningn elemento del eje manipulador entonces se comprueba si existe colisin con alguno de los objetos, actualizando el cursor y el estado del cursor en funcin de si el eje est o no seleccionado, y de la transformacin que estemos llevando a cabo.
F.13.4
Caso de uso: Actores: Tipo:
132
Descripcin:
Esta funcin realiza las mismas comprobaciones que la anterior, pero nicamente comprueba si existe alguna interseccin del cursor del ratn con el eje manipulador, obteniendo exactamente con qu elemento del eje intersecciona y actualizando el estado del mismo, y su apariencia (por ejemplo, resaltando con ms brillo el eje o el plano que estamos seleccionando en el eje manipulador). De esta manera podremos consultar en cualquier momento qu ejes se encuentran seleccionados en cada momento.
F.14
Caso de uso: Actores: Tipo: Descripcin:
Copiar nodo. Copiar nodo Usuario. Evidente. Esta funcin se encarga de copiar un elemento del rbol a otro elemento destino. Este nodo se podr copiar como hijo del nodo destino o como hermano del nodo destino. Adems, el elemento podr copiarse desde un rbol hasta otro distinto, siempre que pertenezcan al mismo grafo. En esta aplicacin, cuando hablamos de copiar un elemento, lo que realmente estaremos haciendo ser instanciarlo, es decir, crearemos una nueva instancia en el rbol, y en el grafo lo que nicamente haremos ser aadir un nuevo padre al nodo que estamos copiando. Esta misma operacin deber repetirse (excepto la modificacin la vinculacin de los elementos del grafo) para todas las vistas que existan duplicadas del rbol del grafo de escena.
F.14.1
Caso de uso: Actores: Tipo: Descripcin:
Replicar seleccin. Copiar nodo Usuario. Evidente. Realiza una rplica del nodo haciendo uso de la funcin copiar nodo, creando su propia matriz de transformacin y desplazando el objeto una distancia respecto del objeto a copiar y tomando como nodo padre el mismo nodo padre del nodo origen.
F.15
Caso de uso: Actores: Tipo:
133
Descripcin:
Esta funcin es exactamente igual que la anterior, con la nica diferencia que despus de copiar el nodo, el nodo origen se elimina, tanto del rbol, como el enlace de su padre.
F.16
Caso de uso: Actores: Tipo: Descripcin:
Duplicar Nodo. Duplicar nodo Usuario. Evidente. Al igual que la funcin Copiar Nodo, esta funcin se encarga de copiar un elemento del rbol a otro elemento destino. Este nodo se podr copiar como hijo del nodo destino o como hermano del nodo destino. En esta ocasin usamos el termino Duplicar, para decir que no vamos a instanciar el nodo, sino que vamos a duplicar por completo el nodo y todos sus descendientes, de manera que la rama que hayamos duplicado ser complemente independiente de la rama origen y cualquier modificacin sobre cualquier nodo de cualquier elemento duplicado no tendr ningn efecto sobre los originales. El procedimiento es el mismo, solo que al copiar los elementos del rbol, adems, copiaremos los elementos del grafo tambin (en el caso de copiar nodo, tan solo agregbamos un padre ms). Duplicar Seleccion. Duplicar nodo Usuario. Evidente. Realiza una rplica del nodo haciendo uso de la funcin duplicar nodo, creando su propia matriz de transformacin y desplazando el objeto una distancia respecto del objeto a duplicar y tomando como nodo padre el mismo nodo padre del nodo origen.
F.16.1
Caso de uso: Actores: Tipo: Descripcin:
F.17
Caso de uso: Actores: Tipo: Descripcin:
Eliminar nodo. Eliminar nodo Usuario. Evidente. Esta funcin elimina un elemento o instancia de un elemento del grafo. Para ello deber deseleccionarlo del visor en caso de que se encuentre seleccionado, y eliminarlo de todas las vistas de rbol que haya abiertas. Adems deber actualizar la informacin del grafo del editor puesto que contiene referencias a los tems del rbol, eliminando las referencias
134
que debamos. Si hemos eliminado todas las distintas instancias de un nodo, y ya no quedan referencias a l, entonces el nodo del grafo podr ser desvinculado.
F.18
Caso de uso: Actores: Tipo: Descripcin:
Activar modo seleccin. Activar modo seleccin Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de seleccin de objetos. En este modo simplemente podr seleccionar objetos en el visor, sin aplicarles ningn tipo de transformacin.
F.19
Caso de uso: Actores: Tipo: Descripcin:
Activar modo traslacin de objetos. Activar modo traslacin de objetos Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de traslacin de objetos. Cuando este modo est activado el usuario podr aplicar transformaciones de traslacin sobre todos los objetos seleccionados en pantalla.
F.20
Caso de uso: Actores: Tipo: Descripcin:
Activar modo escalado de objetos. Activar modo escalado de objetos Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de escalado de objetos. Cuando este modo est activado el usuario podr aplicar transformaciones de escalado sobre todos los objetos seleccionados en pantalla.
135
F.21
Caso de uso: Actores: Tipo: Descripcin:
Activar modo rotacin de objetos. Activar modo rotacin de objetos Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de rotacin de objetos. Cuando este modo est activado el usuario podr aplicar transformaciones de rotacin sobre todos los objetos seleccionados en pantalla.
F.22
Caso de uso: Actores: Tipo: Descripcin:
Activar modo rotar vista. Activar modo rotar vista Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de rotar la vista. Cuando este modo est activado el usuario podr girar la vista como desee para visualizar cualquier objeto en pantalla.
F.23
Caso de uso: Actores: Tipo: Descripcin:
Activar modo trasladar vista. Activar modo trasladar vista Usuario. Evidente. Se invoca esta funcin cuando el usuario quiere activar el modo de trasladar la vista. Cuando este modo est activado el usuario podr trasladar la vista como desee para visualizar cualquier objeto en pantalla.
F.24
Caso de uso: Actores: Tipo:
136
Descripcin:
Cuando hablamos de seleccin, nos referimos a un conjunto de nodos. Por tanto no es ms que repetir la misma operacin para cada uno de los nodos. Esta funcin realiza una transformacin de escalado sobre un objeto. Para ello, el objeto debe de cumplir ciertos requisitos, en primer lugar debe de ser un Geode, y en segundo lugar su padre debe de ser una matriz de transformacin pero de ello ya nos hemos asegurado al seleccionar el objeto. Esta funcin realmente se divide en tres sub-funciones, el comienzo, el transcurso y el final.
F.24.1
Caso de uso: Actores: Tipo: Descripcin:
Comenzar escalado de seleccin. Escalar seleccin Usuario. Oculta. Es como el Setup o la puesta a punto del escalado. Se llama a esta funcin para realizar los ajustes o actualizaciones necesarias o consultar los datos necesarios para prepararse para comenzar la transformacin. Por ejemplo, aqu recalcularemos la BoundingBox de la seleccin y deberemos guardar la posicin del centro geomtrico de la seleccin, lo cual nos servir mas adelante para almacenar correctamente la transformacin como una funcin invertible.
F.24.2
Caso de uso: Actores: Tipo: Descripcin:
Realizar escalado de seleccin. Escalar seleccin Usuario. Oculta. Esta es la funcin que realiza el escalado, aunque realmente la accin no se podr considerar como terminada hasta que soltemos el ratn. En este paso se aplica la misma transformacin a todos los objetos de la seleccin en funcin del desplazamiento del cursor sobre la pantalla, y siempre aplicndola sobre el centro geomtrico de cada objeto colocado en el origen de coordenadas. Una vez hecho esto, deberemos tambin actualizar las cajas de seleccin de los objetos seleccionados, puesto que las transformaciones deben afectarles por igual, as como actualizar su BoundingBox y la posicin del eje manipulador.
137
F.24.3
Caso de uso: Actores: Tipo: Descripcin:
Finalizar escalado de seleccin. Escalar seleccin Usuario. Oculta. Este es el paso que da por finalizado el escalado de la seleccin. Es aqu donde se actualiza la informacin de la seleccin, como por ejemplo los valores de las matrices auxiliares que se utilizan para almacenar informacin que luego servirn para almacenar la accin invertible de la transformacin. Tambin aqu actualizaremos la BoundingBox de la seleccin y actualizaremos la posicin del eje manipulador.
F.25
Caso de uso: Actores: Tipo: Descripcin:
Rotar seleccin. Rotar seleccin Usuario. Evidente. Cuando hablamos de seleccin, nos referimos a un conjunto de nodos. Por tanto no es ms que repetir la misma operacin para cada uno de los nodos. Esta funcin realiza una transformacin de rotacin sobre un objeto. Para ello, el objeto debe de cumplir ciertos requisitos, en primer lugar debe de ser un Geode, y en segundo lugar su padre debe de ser una matriz de transformacin pero de ello ya nos hemos asegurado al seleccionar el objeto. Esta funcin realmente se divide en tres sub-funciones, el comienzo, el transcurso y el final.
F.25.1
Caso de uso: Actores: Tipo: Descripcin:
Comenzar rotacin de seleccin. Rotar seleccin Usuario. Oculta. Es como el Setup o la puesta a punto de la rotacin. Se llama a esta funcin para realizar los ajustes o actualizaciones necesarias o consultar los datos necesarios para prepararse para comenzar la transformacin. Por ejemplo, aqu recalcularemos la BoundingBox de la seleccin y deberemos guardar la posicin del centro geomtrico de la seleccin, lo cual nos servir mas adelante para almacenar correctamente la transformacin como una funcin invertible.
138
F.25.2
Caso de uso: Actores: Tipo: Descripcin:
Realizar rotacin de seleccin. Rotar seleccin Usuario. Oculta. Esta es la funcin que realiza la rotacin, aunque realmente la accin no se podr considerar como terminada hasta que soltemos el ratn. En este paso se aplica la misma transformacin a todos los objetos de la seleccin en funcin del desplazamiento del cursor sobre la pantalla, y siempre aplicndola sobre el centro geomtrico de cada objeto colocado en el origen de coordenadas. Una vez hecho esto, deberemos tambin actualizar las cajas de seleccin de los objetos seleccionados, puesto que las transformaciones deben afectarles por igual, as como actualizar su BoundingBox y la posicin del eje manipulador.
F.25.3
Caso de uso: Actores: Tipo: Descripcin:
Finalizar rotacin de seleccin. Rotar seleccin Usuario. Oculta. Este es el paso que da por finalizada la rotacin de la seleccin. Es aqu donde se actualiza la informacin de la seleccin, como por ejemplo los valores de las matrices auxiliares que se utilizan para almacenar informacin que luego servirn para almacenar la accin invertible de la transformacin. Tambin aqu actualizaremos la BoundingBox de la seleccin y actualizaremos la posicin del eje manipulador.
F.26
Caso de uso: Actores: Tipo: Descripcin:
Trasladar seleccin. Trasladar seleccin Usuario. Evidente. Cuando hablamos de seleccin, nos referimos a un conjunto de nodos. Por tanto no es ms que repetir la misma operacin para cada uno de los nodos. Esta funcin realiza una transformacin de traslacin sobre un objeto. Para ello, el objeto debe de cumplir ciertos requisitos, en primer lugar debe de ser un Geode, y en segundo lugar su padre debe de ser una matriz de transformacin pero de ello ya nos hemos asegurado al seleccionar el objeto.
139
F.26.1
Caso de uso: Actores: Tipo: Descripcin:
Comenzar traslacin de seleccin. Trasladar seleccin Usuario. Oculta. Es como el Setup o la puesta a punto de la traslacin. Se llama a esta funcin para realizar los ajustes o actualizaciones necesarias o consultar los datos necesarios para prepararse para comenzar la transformacin. Por ejemplo, aqu recalcularemos la BoundingBox de la seleccin y deberemos guardar la posicin del centro geomtrico de la seleccin, lo cual nos servir mas adelante para almacenar correctamente la transformacin como una funcin invertible.
F.26.2
Caso de uso: Actores: Tipo: Descripcin:
Realizar traslacin de seleccin. Trasladar seleccin Usuario. Oculta. Esta es la funcin que realiza la traslacin, aunque realmente la accin no se podr considerar como terminada hasta que soltemos el ratn. En este paso se aplica la misma transformacin a todos los objetos de la seleccin en funcin del desplazamiento del cursor sobre la pantalla. Esta transformacin tiene la particularidad de que requiere algunos clculos extraordinarios para calcular el incremento que vamos a aplicar a la traslacin, ya que calcularemos un plano imaginario que sea paralelo al plano seleccionado en el eje manipulador, y que pase por el centro de la seleccin, de esta manera, intersectando una lnea imaginaria desde el cursor hacia este plano obtendremos el punto donde queremos desplazar el objeto, y as calcularemos el incremento a aplicar como traslacin. Una vez hecho esto, deberemos tambin actualizar las cajas de seleccin de los objetos seleccionados, puesto que las transformaciones deben afectarles por igual, as como actualizar su BoundingBox y la posicin del eje manipulador.
F.26.3
Caso de uso:
140
Usuario. Oculta. Este es el paso que da por finalizada la traslacin de la seleccin. Es aqu donde se actualiza la informacin de la seleccin, como por ejemplo los valores de las matrices auxiliares que se utilizan para almacenar informacin que luego servirn para almacenar la accin invertible de la transformacin. Tambin aqu actualizaremos la BoundingBox de la seleccin y actualizaremos la posicin del eje manipulador.
F.27
Caso de uso: Actores: Tipo: Descripcin:
Centrar la vista en la seleccin. Centrar la vista en la seleccin Usuario. Evidente. Cuando el usuario quiera visualizar un objeto en el centro geomtrico de la pantalla, podr hacer uso de esta opcin. Esta funcin tan solo hace que la cmara enfoque al centro geomtrico de la seleccin actual.
F.28
Caso de uso: Actores: Tipo: Descripcin:
Modificar el zoom de la vista. Centrar la vista en la seleccin Usuario. Evidente. Esta funcin permite acercar o alejar la cmara o visor de su foco.
F.29
Caso de uso: Actores: Tipo: Descripcin:
Aadir un StateAttribute a un StateSet. Aadir un StateAttribute a un StateSet Usuario. Evidente. Esta funcin permite aadir un StateAttibute a un StateSet de un nodo del grafo de escena. El usuario deber seleccionar el StateAttribute de la lista de StateAttributes que la aplicacin soporte. Esta lista se obtiene del gestor de objetos, y es el mismo gestor de objetos el que devolver una nueva instancia del StateAttribute que elijamos.
141
F.30
Caso de uso: Actores: Tipo: Descripcin:
Eliminar un StateAttibute de un StateSet. Eliminar un StateAttribute de un StateSet Usuario. Evidente. Si el usuario as lo desea, podr eliminar los StateAttributes del StateSet de un nodo, seleccionando de la lista aquel que quiera. Del mismo modo, dispondremos del nombre del StateAttribute a eliminar, y el gestor de ObjectTypes nos devolver el tipo de StateAttribute, lo cual nos permitir directamente eliminarlo del StateSet.
F.31
Caso de uso: Actores: Tipo: Descripcin:
Aadir un Modo a un StateSet. Aadir un Modo a un StateSet Usuario. Evidente. Esta funcin permite aadir un Modo a un StateSet de un nodo del grafo de escena. El usuario deber seleccionar el Modo de la lista de Modos que la aplicacin soporte. Esta lista de modos est relacionada con los modos que OpenGL soporta.
F.32
Caso de uso: Actores: Tipo: Descripcin:
Eliminar un Modo de un StateSet. Aadir un Modo a un StateSet Usuario. Evidente. Esta funcin permite eliminar un Modo o un valor del Modo de un StateSet de un nodo del grafo de escena. El usuario deber seleccionar el Modo de la lista de Modos que el StateSet tenga actualmente.
F.33
Caso de uso: Actores: Tipo:
142
Descripcin:
El modo de un StateSet es una mscara que puede contener varios flags, por tanto un usuario podr aadir o eliminar estos flags a un modo ya existente de un StateSet.
F.34
Caso de uso: Actores: Tipo: Descripcin:
Modificar el parmetro de un control del panel de comandos. Modificar el parmetro de un control del panel de comandos Usuario. Evidente. Cuando un usuario manipula alguno de los controles del panel de comandos donde aparecen los grupos de parmetros referentes a un nodo, a un objeto, o incluso un TabOutput, se realiza una llamada interna, que hace que se modifiquen algunos valores (por ejemplo, un spinner con un descriptor tipo float asociado har que al pulsar la flecha superior recoja el contenido de la caja de texto asociada al spinner e incremente en una dcima su valor) y despus se realice una llamada a la notificacin de parmetro modificado. De esta manera el desarrollador de TabOutputs podr hacer las gestiones necesarias para modificar la estructura de datos asociada.
F.34.1
Caso de uso: Actores: Tipo: Descripcin:
Establecer el valor de un parmetro. Modificar el parmetro de un control del panel de comandos Usuario. Oculta. El desarrollador de TabOutputs podr establecer una interaccin con los controles asociados a los grupos de parmetros y forzar a establecer los valores que debern contener los controles. Para ello se dispondr de una funcin que permitir establecer ciertos tipos de datos conocidos por el desarrollador y soportados por la aplicacin en los controles de los paneles de comandos.
F.34.2
Caso de uso: Actores: Tipo: Descripcin:
Establecer el valor de un parmetro. Modificar el parmetro de un control del panel de comandos Usuario. Oculta. El desarrollador de TabOutputs podr establecer una interaccin con los controles asociados a los grupos de parmetros y obtener en cualquier momento el valor que el control est almacenando, guardndolo en una 143
estructura de datos conocida por el desarrollador. Para ello se dispondr de una funcin que permitir acceder a estos valores segn el identificador del parmetro que el desarrollador habr asignado previamente.
F.35
Caso de uso: Actores: Tipo: Descripcin:
Establecer el contenido del portapapeles. Establecer el contenido del portapapeles Usuario. Evidente. Al seleccionar elementos del rbol podremos copiarlos y pegarlos en el portapapeles del propio editor. Dependiendo de la operacin que llevemos a cabo, la operacin de pegar podr realizarse como una operacin de mover, copiar o de duplicar. Por tanto al realizar cualquier operacin de portapapeles almacenaremos el tipo de operacin de copia, y el nodo, o conjunto de nodos afectados.
F.36
Caso de uso: Actores: Tipo: Descripcin:
Pegar el contenido del portapapeles. Establecer el contenido del portapapeles Usuario. Evidente. Sabiendo la operacin previa almacenada en el portapapeles, sabremos que tipo de operacin tendremos que llevar a cabo al pegar. Puesto que tenemos un listado de items origen, y tenemos seleccionado el tem destino, podremos levar a cabo la operacin que proceda. Si la operacin del portapapeles era de copia, llevaremos a cabo la operacin de copia, si era una operacin de movimiento, llevaremos a cabo la operacin de movimiento de nodos, y si era una operacin de duplicado, duplicaremos la lista de nodos seleccionados sobre el item destino. Visualizar escena en modo de alambre. Visualizar escena en modo de alambre Usuario. Evidente. Visualiza la informacion geomtrica de la escena en modo de rejilla de alambre.
F.37
Caso de uso: Actores: Tipo: Descripcin:
144
F.38
Caso de uso: Actores: Tipo: Descripcin:
Visualizar escena en modo de relleno. Visualizar escena en modo de relleno Usuario. Evidente. Visualiza la informacion geomtrica de la escena en modo relleno.
F.39
Caso de uso: Actores: Tipo: Descripcin:
Visualizar sombreado en modo plano. Visualizar sombreado en modo plano Usuario. Evidente. Visualiza la escena en modo de sombreado plano.
F.40
Caso de uso: Actores: Tipo: Descripcin:
Visualizar sombreado en modo suavizado. Visualizar escena en modo suavizado Usuario. Evidente. Visualiza la escena en modo de sombreado suavizado.
F.41
Caso de uso: Actores: Tipo: Descripcin:
Mostrar vista superior de la escena. Mostrar vista superior de la escena Usuario. Evidente. Visualiza la escena desde un punto superior al centro de la seleccin actual.
F.42
Caso de uso: Actores:
145
Tipo: Descripcin:
F.43
Caso de uso: Actores: Tipo: Descripcin:
Mostrar vista anterior de la escena. Mostrar vista anterior de la escena Usuario. Evidente. Visualiza la escena desde un punto anterior al centro de la seleccin actual
F.44
Caso de uso: Actores: Tipo: Descripcin:
Mostrar vista posterior de la escena. Mostrar vista posterior de la escena Usuario. Evidente. Visualiza la escena desde un punto posterior al centro de la seleccin actual Mostrar vista lateral izquierda de la escena. Mostrar vista lateral izquierda de la escena Usuario. Evidente. Visualiza la escena desde un punto lateral izquierdo al centro de la seleccin actual
F.45
Caso de uso: Actores: Tipo: Descripcin:
F.46
Caso de uso: Actores: Tipo: Descripcin:
Mostrar vista lateral derecha de la escena. Mostrar vista lateral derecha de la escena Usuario. Evidente. Visualiza la escena desde un punto lateral derecho al centro de la seleccin actual
146
147
148
149
CASO DE USO: Iniciar Accin de los Actores 1. El usuario arranca la aplicacion. Respuesta del sistema 2. La aplicacin crea una vista y el objeto global ActiveViewHandler que su vez inicia los gestores de objetos, nodos, parametros, etc. y registra los tipos de datos que los gestores contendrn inicialmente. 3. Se crea el grafo inicial, conteniendo los datos auxiliares como la rejilla o el eje manipulador. 4. Se Inician las estructuras de datos necesarias para iniciar una escena en OpenSceneGraph. 5. Se crea la barra de herramientas de creacion de nodos, la barra de depuracin y la barra de paneles de comandos.
150
6. Se crea un nuevo rbol para representar el grafo inicial. 7. Se establece le pasa el nodo raiz del grafo al arbol para que se inicie la representacin en rbol del nodo. 8. Se inician los TabOutput y se muestra su contenido en el panel de comandos. 9. Se cargan los plugins del programa, que a su vez registran los objetos de los plugins en sus respectivos gestores.
CASO DE USO: Nueva Escena Accin de los Actores 1. El usuario decide iniciar una nueva escena en el editor pulsando el botn apropiado o seleccionando la opcion desde el men principal. Respuesta del sistema 2. La aplicacin crea una nueva vista. Al iniciar la vista se crea el grafo inicial de la aplicacin, conteniendo los datos auxiliares necesarios, como la rejilla o el eje manipulador, y un nodo de seleccin de objetos donde colgarn las cajas de seleccin de los mismos. 3. Se Inician las estructuras de datos necesarias para iniciar una escena en OpenSceneGraph. 5. Se crea una nueva escena vaca en la Barra de rbol (sin grafo asociado), agregando por tanto un nuevo rbol para representar el grafo inicial. Este arbol deber ser replicado tantas veces como vistas existan abiertas en la aplicacin. 6. Se establece esta escena como la escena activa. 8. Se inicia un nuevo objeto de seleccin con el eje manipulador. 9. Se establece la raz de la representacin en rbol de la escena como el nodo raz de nuestro grafo inicial.
CASO DE USO: Finalizar aplicacin Accin de los Actores Respuesta del sistema
151
2. La aplicacin realiza una llamada a cerrar todas las TreeBar. 3. Esto provoca que se libere la informacion de cada una de las escenas que cada TreeBar almacena, y que se vace la historia de la escena. 3. Se liberan los recursos OSG de cada escena. 4. Se libera la memoria almacenada por los controles de windows usados para representar el rbol.
CASO DE USO: Modificar un parmetro Accin de los Actores 1. El usuario interacta con algun control del panel de comandos, por ejemplo de los parmetros de un nodo del grafo de escena pulsando sobre la flecha superior de un Spinner. Respuesta del sistema 2. La aplicacin envia una notificacin al Gestor de parmetros para avisarle de que un control ha sido modificado o pulsado. 3. El gestor de parmetros comprueba si la notificacion pertenece a algn parmetro existente en sus tablas y en ese caso se le envia la notificacin al ObjectType asociado a tal control. 4. Del mismo modo, se comprueba si el ObjectType est siendo adjuntado por algun otro ObjectType y en caso afirmativo enva tal notificacin al adjuntador.
CASO DE USO: Seleccionar un objeto en el visor Accin de los Actores 1. El usuario coloca el cursor sobre un objeto del visor y pulsa el botn para seleccionar el objeto. Respuesta del sistema 2. La aplicacin recoje la notificacion de pulsacin del ratn y se la pasa al objeto seleccin. 3. El objeto seleccin obtiene la interseccin del ratn con la escena, para comprobar sobre qu est el cursor. 4. Puesto que el cursor est encima de un objeto y no est seleccionado vamos a crear una nueva accion de cambio de seleccin, por tanto guardaremos en dos tablas los datos de la seleccin para pasarlas como argumentos
152
de la nueva accion. De esta manera el sistema dispondr de la informacin necesaria para deshacer la accin que acabamos de llevar a cabo. 5. Ejecutamos la accin. El gestor de historia almacenar la accin internamente. 6. Actualizamos el eje manipulador, posicionandolo en el centro de la seleccin.
CASO DE USO: Insertar un fichero Accin de los Actores 1. El usuario decide insertar un fichero como hijo del nodo seleccionado en el rbol. 3. El usuario elige el fichero que quiere aadir a la escena. Respuesta del sistema 2. El sistema muestra un dilogo de seleccin de archivos. 4. Mediante funciones propias de OpenSceneGraph cargamos el fichero, obteniendo el nodo raiz del grafo de escena del fichero. 4. Obtenemos el objeto seleccionado actualmente en el rbol y comprobamos si su nodo asociado es un nodo que permita contener hijos, en caso de que no se pueda, no se puede llevar a cabo la operacin y no hacemos nada. 5. Establecemos el grafo como hijo del nodo que tenemos seleccionado en el rbol. Para ello se deber recorrer el nuevo grafo, creando para cada nodo los tems necesarios en el rbol. 6. Por ltimo, deberemos crear una rplica de la nueva rama generada en todas las dems vistas del rbol que haya abiertas.
CASO DE USO: Nuevo rbol Accin de los Actores 1. El usuario pulsa el botn de visualizar nuevo rbol en la barra de herramientas, o selecciona la opcin del men principal. Respuesta del sistema 2. El objeto que gestiona todas las TreeBar, crea una nueva ventana que contendr los distintos rboles de las distintas escenas. 3. El gestor de las TreeBar aade esta nueva barra a sus ndices.
153
4. Se aade una nueva escena a la nueva TreeBar, por cada escena de las que ya existen. La escena representa el control de rbol en si. 5. Se realiza una rplica de cada una de las escenas (es decir, del rbol completo de cada una de las escenas) en la nueva TreeBar.
CASO DE USO: Crear Nodo Accin de los Actores 1. El usuario selecciona un elemento del rbol, preferiblemente un tem que est asociado a un nodo que admita tener hijos (derivado de Group). 2. El usuario selecciona el primer panel de comandos, y selecciona un elemento de la lista de nodos disponibles en la aplicacin. 3. El usuario pulsa sobre Crear Como Hijo 7. El gestor de nodos busca un NodeType entre sus ndices segn el nombre indicado, y obtiene una nueva instancia de la clase OpenSceneGraph que soporta el NodeType obtenido. 8. ActiveViewHandler crea un nuevo nodo del editor y le asocia el nodo OpenSceneGraph que acaba de crear. 9. ActiveViewHandler crea una nueva accion CrearNodo y la ejecuta. 10. Al ejecutar la nueva accin se crea el elemento del rbol y se aade la informacion necesaria en el nodo del editor. Respuesta del sistema 4. El TabOutput obtiene el nombre del nodo seleccionado de la lista de seleccin. 5. El TabOutput consulta el item seleccionado actualmente en el rbol. 6. Se invoca al ActiveViewHandler para crear un nodo a partir de su nombre, especificando el padre del cual deber colgar.
CASO DE USO: Deshacer Accin de los Actores 1. El usuario realiza una accin el en editor, por ejemplo desplazar un objeto en la pantalla. 2. El usuario decide deshacer esta accin pulsando en el botn Deshacer. Respuesta del sistema 3. La vista activa realiza una llamada a Undo del gestor de historia. 4. El gestor de historia realiza una llamada a la funcion Undo de la accin y retrocede la posicion del ndice de la ltima accion ejecutada.
154
5. La vista activa obtiene el item actualmente seleccionado, y actualiza la salida del interfaz.
CASO DE USO: Rehacer Accin de los Actores 1. El usuario deshace una accin. 2. El usuario decide que no queria deshacer esa accion y pulsa en el boton Rehacer para recuperarla. Respuesta del sistema 3. La vista activa realiza una llamada a Redo del gestor de historia. 4. El gestor de historia realiza una llamada a la funcion Redo de la accin y avanza la posicion del ndice de la ltima accion ejecutada. 5. La vista activa obtiene el item actualmente seleccionado, y actualiza la salida del interfaz.
CASO DE USO: Seleccionar un item del arbol Accin de los Actores 1. El usuario pulsa sobre un tem del rbol. Respuesta del sistema 2. Se seleccionan en negrita todas las instancias del mismo item, es decir, aquellos elementos del rbol que se identifiquen con el mismo nodo del grafo de escena. 3. Se seleccionan en otro color los items equivalentes al que acabamos de seleccionar en las dems vistas de rbol que existan abiertas. 4. Se pide al ActiveViewHandler que muestre la informacin del nodo asociado al tem que hemos seleccionado.
5. Para ello, si es la primera vez que se va a mostrar ese tipo de nodo, se crean dinmicamente los dilogos que contendran los parmetros del nodo. 6. Seguidamente, se ocultar cualquier contenido de cualquier nodo anterior en caso de existir. 7. Se mostrarn los dilogos de este tipo de nodo y se mostrar el contenido de los datos del nodo en los controles que acabamos de mostrar.
155
8. Almacenaremos este nodo como el ltimo nodo mostrado y como nodo actualmente seleccionado.
CASO DE USO: Seleccionar un elemento del rbol en el visor Accin de los Actores 1. El usuario pulsa sobre un tem o varios items del rbol y lo selecciona. 2. El usuario pulsa el boton derecho sobre tal seleccin y elige la opcion de Seleccionar en visor. Respuesta del sistema 3. El rbol obtiene la lista de los items seleccionados, sin sus descendientes. 4. Puesto que los elementos seleccionados pueden pertenecer a cualquier vista, para cada uno de los elementos seleccionados hallamos su equivalente en el rbol principal. 5. Se comprueba si los items cumplen la condicion de la Matriz de Transformacin padre, y en caso de que sea necesario, creamos tal matriz.
6. Se crea una nueva accion de cambio de seleccin con la seleccin anterior y la posterior. 7. Se le pasa la accion a ActiveViewHandler para ejecutarla.
CASO DE USO: Seleccionar un elemento del visor en el rbol Accin de los Actores 1. El usuario realiza un doble click sobre elemento del visor 3D. Respuesta del sistema 2. El sistema comprueba si existe algn elemento seleccionado. Para este caso se podra deducir que solo habr un elemento seleccionado, por tanto tan solo obtendremos el primero de la lista. 3. El rbol selecciona el elemento en todos los arboles, asi como sus instancias. 4. El ActiveView Handler muestra la informacin del nodo del mismo modo que en el caso de uso Seleccionar un tem del rbol.
156
Accin de los Actores 1. El usuario arrastra un item del rbol y lo suelta dentro de otro manteniendo pulsada la tecla CTRL.
Respuesta del sistema 2. El rbol sobre el que estamos realizando la operacin dispone de dos referencias a dos items, el item que estamos arrastrando y el item sobre el que hemos soltado. Por tanto obtiene el nodo del editor asociado a cada uno de estos items y comprueba que el nodo destino no sea descendiente del nodo origen para que no se produzcan bucles. 3. El rbol obtiene el ndice que ocupa en la lista de TreeBars para obtener el ndice la instancia del item que vamos a mover, y del item destino. 4. Para cada una de las rplicas del rbol existentes realizamos la copia de los items desde el origen hacia el destino, y solamente en la primera de las iteraciones, realizamos tambien la copia del nodo del grafo del editor.
CASO DE USO: Mover un nodo Accin de los Actores 1. El usuario arrastra un item del rbol y lo suelta dentro de otro manteniendo pulsada la tecla CTRL. Respuesta del sistema 2. El rbol sobre el que estamos realizando la operacin dispone de dos referencias a dos items, el item que estamos arrastrando y el item sobre el que hemos soltado. Por tanto obtiene el nodo del editor asociado a cada uno de estos items y comprueba que el nodo destino no sea descendiente del nodo origen para que no se produzcan bucles. 3. El rbol obtiene el ndice que ocupa en la lista de TreeBars para obtener el ndice la instancia del item que vamos a mover, y del item destino. 4. Para cada una de las rplicas del rbol existentes realizamos la copia de los items desde el origen hacia el destino, y solamente en la primera de las iteraciones, realizamos tambien la copia del nodo del grafo del editor. 5. Se realiza una llamada Eliminar Nodo sobre el elemento origen (el que habiamos arrastrado).
157
Accin de los Actores 1. Copia al portapapeles un item del rbol utilizando la combinacin de teclas CTRL+D. 2. El usuario posiciona la seleccin sobre otro item y utiliza la combinacion de teclas CTRL+V para pegar el nodo.
Respuesta del sistema 2. El rbol sobre el que estamos realizando la operacin dispone de dos referencias a dos items, el item que estamos arrastrando y el item sobre el que hemos soltado. Por tanto obtiene el nodo del editor asociado a cada uno de estos items y comprueba que el nodo destino no sea descendiente del nodo origen para que no se produzcan bucles. 3. El rbol obtiene el ndice que ocupa en la lista de TreeBars para obtener el ndice la instancia del item que vamos a mover, y del item destino. 4. Para cada una de las rplicas del rbol existentes realizamos la copia de los items desde el origen hacia el destino. Adems, en el primero de los rboles, en cada item del rbol que recorramos, crearemos una nueva instancia de copia del elemento haciendo uso del gestor de nodos, y enlazando estos nuevos nodos tanto en el grafo del editor como en el grafo de OpenSceneGraph.
CASO DE USO: Trasladar una seleccin Accin de los Actores 1. Con el modo trasladar activo, y con uno o ms objetos seleccionados, el usuario coloca el cursor sobre alguno de estos objetos seleccionados o sobre el eje manipulador y realiza una pulsacin del botn izquierdo del ratn, sin llegar a soltarlo. 6. Con el botn izquierdo pulsado, comenzamos a arrastrar la seleccin por el visor. 14. El usuario suelta el botn izquierdo del ratn. Respuesta del sistema 2. Se realiza una llamada a Comenzar Traslacin. En ella se calcula la normal al plano seleccionado en el eje manipulador y se almacena en una variable. 3. Se actualiza el centro de la seleccin actual y se obtiene en una variable. 4. Se calcula la interseccin de la linea imaginaria que formara una linea que atravesase perpendicularmente la pantalla pasando por la posicion del cursor y el plano imaginario que formara el plano del eje manipulador con centro en el centro de la seleccin. 5. Se guarda el punto de interseccion en una variable que nos servir de referencia para calcular el posterior incremento de la traslacin. 7. Se obtiene la normal del plano seleccionado en el eje manipulador.
158
8. Igual que antes, calculamos el punto de interseccion del cursor con el plano imaginario cuya normal hemos calculado en el paso anterior. 9. Se calcula el incremento restando la posicion calculada en el punto 5 a la posicion de la inserseccin actual. 10. Para cada uno de los elementos de la seleccin construimos una matriz de traslacin que se multiplicar a la actual matriz de transformacin. 11. Se actualiza el centro de la seleccin. 12. Se actualiza la posicin del eje manipulador en funcin del centro de la seleccin. 13. Se actualiza la BoundingBox de la seleccin. 15. Se almacena un vector de informacin de los elementos seleccionados. 16. Para cada uno de los objetos de informacin de seleccion, se actualiza el valor de la matriz de transformacin guardada. 17. Se crea una nueva accin de modificacin de transformacin, almacenando los valores anteriores y posteriores de las matrices.
CASO DE USO: Eliminar un nodo Accin de los Actores 1. El usuario pulsa sobre un tem o varios items del rbol y los selecciona. 2. El usuario pulsa el boton suprimir del teclado. Respuesta del sistema 3. El rbol obtiene la lista de los items seleccionados, sin sus descendientes. 4. Puesto que los elementos seleccionados pueden pertenecer a cualquier vista, para cada uno de los elementos seleccionados hallamos su equivalente en el rbol principal y los almacenamos en un vector. 5. Se crea una nueva accin de Borrar Items, donde se indican en una lista los items a eliminar y se ejecuta. 6. La ejecucin de esta accin consiste en
159
obtener el elemento del grafo de cada item que queremos eliminar para guardar su referencia en caso de un Redo, y eliminar los items de todos sus descendientes en el rbol.
CASO DE USO: Aadir un StateAttribute a un StateSet de un nodo Accin de los Actores 1. El usuario pulsa el botn Aadir StateAttribute del tercer panel de comandos del (panel de StateSet), habiendo ya un nodo seleccionado en el rbol. 3. El usuario pulsa aceptar en el dilogo de confirmacin. 5. El usuario elegir un nombre de un StateAttribute y pulsar Aceptar. Respuesta del sistema 2. En este caso, el nodo no contendr ningun StateSet por tanto se preguntar al usuario si desea crear uno mediante un dilogo de confirmacin. 4. Aparecer otro dilogo con el listado de los nombres StateAttributes que estn registrados en el sistema, obteniendolos del gestor de Objetos. 6. Se comprobar que este StateAttribute no exista ya en este StateSet. 7. Se obtendr una nueva instancia del StateAttribute, pidiendosela al gestor de Objetos. 8. Se crear una nueva accin de Agregar StateAttribute que agregar esta nueva instancia del StateAttribute al StateSet del nodo seleccionado actualmente.
CASO DE USO: Aadir un Modo a un StateSet de un nodo Accin de los Actores 1. El usuario pulsa el botn Aadir Modo del tercer panel de comandos del (panel de StateSet), habiendo ya un nodo seleccionado en el rbol. 3. El usuario elegir un nombre de un Modo y pulsar Aceptar. Respuesta del sistema 2. Aparecer un dilogo con el listado de los nombres de los Modos que estn registrados en el sistema. Este listado ser un listado esttico puesto que est relacionado con los modos que soporta OpenGL. 4. Se crear un nuevo valor por defecto para el modo. 5. Se crear una nueva accin de Agregar Modo que agregar este nuevo modo al StateSet del nodo seleccionado actualmente.
160
Accin de los Actores 1. El usuario pulsa el botn Aadir Modo del tercer panel de comandos del (panel de StateSet), habiendo ya un nodo seleccionado en el rbol. 3. El usuario elegir un nombre de un Modo y pulsar Aceptar.
Respuesta del sistema 2. Aparecer un dilogo con el listado de los nombres de los Modos que estn registrados en el sistema. Este listado ser un listado esttico puesto que est relacionado con los modos que soporta OpenGL. 4. Puesto que el modo ya existe, y tiene un valor o ms de flag asignado, lo que haremos ser obtener el valor de esta mascara y aadir un nuevo flag, que ser el flag por defecto. 5. Obtendremos una lista de los flags que existen ahora en modo, y regeneraremos el listado de modos del StateSet. 6. Se crear una nueva accin de Modificar Modo que establecer un nuevo valor de la mscara de un modo de un StateSet.
CASO DE USO: Modificar un Modo de un StateSet de un nodo (Opcion 2) Accin de los Actores 1. El usuario selecciona uno de los comboboxes que acompaana a cada uno de los nombres de los modos que contiene el StateSet y modifica su valor. Respuesta del sistema 2. Puesto que el modo ya tiene un valor o ms de flag asignado, lo que haremos ser obtener el valor de esta mascara. 3. Crearemos un nuevo valor de mscara, , eliminando el flag anterior y aadiendo el nuevo flag. 4. Obtendremos una lista de los flags que existen ahora en modo, y regeneraremos el listado de modos del StateSet. 5. Se crear una nueva accin de Modificar Modo que establecer un nuevo valor de la mscara de un modo de un StateSet.
CASO DE USO: Cambiar la escena activa Accin de los Actores 1. El usuario tiene abiertas varias escenas de manera simultnea en la aplicacin y realiza un cambio de escena mediante la combinacin de teclado CTRL+TABULADOR. Respuesta del sistema 2. La Vista MFC recibe un mensaje de windows WM_SETFOCUS. 3. Se envia un mensaje a la antigua ventana para que detenga su proceso de render.
161
4. Se establece el rbol de escena activo indicandole la ID de esta vista. 5. Se le pasa al ActiveViewHandler la informacion sobre los nuevos punteros de la vista actualmente activa, la surface de OpenSceneGraph, la historia, la seleccin, etc.
162
PARTE V
DISEO
163
164
INDICE
PARTE V........................................................................................................
5.1. Introduccin. .................................................................... Error! Marcador no definido. 5.2 Diagrama de componentes del sistema. ............................ Error! Marcador no definido. 5.3 Diseo de las funciones del sistema mediante diagramas de secuencia y colaboracin. ................................................................................................. Error! Marcador no definido. 5.3.1 Inicio. ......................................................................... Error! Marcador no definido. 5.3.2 Finalizar aplicacin .................................................... Error! Marcador no definido. 5.3.3 Nueva Escena ............................................................. Error! Marcador no definido. 5.3.4 Insertar fichero. .......................................................... Error! Marcador no definido. 5.3.5 Modificar Parmetro .................................................. Error! Marcador no definido. 5.3.6 Nuevo rbol ................................................................ Error! Marcador no definido. 5.3.7 Seleccionar elemento en visor.................................... Error! Marcador no definido. 5.3.8 Crear Nodo ................................................................. Error! Marcador no definido. 5.3.9 Seleccionar Elemento en rbol ................................... Error! Marcador no definido. 5.3.10 Undo......................................................................... Error! Marcador no definido. 5.3.11 Seleccionar elementos del rbol en el visor ............. Error! Marcador no definido. 5.3.12 Seleccionar elementos del visor en el rbol ............. Error! Marcador no definido. 5.3.13 Copiar elemento de rbol ......................................... Error! Marcador no definido. 5.3.14 Copiar tem de un nico rbol. ................................. Error! Marcador no definido. 5.3.15 SelectAllInstances .................................................... Error! Marcador no definido. 5.3.16 SelectAllMirrors....................................................... Error! Marcador no definido. 5.3.17 CreateParentMatrixTransform ................................. Error! Marcador no definido. 5.3.18 StartTranslation ........................................................ Error! Marcador no definido. 5.3.19 DoTranslate .............................................................. Error! Marcador no definido. 5.3.20 EndTranslate............................................................. Error! Marcador no definido. 5.3.21 RemoveSceneTree.................................................... Error! Marcador no definido. 5.3.22 Exec.......................................................................... Error! Marcador no definido. 5.3.23 RecursiveCreateDialogs ........................................... Error! Marcador no definido. 5.3.24 CreateDialogs. .......................................................... Error! Marcador no definido. 5.3.25 CreateDialogFromGroup.......................................... Error! Marcador no definido. 5.3.26 RegisterTabOutput (TabOutputManager) ................ Error! Marcador no definido. 5.3.27 RegisterType (ObjectTypeManager)........................ Error! Marcador no definido. 5.3.28 NewInstance ............................................................. Error! Marcador no definido. 5.3.29 CreateTreeNode ....................................................... Error! Marcador no definido. 5.3.30 CargarPlugins ........................................................... Error! Marcador no definido. 5.3.31 Update (Selection)................................................... Error! Marcador no definido. 5.3.32 UpdateAxis............................................................... Error! Marcador no definido. 5.3.33 MapIOControls......................................................... Error! Marcador no definido. 5.3.34 RecursiveOnEndSelection........................................ Error! Marcador no definido. 5.3.35 RecursiveGenerateRollupContent (ObjectType)...... Error! Marcador no definido. 5.3.36 RecursiveClearRollupContent (ObjectType) ........... Error! Marcador no definido. 5.3.37 GenerateRollupContent (TabOutput) ....................... Error! Marcador no definido. 5.3.38 ClearRollupContent (TabOutput)............................. Error! Marcador no definido. 5.3.39 GetParamValue (TabOutput) ................................... Error! Marcador no definido. 5.3.40 SetParamValue (TabOutput) .................................... Error! Marcador no definido. 5.3.41 LookAtSelection....................................................... Error! Marcador no definido. 5.3.42 SetRootNode (ActiveViewHandler)......................... Error! Marcador no definido. 5.3.43 SetRootNode (MultiTreeBar)................................... Error! Marcador no definido.
165
5.3.44 ReplicateSceneTree (MultiTreeBar) ........................ Error! Marcador no definido. 5.3.45 CloneFrom (OSGTreeCtrl) ...................................... Error! Marcador no definido. 5.3.46 DeleteNode (OSGTreeCtrl)...................................... Error! Marcador no definido. 5.3.47 ActDeleteMultiItem (Action) ................................... Error! Marcador no definido. 5.3.48 DeleteNode (ActiveViewHandler) ........................... Error! Marcador no definido. 5.3.49 Cambiar escena activa.............................................. Error! Marcador no definido. 5.4. Diagrama de estados del sistema...................................... Error! Marcador no definido. 5.4.1 Estado del cursor ........................................................ Error! Marcador no definido.
166
5.1. Introduccin.
Para realizar cualquier software, una vez reconocidos los requisitos, y realizado un estudio de las necesidades del sistema, no es recomendable en ningn caso comenzar la implementacin sin realizar primero un diseo que cumpla con las caractersticas obtenidas en la fase de anlisis. En la fase de diseo, se especifica la arquitectura software del sistema y se ofrece una primera aproximacin algortmica al sistema global, la cual sea capaz de cumplir con todas las conclusiones alcanzadas en el anlisis anterior. Para ayudar en esta tarea, y hacer comprensibles las decisiones y conclusiones obtenidas, se utilizaran los diagramas UML que correspondan a cada parte del diseo. Siguiendo las conclusiones de la fase de anlisis, se realizar el diseo de las funciones ms importantes del sistema, y no todas ellas debido a que podramos extendernos excesivamente, explicando detalladamente los pasos a seguir para llevarlas a cabo en los casos que sean necesarios. Al finalizar la fase de diseo, ya estarn definidas todas las funciones, clases, y directrices necesarias para realizar la implementacin.
En este diagrama podemos apreciar una vista global de la arquitectura de la aplicacin y de su conexin con los dems componentes. El fichero ejecutable est generado mediante el uso de la librera MFC (Microsoft Foundation Classes), y hace uso de la librera grfica OpenSceneGraph, que a su vez est basada en la librera OpenGL. Adems, la aplicacin se complementa con la carga en memoria de fragmentos de cdigo aadidos en tiempo de ejecucin, que son las DLLs, que a su vez pueden acceder a la aplicacin.
167
5.3 Diseo de las funciones del sistema mediante diagramas de secuencia y colaboracin.
5.3.1 Inicio.
Es la funcin que inicia todos los datos del programa. Al arrancar la aplicacin se iniciar el nico objeto global de la aplicacin (ActiveViewHandler), y se generar una vista vaca, la cual iniciar los datos del grafo por defecto. Cuando el ActiveViewHandler arranque iniciar todos los gestores de la aplicacin, se crearan las barras de herramientas (la principal y la de creacin de nodos) iniciar la barra principal de paneles de comandos y el rbol que contendr la representacin del grafo, y adems iniciar los tipos de datos que soporta la aplicacin aadindolos a sus respectivos gestores. Es en esta fase donde se realizar tambin la carga de los plugins. Al cargar los plugins la aplicacin buscar en el directorio de plugins ficheros dll, estos ficheros los intentar cargar uno por uno, extrayendo informacin necesaria de cada uno de ellos, y registrando en el sistema los objetos que en cada plugin encuentre. Los tipos de Objeto que iniciar la aplicacin sern los siguientes:
ObjTypeStateSet ObjTypeDrwStateSet ObjTypeCounter ObjTypeVariableRateCounter ObjTypeRandomRateCounter ObjTypeConstantRateCounter ObjTypeDrawable ObjTypeShapeDrawable ObjTypeGeometry ObjTypeParticle ObjTypeParticleSystem ObjTypeText
168
TypePagedLOD TypeSwitch TypeGeode TypeSequence TypeBillboard TypeTransform TypeDOFTransform TypePositionAttitudeTransform TypeMatrixTransform TypeAutoTransform TypeLightSource TypeParticleSystemUpdater TypeParticleProcessor TypeEmitter TypeModularEmitter TypeFXEffect TypeFXCartoon TypeFXSpecularHighlights TypeFXBumpMapping
169
170
171
172
173
174
175
176
5.3.10 Undo.
La funcin Undo o Deshacer se invoca desde la vista activa. Esta realiza una llamada directa a la funcin Undo de gestor de Historia, que a su vez realiza una llamada a la funcin Undo de la accin actual apuntada por el gestor. Despus de ello, actualiza la posicin del cursor, retrocedindola un lugar, pero conservando las acciones posteriores. Puesto que la funcin undo puede haber modificado datos de la salida del interfaz, forzaremos una llamada a mostrar los datos del nodo actualmente seleccionado en el rbol.
177
objetos del primer rbol, puesto que un mismo tem en rboles distintos tendr referencias distintas. Por ltimo, indicaremos al gestor de seleccin la lista de los objetos que queremos seleccionar. Este gestor comprobar previamente si los objetos que vamos a seleccionar contienen Matrices de Transformacin como alguno de sus padres, y en caso de que sea necesario, crear una MatrixTransform de OpenSceneGraph. Esta es una medida que adoptamos para poder aplicar transformaciones a los objetos una vez seleccionados.
178
179
5.3.15 SelectAllInstances
Esta funcin es llamada desde el mismo rbol que contiene una escena, y resalta en negrita todas las instancias de un nodo. Puesto que el nodo del editor contiene referencias a las distintas instancias, as como sus mirrors, accederemos a este listado inmediatamente, entrando en un bucle que para cada una de las instancias, cambie el texto a negrita.
5.3.16 SelectAllMirrors
Esta funcin la invoca el propio rbol, pero accede a todas las dems rplicas del rbol en el editor. A partir del nodo del editor sobre el que queremos aplicar la funcin, debemos obtener el ndice de la instancia. Con este ndice identificaremos automticamente en cada uno de los rboles el tem equivalente, que colorearemos de rojo.
180
5.3.17 CreateParentMatrixTransform
Esta funcin se llama automticamente al seleccionar un objeto. La razn de ello es que al seleccionar un objeto, el usuario est indicando en cierto modo su intencin de aplicarle alguna transformacin. Esta transformacin solo se puede llevar a cabo sobre una Matriz de Transformacin que contenga al nodo como uno de sus descendientes. Por tanto, lo que har esta funcin ser comprobar si existe una matriz de transformacin como padre del nodo, y adems, que esa transformacin solo tenga a ese nodo como hijo. En caso contrario, creamos un nuevo nodo tipo Matriz de Transformacin y lo intercalamos entre el nodo que queremos transformar y su padre actual.
5.3.18 StartTranslation
Esta funcin y las dos siguientes solo las explicaremos para la Traslacin, pues que para el escalado y la rotacin siguen comportamientos similares. Esta funcin es como el Setup o la puesta a punto de la traslacin. Se llama a esta funcin para realizar los ajustes o actualizaciones necesarias o consultar los datos necesarios para prepararse para comenzar la transformacin. Por ejemplo, aqu recalcularemos la BoundingBox de la seleccin y deberemos guardar la posicin del centro geomtrico de la seleccin, lo cual nos servir mas adelante para almacenar correctamente la transformacin como una funcin invertible en la Historia.
181
5.3.19 DoTranslate
Es el proceso de trasladar en s. Esta es la funcin que realiza la traslacin a medida que vamos desplazando el ratn, aunque realmente la accin no se podr considerar como terminada hasta que soltemos el ratn. Esta es la funcin que realiza la traslacin, aunque realmente la accin no se podr considerar como terminada hasta que soltemos el ratn. En este paso se aplica la misma transformacin a todos los objetos de la seleccin en funcin del desplazamiento del cursor sobre la pantalla. Esta transformacin tiene la particularidad de que requiere algunos clculos extraordinarios para calcular el incremento que vamos a aplicar a la traslacin, ya que calcularemos un plano imaginario que sea paralelo al plano seleccionado en el eje manipulador, y que pase por el centro de la seleccin, de esta manera, intersectando una lnea imaginaria desde el cursor hacia este plano obtendremos el punto donde queremos desplazar el objeto, y as calcularemos el incremento a aplicar como traslacin. Una vez hecho esto, deberemos tambin actualizar las cajas de seleccin de los objetos seleccionados, puesto que las transformaciones deben afectarles por igual, as como actualizar su BoundingBox y la posicin del eje manipulador.
5.3.20 EndTranslate
Este es el paso que da por finalizada la traslacin de la seleccin. Es aqu donde se actualiza la informacin de la seleccin, como por ejemplo los valores de las matrices auxiliares que se utilizan para almacenar informacin que luego servirn para almacenar la accin invertible de la transformacin. Tambin aqu actualizaremos la BoundingBox de la seleccin y actualizaremos la posicin del eje manipulador.
182
5.3.21 RemoveSceneTree
Esta llamada la realiza el objeto MultiTree. Se invoca al cerrar una escena. Este objeto lo que hace es recorrer todas las TreeBar abiertas, eliminando el objeto del rbol, y liberando as su memoria.
5.3.22 Exec
Esta funcin la proporciona el ActiveViewHandler, y se utiliza para ejecutar cualquier accin en el sistema. Lo que esta funcin hace es ejecutar la accin pasada por referencia, y pasrsela al gestor de historia para aadirla. El gestor de historia comprobar si la posicin actual de la historia est colocada al final, y en caso afirmativo, insertar la accin, incrementando esta posicin. En caso de no ser as, todas las acciones posteriores a las de la posicin actual, debern ser eliminadas, y despus de ello, se insertar la accin, incrementando la posicin actual en uno.
183
5.3.23 RecursiveCreateDialogs
Esta funcin se invoca la primera vez que queremos mostrar un ObjectType por el interfaz, y es invocada por el gestor de parmetros. Esta accin simplemente crea en memoria los dilogos que formarn esta estructura. La primera accin a realizar es crear los dilogos del ObjectType a partir de su grupo de parmetros, ya definido, realizando una llamada recursiva en caso de que existe un ObjectType padre definido y este no haya creado tampoco sus dilogos. Despus de esto, se comprueba si existen ObjectTypes adjuntos, y se realiza la misma llamada a esta misma funcin para cada uno de ellos.
5.3.24 CreateDialogs.
Es la funcin que invoca la funcin recursiva anterior. Aqu se obtiene el vector de grupos de parmetros del objeto, y para cada uno d ellos, se crea un dilogo independiente, indicando el Rollup en el que lo mostraremos. Cada pestaa del panel de comandos tiene un Rollup asociado, por lo que el Rollup equivale a la pestaa del panel de comandos donde queremos que se creen los dilogos.
184
5.3.25 CreateDialogFromGroup.
Esta funcin es invocada por la funcin anterior y es la que crea realmente el dilogo. En un principio se crea un dilogo dinmicamente, inicialmente vaco, y vamos recorriendo cada uno de los descriptores de grupo del grupo de parmetros. Cada uno de estos descriptores tendr unas caractersticas por lo que podremos crear distintos controles en funcin del tipo de descriptor. As pues, donde en el diagrama de colaboracin podemos apreciar CrearControl, deber estar sustituido por una llamada a la funcin Crear del control pertinente. Vamos a nombrar todas estas funciones, pero no entraremos en detalles de ninguna de ellas:
CreateButton CreateStatic CreateTextbox CreateEditbox CreateSpinner CreateCheckbox CreateCheckButton CreateCombobox CreateRadio CreateRange CreateVector3 CreateVector4 CreateColorSwatch CreateListbox CreateGridCtrl
185
186
5.3.28 NewInstance
Esta funcin es propia del gestor de ObjectTypes (aunque tambin del gestor de NodeTypes, pero solo explicaremos este caso). Cuando tengamos un ObjectType registrado y queramos obtener una nueva instancia del objeto al que representa, podremos solicitarle una indicndole el nombre del tipo de objeto.
5.3.29 CreateTreeNode
Esta funcin permite crear un nuevo nodo en el grafo de la escena activa, indicando el nombre del nodo. Para ello necesitaremos una nueva instancia del nodo OpenSceneGraph. Haremos uso de la llamada a NewInstance que nos proporciona el gestor de Nodos para obtener una nueva instancia del nodo, y crearemos un nuevo nodo para nuestro grafo del editor (TreeNodeInfo). Esta estructura contendr informacin como un puntero al nodo OpenSceneGraph que acabamos de crear, y un puntero al NodeType que identifica al nodo.
187
5.3.30 CargarPlugins
Esta funcin es invocada al iniciar el TabOutput de plugins, que es iniciado a su vez al iniciar la aplicacin. En primer lugar cargamos el fichero DLL, obteniendo el manejador del mismo. Creamos una nueva estructura de datos (PluginInfo) que contendr la informacin del plugin que carguemos, para que el gestor de plugins la almacene. Consultaremos el nmero de clases del plugin, as como la descripcin del plugin y obtendremos una instancia de cada una de las clases implementadas en el plugin. Toda esta informacin se guardar en el objeto PluginInfo, que guardaremos en una tabla hash, para posteriormente poder consultar mediante el nombre del fichero.
188
Lo que esta funcin hace realmente es actualizar el cursor segn su posicin, o el eje manipulador, adems del estado del cursor. El estado del cursor define si el cursor est encima de algn objeto, o encima de algn otro elemento, como puede ser el eje manipulador. En primer lugar se comprueba si existe algn objeto seleccionado en la escena, en ese caso sabremos que el eje manipulador estar mostrado, por tanto obtenemos si existe alguna colisin del cursor con tal eje. Si el cursor no esta encima de ningn elemento del eje manipulador entonces se comprueba si existe colisin con alguno de los objetos, actualizando el cursor y el estado del cursor en funcin de si el eje est o no seleccionado, y de la transformacin que estemos llevando a cabo.
5.3.32 UpdateAxis
Esta funcin es invocada por la seleccin. Esta funcin realiza las mismas comprobaciones que la anterior, pero nicamente comprueba si existe alguna interseccin del cursor del ratn con el eje manipulador, obteniendo exactamente con qu elemento del eje intersecciona y actualizando el estado del mismo, y su apariencia (por ejemplo, resaltando con ms brillo el eje o el plano que estamos seleccionando en el eje manipulador). De esta manera podremos consultar en cualquier momento qu ejes se encuentran seleccionados en cada momento.
189
5.3.33 MapIOControls
Esta funcin (nombrada anteriormente como MapearParamGroups) propia de la clase TabOutput, y se invoca al registrar un TabOutput, ObjectType, NodeType o AtributeType. Realiza la llamada CreateIOControls del TabOutput en cuestin. Esta funcin es una funcin virtual pura que deber Una vez hecha la llamada a CreateIOControls, se mapea en la tablas hash el id de cada uno de sus descriptores de los grupos de parmetros asociando como clave en descriptor en s. De esta manera tenemos una tabla hash que asocia Ids de parmetros con sus respectivos descriptores.
5.3.34 RecursiveOnEndSelection
Esta funcin se invoca como notificacin a un ObjectType para indicar que sus datos van a dejar de motrarse en el panel de comandos del interfaz. Primero de todo, se realiza una llamada recursiva sobre su padre, en caso de existir.
190
Para cada uno de los objetos, tambin se realizar una notificacin recursiva a cada uno de los objetos adjuntos. Para finalizar, se desvincula el objeto de cualquier adjuntador (que no adjunto), y se establece el objeto al q representa como null.
191
192
193
A esta funcin se le pasan dos parmetros, uno con el ID del parmetro a modificar, y un segundo parmetro que es una variable con el valor del parmetro. En este caso vamos a mostrar el comportamiento de la funcin para establecer el valor de un parmetro mediante una variable entera. En primer lugar obtendremos el descriptor del parmetro asociado al ID del parmetro que queremos, sabiendo esto, obtendremos el grupo de parmetros al que pertenece el descriptor, y a su vez podremos obtener un puntero al dilogo que lo representa. Puesto que el descriptor del parmetro tambin guarda el ID del control asociado en el dilogo, podremos establecer el valor que almacena el control mediante la llamada a SetDlgItemInt(id, value).
5.3.41 LookAtSelection
Esta funcin la invoca el objeto KeyboardMouse, ya que es el objeto que contiene el TrackBall de OpenSceneGraph. El TrackBall es el objeto que nos permite modificar la cmara del visor. LookAtSelection centra la vista en el centro geomtrico de la seleccin actual del visor. Para ello obtenemos el punto central de la seleccin, y los valores de eye, center y up que actualmente contiene el TrackBall. Con estos valores construimos una matriz usando el mismo valor de eye, y up, pero con el valor de centro como valor del punto central de la seleccin. Por ltimo establecemos esta matriz como la matriz del TrackBall.
194
Por ltimo, se realiza la llamada SetRootNode al objeto MultiTree, indicando que vamos a establecer el nodo como nodo raz (parmetro NULL).
195
196
197
Despus, invocamos a la funcin eliminar sobre cada uno de los elementos del rbol, propia la de clase OSGTreeCtrl.
198
199
primer lugar el sistema comprueba si se est colisionando con el eje manipulador, y en caso de no estarlo, se pasa a comprobar el resto del la escena.
200
PARTE VI
IMPLEMENTACION
201
202
INDICE
PARTE VI ...................................................................................................... 6.1 Introduccin ..............................................Error! Marcador no definido.
6.2 Parametrizacin de datos................................................... Error! Marcador no definido. 6.2.1 El descriptor de parmetros (OSGParamGroupDesc). .............. Error! Marcador no definido. 6.2.2 Los grupos de parmetros (OSGParamGroup) .......... Error! Marcador no definido. 6.2.3 El gestor de parmetros (OSGParamManager) ......... Error! Marcador no definido. 6.2.4 El control ColorSwatch .............................................. Error! Marcador no definido. 6.2.5 Las clases OSGTabOutput y OSGTabOutputManager.............. Error! Marcador no definido. 6.2.6 Un ejemplo de OSGTabOutput : la clase OutCreateNodes........ Error! Marcador no definido. 6.2.7 Las clases OSGObjectType y OSGObjectTypeManager........... Error! Marcador no definido. 6.2.8 Un ejemplo de OSGObjectType: TypeDrawable....... Error! Marcador no definido. 6.3 Implementacin del rbol del grafo de escena. ................. Error! Marcador no definido. 6.3.1 La clase TreeNodeInfo .............................................. Error! Marcador no definido. 6.3.2 La clase CEditTreeCtrl............................................... Error! Marcador no definido. 6.3.3 La clase CEditTreeCtrlEx .......................................... Error! Marcador no definido. 6.3.4 La clase COSGTreeCtrl ............................................. Error! Marcador no definido. 6.3.5 CTreeBar y CmultiTreeBar. ....................................... Error! Marcador no definido. 6.4 Interaccin con el visor 3D ............................................... Error! Marcador no definido. 6.4.1 La clase OSGSelection............................................... Error! Marcador no definido. 6.4.2 La clase OSGAxisManipulator ................................. Error! Marcador no definido. 6.4.3 La clase MFCKeyboardMouseCallback .................... Error! Marcador no definido. 6.5 El sistema de deshacer / rehacer........................................ Error! Marcador no definido. 6.5.1 La clase OSGAction................................................... Error! Marcador no definido. 6.5.2 La clase OSGHistory.................................................. Error! Marcador no definido. 6.6 El sistema gestor de plugins .............................................. Error! Marcador no definido. 6.6.1 El plugin Cartoon ....................................................... Error! Marcador no definido. 6.6.2 La clase OSGPluginManager ..................................... Error! Marcador no definido. 6.6.3 La clase OutPlugins.................................................... Error! Marcador no definido. 6.7 El manejador de la vista activa y las clases MFC ............. Error! Marcador no definido. 6.7.1 La clase OSGActiveViewHandler.............................. Error! Marcador no definido. 6.7.2 La clase COSGWorldView ........................................ Error! Marcador no definido. 6.8 Problemas y tips de implementacin ............................. Error! Marcador no definido. 6.8.1 La actualizacin de OpenSceneGraph 0.9 a 1.0 ......... Error! Marcador no definido. 6.8.2 La clase RefParticle.................................................... Error! Marcador no definido. 6.8.3 La funcin clone......................................................... Error! Marcador no definido. 6.8.4 La funcin DoFrame()................................................ Error! Marcador no definido. 6.8.5 Eliminar un nodo, deshacer y rehacer. ....................... Error! Marcador no definido.
203
204
6.1 Introduccin
Hasta ahora se han definido los requisitos que deben cumplir cada uno de los subsistemas de los cuales est compuesta la aplicacin. Conociendo estos requisitos que marcan lo que se debe hacer, se realiz un anlisis para alcanzar una primera aproximacin lgica de cada sistema. Posteriormente se realizo la fase de diseo en la que se establece una primera solucin, la cul se describe solo de forma global. Por tanto en este momento se conoce todo lo que debe hacerse, y los esquemas generales para hacerlo, con lo cual solo queda implementar la solucin siguiendo la estructura creada en los apartados anteriores. La implementacin es la parte de ms bajo nivel del proyecto, donde se crean soluciones a problemas concretos planteados en el diseo. Esta parte la dividiremos en 6 apartados, explicando las partes relevantes de la implementacin de cada uno: Parametrizacin de datos. Aqu se presentarn todas las estructuras de datos relacionadas con los grupos de parmetros y los descriptores de parmetros, los TabOutput, ObjectType, NodeType y AttributeType y sus respectivos Gestores, el gestor de parmetros y las funciones ms importantes de cada uno. Implementacin del rbol del grafo de escena. Aqu se explicar el rbol y sus funciones, as como el mtodo a seguir en su duplicado y la gestin de eventos de teclado. Interaccin con el visor 3D. Veremos las acciones a llevar a cabo sobre la seleccin de objetos , como se gestionan, y como est estructurada la clase del eje manipulador. Sistema deshacer / rehacer. Veremos como funciona el sistema de deshacer / rehacer y como se implementan nuevas acciones en el sistema. Sistema gestor de plugins. En este apartado explicaremos el cdigo del sistema gestor de plugins, asi como el cdigo necesario para generar un plugin. Manejador de Vista Activa y clases MFC. En este apartado se explicar todo la parte de implementacion del ActiveViewHandler y el cdigo referente a las clases MFCs.
Y por ltimo aadiremos un apartado extra, que llamaremos Problemas de implementacin , donde explicaremos algunos de los problemas encontrados durante la implementacin, y las soluciones adoptadas. Toda la implementacin se realizar utilizando el lenguaje de programacin C++, ya que es el lenguaje utilizado por la librera OpenSceneGraph. El entorno de desarrollo de las aplicaciones es el Visual C++ de Microsoft. Se ha elegido este sistema porque las aplicaciones de prueba se van a realizar haciendo uso de las Microsoft Foundation Classes. Nota: Algunos de los listados de cdigo fuente mostrados a continuacin han sido truncados, mostrando solo la informacin considerada como relevante para la explicacin.
205
class OSGParamGroupDesc { public: OSGParamGroupDesc(void); ~OSGParamGroupDesc(void); OSGParamGroupDesc(int _index,ParamType type, std::string name, int id); OSGParamGroupDesc(int _index,ParamType type,std::vector<std::string> names, int*); void Set(int _index, ParamType _type, std::string _name, int _flags=DESC_EDITABLE); void Add(std::string _name, int _value=-1)
void AddCtrlID(int ctrl, int link_ctrl=-1); CTRLID_INF GetCtrlID(int _index=0); CTRLID_INF GetCtrlIDFromValue(int _value=0); int GetValueFromControl(int _ctrlid) int GetIndexFromValue(int _value) std::string* GetName(int _index=0) int GetValue(int _index=0) void bool void void SetEditable(bool Editable); IsEditable(); AddFlag(int _flag); RemoveFlag(int _flag);
int GetNumNames() int GetNumControls() void SetGroup(OSGParamGroup *_gr) OSGParamGroup *GetGroup() int param_id; // index/orden q ocupa dentro del PARAMGROUP ParamType type; protected: std::vector<CTRLID_INF> ctrl_ids; int flags; // el primer elemento define el nombre del parametro // los demas se utilizan basicamente para los controles // tipo radio, cada name siguiente define una opcion del radio. // del mismo modo seria aplicable al combo box. // por tanto para saber el numero de elementos de un parametro // tipo radio, seria (names.size()-1) std::vector<DESC_INF> names; OSGParamGroup *gr;
206
Como podemos ver, la clase proporciona mecanismos para obtener los datos del control que representa. Nos permite modificar su valor, as como modificar si se trata de un control editable o no.
#define DESC_EDITABLE 0 #define DESC_READONLY 1
El parmetro type define el tipo de parmetro que estamos definiendo, y puede tomar cualquier de los siguientes valores:
typedef enum { TYPE_BUTTON=1, TYPE_SPINNER, TYPE_RADIO, TYPE_CHECKBOX, TYPE_CHECKBUTTON, TYPE_STATIC, TYPE_MULTICHECKBOX, TYPE_COLORSWATCH, TYPE_LISTBOX, TYPE_COMBOBOX, TYPE_TEXTBOX, TYPE_GRIDCTRL, TYPE_STRING, TYPE_INT, TYPE_FLOAT, TYPE_VEC3_FLOAT, TYPE_VEC4_FLOAT, TYPE_RANGE_INT, TYPE_RANGE_FLOAT } ParamType;
Cada uno de ellos se corresponder con uno o un conjunto de controles de la API de Win32.
207
~OSGParamGroup(void); int tab_index; RC_PAGEINFO *page; std::string group_name; bool rollable; bool expanded; CDynDialogEx *dialog; };
208
La funcin NotifyObjectType se invoca por el sistema cuando el un parmetro se ha modificado, y el gestor de parmetros se encarga de notificar al OSGTabOutput que lo contiene del evento.
void OSGParamManager::NotifyObjectType(WPARAM wParam, LPARAM lParam, int notify_type) { bool send_notify = false; WORD wControlID = LOWORD(wParam); WORD wMessageID = HIWORD(wParam); OSGTabOutput *nt = hash_idoutput[wControlID]; OSGParamGroupDesc *desc = hash_idparamgroupdesc[wControlID]; if(!desc || !nt) return; OSGParamGroup *gr = desc->GetGroup(); if(!nt->IsDataShown()) return; if(notify_type==0) // FROM WM_COMMAND { switch(desc->type) { case TYPE_TEXTBOX: case EDITTYPE_STRING: case TYPE_SPINNER: case EDITTYPE_INT: case EDITTYPE_FLOAT: case EDITTYPE_VEC3_FLOAT: case EDITTYPE_VEC4_FLOAT: case EDITTYPE_RANGE_FLOAT: case EDITTYPE_RANGE_INT: if(wMessageID == EN_KILLFOCUS) send_notify = true; break; case case case case TYPE_RADIO: TYPE_BUTTON: TYPE_CHECKBOX: TYPE_CHECKBUTTON: send_notify = true; break; case TYPE_COLORSWATCH: // cuando llega un evento de colorwatch es porque // hemos pulsado OK sobre el dialogo send_notify = true; break; case TYPE_LISTBOX: if(wMessageID == LBN_SELCHANGE) send_notify = true; break; case TYPE_COMBOBOX: if(wMessageID == CBN_SELCHANGE) send_notify = true; break; } } else { // FROM WM_NOTIFY (Solo SpinCtrl) // informacion de la pulsacion LPNMUPDOWN lpnmud = (LPNMUPDOWN) lParam; switch(desc->type) { case TYPE_SPINNER: case EDITTYPE_FLOAT:
209
210
Este control mostrar un dilogo de seleccin de color al pulsar sobre l, que nos permitir seleccionar el color que deseemos.
void CColorSwatch::OnLButtonDown(UINT nFlags, CPoint point) { CSelColorDlg *dlg = new CSelColorDlg(m_bRed, m_bGreen, m_bBlue, m_bAlpha, this); dlg->Create(CSelColorDlg::IDD); dlg->ShowWindow(SW_SHOW); dlg->SetFocus(); CStatic::OnLButtonDown(nFlags, point); }
211
Esta clase proporciona los mecanismos necesarios para construir un objeto que se muestre en la barra de pestaas principal, ms concretamente un dilogo, asi como para consultar y establecer los datos que queramos de los controles.
class OSGTabOutput { public: OSGTabOutput(void); ~OSGTabOutput(void); void Init(); virtual void CreateIOControls()=0; virtual void ShowCustomData(osg::Object *obj) = 0; virtual void ParamModified(osg::Object *obj, int param_id)=0; void ShowData(osg::Object *obj); inline std::string GetName(); inline int OutputType(); bool HasIOGroups(); std::vector<OSGParamGroup*> * GetIOGroups(); void SetDialogsCreated(bool b); bool DialogsCreated; inline bool IsDataShown(); inline bool IsDialogShown(); inline void SetGroupName(int group_idx, std::string name); void GenerateRollupContent(); void ClearRollupContent(); CWnd* GetParamHandle(int param_id); void MapIOControls(); void void void void void void void void void void void GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int GetParamValue(int param_id, param_id, param_id, param_id, param_id, param_id, param_id, param_id, param_id, param_id, param_id, std::string &value); int &value); osg::Vec3f &value); osg::Vec4 &value); float &value); osg::Vec4d &value); osg::Quat &value); osg::Matrixd &value); CPoint &value); std::string &value, int row, int col); float &min, float &max);
void AddParamFlag(int param_id, int addflag); void RemoveParamFlag(int param_id, int addflag); bool IsParamEditable(int param_id); void void void void void void void void void void SetParamValue(int param_id, std::string &value); SetParamValue(int param_id, int &value); SetParamValue(int param_id, float &value); SetParamValue(int param_id, float &min, float &max); SetParamValue(int param_id, osg::Vec3f &value); SetParamValue(int param_id, osg::Vec4 &value); SetParamValue(int param_id, osg::Vec4d &value); SetParamValue(int param_id, osg::Quat &value); SetParamValue(int param_id, osg::Matrixd &value); SetParamValue(int param_id, std::vector<std::string> &values, bool sorted=true); void SetParamValue(int param_id, OSGW_PAIRLIST &values);
212
Las funciones para obtener el valor de un parmetro y establecer este valor son GetParamValue y SetParamValue. Estas funciones estarn sobrecargadas para todos y cada uno de los tipos de datos que soporta el descriptor de parmetros. Tambin podremos asignar flags a los parmetros. De momento solo estn implementados dos flags:
#define DESC_EDITABLE 0 #define DESC_READONLY 1
La funcin MapIOControls() la realiza el TabOutputMananger automticamente, y esta a su vez realiza una llamada a CreateIOControls(), que es una funcion virtual pura que deber estar implementada en cada tipo de TabOutput y lo que hace es rellenar la el vector iogroups de los grupos de parmetros que tendr el TabOutput. Al mismo tiempo se actualiza la tabla hash que relaciona cada uno de los parmetros con su descriptor de parmetros correspondiente.
void OSGTabOutput::MapIOControls() { CreateIOControls(); if(HasIOGroups()){ for(unsigned i=0;i<iogroups.size(); i++){ OSGParamGroup *gr = iogroups[i]; for(unsigned j=0;j<gr->size();j++){ OSGParamGroupDesc *desc = gr->at(j); hash_pidgroupdesc[desc->param_id] = desc; } } } }
213
Este gestor simplemente mantiene una tabla hash que identifica cada TabOutput por su nombre, y permite obtener un puntero al mismo ya sea por nombre o por ndice. La funcion RegisterTabOutput almacena el TabOutput a almacenar, e inicializa los datos de los parmetros con la funciona MapIOControls.
void OSGTabOutputManager::RegisterTabOutput(OSGTabOutput *obj) { // El primer elemento insertado obtendra NULL como padre // ya que default_type vale null inicialmente outputs_v.push_back(obj); outputs[obj->GetName()] = obj; // Inicializamos los valores de los parametros // de que manejar este tipo de nodo obj->MapIOControls(); }
OutCreateNodes::OutCreateNodes(void) { name = "Creador de nodos"; } OutCreateNodes::~OutCreateNodes(void) { } void OutCreateNodes::ShowCustomData(osg::Object *obj) { std::vector<std::string> lista; OSGAVH->nodetypem.GetObjectTypeStrings(lista); SetParamValue(PARAM_NODELIST, lista); } void OutCreateNodes::CreateIOControls() { OSGParamGroupDesc *desc = new OSGParamGroupDesc[NUM_PARAMS]; desc[0].Set(PARAM_NODELIST, TYPE_LISTBOX, "Nodos"); desc[1].Set(PARAM_CREATEASCHILD, TYPE_BUTTON, "Crear como hijo"); desc[2].Set(PARAM_CREATEASPARENT, TYPE_BUTTON, "Crear como padre"); desc[3].Set(PARAM_CREATEFROMFILE, TYPE_BUTTON, "Crear desde archivo..."); OSGParamGroup *mygroup = new OSGParamGroup("Creacion de Nodos", true); for(int i=0;i<NUM_PARAMS;i++) mygroup->push_back(&desc[i]); iogroups.push_back(mygroup);
214
215
void Detach(int key); void Attach(int key, OSGObjectType *obj); bool Attach(int key, std::string name); void EndAttachSelection(int key, osg::Object *obj); void ShowAttachData(int key, osg::Object *obj); void ShowAttach(int key); void HideAttach(int key); int NumAttachs(); OSGObjectType *GetAttach(int key); inline OSGObjectType * GetCurrentAttacher(); inline int GetCurrentAttacherIndex(); protected: void SetCurrentAttacher(OSGObjectType *obj, int att_index); OSGObjectType *parent_type; std::string parent_type_name; osg::ref_ptr<osg::Object> selected_obj; std::map<int, OSGObjectType*> attach_list; // Objectos adjuntos OSGObjectType *current_attacher; // Quien esta actualmente adjuntado este objeto int current_attacher_index; // Indice del Attach al que apunta el Attacher };
Esta clase mantiene una tabla punteros a los ObjectType adjuntos (attach_list), y tambin un puntero al ObjectType que est actualmente enlazando a este ObjectType, y el objeto OpenSceneGraph que est actualmente representando. Tambin mantiene un puntero a su ObjectType padre, lo cual que permite realizar una llamada recursiva al mostrar sus datos (ShowRecursiveData). El gestor de este tipo de objetos es como sigue:
class OSGObjectTypeManager { public: OSGObjectTypeManager(void); ~OSGObjectTypeManager(void); void RegisterType(OSGObjectType *objt); bool UnregisterType(std::string name); OSGObjectType * GetObjectType(std::string name); void SetDefaultType(OSGObjectType *objt); osg::ref_ptr<osg::Object> NewCopyInstance(osg::Object *obj); osg::ref_ptr<osg::Object> NewInstance(std::string &name); void GetObjectTypeStrings(std::vector<std::string> &list); void GetAttributeTypeStrings(std::vector<std::string> &list); protected: std::map<std::string, OSGObjectType*> objtypes; std::vector<std::string> attributetypes; OSGObjectType *default_type; };
216
La funcionalidad de este gestor es similar a la del gestor de TabOutputs con la particularidad de establecer un ObjectType por defecto (SetDefaultType, para cuando una clase no se reconozca en el grafo de escena) , poder obtener un No describiremos la estructura de AttributeType ni de NodeType , ni sus respectivos gestores puesto que siguen estructuras prcticamente idnticas.
OSGParamGroup *mygroup = new OSGParamGroup("Drawable", true); for(int i=0;i<NUM_PARAMS;i++) mygroup->push_back(&desc[i]); mygroup->SetTabIndex(1); iogroups.push_back(mygroup); } void ObjTypeDrawable::OnEndSelection(osg::Object *obj) { HideAttach(ATT_STATESET); } void ObjTypeDrawable::ParamModified(osg::Object *obj, int param_id) { osg::ref_ptr<osg::Drawable> node = (osg::Drawable*) (obj); if(!node.valid()) return; int ival; switch(param_id) { case PARAM_BBMIN: case PARAM_BBMAX: { osg::Vec3 vv[2]; osg::BoundingBox bb; GetParamValue(PARAM_BBMIN, vv[0]); GetParamValue(PARAM_BBMAX, vv[1]); bb.set(vv[0], vv[1]); OSGAVH->Exec(new ActDrwSetInitialBound(node.get(), node->getInitialBound(), bb));
217
// Mostrar la informacion de este tipo de dato // La salida puede ser la que el usuario elija void ObjTypeDrawable::ShowCustomData(osg::Object *obj) { osg::ref_ptr<osg::Drawable> node = (osg::Drawable*) (obj); if(!node.valid()) return; int ival; osg::Vec3f vec3; ival = node->getSupportsDisplayList(); SetParamValue(PARAM_SUPPORTSDISPLAYLIST, ival); ival = node->getUseDisplayList(); SetParamValue(PARAM_USEDISPLAYLIST, ival); ival = node->getUseVertexBufferObjects(); SetParamValue(PARAM_USEVERTEXTBUFFER, ival); ival = node->requiresUpdateTraversal(); SetParamValue(PARAM_REQUIRESUPDATETRAVERSAL, ival); ival = node->requiresEventTraversal(); SetParamValue(PARAM_REQUIRESEVENTTRAVERSAL, ival); osg::BoundingBox bb = node->getInitialBound(); vec3.set(bb.xMin(), bb.yMin(), bb.zMin()); SetParamValue(PARAM_BBMIN, vec3); vec3.set(bb.xMax(), bb.yMax(), bb.zMax()); SetParamValue(PARAM_BBMAX, vec3); ShowAttachData(ATT_STATESET, node->getStateSet()); } void ObjTypeDrawable::AttachParamModified(int attach_id, int param_id) { osg::ref_ptr<osg::Drawable> node = dynamic_cast<osg::Drawable*> (GetSelectedObj().get()); if(!node.valid()) return; ObjTypeDrwStateSet *kkk = dynamic_cast<ObjTypeDrwStateSet *> (GetAttach(ATT_STATESET)); if(attach_id == ATT_STATESET) { if(node->getStateSet() == NULL) { if(AfxMessageBox("No existe ningun StateSet\nCrearlo?", MB_YESNO|MB_ICONQUESTION) == IDYES) { osg::StateSet *sts = new osg::StateSet(); node->setStateSet(sts); ShowAttachData(ATT_STATESET, sts);
218
219
Para construir un grafo a partir de esta estructura, tan solo necesitamos la lista de hijos de de padres y las funciones que nos permitan aadir padres o hijos, asi como desvincularlos. Adems, cada uno de estos Nodos contiene un puntero al nodo de OpenSceneGraph equivalente, y un vector de vectores de enlaces a HTREEITEMs, puesto que un mismo Nodo puede estar mltiplemente instanciado en una escena, pero ademas necesitamos identificar ese mismo item en todos los rboles de todas las TreeBar que hayamos duplicado.
HandleKeyDown(WPARAM wParam, LPARAM lParam); NewItem(TVINSERTSTRUCT & ins); OnNewItem(HTREEITEM hItem); CreateCursorMap(); SortCurrentLevel(HTREEITEM hItem = 0); SortCurrentLevelAndBelow(HTREEITEM hItem = 0); DisplayContextMenu(CPoint & point); ExtendContextMenu(CMenu & menu);
220
protected: EDropHint GetDropHint(UINT flags); HTREEITEM GetDropTarget(EDropHint & hint); HTREEITEM CopyItem(HTREEITEM hOrig, HTREEITEM hParent, HTREEITEM hInsertAfter, int mirror_index, bool tni_too=true, bool duplicate=false, TreeNodeInfo *tni_dup=NULL ); };
La estructura EDropHint sirve para indicar de que manera se va a copiar un elemento respecto al elemento destino:
enum EDropHint { DROP_BELOW, DROP_ABOVE, DROP_CHILD, DROP_NODROP };
Esta clase derivada de CTreeCtrl es la que contiene la correspondencia de los items del rbol con su nodo del grafo. Esta se representa mediante dos tablas hash, una para identificar el puntero al nodo de nuestro grafo duplicado a partir del HRTREEITEM del rbol, y otra para identificar el nodo de OpenSceneGraph a partir del HTREEITEM del rbol tambin. Tambin proporciona funciones para Seleccionar todas las instancias de un mismo nodo, o modificar el color de un subrbol (para cuando cortamos un nodo), y mover nodos entre distintos elementos. Esta clase es la que procesa los eventos de teclas pulsadas, y el arrastre de elementos con el ratn. Tambin permite ordenar un nivel y sus descendientes. Esta clase tambin tendr la funcionalidad de aadir un men contextual (para cuando se pulse el botn derecho del ratn), que permite distintas opciones sobre el elemento seleccionado. Los eventos de copiar y pegar nodos usando el teclado (Copiar y Pegar) estn incluidos en la siguiente funcin para procesar los distintos eventos de teclado:
bool CEditTreeCtrl::HandleKeyDown(WPARAM wParam, LPARAM lParam) { bool bCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; bool bShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; HTREEITEM hCur = GetSelectedItem(); switch(int(wParam)) { // CTRL+C COPIAR (INSTANCIAR) case 'C':
221
// CTRL+V PEGAR case 'V': if (GetKeyState(VK_CONTROL) & 0x80000000) { if(!m_pDragData) { DoPasteClipboard(); } } break; } return false; }
222
class COSGTreeCtrl : public CEditTreeCtrlEx { DECLARE_DYNAMIC(COSGTreeCtrl) public: COSGTreeCtrl(); virtual ~COSGTreeCtrl(); HTREEITEM SetRootNode(osg::Node *node, HTREEITEM hRoot=NULL); HTREEITEM AddNodeToTree( LPSTR lpszItem, osg::Node* node, HTREEITEM parent); HTREEITEM GetItemFromNodePath(osg::NodePath &np); void SetItemImageByType(HTREEITEM hItem, std::string classname); void GetNodePathFromItem(HTREEITEM item, osg::NodePath & res); void Redraw(); inline TreeNodeInfo * GetSelected(){ return selected_tni; } void CloneFrom(COSGTreeCtrl *clone, HTREEITEM hFirst); public: afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); };
Vamos a mostrar una funcin muy importante, SetRootNode(), que permite establecer como nodo raz (o como una rama) un grafo a partir de un Nodo de OpenSceneGraph:
// // // // // Cuelga del grafo del editor, as como del TreeCtrl El grafo de escena que se le pasa Pudiendo ser el destino de este un nodo del arbol del editor, en este caso del TreeCtrl (hRoot). DEVUELVE EL PRIMER ELEMENTO CREADO
223
La clase readNodeVisitor utilizada dentro de la funcin SetRootNode() se encarga de recorrer el grafo, construyendo el rbol imagen del grafo.
class readNodeVisitor : public osg::NodeVisitor { public: readNodeVisitor(HTREEITEM _root=TVI_ROOT); OSGObjectType * GetTypeFromName(std::string name); TreeNodeInfo* getFirst(); void CompleteApply(osg::Group &sN, COSGTreeCtrl *_tree); void CompleteApply(osg::Node &sN, COSGTreeCtrl *_tree); std::vector<TreeNodeInfo*> & getNodeList(); TreeNodeInfo* Contains(osg::Node *node); std::string GetNodeName(osg::Node &sN); HTREEITEM GetRootItem(); protected: virtual void apply(osg::Node &searchNode); virtual void apply(osg::Group &searchNode); void getNodeInfo(osg::Node &sN, TreeNodeInfo *ni); void getGroupInfo(osg::Group &sN, TreeNodeInfo *ni); void SecondPass(); private: std::vector<TreeNodeInfo*> foundNodeList; std::stack<HTREEITEM> m_vec; HTREEITEM root; bool firstTime; COSGTreeCtrl *tree; };
la funcion apply() se llama por primera vez dentro de esta funcin, pero OpenSceneGraph seguir invocndola para todos y cada uno de los nodos del grafo. Dentro de esta funcin es donde se va construyendo el rbol que representar en grafo y el grafo duplicado (incompleto) que utilizar el editor. Al terminar, realizaremos una segunda pasada, SecondPass(), para ajustar los punteros de los padres y los hijos de nuestros nodos del grafo duplicado.
224
Conteniendo a esta clase est MultiTreeBar , que no es ms que un agregado de TreeBars, y es la que permite visualizar varias copias de un mismo rbol en el editor, y copiar elementos entre ellas.
class OSGMultiTreeBar : public std::vector<CTreeBar*> { public: HTREEITEM SetRootNode(osg::Node *node, int scene_idx, HTREEITEM hRoot=NULL); void AddNewBar(); int GetNumScenes(); void RemoveSceneTree(int scene_index); void SetActiveSceneTree(int index); COSGTreeCtrl * CreateSceneTree(); void ReplicateSceneTree(int scene_idx, int to_bar_index, HTREEITEM hFirst); int GetActiveBarIndex(); int GetBarIndex(CEditTreeCtrl *tree); int GetBarIndex(CTreeBar *treebar); inline CEditTreeCtrl * GetClipboardSrc(); inline void SetClipboardSrc(CEditTreeCtrl *tree); inline void SetCopyOp(int cpop); inline int GetCopyOp(){ return copyOp;} inline void SetActiveBar(CTreeBar *tb); inline CTreeBar* GetActiveBar(); inline TreeNodeInfo *GetSelected; inline int GetActiveSceneTree; CEditTreeCtrl *clipboard_src; CTreeBar *active_bar; int active_tree_index; int copyOp; };
Cuando el usuario decide duplicar una escena en el editor, para visualizar dos o ms rboles del mismo grafo de escena, se invoca la funcion AddNewBar():
// Agregamos una nueva DockableBar al programa // que contendr un el treectrl duplicado void OSGMultiTreeBar::AddNewBar() { CTreeBar *m_newtreebar = new CTreeBar(); OSGAVH->bar_manager.CreateBar(m_newtreebar, "SceneTree", "Grafo de escena"); // la agregamos a la lista this->push_back(m_newtreebar);
// Ahora copiamos la informacion de todas las escenas // desde la primera TreeBar a esta. if(this->size()>1) { CTreeBar *bar = this->at(0); if(bar) { // replicamos TODOS los arboles de escena de una barra
225
Podemos ver aqu como MultiTreeBar invoca al Gestor de Bars del Manejador de la Vista Activa para aadir una nueva Bar, conteniendo los rboles de las distintas escenas. La funcin ReplicateSceneTree() permite realizar una replica de una escena de una Bar en otra Bar haciendo uso de la funcion CloneFrom() de COSGTreeCtrl:
void OSGMultiTreeBar::ReplicateSceneTree(int scene_idx, int to_bar_index, HTREEITEM hFirst) { COSGTreeCtrl *thetree = NULL; CTreeBar *to_bar = this->at(to_bar_index); if(this->size()>1) { CTreeBar *from_bar = this->at(0); thetree = from_bar->scenetree_list[scene_idx]; if(from_bar) { COSGTreeCtrl *tree = to_bar->scenetree_list[scene_idx]; tree->CloneFrom(thetree, hFirst); tree->Redraw(); } } }
226
227
La clase se inicializa pasandole, entre otros, el nodo raiz de la escena, y el nodo raiz que contendr los datos de seleccin. Esta clase contiene una tabla de los elementos de la escena seleccionados, en una tabla hash cuya clave es el HTREEITEM del elemento, y cuyo valor es la estructura de datos SelectionInfo. Tambin almacena una instancia de la clase eje manipulador (OSGAxisManipulator), que ser una representacion de los ejes de coordenadas para manipular los objetos. Al comenzar una transformacin se guardar en una variable el valor del centro de la seleccin (mouse_saved_pos) , y el valor actual del centro de la seleccin se almacena tambien en una variable (selection_center). Otra variable muy importante es cursor_over, que indica en que estado se encuentra actualmente el cursor, en referencia a la escena, los valores que puede tomar son:
enum { CURSOR_OVER_NOTHING=0, CURSOR_OVER_UNSELECTED_OBJECT, CURSOR_OVER_SELECTED_OBJECT, CURSOR_OVER_AXIS};
Y definen si el cursor no est encima de nada, esta encima de un objeto no seleccionado, encima de un objeto seleccionado, o est sobre el eje manipulador. La funcion Update() se invoca en cada movimiento del ratn, y se engarga de actualizar la forma del cursor en funcion de la variable cursor_over haciendo uso de la funcion GetIntersection(), la seleccin y la posicion de la boundingbox que la define asi como el eje manipulador.
void OSGSelection::Update(float x, float y, int w_width, int w_height) { osg::Node *node=NULL; osg::Group *parent=NULL; osg::NodePath nodepath; bool axis_target; if(selected_objects.size() > 0) { cursor_over = CURSOR_OVER_NOTHING; axis_target = UpdateAxis(x,y); // Comprobamos si el raton est encima de alguno // de los objetos seleccionados y en caso de estarlo // marcamos el cursor como que est seleccionando // en funcion de la accion actual. if(!axis_target) { GetIntersection(x,y,scene_root.get(), nodepath); if(nodepath.size()>1) { HTREEITEM hItem = tree->GetItemFromNodePath(nodepath); if(IsSelected(hItem)) cursor_over = CURSOR_OVER_SELECTED_OBJECT; else cursor_over = CURSOR_OVER_UNSELECTED_OBJECT; } } } else // ningun objeto seleccionado en pantalla {
228
Si existe algun objeto seleccionado, la funcion Update() realiza una llamada a UpdateAxis() para actualizar tambien el eje manipulador.
bool OSGSelection::UpdateAxis(float x, float y) { osg::NodePath nodepath; // Obtenemos la interseccion con los elementos del EJE auxiliar GetAxisIntersection(x,y, nodepath); if (nodepath.size() >0) { cursor_over = CURSOR_OVER_AXIS; osg::ref_ptr<osg::Node> node= nodepath[nodepath.size()-1]; if(node->getName() == "CONE_X") axisman.SetAxis(AXIS_X); else if(node->getName() == "CONE_Y") axisman.SetAxis(AXIS_Y); else if(node->getName() == "CONE_Z") axisman.SetAxis(AXIS_Z); else if(node->getName() == "PLANE_XY") axisman.SetAxis(AXIS_X | AXIS_Y); else if(node->getName() == "PLANE_ZX") axisman.SetAxis(AXIS_Z | AXIS_X); else if(node->getName() == "PLANE_ZY") axisman.SetAxis(AXIS_Z | AXIS_Y); return true; } return false; }
Los eventos del ratn son la principal herramienta de interaccion en el visor, por tanto es un elemento importante que debe de ser introducido:
void OSGSelection::OnLButtonDown(float x, float y, int w_width, int w_height, bool key_ctrl, bool key_shift) { osg::NodePath nodepath; width = w_width; height = w_height; // // // // // // // // // // Al hacer un click , comprobamos si el objeto sobre el que pulsamos esta seleccionado 1) Esta seleccionado a) Si esta pulsada la tecla CTRL Hacemos un Switch de ese objeto b) Sino , no hacemos nada, y no deseleccionaremos los demas objetos hasta el buttonUP siempre y cuando no hayamos hecho ningun DRAG 2) No esta seleccionaddo a) Si esta pulsada la tecla CTRL lo agregamos b) Sino, directamente lo seleccionamos SOLO A EL
GetIntersection(x,y, scene_root.get(), nodepath); if(key_shift && selected_objects.size()>0 && cursor_over == CURSOR_OVER_AXIS) { CloneAndSelectOnly();
229
La funcin OnLButtonDown() se invoca al pulsar el botn izquierdo del ratn, en funcin de lo que est seleccionando el cursor, o de lo que ya est seleccionado, y de la tecla del teclado que tengamos pulsada, el comportamiento puede ser distinto, as por ejemplo, si tenemos el cursor sobre el eje manipulador y existen objetos seleccionados y adems tenemos pulsada la tecla Shift, lo que conseguiremos ser clonar la seleccin actual.
void OSGSelection::OnLButtonUp(float x, float y, float dragx, float dragy, int w_width, int w_height, bool key_ctrl, bool key_shift) { osg::NodePath nodepath; width = w_width; height = w_height; if(dragx == 0 && dragy == 0) { GetIntersection(x,y, scene_root.get(), nodepath); if( cursor_over == CURSOR_OVER_SELECTED_OBJECT ) { // Hemos hecho click sobre un objeto! if(nodepath.size()>1) { HTREEITEM hItem = tree->GetItemFromNodePath(nodepath); if(hItem) {
230
Esta clase consta de una serie de nodos, Switches e informacin geomtrica que se irn activando y desactivando para el resalte cuando el cursor pase por encima de algun eje. Esta estructura presenta el siguiente aspecto de la siguiente figura 6.1.
231
La funcin SetAxis() es la encargada de activar y desactivar los distintos hijos de los Switches de OpenSceneGraph que darn al eje manipulador el comportamiento que queremos. Los hijos los identificaremos por un nmero:
#define #define #define #define #define #define #define CHILD_NORMAL_AXIS CHILD_X_AXIS CHILD_Y_AXIS CHILD_Z_AXIS CHILD_XY_AXIS CHILD_ZX_AXIS CHILD_ZY_AXIS 0 1 2 3 4 5 6
232
keyPress( Producer::KeyCharacter key); specialKeyRelease( Producer::KeyCharacter key); specialKeyPress( Producer::KeyCharacter key); mouseScroll(Producer::KeyboardMouseCallback::ScrollingMotion sm); mouseMotion( float mx, float my ) ; passiveMouseMotion( float mx, float my ) ; buttonPress( float mx, float my, unsigned int mbutton ); buttonRelease( float mx, float my, unsigned int mbutton ) ; doubleButtonPress(float mx, float my, unsigned int mbutton ) ;
233
HCURSOR crotate, ctranslate, ctranslateview, czoom, crotateview, cscale, cselect; HCURSOR ccursor; // Current bool must_redraw_cursor; bool lb_pressed; };
234
Veamos un ejemplo de accin, por ejemplo la llamada a setColor del StateAttribute FOG de OpenSceneGraph:
class ActSetFogColor : public OSGAction { public: ActSetFogColor(osg::Fog *_sa, const osg::Vec4 &_old, const osg::Vec4 &_new); ~ActSetFogColor(void); virtual void Execute(); virtual void Undo(); virtual std::string getActionString() { return std::string("Modificar Color Fog"); } osg::Vec4 old_value; osg::Vec4 value; osg::ref_ptr<osg::Fog> sa; };
OSGHistory::OSGHistory(void) { position = 0; }
235
236
Crearemos un nuevo proyecto para crear una DLL, que deber contener las funciones que ya hemos explicado:
#define PLUG_API __declspec(dllexport) extern extern extern extern "C" "C" "C" "C" PLUG_API PLUG_API PLUG_API PLUG_API OSGTabOutput* LibClassInstance(int i); int LibNumClasses(); std::string LibDescription(); int LibVersion();
PLUG_API OSGTabOutput* LibClassInstance(int i) { switch(i) { case 0: return new PluginCartoon(); break; } return NULL; } PLUG_API int LibNumClasses() { return 1; } PLUG_API std::string LibDescription() { std::string str; str = "Plugin de extension para agregar el Nodo de efectos FX da un aspecto 2D a la geometria 3D"; return str; } PLUG_API int LibVersion() { return OSGWORLD_VERSION; }
237
Contiene informacin acerca del fichero que se corresponde con el plugin, la ruta, la version con la que fue compilado, la descripcin del mismo, el manejador que nos ha devuelto, y la lista de objetos OSGTabOutput que contiene.
class OSGPluginManager { public: OSGPluginManager(void); ~OSGPluginManager(void); // Carga una DLL PluginInfo* LoadPlugin(std::string szFileName, std::string path=""); PluginInfo * GetPluginInfo(std::string filename); OSGTabOutput* GetPluginClass(std::string name); // libera una DLL ya cargada bool FreePlugin(std::string name); std::map<std::string, PluginInfo*> plugin_files; std::map<std::string, OSGTabOutput*> plugin_classes; };
Este gestor nos permite cargar el plugin, y acceder al mismo mediante el nombre del fichero, o tambien acceder al objeto tipo OSGTabOutput que nos interese obtener haciendo uso del nombre de la clase que nos interesa obtener.
typedef typedef typedef typedef OSGTabOutput* int std::string int (*PL_LIBCLASSINSTANCE)(int); (*PL_LIBNUMCLASSES)(void); (*PL_LIBDESC)(); (*PL_LIBVERSION)(void);
PluginInfo* OSGPluginManager::LoadPlugin(std::string szFileName, std::string path) { std::string full_path = path + szFileName; HMODULE hModule = LoadLibrary(full_path.c_str()); OSGTabOutput *obj = NULL; PluginInfo *inf=NULL; if (!hModule) return false; else { inf = new PluginInfo(); PL_LIBCLASSINSTANCE pClassInstance = (PL_LIBCLASSINSTANCE) GetProcAddress(hModule, _T("LibClassInstance")); PL_LIBNUMCLASSES pNumClasses = (PL_LIBNUMCLASSES) GetProcAddress(hModule, _T("LibNumClasses")); PL_LIBVERSION pVersion = (PL_LIBVERSION) GetProcAddress(hModule, _T("LibVersion")); PL_LIBDESC pDescription = (PL_LIBDESC) GetProcAddress(hModule, _T("LibDescription")); if (pClassInstance != NULL && pNumClasses != NULL) { int numclasses = pNumClasses(); inf->handle = hModule; inf->desc = pDescription(); inf->version = pVersion(); inf->file = szFileName; inf->path = path; if(!GetPluginInfo(szFileName)){ for(int i=0;i<numclasses;i++) {
238
239
240
Y ser la encargada de contener las instancias de todos los distintos gestores del sistema, asi como distintas funcionalidades globales.
class OSGActiveViewHandler { public: OSGActiveViewHandler(void); ~OSGActiveViewHandler(void); void ChangeView(osgUtil::SceneView *scnview, Producer::RenderSurface *surface, osg::Group * scn_root, OSGHistory *history, OSGSelection *selec); void SetMainFrame(CMainFrame *mf); void SetActiveSceneTree(int scene_ID); void SetActiveBar(CWnd *actbar); inline void SetRootNode(osg::Node *node, int scene_ID); void InitObjectTypes(); int InitBars(); void InitTabOutput(); void SaveBarStates(); void SaveToFile(std::string nom); osg::ref_ptr<osg::Node> CreateNode(std::string name); TreeNodeInfo *CreateTreeNode(std::string name); HTREEITEM AddNode(std::string node_name); HTREEITEM AddNodeWithHistory(std::string node_name, HTREEITEM hParent); HTREEITEM AddNode(std::string node_name, HTREEITEM hParent); HTREEITEM AddNode(TreeNodeInfo *tni, HTREEITEM hParent); void AddParentNode(std::string node_name); void DeleteNode(HTREEITEM hItem, int mirror_index); void CleanSubtree(HTREEITEM hItem, int mirror_index); void CopyNode(TreeNodeInfo *tni, TreeNodeInfo *newparent); void void void void void void void void SelectObject(HTREEITEM hItem, bool select=true); SelectObjectOnly(std::vector<HTREEITEM> &vec); SelectObjectOnly(HTREEITEM hItem); SelectObjectFromTree(HTREEITEM hItem, bool select=true); SelectObject(int x, int y); SelectObject(osg::Node * node, osg::Group *parent,bool select); SelectObject(TreeNodeInfo *node, TreeNodeInfo *parent, bool select); SelectAll(bool select);
void ShowTreeNodeInfo(TreeNodeInfo *tni, bool reset=true); void ShowTabOutput(OSGTabOutput *outp); void Exec(OSGAction *action, bool addtohistory=true);
241
inline void SetSelectedTni(TreeNodeInfo *tni); inline TreeNodeInfo * GetSelectedTni(); inline COSGTreeCtrl * GetTreeCtrl(); inline COSGTreeCtrl * GetTreeCtrl(int mirror_index); inline COSGTreeCtrl * GetTreeCtrl(int mirror_index, int scene_index); inline int GetBarIndex(CEditTreeCtrl *tree); inline int GetBarIndex(CTreeBar *treebar); // Supuestamente esta llamada se hace despues de crear un nuevo SceneTree int GetUniqueSceneID(); inline int GetSceneIndex(int scene_id); inline bool IsSceneActive(int scene_id); HTREEITEM GetMirrorItem(HTREEITEM hItem, int mirror_idx=0); // Globales y unicos CMainFrame *mainfr; OSGObjectTypeManager nodetypem; OSGObjectTypeManager objecttypem; OSGDockBarManager bar_manager; OSGParamManager param_manager; OSGTabOutputManager output_manager; OSGPluginManager plugin_manager; std::map<int, int> hash_sceneindex; int last_sceneID; // Dependientes del view activo osg::ref_ptr<osgUtil::SceneView> m_SceneView; osg::ref_ptr<Producer::RenderSurface> m_RenderSurface; osg::ref_ptr<osg::Group> scene_root; OSGHistory *m_History; OSGSelection *selection; CRITICAL_SECTION critical_section; TreeNodeInfo *last_tni; OSGMultiTreeBar m_wndSceneTree; CDebugBar m_wndDebug; CGridBar m_wndDataGrid; CPropSheetBar m_wndSheetBar; //Barra principal de control };
Como podemos ver, esta clase contiene el gestor de NodeTypes, el gestor de ObjectTypes, el Gestor de Bars, el Gestor de parmetros, el gestor de TabOutputs, el gestor de plugins, el gestor de TreeBars, el gestor de historia actual, y la seleccin de objetos, y una instancia de la barra principal que es un conjunto de pestaas, cada una con una funcionalidad diferente. Tambin contiene una referencia al visor actual y su superficie de render, as como el nodo raz de la escena del grafo de escena. Esta clase es la encargada de mostar la informacin de un nodo de un grafo de escena en el interfaz de usuario, lo que hace realmente esta funcin es mostrar los datos del nodo a travs de su NodeType:
void OSGActiveViewHandler::ShowTreeNodeInfo(TreeNodeInfo *tni, bool reset/*sin uso*/) { if(!tni->nodetype->DialogsCreated()){ param_manager.RecursiveCreateDialogs(tni->nodetype); } if(last_tni) { // Si son TIPOS de nodo distintos // regeneramos los controles if(last_tni->nodetype != tni->nodetype){ last_tni->nodetype->RecursiveClearRollupContent(); tni->nodetype->RecursiveGenerateRollupContent();
242
243
if (!m_wndDebug.Create(_T("Debug"), mainfr, CSize(180, 380), TRUE, FIRST_BAR_ID+2)) { TRACE0("Failed to create Debug\n"); return -1; } m_wndDebug.SetBarStyle(m_wndDebug.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndDebug.EnableDocking(CBRS_ALIGN_ANY); mainfr->DockControlBar(&m_wndDebug,AFX_IDW_DOCKBAR_LEFT); m_wndDebug.setCaption("Debug Output"); CreateControlBar(); if (mainfr->VerifyBarState(_T("OSGWORLD_BarState"))) { CSizingControlBar::GlobalLoadState(_T("OSGWORLD_BarState")); mainfr->LoadBarState(_T("OSGWORLD_BarState")); } }
Y crea la barra principal que contiene las distintas pestaas. Los Rollups son dilogos que permiten extenderse ms de lo que la pantalla ocupa, generando una especie de barra de Scroll en caso de extenderse ms de los lmites visuales de la aplicacin:
BOOL OSGActiveViewHandler::CreateControlBar() { CTabContainerDlg *p1 = new CTabContainerDlg(); CTabContainerDlg *p2 = new CTabContainerDlg(); CTabContainerDlg *p3 = new CTabContainerDlg(); CTabContainerDlg *p4 = new CTabContainerDlg(); CTabContainerDlg *p5 = new CTabContainerDlg(); m_wndSheetBar.AddRollup(p1, m_wndSheetBar.AddRollup(p2, m_wndSheetBar.AddRollup(p3, m_wndSheetBar.AddRollup(p4, m_wndSheetBar.AddRollup(p5, IDD_TAB_CONTAINER, IDD_TAB_CONTAINER, IDD_TAB_CONTAINER, IDD_TAB_CONTAINER, IDD_TAB_CONTAINER, IDI_ICON5); IDI_ICON6); IDI_ICON7); IDI_ICON8); IDI_ICON9);
// Creamos la barra y seguidamente creamos los rollups // (necesitan saber cual es su padre una vez creado) m_wndSheetBar.CreateWithRollups(_T("PropSheetBar"), mainfr, CSize(200, 380), TRUE, FIRST_BAR_ID+3); m_wndSheetBar.setCaption("Parametros"); m_wndSheetBar.SetBarStyle(m_wndSheetBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_wndSheetBar.EnableDocking(CBRS_ALIGN_ANY); mainfr->DockControlBar(&m_wndSheetBar);
return true; }
244
AttTypeFog()); AttTypeMaterial()); AttTypeBlendFunc()); AttTypeLight()); AttTypeTexEnv()); AttTypeTexGen()); AttTypeTexture()); AttTypeTexture2D()); AttTypeVertexProgram()); AttTypeFragmentProgram());
OSGNodeType *first = new TypeNode(); // Iniciamos la informacion de los parametros // de los nodos. nodetypem.RegisterType(first); nodetypem.SetDefaultType(first); nodetypem.RegisterType(new TypeGroup()); nodetypem.RegisterType(new TypeLOD()); nodetypem.RegisterType(new TypePagedLOD()); nodetypem.RegisterType(new TypeSwitch()); nodetypem.RegisterType(new TypeGeode()); nodetypem.RegisterType(new TypeSequence()); nodetypem.RegisterType(new TypeBillboard()); nodetypem.RegisterType(new TypeTransform()); nodetypem.RegisterType(new TypeDOFTransform()); nodetypem.RegisterType(new TypePositionAttitudeTransform()); nodetypem.RegisterType(new TypeMatrixTransform()); nodetypem.RegisterType(new TypeAutoTransform()); nodetypem.RegisterType(new TypeLightSource()); nodetypem.RegisterType(new TypeParticleSystemUpdater()); nodetypem.RegisterType(new TypeParticleProcessor()); nodetypem.RegisterType(new TypeEmitter()); nodetypem.RegisterType(new TypeModularEmitter()); nodetypem.RegisterType(new TypeFXEffect()); nodetypem.RegisterType(new TypeFXCartoon()); nodetypem.RegisterType(new TypeFXSpecularHighlights()); nodetypem.RegisterType(new TypeFXBumpMapping()); output_manager.RegisterTabOutput(new OutCreateNodes()); output_manager.RegisterTabOutput(new OutPlugins()); }
245
class COSGWorldView : public CView { public: static COSGWorldView * COSGWorldView::GetActiveView(); // Reemplazos public: virtual void OnDraw(CDC* pDC); void void void void
osg::ref_ptr<MFCKeyboardMouseCallback> m_KBMCallback; osg::ref_ptr<Producer::RenderSurface> m_RenderSurface; osg::ref_ptr<osgUtil::SceneView> m_SceneView; osgDB::DatabasePager* m_DatabasePager; BOOL m_bRenderSurfaceRealized; BOOL m_bModelLoaded; osg::Timer_t m_StartTick; // Frame Number unsigned int m_uiFrameNum; BOOL m_bGotFocus; // indice de la escena correspondiente a esta view // (se usa para el arbol) int scenetree_ID; OSGHistory m_History; osg::ref_ptr<osg::Group> scene_root; osg::ref_ptr<osg::StateSet> global_state_set;
246
Esta clase contiene distintos elementos necesarios para interactuar con OpenSceneGraph: La superficie de render necesaria para dibujar el grafo. El DatabasePager Un manejador de eventos de teclado y ratn La visualizacin del grafo de escena la escena La funcion de dibujado
Adems, contendr una referencia al nodo raz de la escena del grafo de escena y un StateSet global que nos permitir cambiar el modo de visualizacion del editor. Esta clase ser la que contenga la instancia real del gestor de Historia (dehacer / rehacer). El Manejador de la Vista Activa tan solo tendr una referencia al gestor de historia activo en ese momento. La funcin OnInitialUpdate es la que se encarga de inicializar todos los datos iniciales del grafo, incluyendo los datos auxiliares como es el Grid y el Eje manejador:
void COSGWorldView::OnInitialUpdate() { CView::OnInitialUpdate(); osg::ref_ptr<osg::Group> root = new osg::Group(); osg::ref_ptr<osg::Group> node_auxdata = new osg::Group(); osg::ref_ptr<osg::Group> node_selectdata = new osg::Group(); //osg::ref_ptr<osg::Switch> node_axisdata = new osg::Switch(); scene_root = new osg::Group(); osg::ref_ptr<osg::PositionAttitudeTransform> transf2 = new osg::PositionAttitudeTransform(); // La estructura basica del grafo de escena // es un nodo raiz del que cuelgan dos nodos // scene, que es el nodo que representa la escena // y auxdata, que es informacion "invisible" que // ser utilizada por el editor, transparente al usuario root->setName("raiz"); scene_root->setName("escena"); node_auxdata->setName("auxdata"); node_selectdata->setName("selectdata"); // CREAMOS EL GRID osg::ref_ptr<osg::Group> ref_grid00 = OSGBasicShapes::MakeGrid(2000,5); osg::ref_ptr<osg::Group> ref_grid0 = OSGBasicShapes::MakeGrid(2000,10); osg::ref_ptr<osg::Group> ref_grid1 = OSGBasicShapes::MakeGrid(4000,20); osg::ref_ptr<osg::Group> ref_grid2 = OSGBasicShapes::MakeGrid(8000,40); osg::ref_ptr<osg::Group> ref_grid3 = OSGBasicShapes::MakeGrid(12000,80); osg::ref_ptr<osg::LOD> ref_LOD = new osg::LOD(); ref_LOD->addChild(ref_grid00.get()); ref_LOD->addChild(ref_grid0.get()); ref_LOD->addChild(ref_grid1.get()); ref_LOD->addChild(ref_grid2.get()); ref_LOD->addChild(ref_grid3.get()); ref_LOD->setRange(0, 0,500); ref_LOD->setRange(1, 500,1000); ref_LOD->setRange(2, 1000,2000); ref_LOD->setRange(3, 2000,4000); ref_LOD->setRange(4, 4000,12000); node_selectdata->addChild(ref_LOD.get()); node_auxdata->addChild(node_selectdata.get()); node_auxdata->addChild(m_KBMCallback->selection.GetAxis()->GetRootNode().get()); root->addChild(scene_root.get()); root->addChild(node_auxdata.get());
247
248
Esta referencia identifica el dato que estamos mostrando actualmente en el panel de comandos. 249
No existi ningun problema hasta que nos encontramos con el objeto osgParticle::Particle. Este objeto no deriva de ningun otro, y adems, es un objeto importante a la hora de trabajar con sistemas de partculas. La solucin que se decidi adoptar fue crear una nueva clase que encapsulase la anterior y derivase de Referenced:
class RefParticle : public osg::Object { public: RefParticle(){}; RefParticle(osgParticle::Particle &part){Set(part);} RefParticle(osgParticle::Particle *part){Set(part);} inline void Set(osgParticle::Particle *part; inline void Set(const osgParticle::Particle ∂ inline osgParticle::Particle *GetParticle(); virtual Object* cloneType() const; virtual Object* clone(const osg::CopyOp& cp) const; virtual const char* libraryName() const{return "osg";} virtual const char* className() const{return "Particle";} protected: virtual ~RefParticle(){} osgParticle::Particle particle; };
De esta manera podremos trabajar con este tipo de dato. Tan solo tendremos que realizar una llamada a la funcin GetParticle() para acceder a los datos en s.
250
Pero como a nosotros nos interesa que la escena contine mostrndose indefinidamente, para poder apreciar los cambios que se produzcan en la escena al modificar los parmetros de cualquier nodo o cualquier tipo de dato, eliminamos la condicin del bucle y lo dejamos de manera indefinida. Consecuencia : La aplicacin se ralentiza y es imposible manipular los controles. Una posible solucin era indicar a la View que repintase la escena al modificar cualquier parmetro del panel de comandos. El problema de esto es que una vez hemos salido de este bucle, es imposible ponerse en contacto directo con la clase View, puesto que es un hilo que gestiona las MFCs y no permite el acceso. Se intent almacenar algun puntero a esta clase pero dab error de ejecucin o enviar algn tipo de mensaje pero no llegaban. Optamos como ltimo recurso establecer un Timer cuando este bucle terminase. Del mismo modo, cuando volvamos a entrar en el bucle, lo primero que haremos ser eliminar el Timer. De esta manera el usuario tiene siempre la impresin de que la escena est en continuo movimiento, sin afectar en absoluto al resto de la aplicacin.
LRESULT COSGWorldView::OnStartRendering(WPARAM,LPARAM) { KillTimer(scenetree_ID); while (m_bGotFocus) { DoFrame(); MSG msg; if (::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) { AfxGetApp()->PumpMessage(); } } if(scenetree_ID >= 0) { if(OSGAVH->IsSceneActive(scenetree_ID)) { SetTimer(scenetree_ID,17,NULL); } } return 0; }
251
Pero eso no es todo, si al deshacer la accin, continuamos deshaciendo acciones, podremos encontrarnos alguna accin que haga referencia al tem del rbol que ya no existe. Una solucin es utilizar la clase ActionNode para identificar a un elemento del grafo. Esta clase almacena el puntero al nodo del editor y el ndice de la instancia que representa tal nodo. De esta manera, cuando eliminemos un nodo y lo volvamos a crear, aunque si referencia en el rbol sea distinta, el valor del ActionNode se mantendr constante y nos permitir identificar de manera nica el elemento del rbol.
class ActionNode { public: ActionNode(){}; ~ActionNode(){}; inline HTREEITEM Item(){return tni->GetTreeItem(index);} void Set(TreeNodeInfo *tn, int idx){ tni=tn;index=idx;} TreeNodeInfo *tni; int index; };
252
PARTE VII
APLICACIONES DE PRUEBA
253
254
INDICE
PARTE VII......................................................................................................
7.1 Introduccin ...................................................................... Error! Marcador no definido. 7.2 El editor OSGWorld.......................................................... Error! Marcador no definido. 7.2.1 Especificacin de los elementos del Interfaz grfico. Error! Marcador no definido. 7.2.1.1 La barras de menus.............................................. Error! Marcador no definido. 7.2.1.2 La barra principal de herramientas...................... Error! Marcador no definido. 7.2.1.3 La barra de nodos. ............................................... Error! Marcador no definido. 7.2.1.4 Los paneles de comandos .................................... Error! Marcador no definido. 7.2.1.5 La barra de rbol ................................................. Error! Marcador no definido. 7.2.1.6 El Visor 3D.......................................................... Error! Marcador no definido. 7.3 Ejemplos de escenas mediante el uso del editor................ Error! Marcador no definido. 7.3.1 Utilizacin de Sistemas de partculas para crear fuego y humo. Error! Marcador no definido. 7.3.2 Utilizacin de las Luces. ............................................ Error! Marcador no definido. 7.3.3 Efecto Cartoon ........................................................... Error! Marcador no definido. 7.3.4 Efecto BumpMapping ................................................ Error! Marcador no definido. 7.3.5 Efecto de Specular Highlights.................................... Error! Marcador no definido. 7.3.6 Instanciacin multiple ................................................ Error! Marcador no definido. 7.3.7 Efecto de niebla.......................................................... Error! Marcador no definido. 7.3.8. Ejemplo de utilizacion de Shaders ............................ Error! Marcador no definido.
255
256
7.1 Introduccin
Hasta ahora se han desarrollado todos los elementos necesarios para el correcto funcionamiento de la aplicacin. En este captulo, se pretende demostrar la funcionalidad del trabajo realizado, asi como introducir tanto los elementos del interfaz, como los conceptos bsicos para el manejo de la aplicacin, y mostrar algunos ejemplos que se han podido realizar como prueba.
257
Un marco de ventana con botones de minimizar, maximizar y cerrar. Las barras de menus, dando acceso a distintas acciones sobre el editor. Una barra principal de herramientas, con distintos accesos a las acciones ms comunes en la utilizacin del editor. Una barra de nodos para la creacin directa de nodos en el grafo de escena. Una barra de rbol duplicable (se pueden mostrar tantas como se quiera) donde se muestra el grafo actual de escena. Una barra de depuracion, donde se muestra informacin de depuracin del programa. Los paneles de comandos, que consta de 5 paneles, cada uno con una funcionalidad distinta. El visor principal, donde se muestra la representacion final de la geometria del grafo es escena.
La barra de mens se encuentra directamente debajo de la barra de ttulo de la ventana principal. El ttulo de cada men indica la finalidad de los comandos que contiene. Todos los mens siguen las convenciones estndar de Microsoft Windows. Al seleccionar un men, se abre un men desplegable que muestra varios comandos. Como alternativa al uso del ratn (u otro dispositivo sealador), cada nombre de men incluye un carcter subrayado. Al presionar la tecla correspondiente junto con la tecla ALT, el men se abre. Los comandos de los mens abiertos normalmente tienen tambin un carcter subrayado. Mientras el men est abierto, puede presionar la tecla correspondiente al carcter para que el comando se ejecute. Los puntos suspensivos () al final de un comando indican que abre un cuadro de dilogo. Una flecha hacia la derecha despus de un comando indica la aparicin de un submen. Si un comando tiene un mtodo abreviado del teclado, se muestra en el men a la derecha del nombre del comando. Los comandos de men que pueden conmutarse indican su estado mediante una marca de verificacin. El menu Archivo Nuevo: permite crear una nueva escena, con su grafo de escena correspondiente. Abrir: abre un fichero de grafo de escena. Insertar Fichero: Insertar un fichero en la escena actual. Cerrar: Cierrra la escena actual. Guardar: Guarda la escena actual. Guardar como: Permite guardar la escena actual con un nombre de fichero distinto al que ya tiene. Listado de archivos recientes: Muestra una lista de los ltimos 5 archivos cargados en el editor.
258
Menu Edicin
Deshacer: El comando Deshacer invierte la ltima operacin realizada con el objeto u objetos seleccionados. Rehacer: Invierte la ltima operacin realizada por el comando Deshacer. Cortar: Corta los elementos seleccionados en el rbol al portapapeles. Copiar: Copia de manera instanciada los elementos seleccionados en el arbol al portapapeles. Copiar Duplicado: Copia de manera duplicada los elementos seleccionados en el arbol al portapapeles. Pegar: Pega el contenido del portapapeles en funcion de la operacin de copiado. Replicar seleccin: Crear una rplica exacta de la seleccin (instanciada), y desplazada de la original.
Menu Ver Barra de herramientas: Muestra u oculta la barra de herramientas principal de la aplicacin. Barra de estado: Muestra u oculta la barra de estado de la aplicacin. Barra de Nodos: Muestra u oculta la barra de nodos de la aplicacin. Barra de paneles: Muestra u oculta la barra paneles de la aplicacin. Ventana de depuracin: Muestra u oculta la ventana de depuracin de la aplicacin.
259
Menu Escena Nuevo rbol: Crea una nueva barra conteniendo el rbol del grafo de escena. Seleccionar por nombre: Muestra un dilogo de seleccin de nodos por nombre. Centrar seleccin: Centra la seleccin de objetos actual del visor en pantalla. Seleccionar: Activa el modo Seleccionar. Trasladar: Activa el modo Trasladar. Rotar: Activa el modo Rotar. Escalar: Activa el modo Escalar.
260
Menu Representacin Este menu permite cambiar los distintos aspectos de representacion del visor.
Modo o Wireframe: Activa el modo de visualizacion de poligonos en alambre. o Relleno: Activa el modo de visualizacion de poligonos en relleno. Sombreado o Plano: Activa el modo de sombreado plano. o Suavizado: Activa el modo de sombreado suavizado. Vistas o Superior: Muestra la vista superior de la escena. o Inferior: Muestra la vista inferior de la escena. o Izquierda: Muestra la vista lateral izquierda de la escena. o Derecha: Muestra la vista lateral derecha de la escena. o Frontal: Muestra la vista frontal de la escena. o Trasera: Muestra la vista trasera de la escena.
Menu Nodos Permite crear distintos tipos de nodos predeterminados del editor en el grafo de escena como hijos del nodo actualmente seleccionado en el rbol. Estos comandos no funcionarn si no existe ningn elemento seleccionado en el rbol.
261
Menu Ventana: Nueva ventana: Crea una nueva escena. Cascada: Organizar las ventanas para que se superpongan. Mosaico: Organizar las ventnas en mosaico Organizar iconos: permite organizar los iconos en la parte inferior de la ventana. Submenu ventanas: permite seleccionar la escena activa.
Menu Ayuda: Temas de ayuda: Muestra los temas de ayuda. Acerca de OSGWorld: Muestra el dialogo de Acerca de
La barra de herramientas principal predeterminada ofrece acceso rpido a herramientas y cuadros de dilogo para muchas de las tareas comunes del programa.
Nuevo: permite crear una nueva escena, con su grafo de escena correspondiente. Abrir: abre un fichero de grafo de escena. Guardar: Guarda la escena actual. Cortar: Corta los elementos seleccionados en el rbol al portapapeles. Copiar: Copia de manera instanciada los elementos seleccionados en el arbol al portapapeles. Copiar duplicado: Copia de manera duplicada los elementos seleccionados en el arbol al portapapeles. Pegar: Pega el contenido del portapapeles en funcion de la operacin de copiado.
Deshacer: El comando Deshacer invierte la ltima operacin realizada con el objeto u objetos seleccionados. Rehacer: Invierte la ltima operacin realizada por el comando Deshacer.
262
Nuevo rbol: Crea una nueva barra conteniendo el rbol del grafo de escena. Seleccionar: Activa el modo Seleccionar. Seleccionar por nombre: Muestra un dilogo de seleccin de nodos por nombre. Trasladar: Activa el modo Trasladar. Rotar: Activa el modo Rotar. Escalar: Activa el modo Escalar. Insertar fichero: Insertar un fichero en la escena actual. Rotar Vista: Activa el modo de rotar la vista. Desplazar Vista: Activa el modo de desplazar la vista. Centrar seleccin: Centra la seleccin de objetos actual del visor en pantalla.
Nodo Projection: Inserta un nodo Projection como hijo del nodo actual. Nodo LOD: Inserta un nodo LOD como hijo del nodo actual.
263
Nodo Geode: Inserta un nodo Geode como hijo del nodo actual. Nodo LightSource: Inserta un nodo LightSource como hijo del nodo actual. Nodo Switch: Inserta un nodo Switch como hijo del nodo actual. Nodo MatrixTransform: Inserta un nodo MatrixTransform como hijo del nodo actual. Nodo Cartoon: Inserta un nodo Cartoon como hijo del nodo actual. Nodo Group: Inserta un nodo Group como hijo del nodo actual. Nodo PositionAttitudeTransform: Inserta un nodo PositionAttitudeTransform como hijo del nodo actual. Nodo Sequence: Inserta un nodo Sequence como hijo del nodo actual. Nodo Billboard: Inserta un nodo Billboard como hijo del nodo actual. Nodo ParticleSystemUpdater: Inserta un nodo ParticleSystemUpdater como hijo del nodo actual. Nodo ModularEmitter: Inserta un nodo ModularEmitter como hijo del nodo actual. Nodo FluidProgram: Inserta un nodo FluidProgram como hijo del nodo actual. Nodo SpecularHighlights: Inserta un nodo SpecularHighlights como hijo del nodo actual. Nodo AutoTransform: Inserta un nodo AutoTransform como hijo del nodo actual. Nodo BumpMapping: Inserta un nodo BumpMapping como hijo del nodo actual. Nodo AutoTransform: Inserta un nodo AutoTransform como hijo del nodo actual.
264
Panel Crear: Permite seleccionar de una lista cualquiera de los nodos soportados por el editor para crear uno nuevo colgando del nodo actualmente seleccionado en el arbol.
Panel Nodos: Permite manipular los parmetros de los nodos del grafo. Cada escaln en el rbol de jerarquia del nodo se representa por un grupo distinto, pudiendo modificar los parmetros de manera independiente a medida que el nodo va aumentando su complejidad.
265
Panel StateSet: Permite crear o eliminar StateAttributes al StateSet de un nodo o un Drawable y modificar sus parmetros. En este panel los StateAttributes se van a diferenciar en StateAttributes normales y StateAttributes de textura. Se pueden agregar nuevos atributos de los soportados por el editor pulsando sobre Agregar Atributo, asi como eliminarlos del StateSet.
Cada atributo tendr asociados ciertos modos, cuyos valores podemos modificar, asi como agregar nuevos, todos ellos relacionados con OpenGl.
266
Panel Plugins: Muestra un listado de los plugins cargados por el editor asi como informacion adicional sobre cada uno de ellos.
Panel Utilidades: Este panel est disponible para los programadores de plugins.
La siguiente captura del editor muestra un ejemplo de dos vistas de rbol simultneas de una misma escena.
267
Figura 7-10. Visualizacin de varias vistas simultneas del rbol del grafo de escena.
El rbol adems permite la pulsacion del botn derecho del ratn sobre los elementos mostrando un men contextual de Opciones: Seleccionar: Selecciona en el visor los elementos del rbol seleccionados. Agregar a seleccin: Agrega a la seleccin en el visor los elementos del rbol seleccionados. Eliminar: Elimina los elementos del arbol seleccionados. Ordenar: o Nivel Actual: Ordena alfabticamente el nivel actual de los nodos seleccionados en el rbol. o Nivel actual y debajo: Ordena alfabticamente el nivel actual de los nodos seleccionados en el rbol y sus descendientes. Seleccionar todos: Selecciona todos los elementos del rbol. Seleccionar ninguno: Deselecciona todos los elementos del rbol. Expandir subrbol: Expande el subrbol que contiene el elemento actual del rbol en caso de estar contraido. Contraer subrbol: Contrae el subrbol que contiene el elemento actual del rbol en caso de estar expandido.
268
7.2.1.6 El Visor 3D
El visor es el rea de la aplicacin donde se muestra en tiempo real la representacin final de la geometria del grafo es escena. Acciones sobre el editor El visor permite cierta interaccin directa con el usuario haciendo uso del teclado y el ratn de manera conjunta y con ayuda del eje manipulador.
Al seleccionar uno o ms objetos en el visor, automticamente nos aparecer un eje auxiliar como el de la figura. Este eje nos permitir aplicar transformaciones a la seleccin actual sobre el eje o los ejes iluminados de manera simultnea (plano). Las acciones que podemos realizar sobre el visor son las siguientes: Seleccionar objetos: Se pueden seleccionar objetos pulsando simplemente sobre ellos. Agregar objetos a la seleccin actual: Se pueden agregar objetos a la seleccin actual manteniendo pulsada la tecla CTRL y pulsando sobre el objeto que queremos seleccionar. Trasladar objetos: Con el modo de trasladar activo, podemos desplazar el objeto libremente por el espacio 3D haciendo uso del eje manipulador, de esta manera podremos desplazar el objeto en cualquie de estos 3 ejes, y en cualquiera de sus combinaciones que formen un plano. Rotar Objetos: Con el modo de rotar activo
269
podemos rotar objetos alrededor de si mismos sobre cualquiera de los 3 ejes, o sobre dos ejes simultneos. Escalar Objetos: Con el modo escalar activo o Escalado con ayuda del eje manipulador: Podemos rotar objetos alrededor de s sobre cualquiera de los 3 ejes, o sobre dos ejes simultneos. o Escalado uniforme: Si mantenemos pulsada la tecla maysculas podremos escalar el objeto de manera uniforme independientemente de los ejes seleccionados en el eje manipulador. Clonar objetos: Se pueden clonar todos los objetos de una seleccin manteniendo pulsada la tecla maysculas a la vez que hacemos una traslacin. El resultado se puede apreciar en la Figura 7.8. Mostrar los parmetros de un objeto: Se puede forzar la seleccin del objeto actual del rbol del grafo para mostrar sus parmetros en el panel de Nodos haciendo doble click sobre el objeto que queramos en el visor.
270
271
272
273
274
PARTE VIII
CONCLUSIONES
275
276
INDICE
PARTE VIII ....................................................................................................
8.1 Conclusiones ..................................................................... Error! Marcador no definido. 8.2 Trabajos futuros................................................................. Error! Marcador no definido. 8.3 Comparativa con OSGEdit................................................ Error! Marcador no definido.
277
8.1 Conclusiones
Con todo esto, podemos concluir haber cumplido con los objetivos planteados al inicio del proyecto: Hemos construido un interfaz amigable, dinmico y sencillo de manejar. Adems, la barra de paneles de comandos guarda un gran parecido con la barra del panel de comandos de 3D Studio Max, por lo que los usuarios de este programa estarn muy familiarizados con algunos aspectos de la aplicacin. Hemos conseguido mostrar el grafo en una estructura de rbol, permitiendo copiar, cortar, duplicar, y pegar nodos, unos dentro de otros o como hermanos, a golpe de ratn (arrastrando elementos) o de teclado. Adems, podemos estableces tantas vistas simultneas del rbol como queramos, lo cual facilitar en gran medida la manipulacin de rboles que representen grafos de escena muy pesados. Se ha conseguido parametrizar las estructuras de datos de OpenSceneGraph en el panel de comandos antes mencionado. Esto permite al usuario realizar ajustes de parmetros de manera sencilla. Podemos manipular la escena directamente, aplicando transformaciones a los objetos, copindolos o duplicndolos e incluso eliminndolos directamente de la pantalla. Adems, hemos conseguido hacer uso del eje manipulador, al igual que el 3D Studio Max, y conseguir que las traslaciones se hagan al punto donde el ratn se desplaza, de este modo, hemos conseguido que el usuario tenga la impresin de estar realmente moviendo objetos por la pantalla. Hemos conseguido que la mayora de acciones puedan ser invertibles, incluso en aquellos casos en los que la accin requiera eliminar objetos. De este modo, estamos ahorrando al usuario el tiempo que podra dedicar a corregir muchos errores que se cometen en el manejo de aplicaciones, y que podra costarnos mucho mas tiempo del que pensamos. Hemos dotado a la aplicacin de un sistema de plugins, proporcionando un conjunto de libreras o Kit de Desarrollo, que permitirn al desarrollador implementar nuevas funcionalidades en el programa de una manera sencilla, y con un mnimo esfuerzo.
Como conclusiones personales del alumno, podemos destacar que se ha conseguido familiarizar con el entorno de programacin Visual .NET, se ha aprendido a fondo el funcionamiento de la librera OpenSceneGraph, y se ha profundizado en la utilizacin de estructuras de datos en C++. Del mismo modo, se han adquirido nuevos conocimientos sobre la programacin en Windows, y ms concretamente sobre las MFC, la generacin de controles, y las peculiaridades propias de esta librera. Por ltimo, destacar los grandes conocimientos adquiridos en cuanto al desarrollo de aplicaciones altamente modulares, y ampliables gracias a un sistema de carga y desarrollo de plugins.
278
279
Funcionalidad Representacin en rbol del grafo de escena. Copiar y pegar nodos sobre el rbol Duplicar nodos Arrastrar nodos sobre el rbol Crear cualquier tipo de nodo soportado en la aplicacin. Visualizacin mltiple del rbol Mapeado de parmetros de tipos de datos Adicin de StateAttributes Transformacin inteligente de Geodes Transformacin de Geodes mediante eje manipulador Soporte de Vertex y Program Shaders Sistema deshacer/rehacer Unir el grafo con un fichero Posibilidad de desarrollo de plugins Ventanas dockables Posibilidad de abrir varias escenas simultneas
OSGEdit
OSGWorld
280
PARTE IX
BIBLIOGRAFIA
281
282
Bibliografa.
Libros: [1] Marcos Fernndez, apuntes de las asignaturas Informtica Grfica y Ampliacin de Informtica Grfica. Ao 2004. [2] Deitel & Deitel. Cmo programar C++. Prentice Hall. [3] Jeffrey Richter. Programacin Avanzada en Windows. Microsoft Press. [4] Richard C. Leinecket y Tom archer. La Biblia de Microsoft Visual C++ 6.0. Anaya multimedia. Ao 1999. [5] Herbert Schildt. Programacin con MFC 6.0. Osborne McGraw-Hill. Ao 1999. [6] James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes. Computer Graphics, Principles And Practice. Second Edition. IBM Editorial Board. [7] Alan Watt, Mark Watt. Advanced Animation And Rendering Techniques, Theory And Practice. Addison-Wesley Publishing Company. [8] Jackie Neider, Tom Davis, Mason Wood. OpenGL Programming Guide, The official guide to learning OpenGL (Release 1). Addison-Wesley Publishing Company. [9] James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes, Richard L. Phillips, Introduccin a la graficacin por computador. Addison-Wesley Ibero-Americana. [10] Bernie Reahl. El creador de mundos virtuales. Anaya multimedia. Ao 1994. [11] R. Stuart Ferguson. Practical algorithms for 3d computer graphics. Paperback. [12] Andrew S. Glassner. An Introducing to Ray Tracing. Academic Press. [13] Martin Brownlow. Game programming golden rules. Paperback. [14] Richard S. Wright Jr. Michael Sweet. Programacin en OpenGL. Anaya multimedia. Ao 1996. [15] Christopher Lampton. Vuelos de fantasa. Anaya Multimedia. Ao 1993. [16] T. Akenine-Mller and E Haines. Real-Time Rendering, 2nd edition, Junio 2002.
[17] Wolfgang Engel. Programming Vertex & Pixel Shaders. Paperback. [18] Sebastian St-Laurent. Shaders for Game Programmers and Artists. Paperback. Online: [19] Microsoft. Microsoft Developer Network (MSDN) Library Visual Studio. Versin Junio 2006.
283
[20] Autodesk. 3D Studio MAX Software Development Kit Help (SDK). Versin 5.1.
U U
[21] Miguel Lozano, Carlos caldern. Entornos virtuales 3D clsicos e inteligentes: hacia un nuevo marco de simulacin para aplicaciones grficas 3D interactivas. Departmento de Informtica, Universidad de Valencia.
U U U
[22] George Eckel, Ken Jones, Tammy Domeier. OpenGLPerformer Getting Started Guide. Version 3.2. Silicon Graphics, Inc. Ao 2004.
U U
[23] George Eckel,Ken Jones. OpenGLPerformer Programmers Guide. Version 3.2. Silicon Graphics, Inc. Ao 2004.
U U
284
[46] http://www.realityprime.com/scenegraph.php/ Artculo sobre los grafos de escena. Avi Bar-Zeev. Scenegraphs: Past, present and future.
H H
[47] http://www.3dscenegraph.com/ Portal sobre los distintos grafos de escena disponibles actualmente, y gran cantidad de artculos relacionados.
H H
285