Hello,

I'm trying to position a horse above a terrain. But often, the height returned by TerrainBlock.getHeight() is below the terrain 3d mesh.

I searched a bit in TerrainBlock code and found that the height for a given point is computed by bi-linear interpolation of the heightmap :

public float getHeight(float x, float z) {

x /= stepScale.x;

z /= stepScale.z;

float col = FastMath.floor(x);

float row = FastMath.floor(z);

if (col < 0 || row < 0 || col >= size - 1 || row >= size - 1) {

return Float.NaN;

}

float intOnX = x - col, intOnZ = z - row;

float topLeft, topRight, bottomLeft, bottomRight;

int focalSpot = (int) (col + row * size);

// find the heightmap point closest to this position (but will always

// be to the left ( < x) and above (< z) of the spot.

topLeft = heightMap[focalSpot] * stepScale.y;

// now find the next point to the right of topLeft's position...

topRight = heightMap[focalSpot + 1] * stepScale.y;

// now find the next point below topLeft's position...

bottomLeft = heightMap[focalSpot + size] * stepScale.y;

// now find the next point below and to the right of topLeft's

// position...

bottomRight = heightMap[focalSpot + size + 1] * stepScale.y;

// Use linear interpolation to find the height.

return FastMath.LERP(intOnZ, FastMath.LERP(intOnX, topLeft, topRight),

FastMath.LERP(intOnX, bottomLeft, bottomRight));

}

As the terrain mesh is represented by triangles, the returned result is different from the real mesh height at this point. I wonder why you did not decide to compute it considering only the triangle in which the point actually is. I suggest the code below which I think gives more precise results :

// Determine in witch triangle we are

if(intOnX > intOnZ) {

// point is in triangle TL-TR-BR

float dHeightX = (1 - intOnX) * (topLeft - topRight);

float dHeightZ = intOnZ * (bottomRight - topRight);

return topRight + dHeightX + dHeightZ;

} else {

// point is in triangle TL-BR-BL

float dHeightX = (intOnX) * (bottomRight - bottomLeft);

float dHeightZ = (1 - intOnZ) * (topLeft - bottomLeft);

return bottomLeft + dHeightX + dHeightZ;

}

What do you think about that ?

Thanks :)