Hi all, I’m trying to figure out what would be the best approach to create hills/cliffs on the fly, based on a 2D grid of tiles that are either blocked or not. Take a simplified grid like this, with randomly clustered blocked tiles and a random size:
Let’s say I want tiles that are 0 (zero) to become hills or cliffs, where some kind of center of mass determines the height (thus creating peaks the bigger a hill is.
I’ve looked at libraries like Shapely or Open3D to create meshes, but they both seem a bit too much for my purpose. It feels like this could be done much more efficiently for this specific cause.
I am leaning towards cutting up every tile into 4 triangles and have the sides of eacht tile match with neighboring ones. Using some noise algorithm, I’d be able to create a random effect. Counting neighboring blocked tiles might give me a sense of height increase, so that tiles on the edges of the hill shape are lowest (effectively approaching the floor level).
I have also tried writing the grid to a height map image and using that in a GeoMipTerrain, but I need just the hills (not the surrounding flats), I need face shading (not vertex) shading and I’d really like to have more control over some kind of randomness (noise) per vertex.
I can imagine others have struggled with this, and probably have figured out a good to perfect solution. I’d love to be pointed in the right direction!
I haven’t done this myself that I recall, but may have a thought that might help:
Breaking up your tiles as you suggest seems like it it could work–the trick then would be determining the appropriate heights for each edge. What I suggest is that you take an iterative approach:
- First, store all of your “hill” tiles in a list (or other useful structure).
- Then look for all tiles that are bordered by flat ground; give these a height of 1, and remove then from the list/structure.
- From there, look for all tiles bordered by tiles with a height of 1; give these a height of 2 and likewise remove them.
- Now repeat for tiles of increasing height, until you run out of tiles.
This should, I think, result in inner hills being higher than outer ones.
I don’t know how well it might perform for large maps, in all fairness; but for small ones I imagine that it should be fine!
The actual geometry could likely be constructed procedurally, with randomisation done after the assignment of overall heights. To make the tiles fairly seamless, half of the edges (e.g. say bottom- and right- edges) would not randomised, but assigned to the values of the opposite edges of the appropriate neighbouring tiles (in the example given, that would be the top edges of the tiles below and the left edges of the tiles to the right, I believe).
Thanks for your thoughts! This is the way I am leaning to, although I hadn’t thought of some practical elements you mention… so thank you for that. I agree determining a height value for each tile is the real challenge. Using a noise algorithm (or perhaps some kind of diamond-square one with some randomness) should be able to yield kind of a natural effect. I also thought cutting up each tile in even smaller triangles could give an even nicer effect, althought that would be a stage 2.
The geometry itself should be fairly simple, moving from tiles to vertices and faces into Egg data. It doesn’t have to be real-time, the terrain can be generated at the start of a level. But I don’t want to do it in a modelling package; a procedural approach is best in my case, I think.