I found and tested many different implementations when searching for this topic, but my use case seems to be slightly different from others.
I have a static camera, but the player can move freely around the screen.
When the player is at the centre of the screen, my calculation kind of works fine, as seen below.
However, when I move the player to a corner (bottom right corner in this case), it doesn't face the cursor. Seems like the calculation is ignoring the player's position, and only taking into consideration the cursor position in relation to the window.
My code is implemented in Rust (with Bevy Engine), but I'm sure the logic can be adapted from any language.
let window_size = Vec2::new(window.width(), window.height());
let difference = mouse_position.extend(0.0) - window_size.extend(0.0) / 2.0 - player.translation;
let angle = difference.y.atan2(difference.x) + PI;
*transforms.get_mut(game.player.entity.unwrap()).unwrap() = Transform {
translation: player.translation,
rotation: Quat::from_rotation_y(angle),
..default()
};
Note1: .extend(0.0)
converts it from Vec2 to Vec3 by adding 0.0 as z
.
Note2: player.translation
is a Vec3 with the player's position on the screen.
As pointed out by @Locke, it doesn't seem to be a matter of tweaking my calculation, but there's a whole implementation missing: Ray Casting, which is required for 3d applications to be able to translate mouse coordinates into a 3d world position. For Bevy and Rust I found the following lib that seems to provide this functionality: