- Home /
Gradual Terrain Smoothing from a Flat Area (at Runtime)
Hi, I apologise in advanced if the solution to my problem is logic-based rather than code. I've been staring at this for some time now, and may be missing something obvious.
I'm working on a game that has a structure placing element, but I'm struggling with the terrain modification. Basically I want to flatten the terrain directly under the structure being placed, but then gradually smooth out the surrounding terrain so I don't end up with a square platform of terrain sticking out of the ground.
I have the relevant height data in an array called "heights", and subject it to the following code;
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
if ( [various checks to see if current coords are in the area to be flattened] ) {
heights[x, y] = coord.y;
} else {
if (heights[x, y] > coord.y) {
heights[x, y] -= (heights[x, y] - coord.y) / 2;
} else {
heights[x, y] += (coord.y - heights[x, y]) / 2;
}
}
}
}
If I'm understanding things right, that code should just set any height points within the area to be flattened to coord.y (which it does just fine), and then take the rest of the height points and half the difference between where they are now and the flattened area. The result I get is a little inconsistent, but most commonly modifies the terrain with a flattened square under the object being placed, surrounded by another flattened square around it.
If anyone has any useful links, know of any relevant functions, or can tell from this post what I'm doing wrong, it would be greatly appreciated.
Answer by beagrie83 · Mar 10, 2014 at 06:34 PM
I figured it out, eventually. There's probably a much cleaner way of doing this but as no one seems to have any other ideas, here's what I got;
for (int x = 0; x < size + (smoothZone * 2); x++) {
for (int y = 0; y < size + (smoothZone * 2); y++) {
if (x >= smoothZone && y >= smoothZone && x <= (size + smoothZone) && y <= (size + smoothZone)) {
heights[x, y] = coord.y;
} else {
float smoothPercent = new float();
if (x < smoothZone && x <= y && x <= smoothZone - (y - (smoothZone + size))) {
smoothPercent = (float) x / (float) smoothZone;
} else if (x > (smoothZone + size) && x >= y && x >= smoothZone - (y -(smoothZone + size))) {
smoothPercent = 1 - ((float) (x - smoothZone - size) / (float) smoothZone);
} else if (y < smoothZone && y < x && y <= smoothZone - (x - (smoothZone + size))) {
smoothPercent = ((float) x / (float) smoothZone);
} else if (y > (smoothZone + size) && y > x && y > smoothZone - (x -(smoothZone + size))) {
smoothPercent = 1 - ((float) (y - smoothZone - size) / (float) smoothZone);
}
if (heights[x, y] > coord.y) {
heights[x, y] -= ((heights[x, y] - coord.y) * smoothPercent);
} else {
heights[x, y] += ((coord.y - heights[x, t]) * smoothPercent);
}
}
}
}
All of which basically works out the a decimal percentage (eg 0.5 = 50%) of the coord (when it's outside of the flattened area), which then becomes a kind of terrain modification opacity.
So, if the flattened area is 0.01f higher than the current coord height, and the current coord is in the middle of the smoothing zone (50%), then only 0.005f (half) will be added to the height, whereas it would be the full 0.01f would be added if the coord was next to the flattened area, and nothing would be added if it was at the outer edge of the smoothing zone.
If I run this on flat terrain (with the flattened area height artificially set to be higher than the terrain) I get square frustum, but on more natural looking terrain, I get a nice gradual smoothing all around from the flattened area to the surrounding terrain.
Thought I'd post the answer in case anyone else ran into similar problems.
i know this is a funky question but i am looking at that and was wondering if you are using int for all the names above? what did you use for each of their values to begin with? and any chance seeing the full script since this is a question asked over and over in this community and rarely answered with anything other than "look at the reference page and figure it out". i have gotten to the point of manually raising and lowering but like you i want to do it under a gameobject and make the surroundings a clean look. that last part has been weighing on me for months and i am to the point of giving up.
This post might be old, but if I found it while I was looking for help, someone might as well. I had similar problem, but I had flattened area on the "frame" (same ammount of flat area representing "road" from each side of the tile) of the my terrain tile. This code helped me create my own simple solution, here it is:
float smoothX = (i - roadSize) * ((Heigh$$anonymous$$apResolution - roadSize) - i);
smoothPercentX = smoothX / (((Heigh$$anonymous$$apResolution / 2) - roadSize) * ((Heigh$$anonymous$$apResolution - roadSize) - (Heigh$$anonymous$$apResolution / 2)));
float smoothY = (j - roadSize) * ((Heigh$$anonymous$$apResolution - roadSize) - j);
smoothPercentY = smoothY / (((Heigh$$anonymous$$apResolution / 2) - roadSize) * ((Heigh$$anonymous$$apResolution - roadSize) - (Heigh$$anonymous$$apResolution / 2)));
if (height[i, j] > .5f)
height[i, j] = .5f + (height[i, j] - .5f) * $$anonymous$$athf.$$anonymous$$in(smoothPercentX, smoothPercentY);
else
height[i, j] = .5f - (height[i, j] - .5f) * $$anonymous$$athf.$$anonymous$$in(smoothPercentX, smoothPercentY);
Note: .5f is my "flat" value (couldn't make it 0, so I can go down), "roadSide" is how much of the frame I have from each side and Heigh$$anonymous$$apResolution is just what I sounds like: resolution of Height$$anonymous$$ap