Sistemas de partículas
De IberOgre
Los sistemas de partículas son la base de la mayoría de efectos visuales en las aplicaciones desarrolladas con Ogre. Gracias a este sistema, podrás reproducir explosiones, colocar nubes de humo, destellos para tus hechizos y un enorme etcétera. Al igual que el resto de subsistemas de Ogre, las posibilidades son bastante elevadas y ahí es donde radica su complejidad. En este artículo trataremos los conceptos básicos de los sistemas de partículas y conoceremos los mecanismos básicos para manejarlos dentro de nuestra aplicación. Ofreceremos unas pequeñas directrices para poder crear scripts de partículas y haremos referencia a la herramienta libre Particle Editor.
Contenido |
Requisitos previos
Los sistemas de partículas se apoyan en varios de los temas y conceptos que hemos ido conociendo a lo largo de IberOgre y la lista de dependencias va creciendo poco a poco, tal y como cabría pensar.
- Gestión de recursos: las partículas pueden emplear texturas, materiales por lo que un conocimiento básico del sistema de gestión de recursos de Ogre es imprescindible. De hecho, los sistemas de partículas se tratan como un tipo más de recurso.
- Creación básica de escenas: en los ejemplos de todo el artículo crearemos nodos y los gestionaremos dentro de la escena, por tanto, es necesario que conozcas los mecanismos del árbol de escena de Ogre.
- Manejo básico de OIS: algunos de los ejemplos de este texto serán interactivos por lo que deberás conocer cómo funciona la biblioteca de gestión de entrada que utilizamos en la wiki, OIS.
Conceptos básicos
Como ya se ha mencionado al comienzo de este artículo, los sistemas de partículas nos ayudan a crear efectos especiales para nuestra aplicación en Ogre. Si bien es posible prescindir de las partículas para conseguir algunos efectos, suelen simplificar enormemente el proceso. Además, proporcionan una versatilidad importante y consiguen acelerar el desarrollo. En definitiva, si deseamos introducir efectos como humo, llamas, destellos propios de hechizos o similares, deberíamos dirigir nuestras miras a los sistemas de partículas.
Basados en scripts
Los sistemas de partículas suelen estar definidos en scripts de texto plano, algo similar a lo que ocurre con los materiales. Por supuesto, es posible utilizar las clases y métodos de Ogre para crearlos dentro del código pero no es una muy buena idea. Utilizar scripts nos permite separar el código de los datos de nuestro juego y, cualquier cambio en el sistema de partículas, no implicará una recompilación de la aplicación. El uso de scripts facilita el trabajo a los artistas y permite que herramientas externas trabajen sobre ellos.
Partículas en la escena
Al igual que las entidades, las partículas se adjuntan a los nodos de la escena. Esto implica que las transformaciones que le apliquemos a los nodos también afectarán a las partículas adjuntas (traslaciones, rotaciones y escala). Podemos tener un sistema de partículas que emita humo en una dirección, si lo rotamos, la dirección de emisión cambiaría de forma acorde. Por supuesto, si movemos el nodo, la fuente emisora también se desplazará dejando atrás las partículas ya emitidas. Esto podría resultar muy útil si queremos ir dejando un rastro: al mover una antorcha encendida, el tubo de escape de un vehículo, etc.
Estructura y propiedades de los sistemas de partículas
En esta sección haremos un recorrido por la estructura básica de los sistemas de partículas y conoceremos el significado de sus propiedades más reseñables. Esta estructura y propiedades se traducirá posteriormente en los mencionados scripts, los cuales tienen una sintaxis muy similar a la de los materiales. Tal y como indica el gráfico, un sistema de partículas puede estar compuesto por uno o más Emitters y uno o más Affectors.
Entre las propiedades más reseñables a nivel general de los sistemas de partículas se encuentran:
- material: nombre del material que utilizan cada una de las partículas del sistema.
- particle_width: ancho de las partículas en unidades del mundo (por defecto 10).
- particle_height: alto de las partículas en unidades del mundo (por defecto 10).
- sorted: true para ordenar las partículas con respecto a la cámara y false para no hacerlo (por defecto es false). Ordenar las partículas ofrece resultados más realistas pero, lógicamente conlleva una carga computacional bastante importante.
- local_space: por defecto su valor es false y significa que al mover el nodo de un sistema de partículas, sólo se trasladarán los emisores y no las partículas ya emitidas. Si deseamos que las partículas viajen con los emisores debemos indicar true en esta propiedad.
- quota: número de máximo de partículas en un momento dado dentro del sistema, si se llega al límite, no se emitirán más partículas hasta que algunas se consuma. Su valor por defecto es 10.
Esta lista de propiedades no está completa, si deseas buscar más posibilidades de configuración para tu sistema de partículas puedes consultar la traducción del manual de referencia de Ogre. El siguiente ejemplo muestra la estructura básica y las propiedades de un sistema de partículas. Atención porque no cuenta con ningún Emitter ni Affector, por lo que no desplegaría ninguna partícula.
particle_system Prueba
{
material Fuego
particle_width 1
particle_height 1
quota 1000
}Emitters
El concepto de los Emitters (emisores) es tremendamente sencillo, simplemente son las entidades que emiten las partículas. Como hemos visto, podemos tener más de un emisor por sistema de partículas. Cada emisor cuenta con un tipo que define el área por el que se mueven sus partículas así como la fuente de las mismas:
- Point: se emiten las partículas desde un único punto.
- Box: se emiten las partículas desde cualquier punto dentro de un caja rectangular de dimensiones determinadas. Cuenta con los parámetros width, height y depth que definen sus dimensiones.
- Cylinder: las partículas son emitidas dentro de un volumen cilíndrico. Posee los mismos parámetros que Box.
- Ellipsoid: en este caso, las partículas se mueven dentro de un elipsoide. Los elipsoides son similares a los cilindros pero tienen un hueco, por tanto necesitan los parámetros inner_width, inner_height e inner_depth.
- Ring: en el último tipo, las partículas viajan por el interior de un anillo o toro. Los toros necesitan dos parámetros adicionales con respecto a las cajas: inner_width e inner_height.
Las propiedades más reseñables de los Emitters se listan a continuación. Para detalles adicionales, lo mejor es consultar el manual en español.
- angle: ángulo máximo en grados con el que las partículas pueden desviarse de la dirección principal del emisor, por defecto vale 0.
- colour: color para todas las partículas emitidas en formato "r g b a" con valores reales de 0 a 1.
- colour_range_start: idéntico al atributo color aunque utilizado en degradados, color de comienzo.
- colour_range_end: idéntico al atributo color aunque utilizado en degradados, color de final.
- direction: vector dirección que indica hacia donde se emiten las partículas, es relativo al nodo al que está adjunto el sistema.
- emission_rate: número de partículas por segundo emitidas, está limitado por el atributo "quota" del sistema, por defecto vale 10.
- position: posición del emisor dentro del nodo al que iría asociado el sistema de partículas.
- velocity: establece una velocidad constante para todos las partículas del emisor medida en unidades por segundo. Si se desea establecer un intervalo, es necesario utilizar velocity_max y velocity_min.
- time_to_live: tiempo de vida en segundos para cada partícula, si se quiere ofrecer un intervalo es necesario utilizar time_to_live_min y time_to_live_max.
A continuación se muestra un ejemplo de sistema de partículas en formato script con un emisor sencillo de tipo caja.
particle_system Prueba2
{
material Fuego
particle_width 1
particle_height 1
quota 1000
emitter Box
{
width 20
height 10
depth 15
angle 45
emission_rate 10
time_to_live 4
direction 0 1 0
velocity 2
color 1 0 0 0
}
}Affectors
Los Affectors son actuadores que cambian parámetros de partículas ya emitidas. Por ejemplo, podemos hacer que las partículas se vean afectadas por la gravedad, por el viento, que cambien de color conforme avanza el tiempo y un gran número de variaciones adicionales. Existen varios tipos de Affectors, a continuación pasaremos a comentar algunos de ellos.
LinearForce
Como su propio nombre indica, este Affector aplica una fuerza lineal al sistema de partículas completo. Cuenta con un vector que indica la dirección y la magnitud de dicha fuerza y algún parámetro adicional.
- force_vector: vector de la forma "x y z" indicando la dirección y el módulo de la fuerza a aplicar.
- force_application: por defecto su valor es "add" que indica que la fuerza se le aplicará a la velocidad actual de cada partícula, lo que puede resultar en una velocidad infinita con el paso del tiempo. Si le asignamos "average" la velocidad de las partículas se estabilizará.
En el siguiente ejemplo vemos el script de partículas anterior con un Affector de tipo LinnearForce:
particle_system Prueba3
{
material Fuego
particle_width 1
particle_height 1
quota 1000
emitter Box
{
width 20
height 10
depth 15
angle 45
emission_rate 10
time_to_live 4
direction 0 1 0
velocity 2
}
affector LinearForce
{
0.1 -0.3 0.1
}
}ColourFader
Este Affector cambia el color de las partículas emitidas con el paso del tiempo. Cuenta con un atributo por cada componente del color indicando el grado de cambio por segundo de vida de la partícula.
- red
- green
- blue
- alpha
El siguiente ejemplo nos muestra un script sencillo con un Affector de tipo ColourFader:
particle_system Prueba4
{
material Fuego
particle_width 1
particle_height 1
quota 1000
emitter Box
{
width 20
height 10
depth 15
angle 45
emission_rate 10
time_to_live 4
direction 0 1 0
velocity 2
}
affector ColourFader
{
red -0.1
green 0.2
blue 0.1
alpha 0
}
}Scaler
Este Affector modifica el tamaño de las partículas (recuerda que las partículas son texturas bidimensionales) con respecto al tiempo. Su única propiedad es la siguiente:
- rate: ratio de redimensionado con respecto al tiempo en formato "x y".
El siguiente script contiene un sistema de partículas con un Affector de tipo Scaler:
particle_system Prueba5
{
material Fuego
particle_width 1
particle_height 1
quota 1000
emitter Box
{
width 20
height 10
depth 15
angle 45
emission_rate 10
time_to_live 4
direction 0 1 0
velocity 2
}
affector Scaler
{
rate 0.2 0.2
}
}Rotator
Aplica una rotación a las partículas con respecto al tiempo. Cuenta con las siguientes propiedades:
- rotation_speed_range_start: velocidad inicial a la hora de rotar las partículas en grados por segundo.
- rotation_speed_range_end: velocidad a la que terminamos de rotar una partícula.
- rotation_range_start: ángulo inicial de rotación en grados.
- rotation_range_end: ángulo final de rotación en grados.
A continuación, adjuntamos un ejemplo de sistema de partículas incluyendo un Affector de tipo Rotator.
particle_system Prueba6
{
material Fuego
particle_width 1
particle_height 1
quota 1000
emitter Box
{
width 20
height 10
depth 15
angle 45
emission_rate 10
time_to_live 4
direction 0 1 0
velocity 2
}
affector Rotator
{
rotation_speed_range_start 90
rotation_speed_range_end 180
rotation_range_start 0
rotation_range_end 360
}
}
Creación y gestión de sistemas de partículas
En esta sección aprenderemos de forma práctica cargar sistemas de partículas en nuestra escena y gestionar sus propiedades en tiempo de ejecución. La clase ParticleSystem es la encargada de representar los sistemas de partículas en Ogre. En este artículo no daremos detalles acerca de todos y cada uno de sus métodos, por tanto es aconsejable que acudas a la documentación oficial si deseas profundizar en los mismos.
Carga de sistemas de partículas
Para cargar un sistema de partículas tenemos que indicárselo al SceneManager que hayamos creado y debemos conocer el nombre del script que deseamos. En definitiva, utilizaremos el método createParticleSystem de la clase SceneManager como se indica a continuación.
Ogre::ParticleSystem* Ogre::SceneManager::createParticleSystem(const Ogre::String& name, const Ogre::String& templateName);
- const Ogre::String& name: nombre que identificará al sistema de partículas de forma única en todo el sistema.
- const Ogre::String& templateName: nombre del script .particle que deseamos cargar.
Al igual que ocurre con las entidades, podemos tener varios sistemas de partículas a partir del mismo script. Una vez tenemos el puntero a ParticleSystem, necesitamos adjuntarlo en un nodo para visualizarlo en la escena. El siguiente ejemplo ilustra el proceso completo.
// Partimos de Ogre::SceneManager* gestorEscena; // Creamos el sistema de partículas Ogre::ParticleSystem* particulas = gestorEscena->createParticleSystem("particula0001", "particulaFuego"); // Creamos un nodo Ogre::SceneNode* particulasNodo = gestorEscena->getRootSceneNode()->createChildSceneNode("particulasNodo"); // Ajuntamos las partículas al nodo particulasNodo->attachObject(particulas);
Destrucción de sistemas de partículas
Cuando no deseemos utilizar algún sistema de partículas podemos destruirlo, pero hay que ser cuidadosos a la hora de hacerlo ya que es necesario seguir unos pasos definidos. En primer lugar debemos desvincular el sistema de partículas del nodo con el método dettachObject de la clase SceneNode (tal y como hacíamos con las entidades), después haríamos uso del método destroyParticleSystem de la clase SceneManager y finalmente llamaríamos al método destroySceneNode de SceneManager (siempre y cuando sea un nodo hoja).
void Ogre::SceneManager::destroyParticleSystem(Ogre::ParticleSystem* obj); void Ogre::SceneManager::destroyParticleSystem(const Ogre::String& name);
- Ogre::ParticleSystem* obj: puntero al sistema de partículas que deseamos destruir.
- const Ogre::String& name: nombre del sistema de partículas que deseamos destruir.
El proceso completo queda reflejado en el siguiente ejemplo, partiendo de la situación del punto anterior.
// Desvinculamos el sistema de partículas del nodo particulasNodo->dettachObject(particulas); // Destruimos el nodo gestorEscena->destroySceneNode(particulasNodo); // Destruimos el sistema de partículas gestorEscena->destroyParticleSystem(particulas);
Gestión de sistemas de partículas
No es común que deseemos modificar los sistemas de partículas una vez hayan sido cargados. Lo normal es desplazarlos, rotarlos y hacerlos invisibles, y dichas operaciones se realizan desde el nodo asociado. No obstante, es posible conseguir el mismo nivel de personalización en tiempo de ejecución gracias a los métodos que proporcionan las clases ParticleSystem, Particle, ParticleEmitter y ParticleAffector. De hecho, Ogre utiliza de forma interna los métodos de estas clases al procesar los scripts .particle.
Es bastante desaconsejable crear de forma manual sistemas de partículas, ya que cualquier cambio implica recompilar los módulos afectados. Aún así, si deseas modificar sistemas existemtes es recomendable que acudas a la documentación oficial. El número de métodos y clases implicadas es bastante extenso como para trararlos a fondo en este artículo.
La herramienta Particle Editor
Particle Editor es una herramienta para crear y modificar sistemas de partículas de forma visual. Es libre y utiliza Ogre para el renderizado, CEGUI para la interfaz y OIS para la gestión de entrada. Con Particle Editor podemos acceder a los parámetros de los sistemas de partículas de forma sencilla y ver los cambios en tiempo real por lo que no es necesario incluirlos en nuestro juego para probarlos. Cuando hayamos terminado podemos exportar el sistema de partículas a un fichero con extensión .particle. Además, cuenta con varios sistemas de ejemplo sobre los que podemos empezar a trabajar.
Su desventaja es que su desarrollo está completamente paralizado y no se han liberado nuevas versiones desde el año 2006 aunque funciona con la serie 1.7 de Ogre.
Instalación en GNU/Linux
Suponemos que has instalado correctamente tanto Ogre como OIS en tu sistema por lo que la única dependencia que resta es CEGUI. Para instalar CEGUI sigue los siguientes pasos:
- Descarga la última versión estable desde SourceForge.
- Descomprime el paquete y accede a él desde una terminal.
- Configura, compila e instala CEGUI con los siguientes comandos:
./configure make sudo make install
Una vez instalada la biblioteca CEGUI con éxito podemos instalar sin problemas Particle Editor. A tal efecto, sigue los siguientes pasos:
- Descarga la última versión estable desde el repositorio Subversion de herramientas Ogre:
svn checkout https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/particleeditor particleeditor
- Accede al directorio resultante desde la terminal.
- Configura, compila e instala Particle Editor
./configure make sudo make install
- Podrás lanzar la aplicación escribiendo particleeditor en una terminal
Instalación en Windows
Para utilizar Particle Editor en sistemas Windows basta con seguir los siguientes pasos:
- Descargar el paquete con los binarios de Particle Editor.
- Descomprimir el fichero.
- Ejecutar ParticleEditor.exe dentro de la carpeta bin\release.
Manejo básico
La interfaz de Particle Editor es bastante intuitiva y la mayoría de elementos son autoexplicativos. Lo más probable es que no tengas problemas para modificar y crear sistemas de partículas nuevos. A pesar de ello, en esta sección, comentaremos los elementos más reseñables del editor:
- Template management: en este panel podemos visualizar partículas existentes a través de sus plantillas desde la pestaña "Available". Si deseamos componer una plantilla nueva podemos acceder a la pestaña "New Template". Las opciones para gestionar plantillas en visualización se encuentran en la pestaña "Selected".
- Particle System Parameters: en este panel podemos gestionar todos los parámetros del sistema de partículas seleccionado. En la pestaña "Basic" encontraremos las opciones relativas al sistema en general. En la sección inferior podemos ir añadiendo Emitters o Affectors de los tipos deseados. Una vez añadido un Emitter o Affector, lo veremos en forma de nueva pestaña en la parte superior. En cada pestaña podremos retocar los parámetros de cada elemento.
- Icono de interrogación: podemos utilizarlo para desplegar ayuda adicional como la relativa al movimiento de la cámara.
Ejemplo
| Ejemplo de sistemas de partículas Pequeña aplicación que crea una escena en la que podemos visualizar varios sistemas de partículas. |
En el ejemplo de este artículo crearemos una pequeña aplicación para visualizar los sistemas de partículas incluídos en el editor Particle Editor. Como puede verse en el diagrama de, tenemos la clase AplicacionOgre, encargada de inicializar los subsistemas (Ogre y OIS). Así mismo, la clase hija EscenaSimple es la encargada de crear la escena, capturar los eventos y gestionar la lógica de la aplicación. En este caso, cargamos un sistema de partículas por defecto y colocamos un SkyDome.
Contamos con un diccionario (std::map) que asocia teclas de OIS (OIS::KeyCode) con cadenas de Ogre (Ogre::String). De esta manera, podemos saber, dada la pulsación de una tecla, el nombre del sistema de partículas que debemos mostrar. En el manejador del evento KeyPressed comprobamos si la tecla tiene una partícula asociada en el diccionario, en caso afirmativo, destruimos la actual y cargamos la nueva.
Para elegir un sistema de partículas diferente al que se muestra por defecto basta con utilizar los números del 1 al 9.
Recuerda que debes preparar los plugins (pues no vienen incluidos en el paquete). Puedes encontrar más información sobre esto en "Creación de un entorno de trabajo multiplataforma". Los plugins necesarios son:
- RenderSystem_GL
- Plugin_ParticleFX
Conclusiones
Habiendo seguido el artículo probando los ejemplos y comprendiendo los conceptos, serás capaz no sólo de utilizar sistemas de partículas en tus aplicaciones Ogre, sino de crear sistemas nuevos a partir de scripts o utilizando el editor. Debes ser consciente de la importancia de los sistemas de partículas a la hora de introducir efectos especiales en un videojuego. Su manejo es sencillo pero conseguir el efecto deseado a partir de un script es complejo, por ello es recomendable que repases las propiedades de los Emitters y Affectors, crees nuevos sistemas y los incluyas en el ejemplo.


