Stochastic Saturday

The next thing on my list is to create a really nice particle system with loads of options for all kinds of dynamic effects.  It seems that particle systems are also really easy to program at a basic level, but much harder to get right.  For my purposes, the particle effects I will program will rely almost entirely on randomness, and some generic parameters to control their evolution.  Things like particle age, direction, velocity, size, etc, will all use varying amounts of randomness, to keep the effects unique and interesting.  The logical starting point for this system is to ensure that we have a good, clean, way of quickly generating random numbers.  If you do some trawling of the web you may find something like this function:

static signed int _randSeed_a = 7919;

// rand -1 -> +1 - uniform dist
float randf_a( void )
    const float fact =  4.6566129e-010f;
    _randSeed_a *= 87103;
    return (float)_randSeed_a * fact;

The above code shows a reasonable, and exceedingly simple random number generator.  We have an accumulator or a seed as it is commonly called, which here starts off as a prime number, and each time we call the random function, we multiply that seed by another large prime number.  Due to the nature of primes, we can expect that this seed number will not repeat any time soon.  Our seed value will now jump around randomly within the range of values that an integer can take, which is a hell of a large range.  In the second stage, we simply scale down this range to fall somewhere between -1 and +1.  That range is particularly nice to work with because typically in a particle system we want to generate random numbers in a known range, therefore we can multiply our random number by a constant that acts as our maximum value.

I made a quick and dirty program to test and plot the distribution of this random number generator, as can be seen below:

ImageThe above image is not the most intuitive thing to look at so let me take a moment to explain it.  Here we see the percentage chance that a number generated by the above random number generator will fall into a certain column on the x axis, in this case there are 320 columns; Left most representing -1.0f, middle 0.0f, right most obviously 1.0f.  The percentages seen in the graph were constructed after examining the distribution of 60’000 random numbers.  Every column here has a value around 0.3%, which is what I would expect, since 100% / 320 = 0.31%.  We can infer that there is a nice even probability of all numbers being outputted by this random number generator.

There are many ways to test for randomness and testing the distribution for any bias is just one, however this is important for us as we shall see.  We can actually generate many useful effects for use in games on a whole not just particle systems, by skewing, or adding bias to our random number generator.  An extremely useful distribution is what I will reffer to as a pinch distribution (I have no idea what it should be called) where there it is more probable to receive a random number nearer the value 0.0f.  This can be useful when you want to add an amount of error to something while favoring small errors over large ones.  A nice application of pinch randomness can be seen when it has been added to the firing direction of someones weapon in a game,  providing a nice simulation of aiming error.

ImageThe pinch distribution is actually extremely easy to generate, and is aided by our range being from -1 to +1.  If we multiply our random number by the absolute value of itself, then we essentially suck the distribution in around the zero point.  The code can be seen below, as well as a some bit-wise hacking to make a floating point value positive.

static signed int _randSeed_a = 7919;

// rand -1 -> +1 - pinch distribution
float randf_c( void )
    const float fact =  4.6566129e-010f;
    _randSeed_a *= 87103;
    float a = (float)_randSeed_a * fact;
    int   b = (*((int*)&a) & 0x7FFFFFFF);
    float c = *(float*)&b;
    return a * c;

Sadly I wasn’t smart enough to figure out a way to create a nice bell curve, or Gauss distribution, but I did manage to make something truly weird, that will be great in my particle system.  I present, “the bowl” distribution:


With bowl distribution, it is vastly more probably that the random number will be nearer -1 or +1 rather then 0, and I bet this will come in useful when I want a strong polarity in my randomness.  The equation for the bowl distribution was taken and reworked from my sine approximation library and is:

y(x) = 4 * x * (1.0f - abs( x ) )

Another alternative to the pinch is:

y(x) = x * x * x

Which provides a vastly larger peak around the 0 value of around 9.5% probability with the above program.  I am sure there are many more cool distributions out there, and I will incorporate them into the particle system as I find them.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s