Removing the hard-coded limit on the number of particles

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Removing the hard-coded limit on the number of particles

Post by mh »

I can't find a "Tutorials" section (aside from QC stuff) so apologies in advance for posting it here. This must rank as the easiest change to the engine ever, will work for both WinQuake and GLQuake, and is a good thing to have.

It assumes that you're reasonably familiar with r_part.c, or at least with the general layout of it, and it's not going to teach you how to program, but otherwise it's pure copy-and-paste.

At the top of the file:

Code: Select all

#define PARTICLE_BATCH_SIZE		2048
#define PARTICLE_EXTRA_SIZE		1024
Your new R_InitParticles function (yes, this is no joke):

Code: Select all

void R_InitParticles (void)
{
}
Your new R_ClearParticles function:

Code: Select all

void R_ClearParticles (void)
{
	int		i;
	
	free_particles = (particle_t *) Hunk_AllocName (PARTICLE_BATCH_SIZE * sizeof (particle_t), "particles");
	active_particles = NULL;

	for (i = 0; i < PARTICLE_BATCH_SIZE; i++)
		free_particles[i].next = &free_particles[i + 1];

	free_particles[PARTICLE_BATCH_SIZE - 1].next = NULL;
}
The only new function you need, ladies and gents I give you the mighty R_NewParticle:

Code: Select all

particle_t *R_NewParticle (void)
{
	particle_t	*p;
	int i;

	if (free_particles)
	{
		// just take from the free list
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		return p;
	}
	else
	{
		// alloc some more free particles
		free_particles = (particle_t *) Hunk_AllocName (PARTICLE_EXTRA_SIZE * sizeof (particle_t), "particles");

		// link them up
		for (i = 0; i < PARTICLE_EXTRA_SIZE; i++)
			free_particles[i].next = &free_particles[i + 1];

		// finish the link
		free_particles[PARTICLE_EXTRA_SIZE - 1].next = NULL;

		// call recursively to return the first new free particle
		return R_NewParticle ();
	}
}
And finally, replace every occurrance of this:

Code: Select all

	if (!free_particles)
		return;
	p = free_particles;
	free_particles = p->next;
	p->next = active_particles;
	active_particles = p;
With this:

Code: Select all

	p = R_NewParticle ();
Job done. The only room for refinement is that the two memory allocations could be refactored as a single function. You might also want to write your own version of Hunk_AllocName that doesn't memset to 0 for extra performance.

Now you can allocate as many particles as you want until you run out of memory. And because the hunk is cleared between maps, any extra won't carry over.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Labman
Posts: 62
Joined: Fri Nov 05, 2004 2:39 am
Location: Brisbane, Australia
Contact:

Post by Labman »

But do you really need that many particles when they look so crappy anyway. I guess it makes sense if you have a semi customised particle system to go with it.
MeTcHsteekle
Posts: 399
Joined: Thu May 15, 2008 10:46 pm
Location: its a secret

Post by MeTcHsteekle »

hey more paricales = more blood :D
bah
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

Do you really need that many particles when they look so crappy anyway? Depends. If you look at the numbers, Quake out of the box only supports 2048, which - in GLQuake - is enough for two explosions and nothing more (that's why I chose 1024 as the extra number - chances are if you run out of particles it's most likely because you have an explosion incoming, no other effect uses as many). OK, they may look crap but let's not make them look any crapper. :wink:

You can work around it with -particles, but that requires an engine restart and is still a hard limit anyway.

Very very handy for loading pointfiles too. This is one engine feature I'm sure mappers would applaud.

Finally, removing internal hard limits is a good thing in itself. :D
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Post Reply