Skip to content

Instantly share code, notes, and snippets.

@piedoom
Created April 13, 2021 05:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piedoom/67252094d7fc15f6c6cdd809ba8448f7 to your computer and use it in GitHub Desktop.
Save piedoom/67252094d7fc15f6c6cdd809ba8448f7 to your computer and use it in GitHub Desktop.
let ray = screen_to_world(cursor_position, &windows, camera, camera_transform);
let plane = HalfSpace::new(Unit::new_normalize(Vec3::Z.to_vector3()));
if let Some(toi) = plane.cast_local_ray(&ray, Real::MAX, false) {
dbg!(ray.point_at(toi)); // <-- would expect values the same as bevy's units, but is instead y-1. to y1, and x-1.7 to x1.7 (I think this specific # has to do with the aspect ratio)
}
// From https://github.com/aevyrie/bevy_mod_raycast/blob/8b2ee7d015b9bb886684d7ad7796e404944bd5dd/src/primitives.rs
// MIT License
// Gets a ray from our camera to our mouse position on screen
pub fn screen_to_world(
screen_position: Vec2,
windows: &Res<Windows>,
camera: &Camera,
camera_transform: &GlobalTransform,
) -> Ray {
let camera_position = camera_transform.compute_matrix();
let window = windows
.get(camera.window)
.unwrap_or_else(|| panic!("WindowId {} does not exist", camera.window));
let screen_size = Vec2::from([window.width() as f32, window.height() as f32]);
let projection_matrix = camera.projection_matrix;
// Normalized device coordinate cursor position from (-1, -1, -1) to (1, 1, 1)
let cursor_ndc = (screen_position / screen_size) * 2.0 - Vec2::from([1.0, 1.0]);
let cursor_pos_ndc_near: Vec3 = cursor_ndc.extend(-1.0);
let cursor_pos_ndc_far: Vec3 = cursor_ndc.extend(1.0);
// Use near and far ndc points to generate a ray in world space
// This method is more robust than using the location of the camera as the start of
// the ray, because ortho cameras have a focal point at infinity!
let ndc_to_world: Mat4 = camera_position * projection_matrix.inverse();
let cursor_pos_near: Vec3 = ndc_to_world.transform_point3(cursor_pos_ndc_near);
let cursor_pos_far: Vec3 = ndc_to_world.transform_point3(cursor_pos_ndc_far);
let ray_direction = cursor_pos_far - cursor_pos_near;
Ray::new(
cursor_pos_near.to_vector3().into(),
ray_direction.to_vector3(),
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment