This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Noise Generation Class Submitted by

This is the class I ended up with after trying to create a noise function capable of producing noise in any number of dimensions. The constructor is templated to allow a programmer to specify his own random function.
Like the simple:

    noise<2 noise2d(rand);

Or the more useful:

    class seeded_random
    {
    public:
        seeded_random(int seed) { srand(seed); }
        int operator()() { return rand(); }
    };

    noise<2 noise2d(seeded_random(some_seed));

And so on. The rest of the description is in the file it's self. - Chris Stephenson

Download Associated File: noise.h (3,254 bytes)

    //////////////////////////////////////////////////////////////////////////////
    //     File: noise.h
    //  Created: 18 December 2001
    //   Author: Chris Stephenson
    //    Email: chris@icezip.com
    //  Summary: A class for generating N dimensional noise
    //           The noise generated has the following charcteristics:
    //             - noise produced between -1 and +1
    //             - pseudo-random (same value produced by same vector)
    //             - features roughly the same size (no high or low spatial frequencies)
    //////////////////////////////////////////////////////////////////////////////

    #ifndef __NOISE_H__
    #define __NOISE_H__

    #include <math.h>

    #define cubic_spline(t) (t * t * (3.0f - 2.0f * t))
    #define linear_interpolation(t, a, b) (a + t * (b - a))

    template<int N> // N must be > 0
    class noise
    {
    public:
    	// construct the class using the random function/class specified
    	template<class R>
    	noise(R random)
    	{
    		int i,j,k;

    		for(i = 0; i < buffer_size; i++)
    		{
    			// pointers
    			pointers[i] = i;

    			// gradients
    			for(j = 0; j < N; j++)
    				gradients[i][j] = (float)((random() % (buffer_size + buffer_size)) - buffer_size) / buffer_size;

    			// normalize gradients
    			float s = 0.0f;

    			for(j = 0; j < N; j++)
    				s += gradients[i][j] * gradients[i][j];

    			s = 1.0f / sqrtf(s);

    			for(j = 0; j < N; j++)
    				gradients[i][j] *= s;
    		}

    		// randomize pointers
    		while (--i) {
    			k = pointers[i];
    			pointers[i] = pointers[j = (random() & buffer_mask)];
    			pointers[j] = k;
    		}

    		// copy pointers & gradients to 2nd half of array
    		for(i = 0; i < buffer_size + buffer_pad; i++)
    		{
    			pointers[buffer_size + i] = pointers[i];

    			for(j = 0; j < N; j++)
    				gradients[buffer_size + i][j] = gradients[i][j];

    		}
    	}

    	// get some noise based on vector vec
    	float get(float vec[N])
    	{
    		int ivec[N];
    		int p[N];   // pointer offsets
    		float r[N]; // r + ivec = vec (to be dotted with the gradients)
    		float s[N]; // interpolation values

    		// set up all the varables
    		for(int i = 0; i < N; i++)
    		{
    			ivec[i] = floorf(vec[i]);
    			p[i] = ivec[i] & buffer_mask;
    			r[i] = vec[i] - ivec[i];
    			s[i] = cubic_spline(r[i]);
    		}

    		// call helper function
    		return _get(p, r, s, 0, 0);
    	}

    private:
    	// recursive helper function for get(float vec[N])
    	inline float _get(int p[N], float r[N], float s[N], int cumulative_p, int n)
    	{
    		if(n == N)
    		// base case: return r dot gradient
    		{
    			float *g = gradients[cumulative_p];
    			float val = 0.0f;
    			for(int i = 0; i < N; i++)
    				val += r[i] * g[i];
    			return val;
    		}
    		else
    		// recursive case: return interpolation of values
    		{
    			float a, b;

    			a = _get(p, r, s, pointers[cumulative_p + p[n]], n + 1);

    			r[n]-=1.0f;
    			b = _get(p, r, s, pointers[cumulative_p + p[n] + 1], n + 1);
    			r[n]+=1.0f;

    			return linear_interpolation(s[n], a, b);
    		}
    	}

    	enum // some private constants
    	{
    		buffer_size = 0x100, // buffer size, must be a power of 2 for mask to work
    		buffer_mask = 0xff,  // ANDing (&) is much faster than MODing (%)
    		buffer_pad = 2       // a little extra space for simplification of methods
    	};

    	// important variables
    	int pointers[buffer_size + buffer_size + buffer_pad];
    	float gradients[buffer_size + buffer_size + buffer_pad][N];

    };

    #endif // __NOISE_H__

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.