2009-09-23 27 views
10

Estoy diseñando mi propio motor de sistema de partículas, esto es para fines de aprendizaje, realmente no quiero usar un motor existente.Diseño de sistema de partículas?

Ahora mismo he generado partículas hermosas, pero quiero diseñar el motor para que sea más fácil trabajar con ellas.

He estado pensando en un "sistema de partículas" Clase,

esa clase contendría las siguientes referencias:

particlesList: Una lista de las partículas que componen el sistema.

systemEmitter: El emisor sistema para las partículas, la clase del emisor debe ser capaz de realizar varias técnicas de emisión de partículas, como por ejemplo, emitiendo a partir de líneas, puntos, emitiendo al azar de un polígono. También esta clase debería hacer control de emisiones, como emitir hacia un punto, lejos de un punto, en una dirección y hora para emitir.

particleController: administra por ejemplo la rotación alrededor de un punto, los tamaños de partícula variables, colores de partículas variables, zonas de todo el sistema al que las partículas reaccionan de diferentes maneras, de detección de colisión (con otros objetos o dentro de las partículas si se convierte en NECESARIO)

partículas Procesador: A cargo de la elaboración de este sistema, tipos de variables de fusión, texturas de partículas, tipos de partículas como triángulos, círculos, a medida ...

Este cuatro elementos, sería componer la Clase sistema de partículas. Algunos FX pueden requerir más de un sistema de partículas, por ejemplo un Fire FX, podría usar un sistema para el fuego, un sistema para el humo y un sistema para las chispas.

Esto es lo que tengo en mente, pero me encantaría saber si este enfoque de diseño es bueno, o si ve que me falta algo o podría/debería hacer algo diferente. No he pensado en una forma fácil de "guardar" el FX, como por ejemplo, cuál sería la mejor manera de decirle a mi motor, "dibujar fuego", "dibujar explosión", "dibujar una fuente", etc., tal vez almacenando información de FX en los archivos xml sería una buena idea, etc.

Las opiniones son realmente bienvenidas, y como dije antes, realmente quiero construir esto, en lugar de usar otro motor, por razones de aprendizaje.

Respuesta

5

Esta configuración debe estar bien. Lo que espero que estés pensando es qué datos formarán una partícula que estará en la clase de partículas. Solo querrá tener los elementos esenciales para que solo tenga que leer/escribir la menor cantidad de memoria posible al ejecutar el sistema.

Por lo que respecta a la información impulsada, debería ser bastante sencillo. Sugeriría una opción de formato xml y binario para cargar. para que pueda ajustar cosas fácilmente mientras desarrolla (y no tener una herramienta). Una vez que tenga una herramienta o haya terminado de retocar, convertiría el xml en binario para cargarlo rápidamente.

Puede que también desee una clase de administrador que maneje la creación y actualización de estos sistemas de partículas. Esto también le permitiría un lugar para manejar otras funciones que tienen que ver con todos sus sistemas. Algunos ejemplos de esto son la limitación de la cantidad de sistemas de partículas o partículas que se pueden gestionar por motivos de rendimiento o que tengan un plano de colisión que todos los sistemas deberían tener en cuenta.

Mencionas que esto es para fines educativos y, a este respecto, estas cosas son bastante quisquillosas (pero importantes si vas a usar esto en un juego que es pesado en partículas).

Supongo que esto está usando una API como DirectX u OpenGL para renderizar. En ese sentido, quisiera que los efectos de partículas compartan el mismo conjunto de memoria para su información de vértices. Esto ayuda a la velocidad de renderizado mucho. También mantendría un registro de los límites del área afectada por un sistema de partículas para su uso con sacrificio de troncos (AABB o Círculo).

Una gran parte de actualizar un sistema de partículas es cómo los atributos van de un valor a otro. Cuanto más dinámico pueda hacer la interpolación de valores, mejor se verán sus efectos. Simplemente la interpolación lineal podría ser lo suficientemente buena, pero puede ser mejor tener un gráfico dinámico que se utilice para interpolar los valores. Por ejemplo, en lugar de pasar de 0 a 255 azul en un segundo, puede ser genial ir de 0 a 128 en 0.2 segundos y luego de 128-255 en 0.8 segundos. Agregar eso aumentará en gran medida las opciones sobre cómo se ven sus efectos.

Además de eso, creo que tiene una muy buena idea de lo que quiere hacer. Su mención de representar diferentes tipos de partículas me dice que está pensando en esto de la manera correcta. He visto a gente fabricar motores de partículas solo enfocándose en renderizar un quad con billboarded. Tener la opción de emitir geometría 3D realmente hace que las cosas se vean geniales. También es posible que desee pensar (si no lo ha hecho ya) teniendo la capacidad de que su sistema tome la información del modelo y la divida dinámicamente en partículas separadas para emitir. En realidad, explotar un modelo parece mucho mejor que mostrar alguna partícula de explosión y desvanecer el objeto o cambiarlo a un estado dañado.

+0

Gracias por su respuesta! Sí, estoy pensando en hacer esto con OpenGL. Además, la idea de interpolación no lineal es realmente buena, y debería ser capaz de crear visuales bastante buenos con ella. – Goles

1

Algunas ideas para la optimización de partículas sprites 2D simples.

Una buena idea es enviar todas las partículas en una matriz de vértices/VBO, y usar un sombreador de vértices para actualizar sus posiciones a lo largo del tiempo. Esto es genial si tiene un movimiento simple que puede describirse fácilmente usando una fórmula matemática donde x(t) y y(t) (es decir, dependen solo del tiempo).

Otra gran idea es utilizar sprites puntuales en lugar de triángulos y quads. Esto debería reducir el ancho de banda requerido en la tubería a un cuarto.


En mi espacio sim He implementado el enfoque más trivial: partículas enviados como quads textura utilizando glBegin()/glEnd(). Se vierten en el "sector" actual como objetos individuales y son completamente independientes desde el momento del vertido en adelante. Esta es la cosa más primitiva, estúpida e idiota que puede hacer y es responsable de una gran reducción en el rendimiento, especialmente porque lo que hago es iterar a través de los objetos a través del iterador del vector STL y enviarlos a todos y cada uno secuencialmente.

Debe considerar cuántas partículas desea y qué desea que hagan. * ¿Quieres que reaccionen al entorno y colisionen? Luego necesita una actualización manejada en la CPU y datos enviados una y otra vez. * ¿Simplemente vuelan de la manera más estúpida posible? Luego, puede salirse con la suya enviando todas las partículas como VBO y TBO, y actualizarlas en shader.

¡Diviértete!


Actualizado a relacionarse con el comentario # 1 de autor de la pregunta :-)

Lo que me gustaría hacer es utilizar el KISS principle.Esto significa: una clase llamada ParticleEmitter que contiene una matriz de vértices, una matriz de velocidades y una STL vector con instancias de colisionadores simples como plano, esfera, triángulo. Además, tenga un "global" * STL vector con colisionadores. A continuación, actualice las velocidades de acuerdo con colisionadores.

Similar se puede hacer con los afectos (gravedad, viento y similares): otro vector STL en ParticleEmitter con afectos y otro "global" STL vector con afectos.

Affectors y colliders serían clases que implementarían affectParticle(particle_t*). donde struct particle_t { float x,y,z; float vx,vy,vz; }. Lo mantendría como una estructura POD y ejecutaría la actualización en ParticleEmitter::update().

Sin embargo, si está ejecutando esto en un iPhone, ¿podría ser una complicación excesiva? ¿Quizás pueda salirse con la suya con lo que ya implementó? No tengo idea de cómo mi diseño podría afectar los resultados del benchmark, pero me parece lo suficientemente razonable si mantiene la cuenta regresiva de partículas, colisionador y afecto, porque parece que podría escalarse con aproximadamente n*c+n*a.

Estos son solo mis pensamientos ad-hoc, y cómo lo implementaría personalmente. Su diseño, o el diseño de otras personas, probablemente sería mejor :-)

* "Global" entre comillas, porque probablemente tendría sentido utilizar cualquier partición de espacio que tenga en uso.

+0

Hola Ivan, gracias por la respuesta, en este momento estoy desarrollando este sistema en el iPhone, he hecho un buen progreso, ya que alcancé mi hito al renderizar 3.000 16x16 píxeles GL_POINT_SPRITES, usando VBOs y logrando entre 45-55 fps. Creo que eso es bastante decente. Sin embargo, ahora quiero comenzar a trabajar sobre cómo las partículas pueden interactuar y colisionar con otros objetos, he pensado de alguna manera, pero realmente me gustaría escuchar algunas ideas al respecto. Gracias de nuevo. – Goles

1

Implementé el mismo buen diseño para mi propio motor en C++. No utilicé referencias y políticas de plantillas (estrategias; en su lugar, lea el "Diseño moderno en C++" de Alexandresku). El polimorfismo estático proporciona un mejor rendimiento.

0

Quiero hacer algunos comentarios según mi experiencia.

  1. Tradicionalmente, la mayoría de las partículas usa AOS (Array of Struct) para almacenar los atributos de las partículas. Pero esta puede no ser la mejor decisión. El uso de la representación SOA (Struct of Array) le dará mucha flexibilidad para agregar atributos de cada sistema de partículas. Y también, será mucho más fácil mejorar el rendimiento con SIMD con SOA. Por ejemplo, hacer 4 partículas juntas usando instrucciones SSE.
  2. posición de donde emite la partícula es solo la inicialización de un atributo de partícula. Cuando se emiten partículas, es probable que deba inicializar otros atributos, como vida, velocidad, etc. Puede abstraer todas estas características como inicializadores. Para la posición, puede tener un inicializador de disco, inicializador de cuadro, etc.
  3. Algún sistema moderno de partículas adopta el concepto de evento. El sistema de partículas puede generar un evento (por ejemplo, lluvia colisionando con el terreno) y otro sistema de partículas puede escuchar y realizar alguna acción (por ejemplo, emisión de salpicaduras).

Por cierto, creo que la mejor manera es estudiando el diseño de la aplicación existente/middleware, y también mediante la experimentación.

Cuestiones relacionadas