Procedural terrain

I was asked to port here another topic about an infinite procedural terrain generator. I guess I have to explain it in a few words.



Motivation:



I’m just learning to use jME3, just found it a few weeks ago. I have a game idea in my mind and was happy that I don’t have to write everything from the bottom up, instead I can build on a stable engine, and take care of the main concepts. The first thing that was important for me, is to be able to generate terrain content on the fly, sometimes for different regions of the game, sometimes I need different terrain for different users, etc. I’m not as good in designing as in programming, also I do not have a designer yet, and my plans are that I will need so many terrains, that it’s not possible to be designed or even stored.



The solution:



So I found out about procedural terrain generation, which uses noise functions and fractals, that can be defined by a few parameters, and then asked for a value at a given point. There are some rules for these functions that make it reliable, such that it will always generate the same output for the same input. I already had some of these basis functions implemented - mainly ported from C examples - when I found jME. After looking around the tutorials and getting familiar with how to use it, I found the TerrainQuads which seemed to be the perfect spot to wire my functions in. But after playing a few days with it I had to face it, that the existing terrain implementation was optimized for pregenerated terrain data, which makes it possible to optimize the quality and speed when reading the data. This optimization I found too slow for realtime usage, so I created a small implementation based on the basic Geometry object. I designed to be as easy to be configured as possible, but it’s just the basics as far as I can see.



I have uploaded the code to my sourceforge svn and is available at: https://proceduralterra.svn.sourceforge.net/svnroot/proceduralterra



Known limitations:



Increasing the terrain detail can introduce some lags when calculating the next terrain tile, this might be solved by applying some LOD features, as faraway parts of the terrain can never be reached. (It uses a 3x3 grid and the user is always in the actual tile’s center cell)



The current version is using the jME builtin terrain material, and is not responing well when generating the next tile. This means that the texture is reset, so the user can see it change where he’s standing, though the terrain model remains the same. It will be solved soon.



Future plans:



Generating terrain from functions can result in boring worlds, so I’m planning some improvements:


  1. the current heightmap will be interpolated with some other “heightmap” which will contain information about the average height in that region, so it will be possible to create plains, hills, mountains instead of the current hills are everywhere approach
  2. replace the current material with a new, that applies texture based on height + temperature + humidity maps. The temperature and humidity maps can be also generated using preparameterized functions, which can take into count the time factor, so an ever changing world can be created.



    Thanks for your time, any critics and improvements are welcome :slight_smile:



    Anthyon
2 Likes

update: texture mapping bug is fixed

Sounds interesting.

Maybe it would be good to allow mixing it with “static” terrain, so if there is need to modify some part of terrain, modified terrain patch would be converted to explicit representation (heightmap/mesh) and then artist could do whatever he wants with it. And as long as it would be not overused, benefit from procedural terrains would stay.

And maybe this would even enable for player to affect terrain (but some limitations (either nonpersistance of changes, or some limiting cost of changes would be needed).

Have you checked out MonkeyHorizons by @dpwhittaker ? He did practically the exact same thing you did. Started out digging into TerraMonkey only to find out that he couldn’t quite merge his designs with TerraMonkey, so he made it an independent, alternative terrain system instead (later nicknamed MonkeyHorizons).



Maybe neither of you will be extending TerraMonkey any time soon, which is fine, but maybe you and @dpwhittaker have similar enough goals to start a collaboration. Worth exploring :slight_smile: Here’s the latest known source download of his work.

Great ideas.



Heightmap segments can already be saved into any format, cause the fractal function can be used outside of the terrain. And the time needed to compute more detailed terrains are acceptable for terrain editors, I guess.



The other use is more interesting to me. Assigning the terrain another heightmap layer initialized to 0 everywhere, and allowing the player interact with this layer, and be able to deform it sounds a great feature for a game. All one needs to do is interpolate the two layers in some way to get the actual height at one point. It can have some problems though, eg. with the detail level of the terrain.

@erlend_sh: Thanks for the directions :slight_smile: I took a look at the project, and will try to contact him, I guess we can exchange some results.

erlend_sh said:
Maybe neither of you will be extending TerraMonkey any time soon, which is fine

I wouldn't like this trend at all :P

Ive had to take a short break from MonkeyHorizons to work on school projects and research. But I should be able to spend more time on it starting next week. My Ph.D. research is moving in the direction of more geologically accurate terrain generation techniques, but I still plan to work on this project on the side. I hope to have an update with better splatting before the end of the month, then start working on vegetation.



David

dpwhittaker said:
Ive had to take a short break from MonkeyHorizons to work on school projects and research. But I should be able to spend more time on it starting next week.

This is about procedural terrain for TerraMonkey, the thing that MonkeyHorizons cannot do :P

To make it clear: I will try to make it as compatible with the TerraMonkey as I can , but I will need help to understand the main concepts better :slight_smile:

update: updated the FractalTerrain class to implement Terrain interface. I could not define some methods yet, but it already can provide height data at any location in the world. I’m going to fix some detail specific issues now…



edit: also uploaded a zip to sourceforge with the binary, executable version of the sources just for test cases: http://sourceforge.net/projects/proceduralterra/files/hunter-test/hunter-0.0.1.zip/download



Can anyone help what else is needed to be TerraMonkey compatible?

Cool! I guess when @Sploreg is back from his vacation he’s the man to ask… I am sure he’ll drop by here then.

To be compatible with TerraMonkey, your terrain needs to implement the Terrain interface and be a Node. If so, then it is easy to plug into the Terrain Editor in JMP.

Much of the Terrain interface is for modifying the terrain: get/set height, getMaterial (for painting), and some painting helper methods.



There are a couple of hard-coded TerrainQuad areas in TerraMonkey, definitely one where you create the terrain. That spot you would just substitute your terrain instead.

The TerrainEditorController does all the interaction with the actual Terrain object, mostly its material and geometry.



Also, the material and the painting system… I’m not sure how “infinite” will work with that since it applies the ‘paint’ to a percentage point on the texture. So if you paint at x=50%, y=50% along the terrain, you would be painting in the middle of the texture, if you see what I mean. Infinite will have no middle and this method will not work. It might also be a mighty large alpha map to cover that terrain with any detail. How is your material going to work?

So as far as I can understand TerraMonkey is the editor itself. Just to clarify again: procedural terrain generation means that no paining is involved. The terrain is generated by setting a few parameters on a selected set of functions. This can produce a heightmap image as a side effect, that can easily be imported into any editor, including TerraMonkey.



I don’t see the reason why there is the limitation to TerrainQuads in the interfaces and main classes, where all they’re using is just the methods of the Terrain interface? This way one has to reimplement all classes just to create a plug-in that provides a new way of seeding terrain information to the system.



I have experienced with many ways of doing so, and still not decided which way to choose for my own project. I’ll upload the code itself to the svn as soon as I have cleaned it up a bit, but here are a few videos of the latest version I created:



http://www.youtube.com/watch?v=WnQelUbe3Ds



http://www.youtube.com/watch?v=vcAOitQ0_cc



http://www.youtube.com/watch?v=27hZTk8Tz1Q



I hope it shows everything I meant to capture. :slight_smile:

As for the texturing part, as the heightmap is not defined in advance it can hardly have alpha maps and such, so the textures are currently applied by height and slope, but I’m working on introducing climate zones as well.

TerraMonkey is the terrain system, not the editor.

normen said:
TerraMonkey is the terrain system, not the editor.


That's what I though until now, but @Sploreg talked only about, how Terrain fits into the editor... So sorry for the misunderstanding. Than I guess the uses of terrain interfaces needs some generalization where they are used in the code, to not rely on TerrainQuads where it's not necessary. For example the TerrainLodControl class is unnecessarily restricted to TerrainQuads when all it uses is Terrain.update(List)

The thing he is talking about is that the Terrain classes need to have some methods and data accessible that is needed for the editor. In the end you will want to have some control over whats being generated and where/how. Idk the details, but @Sploreg is definitely talking about the base terrain classes.

anthyon said:
So as far as I can understand TerraMonkey is the editor itself. Just to clarify again: procedural terrain generation means that no paining is involved. The terrain is generated by setting a few parameters on a selected set of functions. This can produce a heightmap image as a side effect, that can easily be imported into any editor, including TerraMonkey.

I don't see the reason why there is the limitation to TerrainQuads in the interfaces and main classes, where all they're using is just the methods of the Terrain interface? This way one has to reimplement all classes just to create a plug-in that provides a new way of seeding terrain information to the system.

I have experienced with many ways of doing so, and still not decided which way to choose for my own project. I'll upload the code itself to the svn as soon as I have cleaned it up a bit, but here are a few videos of the latest version I created:

http://www.youtube.com/watch?v=WnQelUbe3Ds

http://www.youtube.com/watch?v=vcAOitQ0_cc

http://www.youtube.com/watch?v=27hZTk8Tz1Q

I hope it shows everything I meant to capture. :)
As for the texturing part, as the heightmap is not defined in advance it can hardly have alpha maps and such, so the textures are currently applied by height and slope, but I'm working on introducing climate zones as well.


So it looks like you're moving towards the approach that the procedural generation spits out a heightmap that can be imported into the Terrain Editor and rendered by Terra Monkey. Maybe you should take a look at... what's the class... HillBasedHeightmap? Something like that anyway. If I remember correctly, it generates a landscape with a bunch of gaussian bumps on it ("hills"), but the important part about it is that it procedurally generates a heightmap that is used in TerraMonkey and the editor. You lose the "infinite" size, but make it implicitly compatibly with any heightmap rendering system under the sun.

On the other hand, the most often cited problem with procedural terrains is lack of control. If you can find a way to allow the user to "paint" on the terrain different areas where there are hills, valleys, plains, rivers, lakes, etc. then it instantly becomes a more useful terrain generator. Giving the user more control than just a "reseed" button is key to making a truly useful procedural terrain generator.

@normen:

Maybe the whole issue with the editor is that it is too tied to a specific idea of what editing a terrain means. For instance, you have a "brush" which changes the height values in a heightmap representation of the terrain, by calling setHeight on the terrain. This concept only means something to a static terrain that can change itself to another static terrain. Procedural terrains may or may not have a notion of exceptions to procedurally generated height values, but may have an idea of editing multiple underlying raster data like a climate map, tectonic fault lines, spatially varying noise parameters, etc, and the underlying raster data may be at a different resolution than the final heightmap. In other words, the brush concept is fundamental to terrain editing, but the alter-every-height-under-the-brush concept is not.

So, perhaps a better interface for a terrain editor might take out all the assumptions that the underlying store is a static heightmap. This means taking away the setHeight, setMaterial, and painting helpers, and replacing them with a simple getBrushes() function which returns a list of TerrainBrushes. TerrainBrush has some way of returning a parameter list or UI element that can be used to alter the brush parameters (i.e. radius, amplitude, noise for a simple Raise brush) and these parameters are displayed in the editor when the brush is selected. It also has a render(Ray) function that takes a ray representing the current mouse position, and is responsible for rendering some user-recognizable visual representation of the brush (whether that's a decal on the terrain or a marker floating over the terrain or whatever). Finally, the TerrainBrush interface also defines a beginStroke(ray), stroke(ray), and endStroke(ray) that are fired off in response to mousedown, mousemove, and mouseup events, respectively. These functions would be responsible for actually painting the terrain, whether that's lowering and raising height values, increasing or decreasing the density of a particular material, creating a path that represents a fault line or mountain range, or whatever. The point is, the editor doesn't have to know anything about the implementation of the underlying terrain, it's just casting rays into the black box of the terrain interface, and letting the terrain edit itself.

Maybe the next step after that would be the ability to draw vector shapes on the terrain. A static heightmap engine would then probably stroke the paths immediately and bake the changes in the heightmap, while the dynamic procedural engines would probably just store the paths and recreate the changes on the fly. Of course, this functionality could be handled by brushes that maintain their own state, and check whether you are clicking on an endpoint or not in the beginStroke, so they can decide whether to move the endpoint in stroke or add a new endpoint in endStroke... but I think the vector shape editing approach may be useful for all types of terrains, and therefore useful to add to a generalized terrain editor.

An approach like this could mean that anthyon's project, MonkeyHorizons, and almost any future terrain system could once again fall under the TerraMonkey interface, and each one can still offer all the features its underlying engine could support.

@Sploreg you mean? :stuck_out_tongue:

TerraMonkey is the whole terrain system, however the Terrain interface is for external tools such as the terrain editor in JMP to interact with it. There are many other possible terrain implementations besides procedural terrain, such as spherical terrain, infinite paged terrain, vertical terrain (caves), etc. And once these potential implementations get flushed out then the terrain quad classes will modify to suit them.



Much of the TerrainQuad API can work for procedural terrain. The TerrainPatch class is the actual geometry is is quite specific to requiring a heightmap.

Largely the TerrainQuad class expects a fixed size tree. What can be done to expand it, is allow each root quad to have neighbours. Then you can load in many trees and page them off of disk to help have an infinite terrain system (think of google maps where each map tile is a quad tree). This is part of the API that I want to add in to support larger terrains, while still retaining physics, collision, and the nice/customizable texturing.



Remember that to fit in with TerraMonkey it must also fit in with JME3, that means collision and physics. Procedural terrain will provide some obstacles for this, but they can be overcome. A lot of those features is why the terrain api is as restrictive as it is, and for several performance reasons.