What you would want in your particle engine

Started by
7 comments, last by Kitt3n 18 years, 2 months ago
I know this is a really broad question and should probably be determined more on the merits of the individual project, skills of the programmer, etc. But my question is, If given 1 week to create a robust, solid, fast particle system, what features would you want it to support. Also, what methodology do most people find allows for highly generalized particle systems. Currently I am using a class CParticleSystem, from which I derive various types of particle systems, smoke, fire, etc. The base class (CParticleSystem) has an array of particles (really just a pointer to the first one, returned by my particle factory) and various other data structures such as an abstracted bounding volume (spheres, boxes and such for supporting interesting shapes for the system). My ParticleManager holds vectors of CParticleSystem subclass pointers (highly unoptimized currently, probably will have to move off of stl before the week is up). My renderer simply calls the ParticleManager's update and draw functions which in turn delegates these responsibilities off to the CParticleSystem subclasses. So, does this sound like a fairly solid design? I'm on a very tight schedule, but so far I'm not all that enthused with this particle system and am considering refactoring (this is in fact a refactor from my previous particle system). Any thoughts are greatly appreciated! Thanks.
Advertisement
Include shader support if you want it to be fast. That would be cool.


how do you handle motion/path updates for particles? is it hardcoded? if it is, i would recommend implementing some way to provide the particle system with a 'behavior' function. that way, particle behavior is not linked to the system in general although such a behavior can also be replicated if done this way. This would be handy coz you can just swap the 'behavior' and the particle/system will adapt to it. Imagine a fire system in a windless environment, then when you introduce wind, the behavior is updated by just providing a new function.

the same can be applied to any modifieable element of the system. I created a system once that had pluggable motion and emission area. It promotes extensibility to the system, though it seriously depends on how much extensibility you'd like to have.
- To learn, we share... Give some to take some -
>Also, what methodology do most people find allows for highly generalized
>particle systems. Currently I am using a class CParticleSystem, from which I
>derive various types of particle systems, smoke, fire, etc.
You are specializing particle systems, although I think that's not
good in this case.

What do fire, smoke, ... have in common?
- Particles are emitted (in one way or the other)
- Forces act on particles.

Now instead of specializing your custom particle system, make generic
"Emitters" and "Affectors".

You can have a point-emitter which will spit particles out in regular
interval maybe with an initial speed or a (random) direction,
or you could have a box-emitter in which particles appear - all derived
from a base "emitter-class"
Then add a few affectors (color-change-over-time, gravity, force, rotation,
or like the previous poster mentioned "wind") - all derived from a
base "affecter-class".

Now your particlesystem-class will have instances of affectors, and emitters.
Every update loop through all emitters, and then let the affectors loop over
all particles... and the fun begins :)

Fire is nothing more than let's say a point-emitter and a colorfader for
the red fire - a second emitter+fader for the smoke and a 3rd emitter+fader
for the little sparks flying off.

And just by playing around with your settings, you can create lots of effects
instantly, without specifically having to program the "fire-particle-system".

Regards
visit my website at www.kalmiya.com
So it seems to me the above two posts sort of recommend the same system, with different implementations. If I'm understanding you Kitt3n, then I would define an emitter which is essentially just a dummy disperser of particles. Then I would modify the behavior of said particles by applying these affectors to them.

Essentially the data is stored in the emitter and the behavior is realized through the affector abstractions. Is this kind of the idea?
Check out this GameDev article; I found the idea of compile-time policy-based particles very practical.
Yeah I've looked through that article and I did take some of the suggestions to heart, but overall I think that solution is a little too convoluted for my tastes. I do appreciate the referral and I am definitely putting some of that ideas in that article to use.

I have decided to implement a system similar to the one proposed by kitt3n, where I have a particle system, from which I derive various particle emitters (point emitters, rotational emitters, etc.) and then I have an abstract base class called particle affector from which I derive various affector classes that will modify the behavior of particles at run time.

for instance I have a CGravityAffector which simply applies gravity to a particle system. This method is working for now but seems a little inefficient as I call CGravityAffector->AffectParticle() for every particle in the system. As long as I get it working soon though I can worry about optimizing later. It just seems like I'm getting a whole lot of function overhead with this system (which I think would remain true if I were to follow the aforementioned article).

Thanks for all your replies, and any more suggestions are welcome!
I've never really developed a particle system, but I've been thinking about starting one. I was reading about it last night, actually, in Core Techniques and Algorithms in Game Programming (good book). A couple of ideas they had were to assign a static "weight" for all particles within a single system. That weight is not really weight, but rather it represents how much each particle is affected by outside forces. And as for the forces themselves, they simply have a function setForce to which you pass probably a vector or something.

I have no idea what features I'd include if I were on a super tight schedule, but I'd want to have:

Different emitters (which you seem to have covered)
Derived systems (also covered)
Variable...
forces
emission speeds
emission rate
emission direction
particle lifetime
Movable particle systems.
Probably a particle system manager to handle initialization, placement, creation and destruction of particle systems.
A way to describe how particles react after the system is destroyed, i.e., do they die with the system? do they remain true to their assigned lifetime?

Another thing I just thought of from the section I read last night was randomization of particle attributes, so they don't all look the same. Most of this is probably obvious to you. They all seem like new ideas to me, since I've never developed a particle system. :P

Anyway, good luck, hopefully we'll get to see your final version.


>Essentially the data is stored in the emitter and the behavior is realized
>through the affector abstractions. Is this kind of the idea?
Thats one possibility, yes.

>as I call CGravityAffector->AffectParticle() for every particle in the system.
You have to do the update for every particle anyway, but just let the
affector immediately work on the particle values

In my case it looks sth like this:

struct Particle{  vector3d position, direction;  float timeToLive, size  Color color;  ...}class ParticleSystem{  // public, for demo-purposes  vector<Particle> particles;//vector<U32>      freeParticles;   // optimization //vector<U32>      livingParticles; // optimization  vector<ParticleEmitter*> pe;   vector<ParticleAffector*> pa;  void advanceTime (float timeInSeconds)  {     // loop through all emitters     // loop x times (how many particles this emitter wants to emit       // get a free particle from the freeParticleList       pe->initializeParticle (newFreeParticle)    // loop through all affectors      pa->affectParticles (this, timeInSeconds);  }}class ParticleEmitter{  ...};class PointEmitter: public ParticleEmitter{};class ParticleAffector{  virtual ... affectParticles (... ) ;};class GravityAffector : public ParticleAffector{    virtual ... affectParticles (ParticleSystem* pSys, ... ) ;  {    for (U32 i=0; i<psys->particles.size(); i++)    {      p = &pSystem->particles;      if (p->canAffect(onEmitter) && p->isAlive())      { // affect the particles values somehow      }    }   }};
visit my website at www.kalmiya.com

This topic is closed to new replies.

Advertisement