Erosion 2

From DaveWiki

Jump to: navigation, search

In this example we will perform a very simple erosion on the sample height map we generated. Our basic erosion algorithm is:

  1. Choose a start point (arbitrary for this example)
  2. Find the lowest pixel adjacent to this point (the darkest of the 8 neighbours)
  3. Stop if already at the lowest point
  4. Move the lowest neighbouring point and continue at step 2

For this example we will only erode beginning at one point and mark the erosion path in black. Add the following methods to the CErosionSample class defined in the previous example and update the main function:

#include "erosion1.h"
 
/*
 * Finds the pixel with the lowest height adjacent to the given map coordinate.
 * Checks all 8 directions from the given location. Returns false if the given
 * point is lower than all 8 adjacent pixels. Otherwise returns true and updates
 * the input X/Y coordinates to the minimum position.
 */
bool FindMinimumNeighbour (utils::NoiseMap& HeightMap, int& X, int& Y)
{
	int OrigX = X;
	int OrigY = Y;
 
	if (HeightMap.GetValue(OrigX-1, OrigY+0) < HeightMap.GetValue(X, Y)) { X = OrigX - 1; Y = OrigY; }
	if (HeightMap.GetValue(OrigX+1, OrigY+0) < HeightMap.GetValue(X, Y)) { X = OrigX + 1; Y = OrigY; }
	if (HeightMap.GetValue(OrigX+0, OrigY-1) < HeightMap.GetValue(X, Y)) { X = OrigX; Y = OrigY - 1; }
	if (HeightMap.GetValue(OrigX+0, OrigY+1) < HeightMap.GetValue(X, Y)) { X = OrigX; Y = OrigY + 1; }
 
	if (HeightMap.GetValue(OrigX+1, OrigY-1) < HeightMap.GetValue(X, Y)) { X = OrigX + 1; Y = OrigY - 1; }
	if (HeightMap.GetValue(OrigX+1, OrigY+1) < HeightMap.GetValue(X, Y)) { X = OrigX + 1; Y = OrigY + 1; }
	if (HeightMap.GetValue(OrigX-1, OrigY-1) < HeightMap.GetValue(X, Y)) { X = OrigX - 1; Y = OrigY - 1; }
	if (HeightMap.GetValue(OrigX-1, OrigY+1) < HeightMap.GetValue(X, Y)) { X = OrigX - 1; Y = OrigY + 1; }
 
	if (OrigX == X && OrigY == Y) return (false);
	return (true);
}
 
class CErosionSample2 : public CErosionSample1
{
public:
 
	/*
	 * Erodes a single point in the height map by setting it to the lowest
	 * possible height for demonstration purposes.
	 */
	virtual void ErodePoint (const int X, const int Y)
	{
		m_HeightMap.SetValue(X, Y, -1);
	}
 
	/*
	 * Performs a complete erosion cycle starting at the given point in the 
	 * height map and continuing downhill until a local minimum is reached.
	 */
	virtual void Erode (utils::NoiseMap& OrigMap, int X, int Y)
	{
		bool Result;
 
		while (true) 
		{
			ErodePoint(X, Y);
 
			Result = davelib::FindMinimumNeighbour(OrigMap, X, Y);
			if (!Result) break;
		}
	}
 
	/*
	 * Test function to initiate an erosion cycle at the given position
	 * in the height map.
	 */
	virtual void StartErosion (const int X, const int Y)
	{
		utils::NoiseMap OrigMap = m_HeightMap;
 
		OrigMap.SetBorderValue(2);
		Erode(OrigMap, X, Y);
	}
 
};
 
int _tmain(int argc, _TCHAR* argv[])
{
	CErosionSample2 ErosionSample;
 
	ErosionSample.CreateBaseNoise();
	ErosionSample.StartErosion(190, 100);
	davelib::OutputHeightMapGrayScale("erosion2.bmp", ErosionSample.m_HeightMap);
 
	return 0;
}

The result of this basic erosion is:

We start the erosion near the top of a hill (bright area) and follow the steepest path down until we reach a local minimum.

Personal tools