0 votes

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 ??

in Engine by (14 points)

2 Answers

0 votes

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 )

by (1,196 points)
0 votes

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)
by (108 points)
edited by
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.