Inspecting the heightfield of TerrainGrid where the camera is

I’m trying to debug why my terrain grid sometimes has small areas of holes. So I was thinking about a way to get at the float[] of the TerrainQuad for where the camera is over when I “press a button” (on demand sort of thingy).



The only way I can think of is to have a TerrainGridListener that uses an LRU-cache and caches the float[] of the attached quads using getHeightMap. When there is demand for a float[] it finds the relevant one from the camera coordinates (using getTileCell). But this is just mirroring what the TerrainGrid already does but wasting memory storing copies of the arrays.



So, is there a cleverer way to do it querying the TerrainGrid “on demand” without storing (possibly stale) copies of the heightmaps?

If you want just a height point on the terrain, you can use Terrain.getHeightmapHeight(). To get the entire heightfield of the terrain (all four loaded quads of the TerrainGrid) you can use TerrainQuad.getHeightMap(). If you want just the heightmap of one of the children you can get the children from the TerrainGrid, see what one the ray intersects, and use getHeightMap() on that child.



TerrainQuad.getHeightMap() will make a copy of the data, so if you change it you will need to reload this. It is meant to just be run once at the start for heightfield physics collision. The size of the heightfield won’t be very large memory-wise, so I wouldn’t worry about it, especially if you are debugging.



The holes might be that the edge of your heightmap does not match the edge of the neightbour heightmap. So it you have a largeheightmap image that you split, each sub hightmap will have to share the same pixels on the edge as their neighbour.



Hope that helps.

Yes, getChildren might do the trick but as you say, the memory cost isn’t that high so I’ll probably go with the listener anyway since the attach/detach are pretty interesting to see also. This is mostly a fun thing to write, some type of debug mini-map. It will help me preview heightmaps since I generate them.

When you say share pixels do you mean that the bottom row of the Quad1 heightmap must have the same values as the top row of Quad2? I assumed that there would be a triangle strip generated between the vertices in the quads but perhaps they are overlapped?



This is what it looks like, almost a rift into space :slight_smile: But I’m pretty sure I probably generate the float[] wrong, either NaN values or something, or off-by-one so I miss to generate a row or column. As you can see the quads don’t line up so I definitely do something iffy.



Yep those edges have to match. If the heightmap is 513x513, the right column (idx 513) needs to equal the left column (idx 0) if you have a left and right quad as neighbours. The polygons don’t overlap, but the points at the edges do. The steeper the slope at the edge the more drastic the tear since the heights will be that much farther apart. That’s what I think is going on in your picture there.

1 Like

The float[] I generate are 512x512, so I’m pretty certain your explanation is totally correct. Thanks.

Yea it’s a little bit misleading. People normally think about a 512x512 heightmap, since it has to be a power of two so it can be divided by two each LOD level. But each height value can’t be a polygon, it has to be a point on the polygon; and when you create a polygon (looking at it linearly or on a grid like terrain) you will have one more point for how many polygons you have: 1 polygon: 2 points (linearly), 2 polygons: 3 points… etc.

So this means the heightmaps have to be 2^n+1 (513x513) so the actual vertices of the polygons get the height values.

I feel pretty dumb since a year ago I wrote a simplified terrain-thingy to use as a live wallpaper in my phone. So I’ve dealt with this before. In my hack I used 64x64 tiles but then I cheated, if the next tile was generated I triangulated by borrowing the 65th row (or column) from that, otherwise I just set the value to 0 until the next tile was generated :slight_smile: Heavy use of fog and a small frustum can hide the ugliest hacks.

hehe yea fog is a good trick for that :slight_smile:

Bringing this old thread to life to show what I ended up doing.



[java]final Vector3f tileCell = this.terrainGrid.getCurrentCell();

final TerrainQuad terrainQuadAt = this.terrainGrid.getGridTileLoader().getTerrainQuadAt(tileCell);[/java]



Edit: I forgot to write: this will of course recreate the entire quad, don’t do this in a game!



btw the holes where NaN values in the heightmap from my broken Simplex noise generator.