views:

788

answers:

4

Hello, I'm designing my own particle System engine, this is for learning purposes, I don't really want to use an existing engine.

Right now I generated beautiful particles, but I want to layout the engine to make it easier to work with them.

I have been thinking on a Class "Particle System",

that class would contain the following references:

particlesList: A list of the particles that compose the system.

systemEmitter: The system emitter for the particles, the Emitter class should be able to perform several particle emission techniques, like for example, emitting from lines, points, randomly emitting from a polygon. Also this class should do Emission Controlling, like emitting towards a point, away from a point, in a direction and time to emit.

particleController: Manages for example rotation around a point, variable particle sizes, variable particle colors, areas around the system to which the particles react in different ways, collision detection ( with other objects or within the particles if becomes necesary ).

Particle Renderer: In charge of drawing this system , Variable Blending types, particle textures, particle types like triangles, circles, custom...

This four items , would compose the particle system Class. Some FX may require more than one particle system, for example a Fire FX, could use one system for the fire, one system for smoke and one system for sparks.

This is what I have in my mind, but I would really love to know if this design approach is good, or if you see I'm missing something or could/should do something different. I haven't thought about some easy way to "save" FX, like for example what would be the best way to tell my engine, "draw Fire", "draw explosion" , "draw fountain", etc, maybe storing FX information in xml files would be a good idea, etc..

Opinions are really welcome, and as I stated before, I really want to build this, instead of using another engine, for learning reasons.

+4  A: 

This set-up should be fine. What I hope you're thinking about is what data will make up a particle that will be in the particle class. You'll want to only have the bare essentials so you only have to read/write as little memory as possible when running the system.

As far as making it data driven that should be pretty straight forward. I would suggest an xml and binary format option for loading. so you can tweak stuff easily while developing (and not having a tool). Once you have a tool or are done tweaking I would convert the xml to binary for quick loading.

You may also want a manager class that handles the creation and updating of these particle systems. This would also allow you a place to handle other functionality that has to do with all your systems. Some examples of this is limiting the amount of particle systems or particles that can be managed for performance reasons or having a collision plane that all systems should take into account.

You mention this is for education purposes and in that regards these things are pretty nit picky (but important if you are to use this in a game that is particle heavy).

I am assuming this is using a API like DirectX or OpenGL to render. In that respect I would have the particle effects all share the same pool of memory for your vertex information. This help the rendering speed a lot. I would also keep track of a bounds of the area affected by a particle system for use with frustum culling (AABB or Circle).

A huge part of updating a particle system is how attributes go from one value to another. The more dynamic you can make the interpolating of values the better your effects can look. Simply linearly interpolating could be good enough, but It may be better to have a dynamic graph that is used to interpolate the values. For example instead of going from 0 to 255 blue in a second, it may be cool to go 0 to 128 in 0.2 seconds then 128-255 in 0.8 seconds. Adding that will greatly increase the options on how your effects look.

Besides that I think you have a pretty good idea about what you want to do. Your mention of rendering different types of particles tells me you are thinking about this in the right way. I've seen people make particle engines just focusing on rendering a billboarded quad. Having the option to emit 3d geometry really makes things look great. You may also want to think about (if you haven't already) having the ability for your system to take model information and dynamically split the it into separate particles to be emitted. Actually exploding a model looks greatly better then displaying some explosion particle and fading out the object or switching it to a damaged state.

resolveaswontfix
Thanks for your response!, yeah, I am thinking about rendering this with OpenGL. Also the non linear interpolation idea is really good, and should be able to create some pretty good visuals with it.
Mr.Gando
+2  A: 

Just some ideas for optimization of simple, 2D sprite particles.

A good idea is to send all particles in a vertex array / VBO, and use a vertex shader to update their positions over time. This is great if you have a simple motion that can be easily described using a mathematical formula where x(t) and y(t) (that is, they depend only on time).

Another great idea is using point sprites instead of triangles and quads. This should reduce the required bandwidth on the pipeline to a quarter.


In my space sim I have implemented the most trivial approach: particles sent as textured quads using glBegin()/glEnd(). They are dumped into the current "sector" as individual objects and are completely independent from the time of dumping onwards. This is the most primitive, stupid, and idiotic thing to do and is responsible for great reduction in performance, especially since what I do is iterate through objects via STL vector's iterator and send each and every one of them sequentially.

You need to consider how many particles you want, and what do you want them to do. * Do you want them to react to surroundings and collide? Then you need updating handled on CPU and data sent over and over again. * Do they just fly around in the most stupid manner possible? Then you may be able to get away with sending all particles as VBO and TBO, and update them in shader.

Have fun!


Updated to relate to the comment #1 from asker :-)

What I would do is use the KISS principle. This means: a class called ParticleEmitter containing a vertex array, an array of velocities, and a STL vector with instances of simple colliders such as plane, sphere, triangle. Additionally, have a "global"* STL vector with colliders. Then update the velocities according to colliders.

Similar can be done with affectors (gravity, wind and such): another STL vector in ParticleEmitter with affectors and another "global" STL vector with affectors.

Affectors and colliders would be classes that would implement affectParticle(particle_t*). where struct particle_t { float x,y,z; float vx,vy,vz; }. I would keep it a POD structure, and run updating in ParticleEmitter::update().

However if you are running this on iPhone, could it be overcomplication? Perhaps you can get away with what you already implemented? I have no idea how my design might affect benchmark results, but it sounds reasonable enough to me if you keep the particle, collider and affector count down, because it sounds like it might scale with approximately n*c+n*a.

These are just my ad-hoc thoughts, and how I'd personally implement it. Your design, or other people's design, would probably be better :-)

* "Global" under quotes, because it would probably make sense to make use of any space partitioning you have in use.

Ivan Vučica
Hello Ivan, thanks for the answer, right now I am developing this system on the iPhone, I have made good progress, since I reached my milestone on rendering 3.000 16x16 pixels GL_POINT_SPRITES, using VBOs and achieving between 45-55 fps. I think that's pretty decent.However now I want to start working on how the particles can interact and collide with other objects, have thought on some ways, but I would really like to hear about some ideas about it.Thanks again.
Mr.Gando
+1  A: 
Mr.Gando
Nice with the followup. Any chance for a class diagram of what you ended up implementing? :)
junior
+1  A: 

I've implemented the same good design for my own engine in C++. I didn't use references and template policies (strategies - read Alexandresku's "Modern C++ Desing") instead. Static polymorphism gives better performance.

topright