Terrain Height at x, y

Hi all,

is there a way of getting the height of the terrain at x, y in terrain. e.g:



the point 0, 0 has a height of 100. The terrain is at -20, -200, 75



would like to be able to do something like:



getHeightAt(0, 0);


and that would return 100.

Can I do such a thing at the moment? or is there a different way of doing so?

Keeping in mind my complete ignorance of general ways of handling terrain, couldn’t you simply refer to the height map used to create the terrain?



If you already know the x, y for the terrain, it should be a simple scaling (or maybe even a null) transformation to get the x,y for the height map.



-Mike

so what your saying is to look into the .raw file and see which gray scale it is and determine the height?

Actually, I’m saying call heightMap.getTrueHeightAtPoint(int x, int z) or getInterpolatedHeight(float x, float z) or getScaledHeightAtPoint(int x, int z).



But again, I’ve been working with Terrain maybe 3 days total now :slight_smile:



-Mike

Actually, let me expand on that a bit.



I’m assuming you’re creating your terrain object with RawHeightMap which extends AbstractHeightMap which has the three methods mentioned above.



-Mike

Currently all the heights are obtained from the heightmap, I do plan on moving that to the terrain itself in the future. That way you don’t have to keep a heightmap object sitting around after you get the height values. Either that, or you will send the heightmap instead of int[] when building terrain, then the calls to get height in terrain will just call the same one in the heightmap object. Not sure yet.

How do I match up my terrain object coordinates to my height map?



I’m using a TerrainPage with heightmap with 257 and a step-size of 10.



From this I should have an object that occupies space between -1285 and 1285 in the x and z dimensions.



But not quite. Objects drawn above the terrain show up either off the edge or inset from the edge. Adding 315 to both the x and z coordinate appears to be the answer, but I don’t understand why.



float terrainwidth = 257 * 10 / 2;

float terraindepth = 257 * 10 / 2;

float terrainoffset = 315;





-Mike

hmmm interesting. If you have a step size, it seems like you should have:



getInterpolatedHeight(position.x/stepsize, position.y/stepsize);



It’s been a long time since I’ve written the get height methods (that’s from the old jME). I’ll have to take a look at it tomorrow.

Before you look too deep in the “get*Height[atPoint]” methods, I’d recommend checking the code that generates the terrain’s location.



It’s the location of the terrain object that appears to be off by 315, not the map.



For instance, the coords of the terrain object appear to be -970,-970 to 1600,1600 rather than -1285 to +1285. (My terrain is generated by mostly-unmodified TestTerrainPage – the modifications being I changed the height-map used.)



-Mike

ok, I’ll look into it.

Let me take a guess… your block size is:



315 * 2 / 10 = 63 ± a couple. 65?



The origin of the blocks is the top left corner, not the center like it should be. This is shifting the whole map over a bit.



I’ll spend tomorrow improving the whole interface for get heights.

Yep. That must be it. The "± a couple" is still preventing me from making this into a formula rather than a hardcoded value.



Thanks.



However, I did find an unrelated bug in getInterpolatedHeight. Off by one, possibly because the array is now 2^N + 1?



Also, inconsistent method name: getInterpolatedHeight vs …AtPoint for True and Scaled.



Index: AbstractHeightMap.java
===================================================================
RCS file: /cvs/jme/src/com/jme/terrain/util/AbstractHeightMap.java,v
retrieving revision 1.2
diff -u -r1.2 AbstractHeightMap.java
--- AbstractHeightMap.java   22 Apr 2004 22:27:07 -0000   1.2
+++ AbstractHeightMap.java   27 Apr 2004 03:06:32 -0000
@@ -178,7 +178,7 @@
 
         low = getScaledHeightAtPoint((int) x, (int) z);
 
-        if (x + 1 > size) {
+        if (x + 1 >= size) {
             return low;
         } else {
             highX = getScaledHeightAtPoint((int) x + 1, (int) z);
@@ -187,7 +187,7 @@
         interpolation = x - (int) x;
         intX = ((highX - low) * interpolation) + low;
 
-        if (z + 1 > size) {
+        if (z + 1 >= size) {
             return low;
         } else {
             highZ = getScaledHeightAtPoint((int) x, (int) z + 1);

"mojomonk" wrote:
The origin of the blocks is the top left corner, not the center like it should be. This is shifting the whole map over a bit.

I'll spend tomorrow improving the whole interface for get heights.

In case this is helpful in speeding up the process, this is what I'm using to find the height under my placed shapes.

As you've guessed:


            int blockSize = 65;
            int heightMapSize = heightMap.getSize(); // 257
            int stepScale = 10;
            TerrainPage tb = new TerrainPage("Terrain", blockSize, heightMapSize, stepScale, heightMap.getHeightMap(), false);


Here's the rest.


            float terrainwidth = heightMapSize * stepScale / 2;
            float terraindepth = heightMapSize * stepScale / 2;
            float terrainoffset = (blockSize / 2 * stepScale) - 5; // -5 to correct unknown error

            float cubeX = someX;
            float cubeZ = someY;
            float mapCubeX = cubeX + terrainwidth - terrainoffset;
            float mapCubeZ = cubeZ + terraindepth - terrainoffset;
            float cubeHeight = heightMap.getInterpolatedHeight((int)(mapCubeX / stepScale), (int)(mapCubeZ / stepScale));
            cubeScene.setLocalTranslation(new Vector3f(cubeX, cubeHeight, cubeZ));

fwiw, You should find that Terrain’s getHeight is working well now. Keep in mind that the params are in coordinates local to the terrain, so if you’ve translated it at all, you’ll need to also translate the params and the result.

Thanks.



Has the terrain offset been corrected, then?



-Mike

if you are referring to the issue where the terrain was not laid equally across the origin in the x and z directions, then yes. The origin of a block is still the upper left and as far as I know, that won’t change.

Right, that’s what getInterpolatedHeight() is for. So long as we can give a world coordinate and get the terrain height at that point, that’s great!



Thank you!



-Mike

Well you can currently give x,z coordinates in the object space of the given TerrainPage/Block and get back y also in the object space. We could have it figure in it’s own world translation to make the sent and recieved coords be world coords if that would make life easier for everyone I suppose.

No, I don’t think that’s necessary.



It was the mysterious offset that was the only inconvenience before.

that would help me abit actually, giving/recieving world coordinates would be handy, otherwise, i would have to do it myself. :slight_smile: