Skip to content

Instantly share code, notes, and snippets.

@Toqozz
Created March 6, 2021 06:29
Show Gist options
  • Save Toqozz/3248bc494b69a89a1a0f0d6a19b57fc3 to your computer and use it in GitHub Desktop.
Save Toqozz/3248bc494b69a89a1a0f0d6a19b57fc3 to your computer and use it in GitHub Desktop.
Basic screen to world bevy code. Missing some stuff like the distance calculation.
pub fn screen_to_world(
cursor: Res<Events<CursorMoved>>,
windows: Res<Windows>,
mut input_state: ResMut<GlobalInputState>,
camera_query: Query<(&Camera, &Transform)>,
) {
// Calculate world space mouse ray. If there's no new mouse move event, then continue.
let pos = match input_state.cursor.latest(&cursor) {
Some(ev) => ev.position,
None => return,
};
let window = windows.get(WindowId::primary()).expect("Couldn't grab primary window.");
let screen_size = Vec2::from([window.width() as f32, window.height() as f32]);
let (c, c_t) = camera_query.iter().next().expect("The world didn't have a camera in it!");
let normal = screen_to_world_dir(&pos, &screen_size, c, c_t);
// This part can easily be done faster.
let camera_matrix = c_t.compute_matrix();
let (_, _, t) = camera_matrix.to_scale_rotation_translation();
let world_coord = t.translation + normal * DISTANCE; // distance from the camera to put the world coord.
}
// Convert a screen space coordinate to a direction out of the camera.
// Does not include camera positioning in the calculation: to get the screen to world coordinate,
// add camera_transform.translation here.
pub fn screen_to_world_dir(
coord: &Vec2,
screen_size: &Vec2,
camera: &Camera,
camera_transform: &Transform
) -> Vec3 {
let proj_mat = camera.projection_matrix;
// Normalized device coordinates (NDC) describes cursor position from (-1, -1) to (1, 1).
let cursor_pos_ndc: Vec3 = ((*coord / *screen_size) * 2.0 - Vec2::one()).extend(1.0);
let camera_matrix = camera_transform.compute_matrix();
// We can't just use camera_transform.translation because that's actually the LOCAL translation.
let (_, _, camera_position) = camera_matrix.to_scale_rotation_translation();
let ndc_to_world: Mat4 = camera_matrix * proj_mat.inverse();
let cursor_position: Vec3 = ndc_to_world.transform_point3(cursor_pos_ndc);
let dir: Vec3 = cursor_position - camera_position;
return dir.normalize();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment