Ok, I have been able to make a terrain using TerrainQuad based on the sample in the API, and with TerrainLighting to “splat” some textures which I was able to draw myself in an image editing tool as well as the height map itself. But my landscape looks like a staircase heaven as each level from the height map is clearly visible. How do I go about getting correct angles for the mesh? I thought that there was already enough information in the height map for the TerrainQuad to generate polygons at the correct angles (and the normals for the joints to smooth the lighting as well).
I assume this is different than the normal maps for the splat textures which I assume is used for the lighting of the texture itself to get some feeling of depth.
Here is a picture showing the “problem” :
this can be due to the compression of the image. The gradients has to be really smooth and compression can introduce some banding.
The best bet is to store your height map using PNG image format.
I am using a PNG image and its gaussian blurred so it cant be that which causes it. Here is my height map image:
And here is my terrain init code:
[java]
mat_terrain = new Material(assetManager,
“Common/MatDefs/Terrain/TerrainLighting.j3md”);
Texture splatTexture = assetManager.loadTexture(“Textures/Terrain/splat/islandsplat.png”);
mat_terrain.setTexture(“AlphaMap”, splatTexture);
Texture grassTexture = assetManager.loadTexture(
“Textures/Terrain/splat/grass2.jpg”);
grassTexture.setWrap(WrapMode.Repeat);
mat_terrain.setTexture(“DiffuseMap”, grassTexture);
mat_terrain.setFloat(“DiffuseMap_0_scale”, 128f);
Texture rockTexture = assetManager.loadTexture(
“Textures/Terrain/splat/rocky.jpg”);
rockTexture.setWrap(WrapMode.Repeat);
mat_terrain.setTexture(“DiffuseMap_1”, rockTexture);
mat_terrain.setFloat(“DiffuseMap_1_scale”, 32f);
Texture sandTexture = assetManager.loadTexture(
“Textures/Terrain/splat/Sand_3_Diffuse.png”);
sandTexture.setWrap(WrapMode.Repeat);
mat_terrain.setTexture(“DiffuseMap_2”, sandTexture);
Texture sandNormal = assetManager.loadTexture(
“Textures/Terrain/splat/Sand_3_Normal.png”);
sandNormal.setWrap(WrapMode.Repeat);
mat_terrain.setTexture(“NormalMap_1”, sandNormal);
mat_terrain.setFloat(“DiffuseMap_2_scale”, 32f);
Texture heightMapImage = assetManager.loadTexture(
“Textures/Terrain/splat/island.png”);
heightmap = new ImageBasedHeightMap(
ImageToAwt.convert(heightMapImage.getImage(), false, true, 0));
heightmap.load();
int patchSize = 65;
terrain = new TerrainQuad(“my terrain”, patchSize, 513, heightmap.getHeightMap());
terrain.setMaterial(mat_terrain);
terrain.setLocalTranslation(0, terrainY, 0);
terrain.setLocalScale(2f, 1f, 2f);
[/java]
Its really just code directly from the sample showing splat texture mapping on a terrain. I havent tried that one on its own but I guess it should have the same “defect”.
Any help appreciated…
The issue is that Terra monkey uses 8 bit height maps instead of higher precision.
@Sploreg : is there a way to increase the precision?
Well even if its 8 bit I dont see why it doesnt create a mesh that just use vertices on 256 levels and just make the triangles between these points, which should generate sloped polygons. Instead it seems to generate flat quad “plateaus” for each level and then triangles to connect these which is rather odd. And naturally also generate normals that average the connecting polys for each vertex so its smooth.
The terrain editor in the IDE seems to create correct polys though when you “hand paint” using the raise/lower tool.
Hm on close inspection (and when switching to wireframe) I can see “connecting slopes” so it seems to be partially correct. Hmm… is it an artifact of the algorithm used perhaps? I guess some sort of interpolation will have to be done if the mesh is of higher resolution than the data. I havent studied the algorithm but I guess it perhaps creates one vertice per pixel in the height map and just create triangles that connect these. So perhaps the normals on each vertice arent averaged between the connecting polygons to create smooth a lighting effect?
Even with correct normals, moving about will still be a bumpy ride with the standard physics collision unless that also takes these normals into account?
I would try creating a terrain in the scene composer but I get errors whenever I try to reopen it within the editor so the file seems somewhat corrupt.
You have to smooth the generated heightmap after it is loaded in with ImageHeightmap. Otherwise the precision just isn’t enough and it causes these steps.
There is a RawHeightmap class you can use if you have actual height values. Or you can use Grayscale16BitHeightMap.
[java]
heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 0.5f);
heightmap.load();
heightmap.smooth(0.9f, 1); // smooth out the image
[/java]
johncl said:
I would try creating a terrain in the scene composer but I get errors whenever I try to reopen it within the editor so the file seems somewhat corrupt.
What errors are you getting and how can we reproduce them? What version of jme are you using?
Ah thank you Sploreg, I will try out that smoothing method. I actually searched for that in the heightmap API but I obviously missed that.
As for the error I just created a TestScene.j3o in the terrain editor, drawing up to 4 different textures, and also made a TestFilter.j3f file with some water, all which displayed rather nicely. I then exited jMonkeyEngine and when I now choose Edit in SceneComposer I get a Warning message saying: Error in scene! (java.lang.OutofMemoryError: Direct buffer memory). I am using jdk 1.6 (latest version) and Win7 32bit with 4GB memory (although naturally not all is available to Win7). JMonkeyPlatform is up there in 900megs memory allocated according to task manager so perhaps it just bumping into the 1G heap roof of 32bit Java VM?
Btw, that smooth function worked wonder! Lovely! Thank you!
Some pictures of sunrise and another scene (250 trees and 200 grass tiles) :
Btw, I have tried calling setCullHint(CullHint.Never) on my sun quad (I changed it from a sphere to a billboard controlled quad to get a halo thing going on the sun) but the sun quad is still being culled when it gets far enough away from the viewer. Any way of making sure its always around?
Also it would be excellent if there were some way of making certain objects not affected by the fog, like the sun.
johncl said:
Btw, I have tried calling setCullHint(CullHint.Never) on my sun quad (I changed it from a sphere to a billboard controlled quad to get a halo thing going on the sun) but the sun quad is still being culled when it gets far enough away from the viewer. Any way of making sure its always around?
I don't think it's a culling issue it's more that your camera frustum far value is too small, so the sun goes off the camera range so it's not rendered anymore.
Default frustumfarvalue is 1000 world units try to raise that value.
cam.setFrustumFar(2000);
for example.
johncl said:
Also it would be excellent if there were some way of making certain objects not affected by the fog, like the sun. :)
There is. you have to create a second view port and add your sun to it. see TestMultiViews
Also don't forget to call updateLogicalState and updateGeometricState on your second viewport scene on every update because it's only automatic for the main scene.
Hm, ok I guess I shouldnt mess too much with the camera frustrum as making that bigger would eat precious GPU cycles as well. The sun object might be very very far away depending on how big my terrain will be. Perhaps the multi views will solve it if that the one with the sun has its own frustrum?
Otherwise I would have to just keep the sun always within the frustrum and move it around relative to the player at all times as the sun isnt suppose to grow/shrink either based on your position. That might work as well.
Ok I checked the multi view code but I dont know how it can help, isnt that for opening several views/windows into the scene?
Also, is there a way I can say that all the objects in a certain Node should adhere to a different culling frustrum? I’d like for example grass, stones and other small objects to disappear from view before the bigger objects (terrain, trees, buildings). Otherwise I will have to divide the terrain clutter into several smaller nodes and do my own distance from viewer testing to decide which ones should be added/removed.
johncl said:
Ok I checked the multi view code but I dont know how it can help, isnt that for opening several views/windows into the scene?
Yes it can be used for multiple views, but you can also have it render on top of an existing viewports. The difference is setting the "Clear Flags".
To have a scene with a separate view port on top of your regular view, create the viewport and set the clearFlags to false, give it the same camera, and then set it to render a separate scene.
Hm, I thought that the frustrum was a function of the camera, so wont the second viewport have the same frustrum then?
It is. So you can give the new viewport its own camera with a control on the original camera that mirrors the position and direction of the main camera onto this new camera in the 2nd viewport. It’s a little bit awkward but it should work.