Terrain too rough

Started by
31 comments, last by Hippokrates 18 years ago
I am currently working on a heightmap-generator. Since I would like to generate the heightmap for an island I searched for algorithms which would do this for me an found this one: http://www.robot-frog.com/3d/hills/island.html Since this algorithm always leaves me with the same circular shape and only one mountain, which is always in the center, I modified it so that half the time the hills would be subtracted. This makes the shape somewhat more interesting. But either way, the terrain is way too rough. It looks as if it was composed of circular slices stacked on top of another. I already tried a box filter to smoothe the terrain but it did not get better... Any ideas?
Im Anfang war die Tat...Faust
Advertisement
Use a multi-fractal? I guess to make this produce an island you would need to add a multiplier based on distance from some center point.
Given the fact that you already coded a box filter, you could just execute it multiple times! Or use a "better" smoothing algorithm, like a gaussian filter.
What are you using to make the those renders?
Actually I am already applying the box filter 20 times. Applying it about 500 times does somewhat soften the terrain but it still looks as if composed of slices (just with less features...).

I am rendering the terrain using Ogre3D so there should be nothing wrong with the renderer.

Will multifractal algorithms solve the circular shape problem? Islands that have a very straight coastline do not look too realistic :(

[Edited by - Hippokrates on March 27, 2006 12:08:35 PM]
Im Anfang war die Tat...Faust
i implemented the robot frog algo and didnt have this issue at all. in fact, my issue was that there wasn't enough "roughness" to the algo. if you're ending with one mountain in the center every time then you havent properly implemented the method. or perhaps the metrics you are using to seed the algo are the source of your problem.

iirc, the algo randomly selects a point on your terrain and raises by variable X that point and does a radial fall off given a slope Y.


wish i had my home pc available i'd give you some screenshots of what is possible with it. smooth, rolling hills that look great and the ability to save it in a very small random seed to be generated later.

for smoother transitions increase your hill radius and store a list of your 10 or so highest points and auto reject them if they are within radius minus Y of the randomly chosen point.
"Let Us Now Try Liberty"-- Frederick Bastiat
Quote:Original post by Hippokrates
It looks as if it was composed of circular slices stacked on top of another.


Sounds like you are using int's instead of floats for the height values.

As for the rest, without an image it's hard to speculate what the problem is.
I made a screenshot to illustrate my problem:


As for my implementation of the algorithm:
bool HeightmapGen::GenerateShape(double * heightmap, HeightmapParameters * params) {	int radius, centerX, centerY, distance;	int xMin, xMax, yMin, yMax, subtract = 1;	double theta;	for(int i = 0; i < params->details; i++) {		radius = params->hillMin + (rand() % (params->hillMax - params->hillMin));		theta = (rand() % (2 * Pi)) / 1000.0f;		distance = (radius / 2) + rand() % static_cast<int>(1 + (params->terrainSize / 2.0f) - radius);		centerX = (params->terrainSize / 2.0f) + cos(theta) * distance;		centerY = (params->terrainSize / 2.0f) + sin(theta) * distance;		xMin = centerX - radius - 1;		xMax = centerX + radius + 1;		yMin = centerY - radius - 1;		yMax = centerY + radius + 1;		if(xMin < 0) xMin = 0;		if(xMax >= params->terrainSize) xMax = params->terrainSize - 1;		if(yMin < 0) yMin = 0;		if(yMax >= params->terrainSize) yMax = params->terrainSize - 1;		if(rand() % 2 == 0) {			subtract = -1;		}else {			subtract = 1;		}		for(int j = xMin; j < xMax; j++) {			for(int k = yMin; k < yMax; k++) {				double squareDistance = (centerX - j) * (centerX - j) + (centerY - k) * (centerY - k);				double height = (radius * radius) - squareDistance;				if(height > 0.0f) {					heightmap[j + (k * params->terrainSize)] += height * subtract;					if(heightmap[j + (k * params->terrainSize)] < 0) heightmap[j + (k * params->terrainSize)] = 0;				}			}		}	}	return true;}


As I mentioned earlier, I modified the algorithm to subtract half of the hills in order to avoid a circular shape. The result isn't very pretty though ^^;
Im Anfang war die Tat...Faust
Their algorithm doesnt look particularly good. (judging by their methods description, not the screenshot)
Have you considered using other approaches?

How about DiamondSquare, with some unitial 'seed' height values to keep it in a general island shape?

or perlin noise with a filter based on distance to center?

or either of the above techniques layered on top of what you have now to add details and hide problem areas?
Sound like you're using bytes in the original height map generation. Bytes only have 256 different values, which easily leads to quantization in height. Try using floats instead. Or, if you're not using the full 0-255 range (or -128-127), scale your terrain such that the highest value you want is 255, and the lowest is 0, to minimize quantization.

Another thing you can do is to generate the heightfield at a much coarser interval, and generate a more tesselated mesh using some kind of interpolation. Cubic interpolation works pretty well for that cases, in my experience.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement