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