How can I get depth coordinates on random X , Y positions ?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By svsdval

I try create a simple 3d “tower defence” game and want to place a towers on random 3d surface ( 3d tilemap / other 3d models ), for this I need to get closest point on 3d surface. I try to project 3d point on surface based on 2d mouse position… result: i get the 3d point with Z-far, which is beyond the 3d surface =(
How i can get scene depth on the mouse position to modify 3d point position ??

:bust_in_silhouette: Reply From: rustyStriker

Try using a Raycast from the mouse’s position(with a reasonable distance from the surface) and get the collision position, but you will need the Raycast to be perpendicular to the view( if the camera’s view was a plane you will need the Raycast to be the normal’s vector only scaled up to reach the surface to it )

:bust_in_silhouette: Reply From: Toshio Araki

In my game I used the same solution you can find in the Navmesh demo project

The Camera node have a very useful feature that allows you to easily project a ray toward whatever you are pointing at with your mouse, here’s the sample code:

func _input(event):
#	if event extends InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
	if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
		var from = get_node("cambase/Camera").project_ray_origin(event.position)
		var to = from + get_node("cambase/Camera").project_ray_normal(event.position)*100
		var p = get_closest_point_to_segment(from, to)
		
		begin = get_closest_point(get_node("robot_base").get_translation())
		end = p

Just remember to change the multiplied value depending on the estimated distance of your surface here is multiplied by 100project_ray_normal(event.position)*100, meaning that the ray is just 100 units large.

This solution works in conjunction with Navigation and NavMesh, as the function get_closest_point_to_segment and get_closest_point and methods belonging to Navigation only.

If you’re not using Navigation you can mix it with RayCast, see this tutorial:

I haven’t tested but it should be this the function you need:

# The first parameter should be origin, the second destination points of the projected ray.
var result = space_state.intersect_ray(Vector2(0, 0), Vector2(50, 100))
print("Hit at point: ", result.position)