TerrainTiler Class Project

Hi all!
Just a quick update on a terrain code I’m working on, something I’ve been building as a replacement for TerrainGrid in my game project and also to push my learning abilities on both Java and jMonkey. I hope to share it with other jMonkey users and once I’ve made it properly functional I’ll attempt to make it a plugin.
My intention is to make this as simple as it can be but flexible enough for most basic use cases. Specifically mine but I see no reason it can’t be used in many projects. TerrainGrid itself was fairly basic in function but I found it did not work in my situation.
Basic concepts for starters is this TerrainTiler class is a Node, all its TerrainQuads are attached to this node internally and loaded in as needed. The class sets up an appState to handle attaching and detaching the quads to the node, also a thread runs on its own tracking a supplied camera to handle loading new tiles, flagging them to be attached or flagging others for detaching.
The TerrainGrid can be 3x3, 5x5, 7x7 or 9x9 viewable tiles, right now it’s square and therefore a tad wasteful at the higher numbers but it will do until I get good enough to make it more circular, maybe.
Terrain Tiles will be loaded from a set of .j3o terrain object files and I intend on making a TerrainTileCreator class to make the creation, modification and saving of these tiles from a height-map graphic or from scratch. Hopefully I can get this part to work inside the SDK :slight_smile:
That’s all for now, getting late here and my brain is protesting (I think I’m wearing out my backspace key… and hoping this post makes sense :woot: ).
If you would like to have a look at the code I’ve put it up on code.google.com/p/my-terraintiler-test
Screenshots are on the blog for my project thegame.radans.net
Keep in mind this is VERY early work in progress :slight_smile: (and as I said I’m just learning Java/OOP & jME too!)
Thanks for reading!

3 Likes

hi, i tried to test ur code and getting this error:
Mar 01, 2013 9:47:35 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
com.jme3.renderer.RendererException: Shader link failure, shader:Shader[numSources=2, numUniforms=20, shaderSources=[ShaderSource[name=Common/MatDefs/Terrain/TerrainLighting.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Terrain/TerrainLighting.frag, defines, type=Fragment, language=GLSL100]]] info:Fragment info

0(155) : error C5041: cannot locate suitable resource to bind parameter “wVertex”
0(156) : error C5041: cannot locate suitable resource to bind parameter “wNormal”

Yeah, pretty much just a “here is code I’m working on” it is very much a work in progress and in no way stable.
At this stage I’ll take advice on code style or best practice tips from the experts but for everyone else just wait until its reached release stage.
Plus there have been a lot of jMe core updates recently that my have upset the code and I’ve been busy dealing with another disaster here so haven’t updated my code yet

Thanks.

Sweet, looking forward to using this. Keep us updated!
EDIT: Oh and if you are working on a cache for the tiles, Google’s Guava library has a great and easy to use cache that I recommend.

@Sploreg said: Sweet, looking forward to using this. Keep us updated! EDIT: Oh and if you are working on a cache for the tiles, Google's Guava library has a great and easy to use cache that I recommend.

Thanks! I need this to work for the game I want to make so I have no excuses to not get it finished, I only hope I can make it flexible enough to be usable by others without too much pain. I guess that’s the challenge with most libraries, though you can never satisfy everyone’s needs.

Current work is back on track after the caching issues and at this stage the terrains won’t have any caching, I’ll work on that during final optimizing stages.
Right now I’m implementing and fleshing out the internal functions and variances. Mainly with the “Implements Terrain, NeighborFinder” functions.
The fun part will be the “setHeight(List xz, List height)” ones, need to sort into a list for each loaded quad and pass on…

If I can ask on these functions though, I have no idea what they do and if I need to implement anything for them:
— generateEntropy(ProgressMonitor monitor)
— public int getNumMajorSubdivisions()
Can anyone fill me in?

Thanks! :slight_smile:

Could you explain in a few words the difference between your terrain and stock terrainGrid ?
It’s not that obvious to me…

Hi,

Thanks for asking, in a few words: it isn’t much different, it is aimed to be an alternative or replacement for TerrainGrid.

Why: TerrainGrid is fixed at only 2x2 grid of active tiles, only worked on image based or fractals and is memory hungry.

my TerrainTiler is aimed to be flexible 3x3,5x5,7x7 or 9x9 active tiles, works off pre-generated TerrainQuad tiles and hopefully more memory efficient.

I hope to implement some of TerrainGrids nicer features such as allowing code execution hooks for “TileAttached” and “TileDetached” as well. This way users can still load objects like buildings/trees etc and attach physics as well, but they can do it any way they like.

As said by devs here TerrainGrid was written on a much older build of jMe and it has not been updated on many of the newer Terrain core features and is in need of a replacement. (I came across this in a discussion a long time ago here and that’s when I set myself to learning more and building this)

I gave TerrainGrid a good go back when I was trying to build some concepts for my game: I wanted a large dynamic customizable terrain like you see in Skyrim etc. However the memory issues and dealing with image tiles just made it impossible to get working right, plus the 2x2 tiles was too limiting, so I decided to build my own.

This is a huge learning curve for me, I’ve basically jumped right into the deep end as I’m learning both java and jMe all while doing this so its very challenging.

Better stop there I tend to ramble a lot, hope this clears some things up :slight_smile:
Thanks.

2 Likes
@radanz said: ...The fun part will be the "setHeight(List xz, List height)" ones, need to sort into a list for each loaded quad and pass on...

If I can ask on these functions though, I have no idea what they do and if I need to implement anything for them:
— generateEntropy(ProgressMonitor monitor)
— public int getNumMajorSubdivisions()
Can anyone fill me in?

First, you can pass that same list to every quad, as long as the coordinates are in world space. Each quad then will check to see if the coordinates are within that quad, and if they are then it will apply the height change.

As for the entropy part, that is for variable LOD terrain. You probably don’t have to worry about it and can leave the method blank. It is only called from the SDK when the user wants to manually generate entropy levels. It precalculates the values for each quad, this can be done whenever is convenient. But it does take many seconds to calculate, so in the editor is the ideal location.

getNumMajorSubdivisions() you can ignore as well. I should remove it as it isn’t used any more.

The Terrain interface is just for compatibility with the Terrain editor in the SDK, so you do not have to implement it. The SDK doesn’t support tiled or infinite terrain yet anyways as it will have to do a lot more than just handle terrain, but also other assets associated with a particular tile.

@radanz said: ... This is a huge learning curve for me, I've basically jumped right into the deep end as I'm learning both java and jMe all while doing this so its very challenging. ..

Don’t forget that you are doing an infinite world too =) A very complex task.

Thanks for that, clears up my doubts nicely and awesome on the set lists, makes life much easier.

I wouldn’t go calling this class an “Infinite World” routine, there are limits in how many tiles one can have, from there it depends on the scales.
The code right now is hard-coded to a maximum 1000x1000 tiles and even then host system may have size or directory limits on that. 1 million .j3o files could be an issue.

For an idea on a world-size example, my game currently is planned for 128x128 (16,384) tiles of each 256x256 world unit terrainQuads, with a final scale of x2.
Assuming best practice of 1 WU = 1m then 128x512 = 65536m each side, or 4294 km2 of terrain… Should be a bit to explore.
(Or I may do 256x256 tiles of 128x128 size, same end result but smaller tiles… I’ll see which is better performance…)

Editing the terrain will probably need me to write a “TerrainTile World Editor” to go with this class, since creating and customizing that much land area is outside the scope of the SDK’s editor or any other I’ve come across… if nothing else but for the fact of making the tiles fit seamlessly and be visually easy to work with.

Thanks! :slight_smile:

Hrm, just read up on jar files, Java6 jar files use standard zip which has a limit of 65536 files, (in this context 256x256 tiles) so I may have to look at packaging ideas to allow larger terrains (just in case someone wants to map the world in scale…) or reduce the limits…
Stuff to think on later.

You can also provide several jars…

Yes, one .jar for each row or segment, tiles within tiles, many ways to achieve.
Probably the simplest way resource-wise to break the terrain into chunks

like 16x16 jar files each containing 16x16 .j3o tiles. result of 256x256 world…

Cross that bridge soon…

Quick video just to show it is working, even though it still needs work…

[video]http://youtu.be/693oIcJG3nU[/video]

The above was generated and shown by the commit push I just made now revision 2f042e3b3575
Uses 32x32 of 128x128 tiles scaled up x2, with 7x7 tiles visible around the camera, just enough to see them load in the distance.

First time I’ve used the VideoRecorderAppState :smiley:

2 Likes

nice vid, gona check ur code later.
can u tell me more about the game ur trying to make?

Thanks, code still needs more additions and cleaning to make it flexible for real-case use, but I think its getting there now. Then it’ll need the World Editor to make it easier to implement into actual games.

Most of the ideas for my game concept is on the blog in the 1st post (thegame.radans.net) just go to the 1st post, mostly just ideas and concepts right now though there is a lot in my head that I’m not ready to make public just yet, let me get the game started first :wink: The test-map in the above code is a reduced size version of the one I’ll be using for my game, you’ll see it also on the blog, the file I’ll be using is 8192x8192 pixels in 16-bit gray-scale. Took a bit of work in Gimp and ImageMagick to get it the way I wanted it, any bigger and my pc gets upset with me :slight_smile:

Like most new people here I really just wanted to grab jMe and start making the game, but as many devs and experienced coders had said many times here, it’s just not that simple, I’m spent most of my time just playing with code, trying out different things in different ways just to see what works and how, after probably about a year or so now on and off that’s all I’ve done and I’ve learnt so much. After all that experimenting I discovered I needed to make this class for my game to become reality. Hard work gets rewards, so I hope anyways :wink:

Stay tuned…

Hi again,

Having rounds of problems again, memory issues and more.

One strange issue that I think is related to other issues is that it seems the assetLoader is not loading the TerrainQuads correctly, it seems to be splitting up the patches.

For example, if I run terrainQuad.getPatchSize() before saving it I get the correct value
however if I run the same function on the terrainQuad when it’s loaded back in I get zero every time…
Also if I set wireframe on the terrainQuad it only sets one patch out of the four currently in the ones I’m using!

@sploreg: sorry to prod but any pointers? am I out of my tree?

quads saved with this:
[java]
BinaryExporter bExp = BinaryExporter.getInstance();
float pc = (tileX+(tileZnTiles));
pc = pc/(nTiles
nTiles)*100f;
System.out.println(pc+"% Saving tile: "+tileRootDir+dirName+tileName);
File file = new File(tileRootDir+dirName+tileName);
try {
bExp.save(tQuad, file);
} catch (IOException ex) {
Logger.getLogger(TerrainTiler.class.getName()).log(Level.SEVERE,
"Error: Failed to save Tile: "+tileRootDir+tileName, ex);
}
[/java]

and then re-loaded later with this:
[java]
String tileName = String.format(tilePrefix + “%02d%02d.j3o”, Fx, Fz);
String dirName = String.format(dirPrefix + “%02d%02d/”, Dx, Dz);
//debug:
System.out.println("Loading Tile: " + dirName + tileName);
ModelKey mk = new ModelKey(dirName + tileName);
TerrainQuad tq = (TerrainQuad) dAssetManager.loadModel(mk);
dAssetManager.deleteFromCache(mk);
[/java]

Is there maybe a way or reason to create a custom assetLoader for terrains? and/or custom assetKey for them?

I’ll keep trying different things but starting to lose confidence…

Thanks.

I have a suspicion my issues are possibly something to do with things not being thread-safe or synchronized and stuff but I’m not knowledgeable in that area to say for sure.

Here is one interesting quirk tho:

When loading tiles with just the ShowNormals material, the desktopAssetManagers .clearCache() and .deleteFromCache() work as expected.

BUT when loading tiles with TerrainLighting material with 4 splats and an alphamap then .deleteFromCache() does nothing and .clearCache() causes the memory usage to go through the roof and tiles to load extremely slowly!!!

Even loading tiles directly with BinaryImporter is no longer making any difference!!! Makes me even wonder if something broke TerrainLighting mat with the shader updates recently!!

This is all starting to get over me… If anyone has ideas or suggestions please throw them to me…

thanks…

@radanz said: I have a suspicion my issues are possibly something to do with things not being thread-safe or synchronized and stuff but I'm not knowledgeable in that area to say for sure.

Here is one interesting quirk tho:

When loading tiles with just the ShowNormals material, the desktopAssetManagers .clearCache() and .deleteFromCache() work as expected.

BUT when loading tiles with TerrainLighting material with 4 splats and an alphamap then .deleteFromCache() does nothing and .clearCache() causes the memory usage to go through the roof and tiles to load extremely slowly!!!

Even loading tiles directly with BinaryImporter is no longer making any difference!!! Makes me even wonder if something broke TerrainLighting mat with the shader updates recently!!

This is all starting to get over me… If anyone has ideas or suggestions please throw them to me…

thanks…

It might be that this is due to the fact that the assetManager manages the loaders as threadlocal, I’ll look into this, I put this post on my read list.

Awesome. thanks for looking, I’m currently putting myself back into reading up on thread-safe java to get my head around it better.
The difference with the two materials is confusing me although I guess its to do with showNormals being asset-less and terrainLighting haven them…
upsets me that going direct with binaryImporter isn’t helping though… thus my suspicions on threading issues…
thanks.