Sign in to follow this  

Terrain too rough

This topic is 4270 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
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 ^^;

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Actually I am using doubles during heightmap generation. After the first step of heightmap generation, the array consists of values with no upper limit (since all hills are added on top of another). These values are then normalized to an intervall between 0 and 1. Finally, when saving the heightmap, the heightmap is scaled up by multiplying the values with 255.

Share this post


Link to post
Share on other sites
This is what I get using the Hill algorithm you mention above. I applied smoothing just once aftewards (based on a box filter from this gamedev article). It does occasionaly generate a large hill in the center, as you mention, but for the most part, it generates a good island scene. I use bytes for the height in the range 0 to 255.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Hippokrates
Actually I am using doubles during heightmap generation.


You're doing this:

int radius;
double squareDistance = (centerX - j) * (centerX - j) + (centerY - k) * (centerY - k);
double height = (radius * radius) - squareDistance;



The problem is you have declared radius as int. So your multiplications are giving you int's as well not doubles. This is giving you the quantized height values. Try:

double radius;
double squareDistance = (double)(centerX - j) * (double)(centerX -j) + (double)(centerY - k) * (double)(centerY - k);
double height = (radius * radius) - squareDistance;

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One other thing, why are you doing this:

theta = (rand() % (2 * Pi)) / 1000.0f;

The division by 1000 makes theta near 0. Therefore, centerX=mapcenter+distance, and centerY=mapcenter.

Which is probably making your island look like a long cammel hump instead of spreading the hills around the map.

Share this post


Link to post
Share on other sites
Changing the values into doubles did not work either :(
As for the "theta = (rand() % (2 * Pi)) / 1000.0f;": I divide the value by 1000 because Pi is defined as 3141 (since you cannot use modulo on floating point numbers)

Share this post


Link to post
Share on other sites
Can you provide an image with polygon lines visible aswell? That would be helpful in diagnosis. It looks to me like some of the terrain is "stepped". That might mean its a drawing problem not a generation problem. Also it could just be that 8 bits isn't accurate enough for how much terrain you are generating.

Share this post


Link to post
Share on other sites
I actually think the image is fine and to be expected. Could you post a wireframe screenshot maybe?

The image in the tutorial looks nicer, but you'll notice that it is far more dense than the lines drawn over it suggest. If they plotted that mountain only on the points where the lines intersect it would also look pretty rough.

Share this post


Link to post
Share on other sites
I made a shot of the terrain in wireframe mode. I hope it will prove helpful. And this time I also used the source code provided by the author to generate the terrain. Therefore my implementation of the algorithm should have been correct.

Share this post


Link to post
Share on other sites
Actually I have no idea. I am rendering the terrain with Ogre's built-in terrain plugin, using standard parameters.
But I think the ground you are referring to, is actually behind the hill - so maybe it just looks more dense because it is farther away.

Share this post


Link to post
Share on other sites
It *really* looks like a quantization artifact, like hplus explained. If the piece of code you posted is correct, then it could be a problem with Ogre's plugin (maybe it converts doubles to 8-bits integers ?), or maybe you have yourself a cast to 8-bits int somewhere when submitting your data to the Ogre API ?

Y.

Share this post


Link to post
Share on other sites
i don't have a solution to the problem but i wouldn't go as far as rick and say that it's alright. The terrain looks like a staircase. I also think that the problem is a result of inaccuracies of variables(like using ints) because every single vertex is lying on a 'step'.

regards,
m4gnus

Share this post


Link to post
Share on other sites
Well, Ogre is of course using 8-bit integers because I do not directly give the heightmap to Ogre - I save it as a 8-bit greyscale .png, first.
But heightmaps usually are 8-bit images, aren't they? So that should not be the problem...?

More zoomed-out version:

Share this post


Link to post
Share on other sites
Quote:
Original post by Hippokrates
I divide the value by 1000 because Pi is defined as 3141 (since you cannot use modulo on floating point numbers)

Just for the record, you can do that with the fmod function.

Share this post


Link to post
Share on other sites

This topic is 4270 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this