+2 votes

I'm trying to get the 3D position of my mouse cursor much like a gridmap coordinates just the X and Y with Z always constant. Using input event mouse motion or global position / relative only returns in pixel units, i need the 3D units. Thank you.

in Engine by (55 points)

2 Answers

+8 votes
Best answer

This is kind of a tricky question because your mouse doesn't really have a 3D position. Your mouse has a 2D position on your screen (screen space) but that third, depth position will always stay the same. What you are probably looking for is raycasting. Raycasting allows you to project a ray out from your mouse's 2D position in the direction that the camera is looking, then you test if that ray collides with anything or alternatively you can return the 3D position at a given projected distance. This image does a good job of illustrating a raycast:
enter image description here
If you want to learn more about Raycasting, this video and the text tutorial it links to will explain the concept in full detail although they are both not made specifically for Godot. Do take a look at Godot's documentation on Raycasting though as it does simplify a lot of the concepts for you already.

Another option that is included in Godot that may be useful to you is the _input_event function on CollisionObjects. This function is called when a collisionObject is clicked on (or even just as the mouse passes over it) and it will give you the mouse position during the event as a Vector3 as well as which object was clicked. Consider connecting it with a signal to another script to make use of it elsewhere.

by (121 points)
selected by

Thanks, but, any bare bone examples (assuming the distance to the object is known). I can't quite figure it out how to rotate the raycast on the x and y axis based on the mouse location on the screen.

I was thinking on making a spotlight.
Maybe collision objects is the solution?

+3 votes

Here's the code you need. Set position2D to the mouse position within the viewport and z to your constant Z.

var dropPlane  = Plane(Vector3(0, 0, 1), z)
var position3D = dropPlane.intersects_ray(
                             camera.project_ray_origin(position2D),
                             camera.project_ray_normal(position2D))
by (96 points)

this worked like a charm!

Can you show me the full code?

I couldn't get the z const...
var dropPlane = Plane(Vector3(0, 0, 1), z)

Okan, you decide what z is based on where you want your drop plane. You can just replace it with a number.

Thanks Arda! You are a riot. That will nicely do

func _input(event):
    if Input.is_action_pressed("click"):
        var position2D = get_viewport().get_mouse_position()
        var dropPlane  = Plane(Vector3(0, 0, 10), z)
        var position3D = dropPlane.intersects_ray(camera.project_ray_origin(position2D),camera.project_ray_normal(position2D))
        print(position3D)

I made this code it only appears on the right side of the screen and 3rd point is constantly the same number

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.

Categories