Dynamic Terrain / CreateGroundFromHeightMap

Hey guys,

I have created a map for my game Morterra, where it loads in the map via a bitmap image, using CreateGroundFromHeightMap. The ground mesh is pretty big, with like 30k vertices (22 zones * 8 subdivisions in each zone, squared), and then that mesh is instanced 8 more times (9 total meshes), because the world is artificially spherical (when you approach the edge, it will show you the opposite edge, and when you cross it will teleport you to the other side of the map. It needs to look seamless, so the map has to line up on the edges). I originally tried using dynamic terrain to achieve this, because it seems that it automatically handles LOD, which would be useful performance wise. I had issues working with Dynamic Terrain, so I eventually gave up and just instanced the ground. I figured that the faces that are outside of the frustum wouldn’t be drawn anyways, so it wouldn’t be a huge impact performance wise. It isn’t a huge impact, but I can notice it, and I’m trying to think of the best way to approach the problem.

Here’s a playground showing what I’m currently doing. It runs at 60 fps for me (with a decent GPU), but with a ton of game meshes included it can effect FPS for my computer by like 5-10 fps.

Playground: Babylon.js Playground

I do also need to be able to use the function (or an equivalent) to ground.getHeightAtCoordinates() efficiently

I think ideally I would have an array of vertices from the bitmap, and then as the player moves throughout the world, it will only show the local (3 zones * 8 subdivisions) * (3 zones terrain * 8 subdivision) = 576 total terrain vertices. I think the best way to achieve this is with Dynamic Terrains, but I’m not 100% sure.

I’m hoping to have a clear idea I’m working towards before taking on the task, so if anyone has any insight on the best ways to achieve something like this, I would greatly appreciate it!

What issues did you have? Can you show them in a playground?

It’s been a while, but if I remember correctly I had a tough time getting it to load from the image, and getting it to mirror correctly (it basically needs to repeat itself when you get to edges). It doesn’t necessarily need to load from the image, but the heights need to be the exact same at the edges, which I could only get to work when using an image.

I don’t have a full grasp of Dynamic Terrain, I guess. But here’s kind of where I get stuck. The map data is taken from the image I use in the previous playground, and then applied to a dynamic terrain.

https://playground.babylonjs.com/#3DT04E#1

You do not have to use groundFromHeightMap as an intermediate stage to create a dynamicTerrain from an image , the work has been done for you - How to Use Dynamic Terrain - Babylon.js Documentation

2 Likes

Gotcha, I’ve cleaned it up, still encountering the same issues. I can probably fix all of them, except for getHeightFromMap() appears to be buggy. It is very jumpy and doesn’t give accurate heights. You can see what I mean as you move around in this demo:

https://playground.babylonjs.com/#3DT04E#5

Bit busy to give it my attention over the next couple of days. Have you looked at Adding Objects to a Dynamic Terrain - Babylon.js Documentation

Hmm, no I haven’t seen that. I will get something rigged up with that and see if it helps. Thank you for your help.

Just curious, is there a reason it needs a specific handler to manage the objects, instead of just calculating the y coordinate from a function?

I would say because there is more going on since objects are re-used in different positions, the movement of the terrain and the obects are part of an SPS mesh rather than a mesh in their own right. Also it is better for users that they just supply the basic data and Babylon.js does the hard work.

If you want a closer look at how it is achieved Extensions/babylon.dynamicTerrain.ts at master · BabylonJS/Extensions · GitHub from line 309

See also Dynamic Terrain Instance Support

Gotcha. Well I see how it is helpful to have the availability to link to a SPS but I don’t think it’s necessary in my case. Also, even if I convert everything to the handler, I will still need the correct height for other reasons as well such as the camera. And since there is a function built, it seems bizarre that it would return incorrect values. I’m imagining it’s a bug that stems from generating the terrain via image, because in the playground that generates the terrain using the sin function (https://www.babylonjs-playground.com/#J6FMJ#5) the getHeight function works fine, but when I use the image to generate the datamap & terrain, it breaks. EDIT: Actually, after further examination, the playground I linked is jumpy as well, but it’s harder to notice because the camera moves so fast. If you slowly traverse the map incrementing the camera position marginally each render you will see noticeable jumps. Must just be a flaw in the getHeight function.

Anyways, I appreciate all of your help, hopefully it’s just a bug I can find soon!

I think some of the numbers you are using in https://playground.babylonjs.com/#3DT04E#5 do not work out. Here is a version with your image that seems to be OK https://playground.babylonjs.com/#3DT04E#9. You will need to adapt to your universal object

Also in #5 mapSubX, mapSubZ are not assigned any numbers

They are assigned, in the parameter for the createTerrain function. If you log the values you will get 176 (which is the 8*22 passed to it from hmOptions)

In your example, if we apply a camera and float around you will see the same jumpiness:

https://playground.babylonjs.com/#3DT04E#12

I made a bug thread and it seems that it is just a bug, here’s the thread: DynamicTerrain returns incorrect map height

And here’s a playground from the thread, where another user replicated the problem much better than I have: https://playground.babylonjs.com/#3DT04E#11

Well done for your persistence. Jerome is usually very good on working on corrections.

1 Like