1 #ifndef NOISE
  2 #define NOISE
  3 
  4 #include "Vec3f.hxx"
  5 #include "Randomizer.hxx"
  6 
  7 typedef struct
  8 {
  9 	int x,
 10 	    y,
 11             z;
 12 } Vec3i;
 13 
 14 class Noise
 15 {
 16 private:
 17 	// A pointer to a 3D grid of random values
 18 	float ***noise;
 19 
 20 	// The PRG
 21 	Randomizer randomizer;
 22 
 23 	// Elongation of the noise grid (granularity)
 24 	Vec3i size;
 25 
 26 	// Generates a 
 27 	void GenerateNoise()
 28 	{
 29 		for (int x = 0; x < size.x + 1; ++x)
 30 			for (int y = 0; y < size.y + 1; ++y)
 31 				for (int z = 0; z < size.z + 1; ++z)
 32 				{
 33 					noise[x][y][z] = randomizer.drand();
 34 
 35 					// Wrap around borders (for correct interpolation)
 36 					if (x == size.x)
 37 						noise[x][y][z] = noise[0][y][z];
 38 					if (y == size.y)
 39 						noise[x][y][z] = noise[x][0][z];
 40 					if (z == size.z)
 41 						noise[x][y][z] = noise[x][y][0];
 42 				}
 43 	};
 44 
 45 public:
 46 	// Build a grid of given granularity (e.g. Vec3f(64)) covering a voxel range
 47 	// of the bounding box spanned by From and To
 48 	Noise(Vec3f Granularity)
 49 #ifdef RANDOMSEED
 50 		:randomizer(RANDOMSEED)
 51 #endif
 52 	{
 53 		// Get the granularity
 54 		size.x = static_cast<int>(Granularity.x);
 55 		size.y = static_cast<int>(Granularity.y);
 56 		size.z = static_cast<int>(Granularity.z);
 57 
 58 		// Create the noise grid...
 59 		noise = new float**[size.x + 1];
 60 
 61 		for (int x = 0; x <= size.x; ++x)
 62 			noise[x] = new float*[size.y + 1];
 63 
 64 		for (int x = 0; x <= size.x; ++x)
 65 			for (int y = 0; y <= size.y; ++y)
 66 				noise[x][y] = new float[size.z + 1];
 67 
 68 		// ...and fill it
 69 		GenerateNoise();
 70 	}
 71 
 72 	virtual ~Noise()
 73 	{
 74 		// Destroy the noise grid...
 75 		for (int x = 0; x <= size.x; ++x)
 76 			for (int y = 0; y <= size.y; ++y)
 77 				delete[] noise[x][y];
 78 
 79 		for (int x = 0; x <= size.x; ++x)
 80 			delete[] noise[x];
 81 
 82 		delete[] noise;
 83 	};
 84 
 85 	// Returns the plain noise value at a given integer position
 86 	// /!\ Does not catch overflows!!
 87 	virtual float GetNoise(int x, int y, int z)
 88 	{
 89 		return noise[x][y][z];
 90 	};
 91 
 92 	// Interpolate in between the noise grid
 93 	virtual float Interpolated(Vec3f Point)
 94 	{
 95 		// Perform a trilinear interpolation
 96 		float x1, x2, x3, x4, y1, y2, z;
 97 
 98 		// Position of the unit cube
 99 		Vec3i p;
100 		p.x = static_cast<int>(floor(Point.x)) % size.x;
101 		p.y = static_cast<int>(floor(Point.y)) % size.y;
102 		p.z = static_cast<int>(floor(Point.z)) % size.z;
103 
104 		if (p.x < 0)
105 			p.x += size.x;
106 		if (p.y < 0)
107 			p.y += size.y;
108 		if (p.z < 0)
109 			p.z += size.z;
110 
111 		// Distance within the unit cube
112 		Vec3f Distance(Point.x - floor(Point.x), Point.y - floor(Point.y), Point.z - floor(Point.z));
113 
114 		Distance = Vec3f(1) - Distance;
115 
116 		// 4 edges  (4 * 2 = 8 points)
117 		x1 = Distance.x * (noise[p.x  ][p.y+1][p.z  ] - noise[p.x+1][p.y+1][p.z  ]) + noise[p.x+1][p.y+1][p.z  ];
118 		x2 = Distance.x * (noise[p.x  ][p.y  ][p.z  ] - noise[p.x+1][p.y  ][p.z  ]) + noise[p.x+1][p.y  ][p.z  ];
119 		x3 = Distance.x * (noise[p.x  ][p.y  ][p.z+1] - noise[p.x+1][p.y  ][p.z+1]) + noise[p.x+1][p.y  ][p.z+1];
120 		x4 = Distance.x * (noise[p.x  ][p.y+1][p.z+1] - noise[p.x+1][p.y+1][p.z+1]) + noise[p.x+1][p.y+1][p.z+1];
121 
122 		// 2 planes (2 * 2 = 4 points)
123 		y1 = Distance.y * (x2 - x1) + x1;
124 		y2 = Distance.y * (x3 - x4) + x4;
125 
126 		// 1 cube   (1 * 2 = 2 points)
127 		z  = Distance.z * (y1 - y2) + y2;
128 
129 		return z;
130 	};
131 
132 	// The Perlin turbulence function
133 	virtual float Turbulence(Vec3f Point, float detail)
134 	{
135 		float result(0.0f);
136 
137 		for (float scale = 1.0f; scale > detail; scale /= 2.0f)
138 		{
139 			Point  /= scale;
140 			result += Interpolated(Point) * scale;
141 		}
142 
143 		return result;
144 	};
145 };
146 
147 #endif


syntax highlighted by Code2HTML, v. 0.9.1