Created
March 6, 2021 06:29
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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