From 6a11541a205d008a579ddbb50edd9878010eeb94 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 19 Jun 2023 20:29:32 -0700 Subject: [PATCH 1/4] Fix wrong length of projected ray --- crates/re_components/src/pinhole.rs | 19 +++++++++++++++++++ .../src/space_camera_3d.rs | 13 +++++++------ crates/re_space_view_spatial/src/ui_3d.rs | 12 ++++++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/crates/re_components/src/pinhole.rs b/crates/re_components/src/pinhole.rs index be9fec57022b..b2dc7303c33b 100644 --- a/crates/re_components/src/pinhole.rs +++ b/crates/re_components/src/pinhole.rs @@ -110,6 +110,25 @@ impl Pinhole { pub fn aspect_ratio(&self) -> Option { self.resolution.map(|r| r[0] / r[1]) } + + #[cfg(feature = "glam")] + #[inline] + pub fn offset(&self) -> glam::Vec2 { + let [x, y, _] = self.image_from_cam[2].0; + glam::vec2(x, y) + } + + /// Given pixel coordinates and a world-space depth, + /// return a position in the camera space. + /// + /// The returned z is the same as the input z (depth). + #[cfg(feature = "glam")] + #[inline] + pub fn unproject(&self, pixel: glam::Vec3) -> glam::Vec3 { + ((pixel.truncate() - self.offset()) * pixel.z + / glam::Vec2::from(self.focal_length_in_pixels())) + .extend(pixel.z) + } } #[test] diff --git a/crates/re_space_view_spatial/src/space_camera_3d.rs b/crates/re_space_view_spatial/src/space_camera_3d.rs index 5ccee39fb1e8..a0148f90490d 100644 --- a/crates/re_space_view_spatial/src/space_camera_3d.rs +++ b/crates/re_space_view_spatial/src/space_camera_3d.rs @@ -81,12 +81,13 @@ impl SpaceCamera3D { /// Unproject a 2D image coordinate as a ray in 3D space pub fn unproject_as_ray(&self, pos2d: Vec2) -> Option { - self.world_from_image().map(|world_from_pixel| { - let origin = self.position(); - let stop = world_from_pixel.transform_point3(pos2d.extend(1.0)); - let dir = (stop - origin).normalize(); - Ray3::from_origin_dir(origin, dir) - }) + let pinhole = self.pinhole?; + + let depth = 1.0; // whatever will do + let stop_in_camera = pinhole.unproject(pos2d.extend(depth)); + let stop = self.world_from_camera.transform_point3(stop_in_camera); + let origin = self.position(); + Some(Ray3::from_origin_dir(origin, (stop - origin).normalize())) } } diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 3248270ea60d..d8e7685f7ddf 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -571,15 +571,23 @@ fn show_projections_from_2d_space( match ctx.selection_state().hovered_space() { HoveredSpace::TwoD { space_2d, pos } => { if let Some(cam) = space_cameras.iter().find(|cam| &cam.ent_path == space_2d) { - if let Some(ray) = cam.unproject_as_ray(glam::vec2(pos.x, pos.y)) { + if let Some(pinhole) = cam.pinhole { // Render a thick line to the actual z value if any and a weaker one as an extension // If we don't have a z value, we only render the thick one. - let thick_ray_length = if pos.z.is_finite() && pos.z > 0.0 { + let depth = if 0.0 < pos.z && pos.z.is_finite() { pos.z } else { cam.picture_plane_distance }; + let stop_in_cam = pinhole.unproject(glam::vec3(pos.x, pos.y, depth)); + let stop_in_world = cam.world_from_cam().transform_point3(stop_in_cam); + + let origin = cam.position(); + let ray = + macaw::Ray3::from_origin_dir(origin, (stop_in_world - origin).normalize()); + + let thick_ray_length = (stop_in_world - origin).length(); add_picking_ray(line_builder, ray, scene_bbox_accum, thick_ray_length); } } From 158f1b84004356931f2f1ee8a55dc3a93768b48a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 19 Jun 2023 20:36:20 -0700 Subject: [PATCH 2/4] Remove footgun --- crates/re_components/src/pinhole.rs | 10 +++++ .../src/space_camera_3d.rs | 38 +++++-------------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/crates/re_components/src/pinhole.rs b/crates/re_components/src/pinhole.rs index b2dc7303c33b..2a34297caa16 100644 --- a/crates/re_components/src/pinhole.rs +++ b/crates/re_components/src/pinhole.rs @@ -118,6 +118,16 @@ impl Pinhole { glam::vec2(x, y) } + /// Project camera-space coordinates into pixel coordinates, + /// returning the same z/depth. + #[cfg(feature = "glam")] + #[inline] + pub fn project(&self, pixel: glam::Vec3) -> glam::Vec3 { + ((pixel.truncate() * glam::Vec2::from(self.focal_length_in_pixels())) / pixel.z + + self.offset()) + .extend(pixel.z) + } + /// Given pixel coordinates and a world-space depth, /// return a position in the camera space. /// diff --git a/crates/re_space_view_spatial/src/space_camera_3d.rs b/crates/re_space_view_spatial/src/space_camera_3d.rs index a0148f90490d..c6f880aca57a 100644 --- a/crates/re_space_view_spatial/src/space_camera_3d.rs +++ b/crates/re_space_view_spatial/src/space_camera_3d.rs @@ -1,4 +1,4 @@ -use glam::{vec3, Affine3A, Mat3, Quat, Vec2, Vec3}; +use glam::{Affine3A, Mat3, Quat, Vec2, Vec3}; use macaw::{IsoTransform, Ray3}; use re_components::{Pinhole, ViewCoordinates}; @@ -52,31 +52,12 @@ impl SpaceCamera3D { } } - /// Projects image coordinates into world coordinates - pub fn world_from_image(&self) -> Option { + /// Returns x, y, and depth in image/pixel coordinates. + pub fn project_onto_2d(&self, point_in_world: Vec3) -> Option { let pinhole = self.pinhole?; - let world_from_cam = self.world_from_cam(); - let image_from_cam: Mat3 = pinhole.image_from_cam.into(); - let cam_from_image = Affine3A::from_mat3(image_from_cam.inverse()); - Some(world_from_cam * cam_from_image) - } - - /// Projects world coordinates onto 2D image coordinates - pub fn image_from_world(&self) -> Option { - let pinhole = self.pinhole?; - let cam_from_world = self.cam_from_world(); - - let image_from_cam = pinhole.image_from_cam.into(); - let image_from_cam = Affine3A::from_mat3(image_from_cam); - Some(image_from_cam * cam_from_world) - } - - /// Returns x, y, and depth in image coordinates. - pub fn project_onto_2d(&self, pos3d: Vec3) -> Option { - self.image_from_world().map(|pixel_from_world| { - let point = pixel_from_world.transform_point3(pos3d); - vec3(point.x / point.z, point.y / point.z, point.z) - }) + let point_in_cam = self.cam_from_world().transform_point3(point_in_world); + let point_in_image = pinhole.project(point_in_cam); + Some(point_in_image) } /// Unproject a 2D image coordinate as a ray in 3D space @@ -84,10 +65,9 @@ impl SpaceCamera3D { let pinhole = self.pinhole?; let depth = 1.0; // whatever will do - let stop_in_camera = pinhole.unproject(pos2d.extend(depth)); - let stop = self.world_from_camera.transform_point3(stop_in_camera); - let origin = self.position(); - Some(Ray3::from_origin_dir(origin, (stop - origin).normalize())) + let stop = pinhole.unproject(pos2d.extend(depth)); + let ray_in_camera = Ray3::from_origin_dir(Vec3::ZERO, stop); + Some(self.world_from_camera * ray_in_camera) } } From 8764d1616ed9e4d306c75fa9e3136fbe7bd09367 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 19 Jun 2023 20:39:45 -0700 Subject: [PATCH 3/4] Remove unused imports --- crates/re_space_view_spatial/src/space_camera_3d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/re_space_view_spatial/src/space_camera_3d.rs b/crates/re_space_view_spatial/src/space_camera_3d.rs index c6f880aca57a..0077d385e8fe 100644 --- a/crates/re_space_view_spatial/src/space_camera_3d.rs +++ b/crates/re_space_view_spatial/src/space_camera_3d.rs @@ -1,4 +1,4 @@ -use glam::{Affine3A, Mat3, Quat, Vec2, Vec3}; +use glam::{Quat, Vec2, Vec3}; use macaw::{IsoTransform, Ray3}; use re_components::{Pinhole, ViewCoordinates}; From d330b739b2a734497f2838b43cf9bba41874ee92 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 20 Jun 2023 07:35:58 -0700 Subject: [PATCH 4/4] remove redundant offset function --- crates/re_components/src/pinhole.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/re_components/src/pinhole.rs b/crates/re_components/src/pinhole.rs index 2a34297caa16..5c345fef8b8b 100644 --- a/crates/re_components/src/pinhole.rs +++ b/crates/re_components/src/pinhole.rs @@ -111,20 +111,13 @@ impl Pinhole { self.resolution.map(|r| r[0] / r[1]) } - #[cfg(feature = "glam")] - #[inline] - pub fn offset(&self) -> glam::Vec2 { - let [x, y, _] = self.image_from_cam[2].0; - glam::vec2(x, y) - } - /// Project camera-space coordinates into pixel coordinates, /// returning the same z/depth. #[cfg(feature = "glam")] #[inline] pub fn project(&self, pixel: glam::Vec3) -> glam::Vec3 { ((pixel.truncate() * glam::Vec2::from(self.focal_length_in_pixels())) / pixel.z - + self.offset()) + + self.principal_point()) .extend(pixel.z) } @@ -135,7 +128,7 @@ impl Pinhole { #[cfg(feature = "glam")] #[inline] pub fn unproject(&self, pixel: glam::Vec3) -> glam::Vec3 { - ((pixel.truncate() - self.offset()) * pixel.z + ((pixel.truncate() - self.principal_point()) * pixel.z / glam::Vec2::from(self.focal_length_in_pixels())) .extend(pixel.z) }