Zylann / godot_heightmap_plugin

HeightMap terrain for Godot implemented in GDScript
Other
1.69k stars 158 forks source link

center terrain get_height_at has diff than true pos #455

Closed yythlj closed 2 weeks ago

yythlj commented 2 weeks ago

var cur_pos = position var map_width = 2048 var map_height = get_node("HTerrain").get_data().get_height_at(int(cur_pos.x + map_width / 2),int(cur_pos.z + map_width / 2))

print(map_height, " ", cur_pos.y)

In my characterbody3d, I stop move, and on floor. it print 64.3496627807617 66.8754653930664

the diff is too more..

Zylann commented 2 weeks ago

get_node("HTerrain").get_data().get_height_at(int(cur_pos.x + map_width / 2),int(cur_pos.z + map_width / 2))

That code assumes things: 1) That 1 pixel of the heightmap is 1 unit of world space (which is not always true) 2) That the terrain's position is at the origin (which is not always true)

HTerrainData.get_height_at does not account for transforms or scaling or centering, because it's a method of a resource, not the node. It gives the raw height from pixel coordinates, not world coordinates. So you likely made a mistake in the way you convert coordinates.

If you want interpolated height in world coordinates, you can use something like this:

static func get_interpolated_height_at_world_position(terrain: HTerrain, pos_world: Vector3) -> float:
    var to_world := terrain.get_internal_transform()
    var to_local := to_world.affine_inverse()
    var pos_local := to_local * pos_world
    var h_local := terrain.data.get_interpolated_height_at(pos_local)
    return (to_world * Vector3(0, h_local, 0)).y

Another way that might be easier is to simply add a raycast to your character pointing down.