diff --git a/src/graphics_imgui.rs b/src/graphics_imgui.rs index 1b4b67d52..d61bff40c 100644 --- a/src/graphics_imgui.rs +++ b/src/graphics_imgui.rs @@ -19,7 +19,7 @@ pub fn run(capture_provider: Arc, calibration_data: k4a_sys::k4 let mut webcam_writer = WebcamWriter::open_file("/dev/video0", 1280, 720, 3) .expect("should be able to create webcamwriter"); - let sdl_arcball = Arc::new(Mutex::new(SdlArcball::new(1280.0, 720.0))); + let sdl_arcball = Arc::new(Mutex::new(SdlArcball::new(1280, 720))); let sdl_context = sdl2::init().unwrap(); let video = sdl_context.video().unwrap(); diff --git a/src/mouse.rs b/src/mouse.rs index a4c00b267..615c47b46 100644 --- a/src/mouse.rs +++ b/src/mouse.rs @@ -4,32 +4,46 @@ use cgmath::Vector3; use sdl2::event::Event; use sdl2::mouse::MouseButton; +const DEFAULT_ZOOM: f32 = 65.0; + +// TODO: Enable camera resizing (or change of texture to differently sized texture) /// Wrap a camera arcball for use with SDL pub struct SdlArcball { - // TODO: Enable camera resizing (or change of texture to differently sized texture) + // Arcball camera state arcball: ArcballCamera, + + // Dimensions of the window + window_width: u32, + window_height: u32, + + // Last mouse state left_mouse_active: bool, right_mouse_active: bool, last_x: f32, last_y: f32, + last_zoom: f32, } impl SdlArcball { /// CTOR - pub fn new(width: f32, height: f32) -> Self { + pub fn new(window_width: u32, window_height: u32) -> Self { let center = Vector3::new(0.0, 0.0, 0.0); let zoom_speed = 1.0; - let screen = [width, height]; + let screen = [window_width as f32, window_height as f32]; let arcball = ArcballCamera::new(center, zoom_speed, screen); Self { arcball, + window_width, + window_height, left_mouse_active: false, right_mouse_active: false, last_x: 0.0, last_y: 0.0, + last_zoom: DEFAULT_ZOOM, } } + /// Process an SDL event. pub fn process_event(&mut self, event: &Event) { match event { Event::MouseWheel { timestamp: _, window_id: _, which: _, x: _, y, direction: _ } => { @@ -52,12 +66,55 @@ impl SdlArcball { } } - pub fn get_mat4(&self) -> Matrix4 { + /// Get the view matrix + pub fn get_view_matrix(&self) -> Matrix4 { self.arcball.get_mat4() } + /// Get the perspective matrix + pub fn get_perspective_matrix(&self) -> Matrix4 { + let zoom = self.last_zoom; + let y_fov = zoom.to_radians(); + let aspect = self.window_width as f32 / self.window_height as f32; + let n = 0.1f32; + let f = 100.0f32; + + // From linmath.h included in Microsoft's k4a open source code + let a = 1.0f32 / (y_fov / 2.0).tan(); + + // NB: This is column-major, which is dumb. + Matrix4::new( + // Column 0 + a / aspect, + 0.0, + 0.0, + 0.0, + + // Column 1 + 0.0, + a, + 0.0, + 0.0, + + // Column 2 + 0.0, + 0.0, + -((f + n) / (f - n)), + -((2.0 * f * n) / (f - n)), + + // Column 3 + 0.0, + 0.0, + -1.0, // NB: This is not zero + 0.0, + ) + } + fn mouse_wheel(&mut self, y: i32) { - self.arcball.zoom(y as f32, 0.16); + let y = y as f32; + println!("Zoom: {}", y); + self.arcball.zoom(y, 0.16); + self.last_zoom = y; } fn mouse_button_press(&mut self, mouse_button: &MouseButton, down: bool) { diff --git a/src/point_cloud/point_cloud_renderer.rs b/src/point_cloud/point_cloud_renderer.rs index f0f579778..59fcef869 100644 --- a/src/point_cloud/point_cloud_renderer.rs +++ b/src/point_cloud/point_cloud_renderer.rs @@ -8,11 +8,14 @@ use std::os::raw::{c_char, c_void}; use std::ptr; use std::ptr::null; use std::str; +use std::sync::{Arc, Mutex}; +use arcball::ArcballCamera; use gl; use gl::types::*; use k4a_sys_wrapper; +use mouse::SdlArcball; use opengl_wrapper::{Buffer, gl_get_error, OpenGlError, VertexArray}; use opengl_wrapper::Texture; use point_cloud::compile_shader::compile_shader; @@ -188,6 +191,8 @@ void main() "; pub struct PointCloudRenderer { + arcball_camera: Arc>, + /// The OpenGL program shader_program_id: GLuint, @@ -200,7 +205,8 @@ pub struct PointCloudRenderer { // TODO: better matrix types view: [f32; 16], projection: [f32; 16], - proj_view: [[f32; 4]; 4], + view_matrix: [[f32; 4]; 4], + projection_matrix: [[f32; 4]; 4], /// Renderer setting: size of the rendered points point_size: u8, @@ -276,7 +282,7 @@ const fn initial_projection_matrix_4x4() -> [f32; 16] { impl PointCloudRenderer { - pub fn new() -> Self { + pub fn new(arcball: Arc>) -> Self { let vertex_array_object = VertexArray::new_initialized(); let vertex_color_buffer_object = Buffer::new_initialized(); @@ -335,10 +341,19 @@ impl PointCloudRenderer { [2.62268e-07, 1.0, -5.0, 1.0], ]; + let initial_projection = [ + [1.41272, 0.0, 0.0, 0.0], + [0.0, 1.56969, 0.0, 0.0], + [0.0, 0.0, -1.002, -1.0], + [0.0, 0.0, -0.2002, 0.0], + ]; + Self { + arcball_camera: arcball, view: initial_view_matrix_4x4(), projection: initial_projection_matrix_4x4(), - proj_view: initial_view, + view_matrix: initial_view, + projection_matrix: initial_projection, shader_program_id: program_id, vertex_shader_id, fragment_shader_id, @@ -355,11 +370,26 @@ impl PointCloudRenderer { } /// - /// Update the view matrix + /// Update the view matrices /// - pub fn update_view_projection(&mut self, proj_view: [[f32; 4]; 4]) { - //println!("Matrix: {:?}", proj_view); - self.proj_view = proj_view; + pub fn update_view_projection(&mut self, view: [[f32; 4]; 4], projection: [[f32; 4]; 4]) { + println!("\nView Matrix: {:?}", view); + println!("Updated: {:?}", projection); + self.view_matrix = view; + //self.projection_matrix = projection; + + let initial_projection = [ + [1.41272, 0.0, 0.0, 0.0], + [0.0, 1.56969, 0.0, 0.0], + [0.0, 0.0, -1.002, -1.0], + [0.0, 0.0, -0.2002, 0.0], + ]; + + // Initial: [[1.41272, 0.0, 0.0, 0.0], [0.0, 1.56969, 0.0, 0.0], [0.0, 0.0, -1.002, -1.0], [0.0, 0.0, -0.2002, 0.0]] + // Updated: [[0.88294804, 0.0, 0.0, 0.0], [0.0, 1.5696855, 0.0, 0.0], [0.0, 0.0, -1.002002, -0.2002002], [0.0, 0.0, -1.0, 0.0]] + println!("Initial: {:?}", initial_projection); + + self.projection_matrix = initial_projection; } /// @@ -495,9 +525,11 @@ impl PointCloudRenderer { // Update view/projection matrices in shader //gl::UniformMatrix4fv(self.view_index, 1, gl::FALSE, self.view.as_ptr()); - gl::UniformMatrix4fv(self.projection_index, 1, gl::FALSE, self.projection.as_ptr()); + //gl::UniformMatrix4fv(self.projection_index, 1, gl::FALSE, self.projection.as_ptr()); + let typed_projection = self.projection_matrix.as_ptr() as *const GLfloat; + gl::UniformMatrix4fv(self.projection_index, 1, gl::FALSE, typed_projection); - let typed_view = self.proj_view.as_ptr() as *const GLfloat; + let typed_view = self.view_matrix.as_ptr() as *const GLfloat; gl::UniformMatrix4fv(self.view_index, 1, gl::FALSE, typed_view); //gl::UniformMatrix4fv(self.projection_index, 1, gl::FALSE, typed_view); diff --git a/src/point_cloud/point_cloud_visualiser.rs b/src/point_cloud/point_cloud_visualiser.rs index f65bab3b4..a1718589a 100644 --- a/src/point_cloud/point_cloud_visualiser.rs +++ b/src/point_cloud/point_cloud_visualiser.rs @@ -182,11 +182,11 @@ impl PointCloudVisualizer { .expect("Should be in correct depth sensor mode."); let mut visualizer = Self { - arcball_camera, + arcball_camera: arcball_camera.clone(), m_dimensions_width: width, m_dimensions_height: height, enable_color_point_cloud, - point_cloud_renderer: PointCloudRenderer::new(), + point_cloud_renderer: PointCloudRenderer::new(arcball_camera.clone()), point_cloud_converter: GpuPointCloudConverter::new(), frame_buffer: Framebuffer::new_initialized(), depth_buffer, @@ -273,9 +273,9 @@ impl PointCloudVisualizer { match self.arcball_camera.lock() { Ok(arcball) => { - let proj_view: [[f32; 4]; 4] = (arcball.get_mat4()).into(); - // TODO: View matrix maths - self.point_cloud_renderer.update_view_projection(proj_view); + let view: [[f32; 4]; 4] = (arcball.get_view_matrix()).into(); + let perspective: [[f32; 4]; 4] = (arcball.get_perspective_matrix()).into(); + self.point_cloud_renderer.update_view_projection(view, perspective); }, Err(_) => {}, }