Jump to content
  • Advertisement
Sign in to follow this  
Fire Lancer

2D Partical System Mempory Management

This topic is 3417 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Under my particle system there are a number of structs that define the behaviour of emitters, particles, systems, etc. Stuff like life, how many times the system loops, emitter rate, etc. Currently I only have 1 particle type/object, which is just a sprite. Origenally the particle systems just used new and delete to create and destroy there own particles, but this became somewhat slow, exspecially with a large number of shortlived particles. I came up with this solution, which is substantially faster, however I'm not sure its the best approach. I needed to have a stack of inactive particles, and also a list of active ones in each system (I need to remove from the middle, and add to the ends, so that I can control if particles are rendered newest to oldest or oldest to newest based on which end I added them). Todo this I decided to implement a doubly linked list where the particles are the node. This has the advantage of the only memory allocation involving particles being the allocation of a new particle, which is somewhat rare once the game has started.
class Particle
{
...
    Particle *Next, *Last;
...
};


The inactive pool then looks like this:
Particle *particlePool;//singly linked list
//particle systems call this to get a new particle
Particle *getParticle()
{
    if(particlePool)
    {
        Particle *p = particlePool;
        particlePool = p->Next;
        return p;
        }
    //I was thinking about the posibility of allocating large groups at once
    else return new Particle();
}


Particle trackers are responsible for tracking particles within a system
class ParticleTracker
{
...
    Particle *first, *last;//doubly link list
...
};
void PartTracker::Update()
{
    Particle *p = first;
    while(p)
    {
        //Particle::Update returns false if the particles dead
        if(!p->Update())
        {
             //remove from this list
             if(p->Prev)p->Prev->Next = p->Next;
             else       first = p->Next;
             if(p->Next)p->Next->Prev = p->Prev;
             else       last  = p->Prev;
             //add to particle pool
	     Particle *prt = p;
             p = p->Next;
             prt->Next = particlePool;
             particlePool = prt;
        }
        else p = p->Next;
    }
}


Share this post


Link to post
Share on other sites
Advertisement
Quote:

So that I can control if particles are rendered newest to oldest or oldest to newest based on which end I added them


Is it really necessary to render your particles in this way? That is, should the particles really be sorted by lifetime? If not, it might be more efficient to determine the maximum number of particles once and allocate one big block of memory for that number of particles. If you keep track of the number of particles that are alive, spawning a particle can be done like this:


m_Particles[m_NumAliveParticles].SetLifeTime(10.0f);
m_Particles[m_NumAliveParticles].SetInitialColor(1.0f, 0.0f, 0.0f);
...
++m_NumAliveParticles;



Removing a dead particle can be done by swapping the particle with the last life particle:


Swap(m_Particles[deadParticleIndex], m_Particles[m_NumAliveParticles - 1]);



This way you don't have to worry about dymamic allocations anymore.

Share this post


Link to post
Share on other sites
But then I have noway to order the particles. This works fine for addicitve particles because draw order doesnt matter, but with alpha blended particles like smoke, dust, etc it does matter.

Eg lets say from a side view I have a chimmy with smoke coming out

SSSS
SSS
SSS
SS
| |
| |
| |


In order to look right from a top down view the smoke particles must be drawn newest first, so that the older ones appear ontop, and thus with the change in size/density they look like their rising.

Share this post


Link to post
Share on other sites
You seem not to have explicitly asked a question, so I'm assuming you're looking for comments/criticism.

In which case.

Madness? No. This is C++!

Don't build your own linked list. Use a standard library container, such as std::list or std::vector.

And don't build your own pool allocators. Boost already has some.

You don't even need the ability to insert at either end. Insert new elements at the end so that your container is always sorted oldest to newest. Then when you want to draw newest to oldest, simply use reverse_iterators instead of ordinary ones to traverse the container.

Share this post


Link to post
Share on other sites
If I use std::list<Particle*> so that I can resuse particles, wont the std::list cause tons of memory allocations creating and destroying the list nodes that just contain a Particle pointer?

Share this post


Link to post
Share on other sites
That's what the pool allocator is for. But also, why not hold your Particles by value in the list? (They won't get copied by list element removal/insertion operations - except to actually put things into the list - and you'll avoid an extra level of indirection.)

Share this post


Link to post
Share on other sites
The reason I moved the particles to a pool in the first place, is because in my particulur game there are alot of shortlived effects, such as bullet impacts and muzzle effects, which resulted in a very large number of particles being allocated and deallocated a second. Although thinking about it mayby a pool allocater could solve that *creates another svn branch to test :) *

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!