How to interpolate between multiple biome height-maps? - c#

For biome area distribution I combine perlin noise representing temperature, and moisture levels using voronoi cell distribution. The world is divided by some modulo and another perlin noise function to return a voronoi control point. The seams between biomes show. I thought a simple weight function will do:
Orange point = the sample point which the weights will be calculated according to.
Using cellular noise (some kind of voronoi distribution similar to what I'm looking for, but doesn't blend different biomes):
To clarify vertex height:
float HeightAtPosition(float x, float z)
{
//Returns an array containing information of all the adjacent biome
//control points(mainly their position and their biome type)
BiomeControlPoint[] adjacentControlPoints = GetAdjacentBiomePoints(x, z);
//Returns an array containing values between 0 and 1
//Iputs: An array of all the adjacent biome points, a sample coordinate
//Output: A float array containing the weight of each biome on the
// coordinate(between 0 and 1)
float[] weights = CalcWeights(adjacentControlPoints, new Vector2(x, z));
float finalHeight = 0;
for (int i = 0; i < adjacentControlPoints.Length; i++)
{
finalHeight += adjacentControlPoints[i] * weights[i];
}
return finalHeight;
}
A good solution if GetAdjacentBiomePoints(x, z) and CalcWeights(adjacentControlPoints, new Vector2(x, z)) were more performance efficient. Bilinear interpolation I don't understand.

You could try a weighted voronoi diagram. My php implementation:https://tetramatrix.github.io/awvd/.

You could go the other way:
generate temperature and moisture levels for each pixel
generate how much each biome matches those values
precalculate strength of each biome as a 2d lookup table?
take the X best matches
normalize the strengths (sum is 1)
your a unique noise function combination is weighted sum of the X best biomes
Personally I work with gridmaps and interpolate the biome's valus from a small map with large cells to a large map with small cells. Interpolation is much easier there:
MapInterpolator.java
interpolation classes
Sorry that it is java.

Related

How do you Calculate with floats in c#

I want to programm a terrain generator in Unity and already have some working code for a Perlin Noise Terrain Generator. Im currently using Unity (using c#) and i cant figure out how to seperate the generation of the terrain depth(z)(the height of the mountains/depth of the valleys which i want to calculate using a Sqrt function) depending on x and the terrain depth depending on y. My problem is, when i try to convert the floats into ints, i would have to round them up or else they wont work, but i want to calculate the Terraindepth smoothly, is there a way i can combine those 2 heights into 1 without roughening the terrain?
float CalculateHeights(int x, int y)
{
float xCoord = x;
private int xz = float xCoord;
float yCoord = (float)y / height;
private int yz =float yCoord;
int z = (xz + yz) / 2;
return Mathf.Sqrt(z);
}
If you're trying to use Perlin Noise in Unity, you can always use the inbuilt generator.
Ex:
float height = Mathf.PerlinNoise(X,Y);
Warning though: If you don't use floating point values for X and Y with this function, you'll have issues with always getting the same value.
Hope this helps.
Docs - https://docs.unity3d.com/ScriptReference/Mathf.PerlinNoise.html

finding unknown 4th point in arbitrary space programmatically

Problem:
I know the x and y of three arbitrary points on a 2d plane.
I know the vague distance from each point to the unknown, though I don't know the x y components.
I want to find the position of the 4th point.
The data is stored in a list >3 of type Data where
public class Data
{
double m_x, m_y, m_distance;
}
I've tried:
Walking the list, calculating the components of the distance, then adding the known x and y. I then calculated the average position of the predicted point from the 3 known points, but the accuracy was inconsistent.
foreach (var item in data_list)
{
var dx = item.m_x + item.m_distance * Math.Cos(item.m_distance);
var dy = item.m_y + item.m_distance * Math.Sin(item.m_distance);
out_list.Add(new Data { m_x = dx, m_y = dy });
}
foreach (var item in out_list)
{
__dx += item.m_x;
__dy += item.m_y;
}
__dx /= return_list.Count;
__dy /= return_list.Count;
Creating three circles at the known x and y, extending their radii equal to the distance component and checking intersection. The problem is that the distance varies since its rather imprecise, more like a suggestion.
Is there a simple, ok-performing, witty solution to this problem that I can't grasp?
I've thought of extending lines 360 degrees around each point and checking where three lines intersect, the shortest distance away from the origin, but I'm not entirely sure about the implementation.

Formula For Calculating Length Of Line In BMP Image using c#

I want to calculate the length of some lines in this BMP Image.
I do not know the formula how to calculate these type of lines ? Or there is any other formula to calculate length in image processing.
By searching I came to know that we have to +1 in length if line if it go 1 pixel long vertically or horizontally. What if length is increasing diagonally ?
If any one can provide a mathematical formula that would be great.
Thanks.
The length when the direction is 1 pixel in diagonal is 1.4142135623730950488016887242097.
The math behind this factor is plain vector math, let me explain. According to vector math we can compute the length of a 2D vector as Math.Sqrt(Vector.X * Vector.X + Vector.Y * Vector.Y)). If we take as origin (0,0) and as target (1,1) we know the distance vector between origin and target is (1,1). So, if we compute the length of this vector we get: sqrt(1 * 1 + 1 * 1) what reduced is sqrt(2) and yields a result of 1.4142135623730950488016887242097.
You can use vector math to calculate a bunch of pixels instead of adding this factor to achieve a better precission, to do this just apply the previous math:
distanceVector = targetVector - originVector
distance = sqrt(distanceVector.X * distanceVector.X + distanceVector.Y * distanceVector.Y)
If you use the System.Numeric package then you can use the integrated functions:
Vector2 origin = new Vector2(originPixelX, originPixelY);
Vector2 target = new Vector2(targetPixelX, targetPixelY);
Vector2 distanceVector = target - origin;
float length = distanceVector.Length();
EDIT:
To simplify your problem there is a very easy solution which will give you the best precission.
If you sum the total of straight pixels and diagonal pixels in two variables, let's name those straightPixels and diagonalPixels you can do this:
var length = straightPixels + (new Vector2(diagonalPixels, diagonalPixels)).Length();
If you don't want to use the System.Numeric you can do:
var length = straightPixels + Math.Sqrt(diagonalPixels * diagonalPixels + diagonalPixels * diagonalPixels);
Very simple and effective.
If you want only lenght of diagonal for 1 pixel up and right, then it is very simple.
So it will be square of two.

Approximating an ellipse with a polygon

I am working with geographic information, and recently I needed to draw an ellipse. For compatibility with the OGC convention, I cannot use the ellipse as it is; instead, I use an approximation of the ellipse using a polygon, by taking a polygon which is contained by the ellipse and using arbitrarily many points.
The process I used to generate the ellipse for a given number of point N is the following (using C# and a fictional Polygon class):
Polygon CreateEllipsePolygon(Coordinate center, double radiusX, double radiusY, int numberOfPoints)
{
Polygon result = new Polygon();
for (int i=0;i<numberOfPoints;i++)
{
double percentDone = ((double)i)/((double)numberOfPoints);
double currentEllipseAngle = percentDone * 2 * Math.PI;
Point newPoint = CalculatePointOnEllipseForAngle(currentEllipseAngle, center, radiusX, radiusY);
result.Add(newPoint);
}
return result;
}
This has served me quite while so far, but I've noticed a problem with it: if my ellipse is 'stocky', that is, radiusX is much larger than radiusY, the number of points on the top part of the ellipse is the same as the number of points on the left part of the ellipse.
That is a wasteful use of points! Adding a point on the upper part of the ellipse would hardly affect the precision of my polygon approximation, but adding a point to the left part of the ellipse can have a major effect.
What I'd really like, is a better algorithm to approximate the ellipse with a polygon. What I need from this algorithm:
It must accept the number of points as a parameter; it's OK to accept the number of points in every quadrant (I could iteratively add points in the 'problematic' places, but I need good control on how many points I'm using)
It must be bounded by the ellipse
It must contain the points straight above, straight below, straight to the left and straight to the right of the ellipse's center
Its area should be as close as possible to the area of the ellipse, with preference to optimal for the given number of points of course (See Jaan's answer - appearantly this solution is already optimal)
The minimal internal angle in the polygon is maximal
What I've had in mind is finding a polygon in which the angle between every two lines is always the same - but not only I couldn't find out how to produce such a polygon, I'm not even sure one exists, even if I remove the restrictions!
Does anybody have an idea about how I can find such a polygon?
finding a polygon in which the angle between every two lines is
always the same
Yes, it is possible. We want to find such points of (the first) ellipse quadrant, that angles of tangents in these points form equidistant (the same angle difference) sequence. It is not hard to find that tangent in point
x=a*Cos(fi)
y=b*Sin(Fi)
derivatives
dx=-a*Sin(Fi), dy=b*Cos(Fi)
y'=dy/dx=-b/a*Cos(Fi)/Sin(Fi)=-b/a*Ctg(Fi)
Derivative y' describes tangent, this tangent has angular coefficient
k=b/a*Cotangent(Fi)=Tg(Theta)
Fi = ArcCotangent(a/b*Tg(Theta)) = Pi/2-ArcTan(a/b*Tg(Theta))
due to relation for complementary angles
where Fi varies from 0 to Pi/2, and Theta - from Pi/2 to 0.
So code for finding N + 1 points (including extremal ones) per quadrant may look like (this is Delphi code producing attached picture)
for i := 0 to N - 1 do begin
Theta := Pi/2 * i / N;
Fi := Pi/2 - ArcTan(Tan(Theta) * a/b);
x := CenterX + Round(a * Cos(Fi));
y := CenterY + Round(b * Sin(Fi));
end;
// I've removed Nth point calculation, that involves indefinite Tan(Pi/2)
// It would better to assign known value 0 to Fi in this point
Sketch for perfect-angle polygon:
One way to achieve adaptive discretisations for closed contours (like ellipses) is to run the Ramer–Douglas–Peucker algorithm in reverse:
1. Start with a coarse description of the contour C, in this case 4
points located at the left, right, top and bottom of the ellipse.
2. Push the initial 4 edges onto a queue Q.
while (N < Nmax && Q not empty)
3. Pop an edge [pi,pj] <- Q, where pi,pj are the endpoints.
4. Project a midpoint pk onto the contour C. (I expect that
simply bisecting the theta endpoint values will suffice
for an ellipse).
5. Calculate distance D between point pk and edge [pi,pj].
if (D > TOL)
6. Replace edge [pi,pj] with sub-edges [pi,pk], [pk,pj].
7. Push new edges onto Q.
8. N = N+1
endif
endwhile
This algorithm iteratively refines an initial discretisation of the contour C, clustering points in areas of high curvature. It terminates when, either (i) a user defined error tolerance TOL is satisfied, or (ii) the maximum allowable number of points Nmax is used.
I'm sure that it's possible to find an alternative that's optimised specifically for the case of an ellipse, but the generality of this method is, I think, pretty handy.
I assume that in the OP's question, CalculatePointOnEllipseForAngle returns a point whose coordinates are as follows.
newPoint.x = radiusX*cos(currentEllipseAngle) + center.x
newPoint.y = radiusY*sin(currentEllipseAngle) + center.y
Then, if the goal is to minimize the difference of the areas of the ellipse and the inscribed polygon (i.e., to find an inscribed polygon with maximal area), the OP's original solution is already an optimal one. See Ivan Niven, "Maxima and Minima Without Calculus", Theorem 7.3b. (There are infinitely many optimal solutions: one can get another polygon with the same area by adding an arbitrary constant to currentEllipseAngle in the formulae above; these are the only optimal solutions. The proof idea is quite simple: first one proves that these are the optimal solutions in case of a circle, i.e. if radiusX=radiusY; secondly one observes that under a linear transformation that transforms a circle into our ellipse, e.g. a transformation of multiplying the x-coordinate by some constant, all areas are multiplied by a constant and therefore a maximal-area inscribed polygon of the circle is transformed into a maximal-area inscribed polygon of the ellipse.)
One may also regard other goals, as suggested in the other posts: e.g. maximizing the minimal angle of the polygon or minimizing the Hausdorff distance between the boundaries of the polygon and ellipse. (E.g. the Ramer-Douglas-Peucker algorithm is a heuristic to approximately solve the latter problem. Instead of approximating a polygonal curve, as in the usual Ramer-Douglas-Peucker implementation, we approximate an ellipse, but it is possible to devise a formula for finding on an ellipse arc the farthest point from a line segment.) With respect to these goals, the OP's solution would usually not be optimal and I don't know if finding an exact solution formula is feasible at all. But the OP's solution is not as bad as the OP's picture shows: it seems that the OP's picture has not been produced using this algorithm, as it has less points in the more sharply curved parts of the ellipse than this algorithm produces.
I suggest you switch to polar coordinates:
Ellipse in polar coord is:
x(t) = XRadius * cos(t)
y(t) = YRadius * sin(t)
for 0 <= t <= 2*pi
The problems arise when Xradius >> YRadius (or Yradius >> Yradius)
Instead of using numberOfPoints you can use an array of angles obviously not all identical.
I.e. with 36 points and dividing equally you get angle = 2*pi*n / 36 radiants for each sector.
When you get around n = 0 (or 36) or n = 18 in a "neighborhood" of these 2 values the approx method doesn't works well cause the ellipse sector is significantly different from the triangle used to approximate it. You can decrease the sector size around this points thus increasing precision. Instead of just increasing the number of points that would also increase segments in other unneeded areas. The sequence of angles should become something like (in degrees ):
angles_array = [5,10,10,10,10.....,5,5,....10,10,...5]
The first 5 deg. sequence is for t = 0 the second for t = pi, and again the last is around 2*pi.
Here is an iterative algorithm I've used.
I didn't look for theoretically-optimal solution, but it works quit well for me.
Notice that this algorithm gets as an input the maximal error of the prime of the polygon agains the ellipse, and not the number of points as you wish.
public static class EllipsePolygonCreator
{
#region Public static methods
public static IEnumerable<Coordinate> CreateEllipsePoints(
double maxAngleErrorRadians,
double width,
double height)
{
IEnumerable<double> thetas = CreateEllipseThetas(maxAngleErrorRadians, width, height);
return thetas.Select(theta => GetPointOnEllipse(theta, width, height));
}
#endregion
#region Private methods
private static IEnumerable<double> CreateEllipseThetas(
double maxAngleErrorRadians,
double width,
double height)
{
double firstQuarterStart = 0;
double firstQuarterEnd = Math.PI / 2;
double startPrimeAngle = Math.PI / 2;
double endPrimeAngle = 0;
double[] thetasFirstQuarter = RecursiveCreateEllipsePoints(
firstQuarterStart,
firstQuarterEnd,
maxAngleErrorRadians,
width / height,
startPrimeAngle,
endPrimeAngle).ToArray();
double[] thetasSecondQuarter = new double[thetasFirstQuarter.Length];
for (int i = 0; i < thetasFirstQuarter.Length; ++i)
{
thetasSecondQuarter[i] = Math.PI - thetasFirstQuarter[thetasFirstQuarter.Length - i - 1];
}
IEnumerable<double> thetasFirstHalf = thetasFirstQuarter.Concat(thetasSecondQuarter);
IEnumerable<double> thetasSecondHalf = thetasFirstHalf.Select(theta => theta + Math.PI);
IEnumerable<double> thetas = thetasFirstHalf.Concat(thetasSecondHalf);
return thetas;
}
private static IEnumerable<double> RecursiveCreateEllipsePoints(
double startTheta,
double endTheta,
double maxAngleError,
double widthHeightRatio,
double startPrimeAngle,
double endPrimeAngle)
{
double yDelta = Math.Sin(endTheta) - Math.Sin(startTheta);
double xDelta = Math.Cos(startTheta) - Math.Cos(endTheta);
double averageAngle = Math.Atan2(yDelta, xDelta * widthHeightRatio);
if (Math.Abs(averageAngle - startPrimeAngle) < maxAngleError &&
Math.Abs(averageAngle - endPrimeAngle) < maxAngleError)
{
return new double[] { endTheta };
}
double middleTheta = (startTheta + endTheta) / 2;
double middlePrimeAngle = GetPrimeAngle(middleTheta, widthHeightRatio);
IEnumerable<double> firstPoints = RecursiveCreateEllipsePoints(
startTheta,
middleTheta,
maxAngleError,
widthHeightRatio,
startPrimeAngle,
middlePrimeAngle);
IEnumerable<double> lastPoints = RecursiveCreateEllipsePoints(
middleTheta,
endTheta,
maxAngleError,
widthHeightRatio,
middlePrimeAngle,
endPrimeAngle);
return firstPoints.Concat(lastPoints);
}
private static double GetPrimeAngle(double theta, double widthHeightRatio)
{
return Math.Atan(1 / (Math.Tan(theta) * widthHeightRatio)); // Prime of an ellipse
}
private static Coordinate GetPointOnEllipse(double theta, double width, double height)
{
double x = width * Math.Cos(theta);
double y = height * Math.Sin(theta);
return new Coordinate(x, y);
}
#endregion
}

artefacts during heightmap generation using plasma style fractal

I've spent a few hours today researching how random terrain generation tends to be done and after reading about the plasma fractal (midpoint displacement and diamond square algo's) I decided to try and have a go at implementing one. My result was actually not terriable, but I have these horrible square/line/grid type artefacts that I just can not seem to get rid of!
When rendered as a gray scale image my height map looks something like:
height map http://sphotos-d.ak.fbcdn.net/hphotos-ak-ash3/535816_10151739010123327_225111175_n.jpg
Obviously there is a fair amount of code involved in this but I will try to post what is only relevant. I've not not posted the code that turns it into a texture for example, but do not worry I have already tried just filling my height array with a smooth gradient and the texture comes out fine :)
I begin by setting the four corners of the map to random values between 0 and 1 and then start the recursive displacement algo:
public void GenerateTerrainLayer()
{
//set the four corners of the map to have random values
TerrainData[0, 0] = (float)RandomGenerator.NextDouble();
TerrainData[GenSize, 0] = (float)RandomGenerator.NextDouble();
TerrainData[0, GenSize] = (float)RandomGenerator.NextDouble();
TerrainData[GenSize, GenSize] = (float)RandomGenerator.NextDouble();
//begin midpoint displacement algorithm...
MidPointDisplace(new Vector2_I(0, 0), new Vector2_I(GenSize, 0), new Vector2_I(0, GenSize), new Vector2_I(GenSize, GenSize));
}
TerrainData is simply a 2D array of floats*. Vector2_I is just my own integer vector class. The last four functions are MidPointDisplace which is the recursive function, CalculateTerrainPointData which averages 2 data values and adds some noise, CalculateTerrainPointData2 which averages 4 data values and adds some noise and has a slightly higher scale value (its only used for center points) and finally my noise function which atm is just some random noise and not a real noise like perlin etc. They look like this:
private void MidPointDisplace(Vector2_I topleft, Vector2_I topright, Vector2_I bottomleft, Vector2_I bottomright)
{
//check size of square working on.. if its shorter than a certain amount stop the algo, we've done enough
if (topright.X - topleft.X < DisplacementMaxLOD)
{
return;
}
//calculate the positions of all the middle points for the square that has been passed to the function
Vector2_I MidLeft, MidRight, MidTop, MidBottom, Center;
MidLeft.X = topleft.X;
MidLeft.Y = topleft.Y + ((bottomleft.Y - topleft.Y) / 2);
MidRight.X = topright.X;
MidRight.Y = topright.Y + ((bottomright.Y - topright.Y) / 2);
MidTop.X = topleft.X + ((topright.X - topleft.X) / 2);
MidTop.Y = topleft.Y;
MidBottom.X = bottomleft.X + ((bottomright.X - bottomleft.X) / 2);
MidBottom.Y = bottomleft.Y;
Center.X = MidTop.X;
Center.Y = MidLeft.Y;
//collect the existing data from the corners of the area passed to algo
float TopLeftDat, TopRightDat, BottomLeftDat, BottomRightDat;
TopLeftDat = GetTerrainData(topleft.X, topleft.Y);
TopRightDat = GetTerrainData(topright.X, topright.Y);
BottomLeftDat = GetTerrainData(bottomleft.X, bottomleft.Y);
BottomRightDat = GetTerrainData(bottomright.X, bottomright.Y);
//and the center
//adverage data and insert for midpoints..
SetTerrainData(MidLeft.X, MidLeft.Y, CalculateTerrainPointData(TopLeftDat, BottomLeftDat, MidLeft.X, MidLeft.Y));
SetTerrainData(MidRight.X, MidRight.Y, CalculateTerrainPointData(TopRightDat, BottomRightDat, MidRight.X, MidRight.Y));
SetTerrainData(MidTop.X, MidTop.Y, CalculateTerrainPointData(TopLeftDat, TopRightDat, MidTop.X, MidTop.Y));
SetTerrainData(MidBottom.X, MidBottom.Y, CalculateTerrainPointData(BottomLeftDat, BottomRightDat, MidBottom.X, MidBottom.Y));
SetTerrainData(Center.X, Center.Y, CalculateTerrainPointData2(TopLeftDat, TopRightDat, BottomLeftDat, BottomRightDat, Center.X, Center.Y));
debug_displacement_iterations++;
//and recursively fire off new calls to the function to do the smaller squares
Rectangle NewTopLeft = new Rectangle(topleft.X, topleft.Y, Center.X - topleft.X, Center.Y - topleft.Y);
Rectangle NewTopRight = new Rectangle(Center.X, topright.Y, topright.X - Center.X, Center.Y - topright.Y);
Rectangle NewBottomLeft = new Rectangle(bottomleft.X, Center.Y, Center.X - bottomleft.X, bottomleft.Y - Center.Y);
Rectangle NewBottomRight = new Rectangle(Center.X , Center.Y, bottomright.X - Center.X, bottomright.Y - Center.Y);
MidPointDisplace(new Vector2_I(NewTopLeft.Left, NewTopLeft.Top), new Vector2_I(NewTopLeft.Right, NewTopLeft.Top), new Vector2_I(NewTopLeft.Left, NewTopLeft.Bottom), new Vector2_I(NewTopLeft.Right, NewTopLeft.Bottom));
MidPointDisplace(new Vector2_I(NewTopRight.Left, NewTopRight.Top), new Vector2_I(NewTopRight.Right, NewTopRight.Top), new Vector2_I(NewTopRight.Left, NewTopRight.Bottom), new Vector2_I(NewTopRight.Right, NewTopRight.Bottom));
MidPointDisplace(new Vector2_I(NewBottomLeft.Left, NewBottomLeft.Top), new Vector2_I(NewBottomLeft.Right, NewBottomLeft.Top), new Vector2_I(NewBottomLeft.Left, NewBottomLeft.Bottom), new Vector2_I(NewBottomLeft.Right, NewBottomLeft.Bottom));
MidPointDisplace(new Vector2_I(NewBottomRight.Left, NewBottomRight.Top), new Vector2_I(NewBottomRight.Right, NewBottomRight.Top), new Vector2_I(NewBottomRight.Left, NewBottomRight.Bottom), new Vector2_I(NewBottomRight.Right, NewBottomRight.Bottom));
}
//helper function to return a data value adveraged from two inputs, noise value added for randomness and result clamped to ensure a good value
private float CalculateTerrainPointData(float DataA, float DataB, int NoiseX, int NoiseY)
{
return MathHelper.Clamp(((DataA + DataB) / 2.0f) + NoiseFunction(NoiseX, NoiseY), 0.0f, 1.0f) * 1.0f;
}
//helper function to return a data value adveraged from four inputs, noise value added for randomness and result clamped to ensure a good value
private float CalculateTerrainPointData2(float DataA, float DataB, float DataC, float DataD, int NoiseX, int NoiseY)
{
return MathHelper.Clamp(((DataA + DataB + DataC + DataD) / 4.0f) + NoiseFunction(NoiseX, NoiseY), 0.0f, 1.0f) * 1.5f;
}
private float NoiseFunction(int x, int y)
{
return (float)(RandomGenerator.NextDouble() - 0.5) * 0.5f;
}
Ok thanks for taking the time to look - hopefully someone knows where this grid-like pattern is appearing from :)
*edit - accidently wrote ints, corrected to floats
I identified 3 problems in your code. (2 of which are related)
You don't scale down the randomness in each step. There must be a reduction of the randomness in each step. Otherwise you get white(-ish) noise. You choose a factor (0.5-0.7 worked fine for my purposes) and multiply the reduction by alpha in each recursion and scale the generated random number by that factor.
You swapped the diamond and square step. First the diamonds, then the squares. The other way round is impossible (see next).
Your square step uses only points in one direction. This one probably causes the rectangular structures you are talking about. The squares must average the values to all four sides. This means that the square step depends on the point generated by the diamond step. And not only the diamond step of the rectangle you are currently looking at, also of the rectangles next to it. For values outside of the map, you can either wrap, use a fixed value or only average 3 values.
I see a problem in your CalculateTerrainPointData implementation: you're not scaling down the result of NoiseFunction with each iteration.
See this description of the Midpoint Displacement algorithm:
Start with a single horizontal line segment.
Repeat for a sufficiently large number of times:
Repeat over each line segment in the scene:
Find the midpoint of the line segment.
Displace the midpoint in Y by a random amount.
Reduce the range for random numbers.
A fast way to do it in your code without changing too much is by adding some scale parameter to MidPointDisplace (with default set to 1.0f) and CalculateTerrainPointData; use it in CalculateTerrainPointData to multiply result of NoiseFunction; and reduce it with each recursive call to MidPointDisplace(..., 0.5f * scale).
Not sure though if that is the only cause to your image looking wrong or there are other problems.
According to Wikipedia's summary of midpoint displacement, only the average for the center most point get noise added to it - try only adding noise via CalculateTerrainPointData2 & removing the noise in CalculateTerrainPointData.

Categories

Resources