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