Joining heightmaps

I’m experimenting with different types of noise filtering and merging, and having some success, however I’m unsure on how to knit them together; for example:

Each “tile” extends TerrainQuad, and i’m aware (by googling) that there is a neighbor finding method within TerrainQuad, but i’m unsure on how to go about using it effectively to achieve the desired effect of seaming each heightmap together…

The problem you are running into there is that the heights at the edges of the terrain do not match. The NeighbourFinder handles the LOD of the terrain and lets you seam the edges together, but just when the LOD control is activated. It won’t modify the height for you. TerrainTestTile.java shows how to use the neighbour finder. Just make sure the edge heights of one quad are exactly equal to the edge heights of its neighbour.

Yeah. I’m not too familiar with terrain generation and how it all works right now, i’m mostly reading up on the theory. To solve this problem you take the final height value of the right and bottom edges at an addition +1 co-ordinate, and thus each adjacent tile will be at the same height. I believe it’s called wrapping.

Ok, so i’m trying to write a filter for FilteredBasis, but i’m a little lost since as far as I’m aware there is as yet no documentation provided other than the javadocs.

There are pre and post filters. When should something be considered a pre filter and a pro filter?

I have a block size of 129 and tile size of 65. The height array is usually 129129 = 16641 but the size of the array in the filter has a size of 181181, which is oversized by 52. What is this extra data?

I’m still in the dark as to the above questions, but here is some working screenshots of a thermal erosion filter :smiley:

before:

after:

before:

after:

After spending a couple of days swimming in math, it’s finally starting to pay off. If I manage to get a few more filters working well i’ll happily push some code.

I’m not intimately familiar with the filters, someone else wrote them and unfortunately didn’t document them =(
Your terrain is looking great however!

@jayfella Hey this looks really cool! Does it do paging as well as stitching? I am still on the look out for a nice large terrain solution for JME myself too :slight_smile:

@monkeychops it works by monitoring the location of the camera (which is usually stuck to a character or vehicle or whatever) and loads terrain surrounding the player. You can set the view distance. So for example, if you have a view distance of 3, it will load 3 TerrainQuads in all directions. As you move from one TerrainQuad to another, it removes the ones behind and loads the ones in front of you. The TerrainQuads are loaded in a callable, and when ready, are added to the rootNode, so there is no “lag” when you move around. Kinda like this:

The image shows a view distance of one chunk. The blue dot is the player. When the player moves from the central chunk, the chunk location will change. You can know this by simple bitshifting. In my terrain, each chunk is 129x129, so by bitshifting you can work out the chunk location:

[java]
int playerX = (int)playerLocation.getX();
int playerZ = (int)playerLocation.getZ();

int chunkX = playerX >> 7;
int chunkZ = playerZ >>7;
[/java]

So now we know whether the player left the chunk. Then you simply calculate the theoretical surrounding chunks, compare it to the already loaded chunks, which leaves you with the new chunks to load, and also, using the same method, the old chunks to remove.

This method allows for easy view distance extension. Personally, I like to have a view distance of 3, which, gives us a fairly pleasant view distance. This also has the advantage of allowing us to maintain vegetation (trees, grass, etc…) on a “per chunk” basis, allowing us to add and remove vegetation automatically with the chunk. It also has the advantage of allowing us to maintain a relatively small set of static rigid objects (trees, for example) in one optimized node, and static non-rigid objects in another, and optimize them using GeometryBatchFactory per chunk, meaning we have decent sized RigidBodyControls - not too big, not too small (too big, and jme doesnt like it. Too small, too many objects, same result). This works really well with JmE.

The result:

Bearing in mind that this has no effects (AA, AF, bloom, shadows, etc…) running, (but I do have my atmospherics running, which drops the fps quite a bit) this has a view distance of 3, so 49 (7x7=49) chunks are loaded, 350 trees, 25088 grass billboards(!), 196 fir plants, and 147 rocks. Oh, and the player. i get an average of 260-280 fps when walking around - and I’m sure I can increase that at a guess by another 30-50 fps by optimizing the update loop. The FPS approximately doubles with a view distance of 2 (to around 500fps - 25 chunks) and again with a view distance of 1 (around 1000 - 1100 fps - 9 chunks).

I was thinking of providing some sort of structed useful code for others to use this, but i didnt think it was something people wanted. I’m happy to do so if it’s of any use.

2 Likes

@jayfella that looks really awesome… that’s exactly what I want but I’ve never found any examples that work how I want in JME and my maths sucks so I never attempted it.
I would certainly like to try it out.
Have you got the trees and grass paging with the terrain too?

Yes, all vegetation is bound to each chunk, so they are added and removed as the each chunk is added and removed.

I can make a candidate for a new TerrainGrid (since I see the existing one is deprecated with no current candidate) if one of the core developers are happy to consider it? Subject to quality control, naturally.

2 Likes

@jayfella I would super-support that idea. It has bugged me for years that there’s no usable paging terrain and vegetation system in JME. There have been loads of valiant efforts, but nothing that’s quite solid enough to actually use in my humble opinion.

@Sploreg already stated some time ago that TerrainGrid was going to be deprecated but I don’t think there’s a successor yet, so if this thing works it would be a great start!

The volume terrain component that was contributed a while ago also looks promising (I can’t find a link because the forum search seems messed up for me). It would be great to have the volume terrain stitched and paged in this way too, but I guess that’s too tricky (we’d have to stitch tunnels and such as well, god knows how!) and without paging it’s kinda useless, so this approach might be the best we can do realistically.

Correct, there is no candidate yet. For anything to be considered a candidate it needs to be able to have a non-square grid, adjustable paging range, be able to load tiles generated in an editor (not just with noise), and publish “loadingTile” and “finishedLoadingTile” events.
This one looks good so far. If the paging system is generic, then a vegetation system can be laid over top of it and you wouldn’t have to build it.

Something to consider with paging, is will it support two cameras (ie. 2-player couch-coop). I wouldn’t say it has to. TerrainQuad has the hooks plugged in for that and its LOD, but it isn’t implemented. There haven’t been any requests for that feature yet. And I’m not sure how many expansive terrain 2-player games there are out there. Those people can always add that feature in themselves.

With these paging systems it is very easy to plan for everything but get nothing completed. So keep the scope small and add to it when the core features are complete.

@Sploreg: I don’t think dealing with 2 players is a major concern - because most multiplayer games will be networked these days and games where you play co-op will usually force you to wait for the other player to catch up before letting you advance.

I rarely see split-screen games these days.
I did see a nice demo of using 3D glasses with interlaced screens an 2 “left” eyes for one player and 2 “right” eyes for the other player to show different images to each player using one 3dTV I guess that might catch on :slight_smile:

My opinion is, right now, anything is better than nothing. Even if it doesn’t support non-square grids just yet, if it supports smooth paging and no visible popping it’s already a step ahead of what we have so why not start with it and evolve it?

@Sploreg Other than multiple cameras, the system I have right now is able to do all that. One thing i’m not completely sure about - non-square grid. Do you mean that the north, east, south and west grids must be configurable, so you can theoretically have a different view distance in any direction? If so, I dont see that as a problem, I just never really thought of it as an option.

@monkeychops I do think that doing it right the first time is the best solution. It may work for you and me, but others may be frustrated at its lack of configuration - and it ends up being a very niche addition, or even worse than the implementation we are trying to improve.

I started working on this implementation late this morning, and it works with image-based height and noise. I havent looked into scenes from the sceneviewer yet, though I gather it’s just AssetManager related.

The hardest problem I can see is in implementing it in such a way that it is both intuitive and uncomplicated. The jme object design usually implements defaults and gives optional parameters for further customization, so I’ll follow that method.

Sigh, I tried to post to this thread several time but the forum just ate all the messages. Doing a final try :slight_smile:
You could package this as a an SDK plugin and put in the contribution repo. That way it is easily accessible and others can help fix bugs and help it grow.

@jayfella In that case I guess the holy grail would be to integrate with the scene editor so that you can just add as many tiles as you want or import heightmaps as needed.

I favour the Esenthel way of doing it:

We almost had this kind of editing in by using the old TerrainGrid and saving the tiles to j3o files. This way you could also stream in linked models and add vegetation Controls and whatnot. But how editor plugins work in the SDK is bound to change for 3.1 and we don’t have a complete vision of how the terrain and any “endless terrain” support in the engine will look, just that it won’t look like TerrainGrid. So any prototypes and code will come handy when we get back to this :slight_smile:

Well after some thought of how to implement the three main kinds of terrain generation that @Sploreg mentioned (noise, image heightmaps, pre-created scenes) I decided to create an abstract World class, and create three seperate classes that inherit it for each type of terrain generation. This is better for 2 reasons: firstly it doesnt have long, confusing constructors with overloads for each type of world, and secondly it cuts down a whole bunch of if/else/nullcheck logic - primarily in the update loop - which means better performance.

I haven’t really looked into how controls interact with the scene editor, for example, if I implemented this as a control, theoretically you could view your entire world within the composer. This would be really interesting because a noise generated world would be totally explorable within the composer, and you could even place things wherever you wanted and save the changes. Ultimately, no matter how the terrain is generated, it can always be saved in the same fomat. This sounds like a very nice toy to play with and I believe from what i’ve seen and read about jme thus far, entirely possible.

Having said that, this is further than the scope I visioned, lets first get back to the real world and write it so that it is in accordance with what the core devs expect. I’ve written the parent and noisebased class already and it’s all working as expected with all the requirement @Sploreg indicated were required. The imageBased class is easy enough, and I’m pretty sure the scene-based setup is similarly trivial. I’ll push some code tomorrow (i’m UK time, its 23:30 here) and we can go from there.

@Normen the only problem I havent been able to address with “endless terrain” is float precision in extremely distant co-ordinates. I am aware of a “conveyor-belt” type work-around, whereby the terrain moves, not the player, but this doesnt seem simple from a glance. The physics for a start… This problem has left me scratching my head, and as yet are unable to find a simple logical resolution.

By non-square grids I don’t mean non-square tiles. I mean that you can lay out the terrain tiles in a long strip if needed. TerrainGrid was forced to always show 4x4 tiles. But 14x2 should be possible.

@Sploreg Surely non-square grids could be as simple as allowing the tiles to be nullable?

@jayfella To deal with the float precision issue, can’t we just use 64 bit doubles or even mega big numbers like http://tsusiatsoftware.net/dd/main.html ?
It doesn’t go away but we should have more land than anyone can ever hope to travel across.

We can also use a torus approach, so if you do get to the end it loops back around to the beginning