1 #ifndef FRACTALMOUNTAIN_HXX
2 #define FRACTALMOUNTAIN_HXX
3
4 #include "Vec3f.hxx"
5 #include "Shader.hxx"
6 #include "PhotonDistributor.hxx"
7
8 // This class creates fractal mountains within a given scene based
9 // on the algorithm presented in Texturing and Modelling, p.500f,
10 // and terminates afterwards.
11 // It will create the aquarium ground landscape in the fishtank.
12 //
13 // *FISCHBECKEN!!*
14 //
15 // Sorry, insider joke. :-)
16 class FractalMountain
17 {
18 Noise *noise;
19 Vec3f **pointarray;
20 int resolution;
21
22 // Get rid of that fuckin' boundary conditions... this way we will always get
23 // meaningful values, even if we do not have any boundary checks
24 Vec3f GetPoint(int x, int y)
25 {
26 x %= resolution + 1;
27 y %= resolution + 1;
28
29 if (x < 0)
30 x += resolution + 1;
31
32 if (y < 0)
33 y += resolution + 1;
34
35 return pointarray[x][y];
36 };
37 public:
38 // Y
39 // |
40 // ORG -- X
41 FractalMountain(Scene *scene, Vec3f origin, Vec3f vertexX, Vec3f vertexY,
42 int resolution,
43 float frac_dimension, float gapwidth, int iterations, float height,
44 Shader *shader, PhotonDistributor *photon_distributor)
45 : resolution(resolution)
46 {
47 // Initialize the noise function
48 noise = new Noise(Vec3f(resolution));
49
50 // Create the array of points
51 pointarray = new Vec3f*[resolution + 1];
52
53 for (int i = 0; i < resolution + 1; ++i)
54 pointarray[i] = new Vec3f[resolution + 1];
55
56 // Create the weight function
57 float weight[iterations + 1],
58 frequency = 1.0f;
59
60 for (int i = 0; i <= iterations; ++i)
61 {
62 weight[i] = powf(frequency, -frac_dimension);
63 frequency *= gapwidth;
64 }
65
66 // We assume that the four points are situated in a plane...
67 // So get two direction vectors.
68 Vec3f dirX = vertexX - origin,
69 dirY = vertexY - origin;
70
71 // Get the common normal.
72 Vec3f normal = Cross(dirX, dirY);
73 Normalize(normal);
74
75 // Get the stepsize in each direction
76 float stepX = Length(dirX) / static_cast<float>(resolution),
77 stepY = Length(dirY) / static_cast<float>(resolution);
78
79 Normalize(dirX);
80 Normalize(dirY);
81
82 // Okay then... Now comes the tedious part... scan all points and calculate
83 // their values. Afterwards these values, applied to the points,
84 // are stored in the point array, providing them for the triangulation
85 // routine.
86 // Remember that we do not use the turbulence function this time, but
87 // build something very similar from scratch. That way, we can make
88 // valleys smoother than hills, which is especially important for
89 // underwater scenes :-) *FISCHBECKEN!!* - Sorry.
90 for (int x = 0; x < resolution + 1; ++x)
91 for (int y = 0; y < resolution + 1; ++y)
92 {
93 // Again, remember we are in a perfect rectangle!
94 // Here, we need two copies of the point: On to move around, for fractal generation,
95 // and one to be modified in height.
96 pointarray[x][y] = origin + dirX * stepX * static_cast<float>(x) + dirY * stepY * static_cast<float>(y);
97 Vec3f point = Vec3f(x,y,0) / resolution * 5.0f;
98
99 // The later pertubation
100 float dist = 1.0f;
101
102 // Generate fractal surface
103 for (int i = 0; i < iterations; ++i)
104 {
105 // Disturbation within this iteration
106 dist += dist * noise->Interpolated(point) * weight[i];
107 point *= gapwidth;
108 }
109 dist -= 1.0f;
110
111 pointarray[x][y] += dist * height * normal;
112 }
113
114 // Triangulate the points
115 for (int x = 0; x < resolution; ++x)
116 for (int y = 0; y < resolution; ++y)
117 {
118 // Calculate the vertex normals in ground coordinates
119 Vec3f vn1 = Cross(GetPoint(x, y) - GetPoint(x-1,y), GetPoint(x, y) - GetPoint(x, y+1)),
120 vn2 = Cross(GetPoint(x+1,y) - GetPoint(x, y), GetPoint(x+1,y) - GetPoint(x+1,y+1)),
121 vn3 = Cross(GetPoint(x, y+1) - GetPoint(x-1,y+1), GetPoint(x, y+1) - GetPoint(x, y+2)),
122 vn4 = Cross(GetPoint(x+1,y+1) - GetPoint(x, y+1), GetPoint(x+1,y+1) - GetPoint(x+1,y+2));
123
124 Normalize(vn1);
125 Normalize(vn2);
126 Normalize(vn3);
127 Normalize(vn4);
128
129 // Construct the quadrangle with two triangles
130 scene->Add(new SmoothTriangle(pointarray[x][y], pointarray[x+1][y], pointarray[x][y+1],
131 vn1, vn2, vn3, shader, photon_distributor));
132 scene->Add(new SmoothTriangle(pointarray[x][y+1], pointarray[x+1][y], pointarray[x+1][y+1],
133 vn3, vn2, vn4, shader, photon_distributor));
134 }
135
136 // Delete the array
137 for (int i = 0; i < resolution + 1; ++i)
138 delete[] pointarray[i];
139
140 delete[] pointarray;
141 };
142 };
143
144 #endif
syntax highlighted by Code2HTML, v. 0.9.1