diff --git a/Cargo.toml b/Cargo.toml index 691aae0..d73e724 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,18 +21,18 @@ include = [ ] keywords = ["robotics", "optimization"] license = "MIT OR Apache-2.0" -repository = "https://github.com/farm-ng/sophus-rs/" -version = "0.7.0" +repository = "https://github.com/sophus-vision/sophus-rs/" +version = "0.8.0" [workspace.dependencies] -sophus = {path = "crates/sophus", version = "0.7.0"} -sophus_core = {path = "crates/sophus_core", version = "0.7.0"} -sophus_image = {path = "crates/sophus_image", version = "0.7.0"} -sophus_lie = {path = "crates/sophus_lie", version = "0.7.0"} -sophus_opt = {path = "crates/sophus_opt", version = "0.7.0"} -sophus_pyo3 = {path = "crates/sophus_pyo3", version = "0.7.0"} -sophus_sensor = {path = "crates/sophus_sensor", version = "0.7.0"} -sophus_viewer = {path = "crates/sophus_viewer", version = "0.7.0"} +sophus = {path = "crates/sophus", version = "0.8.0"} +sophus_core = {path = "crates/sophus_core", version = "0.8.0"} +sophus_image = {path = "crates/sophus_image", version = "0.8.0"} +sophus_lie = {path = "crates/sophus_lie", version = "0.8.0"} +sophus_opt = {path = "crates/sophus_opt", version = "0.8.0"} +sophus_pyo3 = {path = "crates/sophus_pyo3", version = "0.8.0"} +sophus_sensor = {path = "crates/sophus_sensor", version = "0.8.0"} +sophus_viewer = {path = "crates/sophus_viewer", version = "0.8.0"} approx = "0.5" as-any = "0.3" @@ -45,7 +45,7 @@ eframe = {version = "0.27", features = ["wgpu"]} egui_extras = "0.27" env_logger = "0.11" faer = "0.19" -hollywood = {version = "0.7.0"} +hollywood = {version = "0.8.0"} image = {version = "0.25", features = [ "jpeg", "png", diff --git a/README.md b/README.md index cbfaa4c..2a8b1c3 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ sophus-rs builds on stable. ```toml [dependencies] -sophus = "0.7.0" +sophus = "0.8.0" ``` To allow for batch types, such as BatchScalarF64, the 'simd' feature is required. This feature @@ -38,5 +38,5 @@ are no plans to rely on any other nightly features. ```toml [dependencies] -sophus = { version = "0.7.0", features = ["simd"] } +sophus = { version = "0.8.0", features = ["simd"] } ``` diff --git a/crates/sophus/examples/pose_graph.rs b/crates/sophus/examples/pose_graph.rs index eb6209a..9f23b3b 100644 --- a/crates/sophus/examples/pose_graph.rs +++ b/crates/sophus/examples/pose_graph.rs @@ -15,7 +15,7 @@ use sophus_lie::Isometry3; use sophus_sensor::camera_enum::perspective_camera::PerspectiveCameraEnum; use sophus_sensor::dyn_camera::DynCamera; use sophus_sensor::KannalaBrandtCamera; -use sophus_viewer::interactions::WgpuClippingPlanes; +use sophus_viewer::views::interactions::WgpuClippingPlanes; use sophus_viewer::simple_viewer::SimpleViewer; use crate::color::Color; diff --git a/crates/sophus/examples/viewer_ex.rs b/crates/sophus/examples/viewer_ex.rs index 3f8cd49..5a13df7 100644 --- a/crates/sophus/examples/viewer_ex.rs +++ b/crates/sophus/examples/viewer_ex.rs @@ -15,7 +15,7 @@ use sophus_image::mut_image_view::IsMutImageView; use sophus_lie::traits::IsTranslationProductGroup; use sophus_lie::Isometry3; use sophus_sensor::DynCamera; -use sophus_viewer::interactions::WgpuClippingPlanes; +use sophus_viewer::views::interactions::WgpuClippingPlanes; use sophus_viewer::renderables::color::Color; use sophus_viewer::renderables::renderable2d::Points2; use sophus_viewer::renderables::renderable2d::Renderable2d; diff --git a/crates/sophus_viewer/src/actor.rs b/crates/sophus_viewer/src/actor.rs index f18cf56..b54d3e3 100644 --- a/crates/sophus_viewer/src/actor.rs +++ b/crates/sophus_viewer/src/actor.rs @@ -8,8 +8,8 @@ use sophus_lie::traits::IsTranslationProductGroup; use sophus_lie::Isometry3; use sophus_sensor::dyn_camera::DynCamera; -use crate::interactions::WgpuClippingPlanes; use crate::renderables::Packets; +use crate::views::interactions::WgpuClippingPlanes; use crate::ViewerRenderState; /// Viewer camera configuration. diff --git a/crates/sophus_viewer/src/lib.rs b/crates/sophus_viewer/src/lib.rs index 9438296..1a4a980 100644 --- a/crates/sophus_viewer/src/lib.rs +++ b/crates/sophus_viewer/src/lib.rs @@ -6,16 +6,10 @@ /// The actor for the viewer. pub mod actor; -/// Interactions -pub mod interactions; /// The offscreen texture for rendering. -pub mod offscreen; -/// The pixel renderer for 2D rendering. -pub mod pixel_renderer; +pub mod offscreen_renderer; /// The renderable structs. pub mod renderables; -/// The scene renderer for 3D rendering. -pub mod scene_renderer; /// The simple viewer. pub mod simple_viewer; /// The view struct. diff --git a/crates/sophus_viewer/src/offscreen_renderer.rs b/crates/sophus_viewer/src/offscreen_renderer.rs new file mode 100644 index 0000000..3e3d56b --- /dev/null +++ b/crates/sophus_viewer/src/offscreen_renderer.rs @@ -0,0 +1,11 @@ +/// offscreen texture for rendering +pub mod textures; + +/// Renderer for offscreen rendering +pub mod renderer; + +/// The pixel renderer for 2D rendering. +pub mod pixel_renderer; + +/// The scene renderer for 3D rendering. +pub mod scene_renderer; diff --git a/crates/sophus_viewer/src/pixel_renderer.rs b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer.rs similarity index 62% rename from crates/sophus_viewer/src/pixel_renderer.rs rename to crates/sophus_viewer/src/offscreen_renderer/pixel_renderer.rs index 9c2b6aa..44c1c35 100644 --- a/crates/sophus_viewer/src/pixel_renderer.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer.rs @@ -10,10 +10,11 @@ use std::num::NonZeroU64; use wgpu::util::DeviceExt; use wgpu::DepthStencilState; -use crate::interactions::InteractionEnum; -use crate::offscreen::ZBufferTexture; -use crate::pixel_renderer::line::PixelLineRenderer; -use crate::pixel_renderer::pixel_point::PixelPointRenderer; +use crate::offscreen_renderer::pixel_renderer::line::PixelLineRenderer; +use crate::offscreen_renderer::pixel_renderer::pixel_point::PixelPointRenderer; +use crate::offscreen_renderer::textures::ZBufferTexture; +use crate::views::interactions::inplane_interaction::InplaneInteraction; +use crate::views::interactions::orbit_interaction::OrbitalInteraction; use crate::ViewerRenderState; /// Renderer for pixel data @@ -120,72 +121,73 @@ impl PixelRenderer { } } - pub(crate) fn show_interaction_marker( + pub(crate) fn show_interaction_marker0( &self, state: &ViewerRenderState, - interaction_state: &InteractionEnum, + orbital_interaction: &OrbitalInteraction, ) { - match interaction_state { - InteractionEnum::OrbitalInteraction(orbital_interaction) => { - if let Some(scene_focus) = orbital_interaction.maybe_scene_focus { - *self.point_renderer.show_interaction_marker.lock().unwrap() = - if orbital_interaction.maybe_pointer_state.is_some() - || orbital_interaction.maybe_scroll_state.is_some() - { - let mut vertex_data = vec![]; - - for _i in 0..6 { - vertex_data.push(PointVertex2 { - _pos: [ - scene_focus.uv_in_virtual_camera[0] as f32, - scene_focus.uv_in_virtual_camera[1] as f32, - ], - _color: [0.5, 0.5, 0.5, 1.0], - _point_size: 5.0, - }); - } - state.queue.write_buffer( - &self.point_renderer.interaction_vertex_buffer, - 0, - bytemuck::cast_slice(&vertex_data), - ); - - true - } else { - false - }; - } - } - InteractionEnum::InplaneInteraction(inplane_interaction) => { - if let Some(scene_focus) = inplane_interaction.maybe_scene_focus { - *self.point_renderer.show_interaction_marker.lock().unwrap() = - if inplane_interaction.maybe_pointer_state.is_some() - || inplane_interaction.maybe_scroll_state.is_some() - { - let mut vertex_data = vec![]; - - for _i in 0..6 { - vertex_data.push(PointVertex2 { - _pos: [ - scene_focus.uv_in_virtual_camera[0] as f32, - scene_focus.uv_in_virtual_camera[1] as f32, - ], - _color: [0.5, 0.5, 0.5, 1.0], - _point_size: 5.0, - }); - } - state.queue.write_buffer( - &self.point_renderer.interaction_vertex_buffer, - 0, - bytemuck::cast_slice(&vertex_data), - ); - - true - } else { - false - }; - } - } + if let Some(scene_focus) = orbital_interaction.maybe_scene_focus { + *self.point_renderer.show_interaction_marker.lock().unwrap() = + if orbital_interaction.maybe_pointer_state.is_some() + || orbital_interaction.maybe_scroll_state.is_some() + { + let mut vertex_data = vec![]; + + for _i in 0..6 { + vertex_data.push(PointVertex2 { + _pos: [ + scene_focus.uv_in_virtual_camera[0] as f32, + scene_focus.uv_in_virtual_camera[1] as f32, + ], + _color: [0.5, 0.5, 0.5, 1.0], + _point_size: 5.0, + }); + } + state.queue.write_buffer( + &self.point_renderer.interaction_vertex_buffer, + 0, + bytemuck::cast_slice(&vertex_data), + ); + + true + } else { + false + }; + } + } + + pub(crate) fn show_interaction_marker1( + &self, + state: &ViewerRenderState, + inplane_interaction: &InplaneInteraction, + ) { + if let Some(scene_focus) = inplane_interaction.maybe_scene_focus { + *self.point_renderer.show_interaction_marker.lock().unwrap() = + if inplane_interaction.maybe_pointer_state.is_some() + || inplane_interaction.maybe_scroll_state.is_some() + { + let mut vertex_data = vec![]; + + for _i in 0..6 { + vertex_data.push(PointVertex2 { + _pos: [ + scene_focus.uv_in_virtual_camera[0] as f32, + scene_focus.uv_in_virtual_camera[1] as f32, + ], + _color: [0.5, 0.5, 0.5, 1.0], + _point_size: 5.0, + }); + } + state.queue.write_buffer( + &self.point_renderer.interaction_vertex_buffer, + 0, + bytemuck::cast_slice(&vertex_data), + ); + + true + } else { + false + }; } } diff --git a/crates/sophus_viewer/src/pixel_renderer/line.rs b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/line.rs similarity index 98% rename from crates/sophus_viewer/src/pixel_renderer/line.rs rename to crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/line.rs index 4e18e29..5b04c32 100644 --- a/crates/sophus_viewer/src/pixel_renderer/line.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/line.rs @@ -4,7 +4,7 @@ use eframe::egui_wgpu::wgpu::util::DeviceExt; use nalgebra::SVector; use wgpu::DepthStencilState; -use crate::pixel_renderer::LineVertex2; +use crate::offscreen_renderer::pixel_renderer::LineVertex2; use crate::renderables::renderable2d::Line2; use crate::ViewerRenderState; diff --git a/crates/sophus_viewer/src/pixel_renderer/line_pixel_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/line_pixel_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/pixel_renderer/line_pixel_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/line_pixel_shader.wgsl diff --git a/crates/sophus_viewer/src/pixel_renderer/pixel_point.rs b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/pixel_point.rs similarity index 98% rename from crates/sophus_viewer/src/pixel_renderer/pixel_point.rs rename to crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/pixel_point.rs index fcb4b58..120bcda 100644 --- a/crates/sophus_viewer/src/pixel_renderer/pixel_point.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/pixel_point.rs @@ -4,7 +4,7 @@ use std::sync::Mutex; use eframe::egui_wgpu::wgpu::util::DeviceExt; use wgpu::DepthStencilState; -use crate::pixel_renderer::PointVertex2; +use crate::offscreen_renderer::pixel_renderer::PointVertex2; use crate::renderables::renderable2d::Point2; use crate::ViewerRenderState; diff --git a/crates/sophus_viewer/src/pixel_renderer/point_pixel_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/point_pixel_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/pixel_renderer/point_pixel_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/pixel_renderer/point_pixel_shader.wgsl diff --git a/crates/sophus_viewer/src/offscreen_renderer/renderer.rs b/crates/sophus_viewer/src/offscreen_renderer/renderer.rs new file mode 100644 index 0000000..ac119b9 --- /dev/null +++ b/crates/sophus_viewer/src/offscreen_renderer/renderer.rs @@ -0,0 +1,414 @@ +use eframe::egui; +use sophus_core::linalg::VecF64; +use sophus_image::arc_image::ArcImage4U8; +use sophus_image::arc_image::GenArcImage; +use sophus_image::ImageSize; +use sophus_lie::Isometry3; +use sophus_sensor::DynCamera; + +use crate::offscreen_renderer::pixel_renderer::LineVertex2; +use crate::offscreen_renderer::pixel_renderer::PixelRenderer; +use crate::offscreen_renderer::pixel_renderer::PointVertex2; +use crate::offscreen_renderer::scene_renderer::line::LineVertex3; +use crate::offscreen_renderer::scene_renderer::mesh::MeshVertex3; +use crate::offscreen_renderer::scene_renderer::point::PointVertex3; +use crate::offscreen_renderer::scene_renderer::textured_mesh::TexturedMeshVertex3; +use crate::offscreen_renderer::scene_renderer::SceneRenderer; +use crate::offscreen_renderer::textures::OffscreenTextures; +use crate::renderables::renderable2d::Renderable2d; +use crate::renderables::renderable3d::Renderable3d; +use crate::renderables::renderable3d::TexturedMesh3; +use crate::views::aspect_ratio::HasAspectRatio; +use crate::ViewerRenderState; + +pub(crate) struct OffscreenRenderer { + intrinsics: DynCamera, + state: ViewerRenderState, + scene: SceneRenderer, + pixel: PixelRenderer, + textures: OffscreenTextures, + maybe_background_image: Option, +} + +/// Render result +pub struct OffscreenRenderResult { + /// depth image - might have a greater width than the requested width + pub depth: GenArcImage<2, 0, f32, f32, 1, 1>, + /// rgba texture id + pub rgba_tex_id: egui::TextureId, +} + +impl HasAspectRatio for OffscreenRenderer { + fn aspect_ratio(&self) -> f32 { + self.intrinsics.image_size().aspect_ratio() + } +} + +impl OffscreenRenderer { + pub fn new(state: &ViewerRenderState, intrinsics: &DynCamera) -> Self { + let depth_stencil = Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }); + Self { + scene: SceneRenderer::new(state, intrinsics, depth_stencil.clone()), + pixel: PixelRenderer::new(state, &intrinsics.image_size(), depth_stencil), + textures: OffscreenTextures::new(state, &intrinsics.image_size()), + intrinsics: intrinsics.clone(), + state: state.clone(), + maybe_background_image: None, + } + } + + pub fn intrinsics(&self) -> DynCamera { + self.intrinsics.clone() + } + + pub fn update_2d_frame( + &mut self, + intrinsics: &DynCamera, + maybe_background_image: Option<&ArcImage4U8>, + ) { + self.intrinsics = intrinsics.clone(); + if let Some(background_image) = maybe_background_image { + let w = self.intrinsics.image_size().width; + let h = self.intrinsics.image_size().height; + + let far = 500.0; + + let p0 = self + .intrinsics + .cam_unproj_with_z(&VecF64::<2>::new(-0.5, -0.5), far) + .cast(); + let p1 = self + .intrinsics + .cam_unproj_with_z(&VecF64::<2>::new(w as f64 - 0.5, -0.5), far) + .cast(); + let p2 = self + .intrinsics + .cam_unproj_with_z(&VecF64::<2>::new(-0.5, h as f64 - 0.5), far) + .cast(); + let p3 = self + .intrinsics + .cam_unproj_with_z(&VecF64::<2>::new(w as f64 - 0.5, h as f64 - 0.5), far) + .cast(); + + let tex_mesh = TexturedMesh3::make(&[ + [(p0, [0.0, 0.0]), (p1, [1.0, 0.0]), (p2, [0.0, 1.0])], + [(p1, [1.0, 0.0]), (p2, [0.0, 1.0]), (p3, [1.0, 1.0])], + ]); + self.scene + .textured_mesh_renderer + .mesh_table + .insert("background".to_owned(), tex_mesh.mesh); + self.maybe_background_image = Some(background_image.clone()); + } + } + + pub fn update_2d_renderables(&mut self, renderables: Vec) { + for m in renderables { + match m { + Renderable2d::Lines2(lines) => { + self.pixel + .line_renderer + .lines_table + .insert(lines.name, lines.lines); + } + Renderable2d::Points2(points) => { + self.pixel + .point_renderer + .points_table + .insert(points.name, points.points); + } + } + } + + self.pixel.clear_vertex_data(); + + for (_, points) in self.pixel.point_renderer.points_table.iter() { + for point in points.iter() { + let v = PointVertex2 { + _pos: [point.p[0], point.p[1]], + _color: [point.color.r, point.color.g, point.color.b, point.color.a], + _point_size: point.point_size, + }; + for _i in 0..6 { + self.pixel.point_renderer.vertex_data.push(v); + } + } + } + for (_, lines) in self.pixel.line_renderer.lines_table.iter() { + for line in lines.iter() { + let p0 = line.p0; + let p1 = line.p1; + let d = (p0 - p1).normalize(); + let normal = [d[1], -d[0]]; + + let v0 = LineVertex2 { + _pos: [p0[0], p0[1]], + _normal: normal, + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + let v1 = LineVertex2 { + _pos: [p1[0], p1[1]], + _normal: normal, + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + self.pixel.line_renderer.vertex_data.push(v0); + self.pixel.line_renderer.vertex_data.push(v0); + self.pixel.line_renderer.vertex_data.push(v1); + self.pixel.line_renderer.vertex_data.push(v0); + self.pixel.line_renderer.vertex_data.push(v1); + self.pixel.line_renderer.vertex_data.push(v1); + } + } + for (_, points) in self.scene.point_renderer.point_table.iter() { + for point in points.iter() { + let v = PointVertex3 { + _pos: [point.p[0], point.p[1], point.p[2]], + _color: [point.color.r, point.color.g, point.color.b, point.color.a], + _point_size: point.point_size, + }; + for _i in 0..6 { + self.scene.point_renderer.vertex_data.push(v); + } + } + } + for (_, lines) in self.scene.line_renderer.line_table.iter() { + for line in lines.iter() { + let p0 = line.p0; + let p1 = line.p1; + + let v0 = LineVertex3 { + _p0: [p0[0], p0[1], p0[2]], + _p1: [p1[0], p1[1], p1[2]], + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + let v1 = LineVertex3 { + _p0: [p0[0], p0[1], p0[2]], + _p1: [p1[0], p1[1], p1[2]], + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v1); + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v1); + self.scene.line_renderer.vertex_data.push(v1); + } + } + for (_, mesh) in self.scene.mesh_renderer.mesh_table.iter() { + for trig in mesh.iter() { + let v0 = MeshVertex3 { + _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + let v1 = MeshVertex3 { + _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + let v2 = MeshVertex3 { + _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + self.scene.mesh_renderer.vertices.push(v0); + self.scene.mesh_renderer.vertices.push(v1); + self.scene.mesh_renderer.vertices.push(v2); + } + } + for (_, mesh) in self.scene.textured_mesh_renderer.mesh_table.iter() { + for trig in mesh.iter() { + let v0 = TexturedMeshVertex3 { + _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], + _tex: [trig.tex0[0], trig.tex0[1]], + }; + let v1 = TexturedMeshVertex3 { + _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], + _tex: [trig.tex1[0], trig.tex1[1]], + }; + let v2 = TexturedMeshVertex3 { + _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], + _tex: [trig.tex2[0], trig.tex2[1]], + }; + self.scene.textured_mesh_renderer.vertices.push(v0); + self.scene.textured_mesh_renderer.vertices.push(v1); + self.scene.textured_mesh_renderer.vertices.push(v2); + } + } + } + + pub fn update_3d_renderables(&mut self, renderables: Vec) { + for m in renderables { + match m { + Renderable3d::Lines3(lines3) => { + self.scene + .line_renderer + .line_table + .insert(lines3.name, lines3.lines); + } + Renderable3d::Points3(points3) => { + self.scene + .point_renderer + .point_table + .insert(points3.name, points3.points); + } + Renderable3d::Mesh3(mesh) => { + self.scene + .mesh_renderer + .mesh_table + .insert(mesh.name, mesh.mesh); + } + } + } + + // maybe separate call needed + + self.scene.clear_vertex_data(); + + for (_, points) in self.scene.point_renderer.point_table.iter() { + for point in points.iter() { + let v = PointVertex3 { + _pos: [point.p[0], point.p[1], point.p[2]], + _color: [point.color.r, point.color.g, point.color.b, point.color.a], + _point_size: point.point_size, + }; + for _i in 0..6 { + self.scene.point_renderer.vertex_data.push(v); + } + } + } + for (_, lines) in self.scene.line_renderer.line_table.iter() { + for line in lines.iter() { + let p0 = line.p0; + let p1 = line.p1; + + let v0 = LineVertex3 { + _p0: [p0[0], p0[1], p0[2]], + _p1: [p1[0], p1[1], p1[2]], + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + let v1 = LineVertex3 { + _p0: [p0[0], p0[1], p0[2]], + _p1: [p1[0], p1[1], p1[2]], + _color: [line.color.r, line.color.g, line.color.b, line.color.a], + _line_width: line.line_width, + }; + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v1); + self.scene.line_renderer.vertex_data.push(v0); + self.scene.line_renderer.vertex_data.push(v1); + self.scene.line_renderer.vertex_data.push(v1); + } + } + for (_, mesh) in self.scene.mesh_renderer.mesh_table.iter() { + for trig in mesh.iter() { + let v0 = MeshVertex3 { + _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + let v1 = MeshVertex3 { + _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + let v2 = MeshVertex3 { + _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], + _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], + }; + self.scene.mesh_renderer.vertices.push(v0); + self.scene.mesh_renderer.vertices.push(v1); + self.scene.mesh_renderer.vertices.push(v2); + } + } + for (_, mesh) in self.scene.textured_mesh_renderer.mesh_table.iter() { + for trig in mesh.iter() { + let v0 = TexturedMeshVertex3 { + _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], + _tex: [trig.tex0[0], trig.tex0[1]], + }; + let v1 = TexturedMeshVertex3 { + _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], + _tex: [trig.tex1[0], trig.tex1[1]], + }; + let v2 = TexturedMeshVertex3 { + _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], + _tex: [trig.tex2[0], trig.tex2[1]], + }; + self.scene.textured_mesh_renderer.vertices.push(v0); + self.scene.textured_mesh_renderer.vertices.push(v1); + self.scene.textured_mesh_renderer.vertices.push(v2); + } + } + } + + pub fn render( + &mut self, + view_port_size: &ImageSize, + scene_from_camera: Isometry3, + ) -> OffscreenRenderResult { + if self.textures.view_port_size != *view_port_size { + self.textures = OffscreenTextures::new(&self.state, view_port_size); + } + + self.scene.prepare( + &self.state, + &self.intrinsics, + &scene_from_camera, + &self.maybe_background_image, + ); + + self.maybe_background_image = None; + self.pixel.prepare(&self.state); + + let mut command_encoder = self + .state + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + + self.scene.paint( + &mut command_encoder, + &self.textures.rgba.rgba_texture_view, + &self.textures.z_buffer, + ); + + // self. + // .pixel + // .show_interaction_marker0(&self.state, &self.orbit_interaction); + + self.pixel.paint( + &mut command_encoder, + &self.textures.rgba.rgba_texture_view, + &self.textures.z_buffer, + ); + + self.state.queue.submit(Some(command_encoder.finish())); + + let mut command_encoder = self + .state + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + self.scene.depth_paint( + &mut command_encoder, + &self.textures.depth.depth_texture_view_f32, + &self.textures.z_buffer, + ); + + let depth_image = + self.textures + .depth + .download_image(&self.state, command_encoder, view_port_size); + + OffscreenRenderResult { + depth: depth_image, + rgba_tex_id: self.textures.rgba.rgba_tex_id, + } + } +} diff --git a/crates/sophus_viewer/src/scene_renderer.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer.rs similarity index 93% rename from crates/sophus_viewer/src/scene_renderer.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer.rs index f0c99f9..e4c2edf 100644 --- a/crates/sophus_viewer/src/scene_renderer.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer.rs @@ -13,23 +13,21 @@ pub mod point; /// textured mesh renderer pub mod textured_mesh; -use eframe::egui; use sophus_core::calculus::region::IsRegion; -use sophus_core::linalg::VecF32; use sophus_core::tensor::tensor_view::IsTensorLike; use sophus_image::arc_image::ArcImage4U8; -use sophus_image::arc_image::ArcImageF32; use sophus_image::image_view::IsImageView; +use sophus_lie::Isometry3; use sophus_sensor::distortion_table::distort_table; use sophus_sensor::dyn_camera::DynCamera; use wgpu::DepthStencilState; -use crate::interactions::InteractionEnum; -use crate::offscreen::ZBufferTexture; -use crate::scene_renderer::buffers::Frustum; -use crate::scene_renderer::buffers::SceneRenderBuffers; -use crate::scene_renderer::mesh::MeshRenderer; -use crate::scene_renderer::point::ScenePointRenderer; +use crate::offscreen_renderer::scene_renderer::buffers::Frustum; +use crate::offscreen_renderer::scene_renderer::buffers::SceneRenderBuffers; +use crate::offscreen_renderer::scene_renderer::mesh::MeshRenderer; +use crate::offscreen_renderer::scene_renderer::point::ScenePointRenderer; +use crate::offscreen_renderer::textures::ZBufferTexture; +use crate::views::interactions::WgpuClippingPlanes; use crate::ViewerRenderState; /// Scene renderer @@ -44,8 +42,6 @@ pub struct SceneRenderer { pub point_renderer: ScenePointRenderer, /// Line renderer pub line_renderer: line::SceneLineRenderer, - /// Interaction state - pub interaction: InteractionEnum, } impl SceneRenderer { @@ -54,7 +50,6 @@ impl SceneRenderer { wgpu_render_state: &ViewerRenderState, intrinsics: &DynCamera, depth_stencil: Option, - interaction: InteractionEnum, ) -> Self { let device = &wgpu_render_state.device; @@ -169,21 +164,9 @@ impl SceneRenderer { &pipeline_layout, depth_stencil, ), - interaction, } } - pub(crate) fn process_event( - &mut self, - cam: &DynCamera, - response: &egui::Response, - scales: &VecF32<2>, - z_buffer: ArcImageF32, - ) { - self.interaction - .process_event(cam, response, scales, &z_buffer); - } - pub(crate) fn paint<'rp>( &'rp self, command_encoder: &'rp mut wgpu::CommandEncoder, @@ -293,6 +276,7 @@ impl SceneRenderer { &self, state: &ViewerRenderState, intrinsics: &DynCamera, + scene_from_camera: &Isometry3, background_image: &Option, ) { state.queue.write_buffer( @@ -319,8 +303,8 @@ impl SceneRenderer { let frustum_uniforms = Frustum { camera_image_width: intrinsics.image_size().width as f32, camera_image_height: intrinsics.image_size().height as f32, - near: 0.1, - far: 1000.0, + near: WgpuClippingPlanes::DEFAULT_NEAR as f32, + far: WgpuClippingPlanes::DEFAULT_FAR as f32, fx: intrinsics.pinhole_params()[0] as f32, fy: intrinsics.pinhole_params()[1] as f32, px: intrinsics.pinhole_params()[2] as f32, @@ -337,7 +321,7 @@ impl SceneRenderer { for i in 0..4 { for j in 0..4 { scene_from_camera_uniform[j][i] = - self.interaction.scene_from_camera().inverse().matrix()[(i, j)] as f32; + scene_from_camera.inverse().matrix()[(i, j)] as f32; } } state.queue.write_buffer( diff --git a/crates/sophus_viewer/src/scene_renderer/buffers.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/buffers.rs similarity index 98% rename from crates/sophus_viewer/src/scene_renderer/buffers.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/buffers.rs index f5ac268..872b5c5 100644 --- a/crates/sophus_viewer/src/scene_renderer/buffers.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/buffers.rs @@ -4,6 +4,7 @@ use sophus_sensor::distortion_table::DistortTable; use sophus_sensor::DynCamera; use wgpu::util::DeviceExt; +use crate::views::interactions::WgpuClippingPlanes; use crate::ViewerRenderState; #[repr(C)] @@ -103,8 +104,8 @@ impl SceneRenderBuffers { let frustum_uniforms = Frustum { camera_image_width: intrinsics.image_size().width as f32, camera_image_height: intrinsics.image_size().height as f32, - near: 0.1, - far: 1000.0, + near: WgpuClippingPlanes::DEFAULT_NEAR as f32, + far: WgpuClippingPlanes::DEFAULT_FAR as f32, fx: intrinsics.pinhole_params()[0] as f32, fy: intrinsics.pinhole_params()[1] as f32, px: intrinsics.pinhole_params()[2] as f32, diff --git a/crates/sophus_viewer/src/scene_renderer/depth_triangle_scene_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/depth_triangle_scene_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/depth_triangle_scene_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/depth_triangle_scene_shader.wgsl diff --git a/crates/sophus_viewer/src/scene_renderer/line.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/line.rs similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/line.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/line.rs diff --git a/crates/sophus_viewer/src/scene_renderer/line_scene_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/line_scene_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/line_scene_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/line_scene_shader.wgsl diff --git a/crates/sophus_viewer/src/scene_renderer/mesh.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/mesh.rs similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/mesh.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/mesh.rs diff --git a/crates/sophus_viewer/src/scene_renderer/mesh_scene_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/mesh_scene_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/mesh_scene_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/mesh_scene_shader.wgsl diff --git a/crates/sophus_viewer/src/scene_renderer/point.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/point.rs similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/point.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/point.rs diff --git a/crates/sophus_viewer/src/scene_renderer/point_scene_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/point_scene_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/point_scene_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/point_scene_shader.wgsl diff --git a/crates/sophus_viewer/src/scene_renderer/textured_mesh.rs b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/textured_mesh.rs similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/textured_mesh.rs rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/textured_mesh.rs diff --git a/crates/sophus_viewer/src/scene_renderer/textured_mesh_scene_shader.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/textured_mesh_scene_shader.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/textured_mesh_scene_shader.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/textured_mesh_scene_shader.wgsl diff --git a/crates/sophus_viewer/src/scene_renderer/utils.wgsl b/crates/sophus_viewer/src/offscreen_renderer/scene_renderer/utils.wgsl similarity index 100% rename from crates/sophus_viewer/src/scene_renderer/utils.wgsl rename to crates/sophus_viewer/src/offscreen_renderer/scene_renderer/utils.wgsl diff --git a/crates/sophus_viewer/src/offscreen.rs b/crates/sophus_viewer/src/offscreen_renderer/textures.rs similarity index 98% rename from crates/sophus_viewer/src/offscreen.rs rename to crates/sophus_viewer/src/offscreen_renderer/textures.rs index 860d2db..bd95104 100644 --- a/crates/sophus_viewer/src/offscreen.rs +++ b/crates/sophus_viewer/src/offscreen_renderer/textures.rs @@ -250,16 +250,13 @@ impl DepthTexture { #[derive(Debug)] pub(crate) struct OffscreenTextures { - view_port_size: ImageSize, + pub(crate) view_port_size: ImageSize, pub(crate) rgba: RgbaTexture, pub(crate) z_buffer: ZBufferTexture, pub(crate) depth: DepthTexture, } impl OffscreenTextures { - pub(crate) fn view_port_size(&self) -> &ImageSize { - &self.view_port_size - } pub(crate) fn new(render_state: &ViewerRenderState, view_port_size: &ImageSize) -> Self { Self { view_port_size: *view_port_size, diff --git a/crates/sophus_viewer/src/simple_viewer.rs b/crates/sophus_viewer/src/simple_viewer.rs index 40a86cc..db50f22 100644 --- a/crates/sophus_viewer/src/simple_viewer.rs +++ b/crates/sophus_viewer/src/simple_viewer.rs @@ -11,14 +11,8 @@ use sophus_core::linalg::VecF32; use sophus_lie::Isometry3; use crate::actor::ViewerBuilder; -use crate::pixel_renderer::LineVertex2; -use crate::pixel_renderer::PointVertex2; use crate::renderables::Packet; use crate::renderables::Packets; -use crate::scene_renderer::line::LineVertex3; -use crate::scene_renderer::mesh::MeshVertex3; -use crate::scene_renderer::point::PointVertex3; -use crate::scene_renderer::textured_mesh::TexturedMeshVertex3; use crate::views::aspect_ratio::get_adjusted_view_size; use crate::views::aspect_ratio::get_max_size; use crate::views::aspect_ratio::HasAspectRatio; @@ -79,220 +73,7 @@ impl SimpleViewer { if self.views.contains_key(&view_label) { let view = self.views.get(&view_label).unwrap(); if let View::View3d(view) = view { - request.reply(view.scene.interaction.scene_from_camera()); - } - } - } - - for (_, view) in self.views.iter_mut() { - match view { - View::View3d(view) => { - for (_, points) in view.scene.point_renderer.point_table.iter() { - for point in points.iter() { - let v = PointVertex3 { - _pos: [point.p[0], point.p[1], point.p[2]], - _color: [ - point.color.r, - point.color.g, - point.color.b, - point.color.a, - ], - _point_size: point.point_size, - }; - for _i in 0..6 { - view.scene.point_renderer.vertex_data.push(v); - } - } - } - for (_, lines) in view.scene.line_renderer.line_table.iter() { - for line in lines.iter() { - let p0 = line.p0; - let p1 = line.p1; - - let v0 = LineVertex3 { - _p0: [p0[0], p0[1], p0[2]], - _p1: [p1[0], p1[1], p1[2]], - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - let v1 = LineVertex3 { - _p0: [p0[0], p0[1], p0[2]], - _p1: [p1[0], p1[1], p1[2]], - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v1); - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v1); - view.scene.line_renderer.vertex_data.push(v1); - } - } - for (_, mesh) in view.scene.mesh_renderer.mesh_table.iter() { - for trig in mesh.iter() { - let v0 = MeshVertex3 { - _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - let v1 = MeshVertex3 { - _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - let v2 = MeshVertex3 { - _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - view.scene.mesh_renderer.vertices.push(v0); - view.scene.mesh_renderer.vertices.push(v1); - view.scene.mesh_renderer.vertices.push(v2); - } - } - for (_, mesh) in view.scene.textured_mesh_renderer.mesh_table.iter() { - for trig in mesh.iter() { - let v0 = TexturedMeshVertex3 { - _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], - _tex: [trig.tex0[0], trig.tex0[1]], - }; - let v1 = TexturedMeshVertex3 { - _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], - _tex: [trig.tex1[0], trig.tex1[1]], - }; - let v2 = TexturedMeshVertex3 { - _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], - _tex: [trig.tex2[0], trig.tex2[1]], - }; - view.scene.textured_mesh_renderer.vertices.push(v0); - view.scene.textured_mesh_renderer.vertices.push(v1); - view.scene.textured_mesh_renderer.vertices.push(v2); - } - } - } - View::View2d(view) => { - for (_, points) in view.pixel.point_renderer.points_table.iter() { - for point in points.iter() { - let v = PointVertex2 { - _pos: [point.p[0], point.p[1]], - _color: [ - point.color.r, - point.color.g, - point.color.b, - point.color.a, - ], - _point_size: point.point_size, - }; - for _i in 0..6 { - view.pixel.point_renderer.vertex_data.push(v); - } - } - } - for (_, lines) in view.pixel.line_renderer.lines_table.iter() { - for line in lines.iter() { - let p0 = line.p0; - let p1 = line.p1; - let d = (p0 - p1).normalize(); - let normal = [d[1], -d[0]]; - - let v0 = LineVertex2 { - _pos: [p0[0], p0[1]], - _normal: normal, - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - let v1 = LineVertex2 { - _pos: [p1[0], p1[1]], - _normal: normal, - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - view.pixel.line_renderer.vertex_data.push(v0); - view.pixel.line_renderer.vertex_data.push(v0); - view.pixel.line_renderer.vertex_data.push(v1); - view.pixel.line_renderer.vertex_data.push(v0); - view.pixel.line_renderer.vertex_data.push(v1); - view.pixel.line_renderer.vertex_data.push(v1); - } - } - for (_, points) in view.scene.point_renderer.point_table.iter() { - for point in points.iter() { - let v = PointVertex3 { - _pos: [point.p[0], point.p[1], point.p[2]], - _color: [ - point.color.r, - point.color.g, - point.color.b, - point.color.a, - ], - _point_size: point.point_size, - }; - for _i in 0..6 { - view.scene.point_renderer.vertex_data.push(v); - } - } - } - for (_, lines) in view.scene.line_renderer.line_table.iter() { - for line in lines.iter() { - let p0 = line.p0; - let p1 = line.p1; - - let v0 = LineVertex3 { - _p0: [p0[0], p0[1], p0[2]], - _p1: [p1[0], p1[1], p1[2]], - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - let v1 = LineVertex3 { - _p0: [p0[0], p0[1], p0[2]], - _p1: [p1[0], p1[1], p1[2]], - _color: [line.color.r, line.color.g, line.color.b, line.color.a], - _line_width: line.line_width, - }; - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v1); - view.scene.line_renderer.vertex_data.push(v0); - view.scene.line_renderer.vertex_data.push(v1); - view.scene.line_renderer.vertex_data.push(v1); - } - } - for (_, mesh) in view.scene.mesh_renderer.mesh_table.iter() { - for trig in mesh.iter() { - let v0 = MeshVertex3 { - _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - let v1 = MeshVertex3 { - _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - let v2 = MeshVertex3 { - _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], - _color: [trig.color.r, trig.color.g, trig.color.b, trig.color.a], - }; - view.scene.mesh_renderer.vertices.push(v0); - view.scene.mesh_renderer.vertices.push(v1); - view.scene.mesh_renderer.vertices.push(v2); - } - } - for (_, mesh) in view.scene.textured_mesh_renderer.mesh_table.iter() { - for trig in mesh.iter() { - let v0 = TexturedMeshVertex3 { - _pos: [trig.p0[0], trig.p0[1], trig.p0[2]], - _tex: [trig.tex0[0], trig.tex0[1]], - }; - let v1 = TexturedMeshVertex3 { - _pos: [trig.p1[0], trig.p1[1], trig.p1[2]], - _tex: [trig.tex1[0], trig.tex1[1]], - }; - let v2 = TexturedMeshVertex3 { - _pos: [trig.p2[0], trig.p2[1], trig.p2[2]], - _tex: [trig.tex2[0], trig.tex2[1]], - }; - view.scene.textured_mesh_renderer.vertices.push(v0); - view.scene.textured_mesh_renderer.vertices.push(v1); - view.scene.textured_mesh_renderer.vertices.push(v2); - } - } + request.reply(view.orbit_interaction.scene_from_camera); } } } @@ -307,17 +88,17 @@ impl eframe::App for SimpleViewer { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui_extras::install_image_loaders(ctx); - // Clear vertex data - for (_, view) in self.views.iter_mut() { - if let View::View3d(view) = view { - view.scene.clear_vertex_data(); - //view.pixel.clear_vertex_data(); - } - if let View::View2d(view) = view { - view.scene.clear_vertex_data(); - view.pixel.clear_vertex_data(); - } - } + // // Clear vertex data + // for (_, view) in self.views.iter_mut() { + // if let View::View3d(view) = view { + // view.renderer.scene.clear_vertex_data(); + // //view.renderer.pixel.clear_vertex_data(); + // } + // if let View::View2d(view) = view { + // view.renderer.scene.clear_vertex_data(); + // view.renderer.pixel.clear_vertex_data(); + // } + // } // Add renderables to tables self.add_renderables_to_tables(); @@ -342,49 +123,9 @@ impl eframe::App for SimpleViewer { get_adjusted_view_size(view_aspect_ratio, max_width, max_height); match view { View::View3d(view) => { - view.update_offscreen_texture( - &self.state, - &adjusted_size.image_size(), - ); - let offscreen = view.offscreen.as_ref().unwrap(); - - view.scene.prepare(&self.state, &view.intrinsics, &None); - view.pixel_for_interaction_marker.prepare(&self.state); - - let mut command_encoder = self.state.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor::default(), - ); - - view.scene.paint( - &mut command_encoder, - &offscreen.rgba.rgba_texture_view, - &offscreen.z_buffer, - ); - - view.pixel_for_interaction_marker - .show_interaction_marker(&self.state, &view.scene.interaction); - - view.pixel_for_interaction_marker.paint( - &mut command_encoder, - &offscreen.rgba.rgba_texture_view, - &offscreen.z_buffer, - ); - - self.state.queue.submit(Some(command_encoder.finish())); - - let mut command_encoder = self.state.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor::default(), - ); - view.scene.depth_paint( - &mut command_encoder, - &offscreen.depth.depth_texture_view_f32, - &offscreen.z_buffer, - ); - - let depth_image = offscreen.depth.download_image( - &self.state, - command_encoder, + let render_result = view.renderer.render( &adjusted_size.image_size(), + view.orbit_interaction.scene_from_camera, ); let response = ui.add( @@ -393,7 +134,7 @@ impl eframe::App for SimpleViewer { adjusted_size.width, adjusted_size.height, ), - id: offscreen.rgba.rgba_tex_id, + id: render_result.rgba_tex_id, }) .fit_to_exact_size(egui::Vec2 { x: adjusted_size.width, @@ -407,64 +148,19 @@ impl eframe::App for SimpleViewer { ( response, VecF32::<2>::new( - view.intrinsics.image_size().width as f32 + view.intrinsics().image_size().width as f32 / adjusted_size.width, - view.intrinsics.image_size().height as f32 + view.intrinsics().image_size().height as f32 / adjusted_size.height, ), - depth_image, + render_result.depth, ), ); } View::View2d(view) => { - view.update_offscreen_texture( - &self.state, - &adjusted_size.image_size(), - ); - let offscreen = view.offscreen.as_ref().unwrap(); - - view.scene.prepare( - &self.state, - &view.intrinsics, - &view.background_image, - ); - view.pixel.prepare(&self.state); - - view.background_image = None; - - let mut command_encoder = self.state.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor::default(), - ); - - view.scene.paint( - &mut command_encoder, - &offscreen.rgba.rgba_texture_view, - &offscreen.z_buffer, - ); - view.pixel.paint( - &mut command_encoder, - &offscreen.rgba.rgba_texture_view, - &offscreen.z_buffer, - ); - - self.state.queue.submit(Some(command_encoder.finish())); - - view.pixel - .show_interaction_marker(&self.state, &view.scene.interaction); - - let mut command_encoder = self.state.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor::default(), - ); - view.scene.depth_paint( - &mut command_encoder, - &offscreen.depth.depth_texture_view_f32, - &offscreen.z_buffer, - ); - - let depth_image = offscreen.depth.download_image( - &self.state, - command_encoder, + let render_result = view.renderer.render( &adjusted_size.image_size(), + view.inplane_interaction.scene_from_camera, ); let response = ui.add( @@ -473,7 +169,7 @@ impl eframe::App for SimpleViewer { adjusted_size.width, adjusted_size.height, ), - id: offscreen.rgba.rgba_tex_id, + id: render_result.rgba_tex_id, }) .fit_to_exact_size(egui::Vec2 { x: adjusted_size.width, @@ -487,12 +183,12 @@ impl eframe::App for SimpleViewer { ( response, VecF32::<2>::new( - view.intrinsics.image_size().width as f32 + view.intrinsics().image_size().width as f32 / adjusted_size.width, - view.intrinsics.image_size().height as f32 + view.intrinsics().image_size().height as f32 / adjusted_size.height, ), - depth_image, + render_result.depth, ), ); } @@ -507,11 +203,11 @@ impl eframe::App for SimpleViewer { View::View3d(view) => { let response = responses.get(view_label).unwrap(); - view.scene.process_event( - &view.intrinsics, + view.orbit_interaction.process_event( + &view.intrinsics(), &response.0, &response.1, - response.2.clone(), + &response.2, ); } View::View2d(_) => {} diff --git a/crates/sophus_viewer/src/views.rs b/crates/sophus_viewer/src/views.rs index 276e1a2..9c78ec2 100644 --- a/crates/sophus_viewer/src/views.rs +++ b/crates/sophus_viewer/src/views.rs @@ -1,5 +1,7 @@ /// aspect ratio pub mod aspect_ratio; +/// Interactions +pub mod interactions; /// 2d view pub mod view2d; /// 3d view diff --git a/crates/sophus_viewer/src/interactions.rs b/crates/sophus_viewer/src/views/interactions.rs similarity index 84% rename from crates/sophus_viewer/src/interactions.rs rename to crates/sophus_viewer/src/views/interactions.rs index 8d6fead..2f933c4 100644 --- a/crates/sophus_viewer/src/interactions.rs +++ b/crates/sophus_viewer/src/views/interactions.rs @@ -10,8 +10,8 @@ use sophus_image::arc_image::ArcImageF32; use sophus_lie::Isometry3; use sophus_sensor::dyn_camera::DynCamera; -use crate::interactions::inplane_interaction::InplaneInteraction; -use crate::interactions::orbit_interaction::OrbitalInteraction; +use crate::views::interactions::inplane_interaction::InplaneInteraction; +use crate::views::interactions::orbit_interaction::OrbitalInteraction; /// Clipping planes for the Wgpu renderer #[derive(Clone, Copy, Debug)] @@ -22,11 +22,18 @@ pub struct WgpuClippingPlanes { pub far: f64, } +impl WgpuClippingPlanes { + /// default near clipping plabe + pub const DEFAULT_NEAR: f64 = 0.1; + /// default far clipping plabe + pub const DEFAULT_FAR: f64 = 1000.0; +} + impl Default for WgpuClippingPlanes { fn default() -> Self { WgpuClippingPlanes { - near: 0.1, - far: 1000.0, + near: WgpuClippingPlanes::DEFAULT_NEAR, + far: WgpuClippingPlanes::DEFAULT_FAR, } } } diff --git a/crates/sophus_viewer/src/interactions/inplane_interaction.rs b/crates/sophus_viewer/src/views/interactions/inplane_interaction.rs similarity index 50% rename from crates/sophus_viewer/src/interactions/inplane_interaction.rs rename to crates/sophus_viewer/src/views/interactions/inplane_interaction.rs index 77e7f76..aa43ed6 100644 --- a/crates/sophus_viewer/src/interactions/inplane_interaction.rs +++ b/crates/sophus_viewer/src/views/interactions/inplane_interaction.rs @@ -1,13 +1,15 @@ use eframe::egui; use sophus_core::linalg::VecF32; +use sophus_core::linalg::VecF64; use sophus_image::arc_image::ArcImageF32; +use sophus_lie::traits::IsTranslationProductGroup; use sophus_lie::Isometry3; use sophus_sensor::DynCamera; -use crate::interactions::InteractionPointerState; -use crate::interactions::SceneFocus; -use crate::interactions::ScrollState; -use crate::interactions::WgpuClippingPlanes; +use crate::views::interactions::InteractionPointerState; +use crate::views::interactions::SceneFocus; +use crate::views::interactions::ScrollState; +use crate::views::interactions::WgpuClippingPlanes; #[derive(Clone, Copy)] /// Interaction state @@ -19,6 +21,21 @@ pub struct InplaneInteraction { pub(crate) scene_from_camera: Isometry3, } +impl InplaneInteraction { + pub(crate) fn new() -> Self { + InplaneInteraction { + maybe_pointer_state: None, + maybe_scroll_state: None, + maybe_scene_focus: None, + _clipping_planes: WgpuClippingPlanes { + near: WgpuClippingPlanes::DEFAULT_NEAR, + far: WgpuClippingPlanes::DEFAULT_FAR, + }, + scene_from_camera: Isometry3::from_t(&VecF64::<3>::new(0.0, 0.0, 0.0)), + } + } +} + impl InplaneInteraction { /// Process event pub fn process_event( diff --git a/crates/sophus_viewer/src/interactions/orbit_interaction.rs b/crates/sophus_viewer/src/views/interactions/orbit_interaction.rs similarity index 93% rename from crates/sophus_viewer/src/interactions/orbit_interaction.rs rename to crates/sophus_viewer/src/views/interactions/orbit_interaction.rs index 3383a5d..afda5db 100644 --- a/crates/sophus_viewer/src/interactions/orbit_interaction.rs +++ b/crates/sophus_viewer/src/views/interactions/orbit_interaction.rs @@ -8,10 +8,10 @@ use sophus_lie::traits::IsTranslationProductGroup; use sophus_lie::Isometry3; use sophus_sensor::DynCamera; -use crate::interactions::InteractionPointerState; -use crate::interactions::SceneFocus; -use crate::interactions::ScrollState; -use crate::interactions::WgpuClippingPlanes; +use crate::views::interactions::InteractionPointerState; +use crate::views::interactions::SceneFocus; +use crate::views::interactions::ScrollState; +use crate::views::interactions::WgpuClippingPlanes; #[derive(Clone, Copy)] /// Interaction state @@ -23,6 +23,21 @@ pub struct OrbitalInteraction { pub(crate) scene_from_camera: Isometry3, } +impl OrbitalInteraction { + pub(crate) fn new( + scene_from_camera: Isometry3, + clipping_planes: WgpuClippingPlanes, + ) -> OrbitalInteraction { + OrbitalInteraction { + maybe_pointer_state: None, + maybe_scroll_state: None, + maybe_scene_focus: None, + clipping_planes, + scene_from_camera, + } + } +} + impl OrbitalInteraction { fn median_scene_depth(&self, z_buffer: &ArcImageF32) -> f64 { // to median ndc z diff --git a/crates/sophus_viewer/src/views/view2d.rs b/crates/sophus_viewer/src/views/view2d.rs index 25247b6..f213fb0 100644 --- a/crates/sophus_viewer/src/views/view2d.rs +++ b/crates/sophus_viewer/src/views/view2d.rs @@ -1,31 +1,17 @@ use linked_hash_map::LinkedHashMap; -use sophus_core::linalg::VecF64; -use sophus_image::arc_image::ArcImage4U8; -use sophus_image::ImageSize; -use sophus_lie::traits::IsTranslationProductGroup; -use sophus_lie::Isometry3; use sophus_sensor::DynCamera; -use crate::interactions::inplane_interaction::InplaneInteraction; -use crate::interactions::InteractionEnum; -use crate::interactions::WgpuClippingPlanes; -use crate::offscreen::OffscreenTextures; -use crate::pixel_renderer::PixelRenderer; -use crate::renderables::renderable2d::Renderable2d; +use crate::offscreen_renderer::renderer::OffscreenRenderer; use crate::renderables::renderable2d::View2dPacket; -use crate::renderables::renderable3d::Renderable3d; -use crate::renderables::renderable3d::TexturedMesh3; -use crate::scene_renderer::SceneRenderer; use crate::views::aspect_ratio::HasAspectRatio; +use crate::views::interactions::inplane_interaction::InplaneInteraction; use crate::views::View; use crate::ViewerRenderState; pub(crate) struct View2d { - pub(crate) scene: SceneRenderer, - pub(crate) pixel: PixelRenderer, - pub(crate) intrinsics: DynCamera, - pub(crate) offscreen: Option, - pub(crate) background_image: Option, + pub(crate) renderer: OffscreenRenderer, + //pub(crate) intrinsics: DynCamera, + pub(crate) inplane_interaction: InplaneInteraction, } impl View2d { @@ -38,39 +24,12 @@ impl View2d { return false; } if let Some(frame) = &packet.frame { - let depth_stencil = Some(wgpu::DepthStencilState { - format: wgpu::TextureFormat::Depth32Float, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilState::default(), - bias: wgpu::DepthBiasState::default(), - }); views.insert( packet.view_label.clone(), View::View2d(View2d { - scene: SceneRenderer::new( - state, - frame.intrinsics(), - depth_stencil.clone(), - InteractionEnum::InplaneInteraction(InplaneInteraction { - maybe_pointer_state: None, - maybe_scroll_state: None, - maybe_scene_focus: None, - _clipping_planes: WgpuClippingPlanes { - near: 0.1, - far: 1000.0, - }, - scene_from_camera: Isometry3::from_t(&VecF64::<3>::new(0.0, 0.0, -5.0)), - }), - ), - pixel: PixelRenderer::new( - state, - &frame.intrinsics().image_size(), - depth_stencil.clone(), - ), - intrinsics: frame.intrinsics().clone(), - background_image: frame.maybe_image().cloned(), - offscreen: None, + //background_image: frame.maybe_image().cloned(), + renderer: OffscreenRenderer::new(state, frame.intrinsics()), + inplane_interaction: InplaneInteraction::new(), }), ); return true; @@ -93,78 +52,15 @@ impl View2d { }; if let Some(frame) = packet.frame { - let depth_stencil = Some(wgpu::DepthStencilState { - format: wgpu::TextureFormat::Depth32Float, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilState::default(), - bias: wgpu::DepthBiasState::default(), - }); - let new_intrinsics = frame.intrinsics(); // We got a new frame, hence we need to clear all renderables and then add the // intrinsics and background image if present. The easiest and most error-proof way to // do this is to create a new SceneRenderer and PixelRenderer and replace the old ones. - view.pixel = PixelRenderer::new( - state, - &frame.intrinsics().image_size(), - depth_stencil.clone(), - ); - - view.scene = SceneRenderer::new( - state, - frame.intrinsics(), - depth_stencil, - InteractionEnum::InplaneInteraction(InplaneInteraction { - maybe_pointer_state: None, - maybe_scroll_state: None, - maybe_scene_focus: None, - _clipping_planes: WgpuClippingPlanes { - near: 0.1, - far: 1000.0, - }, - scene_from_camera: Isometry3::from_t(&VecF64::<3>::new(0.0, 0.0, 0.0)), - }), - ); - - view.offscreen = Some(OffscreenTextures::new(state, &new_intrinsics.image_size())); - - view.intrinsics = new_intrinsics.clone(); - if let Some(background_image) = frame.maybe_image() { - view.background_image = Some(background_image.clone()); + view.renderer = OffscreenRenderer::new(state, new_intrinsics); - let w = view.intrinsics.image_size().width; - let h = view.intrinsics.image_size().height; - - let far = 500.0; - - let p0 = view - .intrinsics - .cam_unproj_with_z(&VecF64::<2>::new(-0.5, -0.5), far) - .cast(); - let p1 = view - .intrinsics - .cam_unproj_with_z(&VecF64::<2>::new(w as f64 - 0.5, -0.5), far) - .cast(); - let p2 = view - .intrinsics - .cam_unproj_with_z(&VecF64::<2>::new(-0.5, h as f64 - 0.5), far) - .cast(); - let p3 = view - .intrinsics - .cam_unproj_with_z(&VecF64::<2>::new(w as f64 - 0.5, h as f64 - 0.5), far) - .cast(); - - let tex_mesh = TexturedMesh3::make(&[ - [(p0, [0.0, 0.0]), (p1, [1.0, 0.0]), (p2, [0.0, 1.0])], - [(p1, [1.0, 0.0]), (p2, [0.0, 1.0]), (p3, [1.0, 1.0])], - ]); - view.scene - .textured_mesh_renderer - .mesh_table - .insert("background".to_owned(), tex_mesh.mesh); - } + view.renderer + .update_2d_frame(new_intrinsics, frame.maybe_image()); } let view = views.get_mut(&packet.view_label).unwrap(); @@ -173,67 +69,16 @@ impl View2d { _ => panic!("View type mismatch"), }; - for m in packet.renderables2d { - match m { - Renderable2d::Lines2(lines) => { - view.pixel - .line_renderer - .lines_table - .insert(lines.name, lines.lines); - } - Renderable2d::Points2(points) => { - view.pixel - .point_renderer - .points_table - .insert(points.name, points.points); - } - } - } - for m in packet.renderables3d { - match m { - Renderable3d::Lines3(lines3) => { - view.scene - .line_renderer - .line_table - .insert(lines3.name, lines3.lines); - } - Renderable3d::Points3(points3) => { - view.scene - .point_renderer - .point_table - .insert(points3.name, points3.points); - } - Renderable3d::Mesh3(mesh) => { - view.scene - .mesh_renderer - .mesh_table - .insert(mesh.name, mesh.mesh); - } - } - } + view.renderer.update_2d_renderables(packet.renderables2d); } - pub fn update_offscreen_texture( - &mut self, - render_state: &ViewerRenderState, - view_port_size: &ImageSize, - ) { - match &mut self.offscreen { - Some(offscreen) => { - let current_view_port_size = offscreen.view_port_size(); - if current_view_port_size != view_port_size { - *offscreen = OffscreenTextures::new(render_state, view_port_size); - } - } - None => { - self.offscreen = Some(OffscreenTextures::new(render_state, view_port_size)); - } - } + pub fn intrinsics(&self) -> DynCamera { + self.renderer.intrinsics() } } impl HasAspectRatio for View2d { fn aspect_ratio(&self) -> f32 { - self.intrinsics.image_size().aspect_ratio() + self.renderer.aspect_ratio() } } diff --git a/crates/sophus_viewer/src/views/view3d.rs b/crates/sophus_viewer/src/views/view3d.rs index cb2b81e..e46997d 100644 --- a/crates/sophus_viewer/src/views/view3d.rs +++ b/crates/sophus_viewer/src/views/view3d.rs @@ -1,24 +1,17 @@ use linked_hash_map::LinkedHashMap; -use sophus_image::ImageSize; use sophus_sensor::DynCamera; -use crate::interactions::orbit_interaction::OrbitalInteraction; -use crate::interactions::InteractionEnum; -use crate::offscreen::OffscreenTextures; -use crate::pixel_renderer::PixelRenderer; -use crate::renderables::renderable3d::Renderable3d; +use crate::offscreen_renderer::renderer::OffscreenRenderer; use crate::renderables::renderable3d::View3dPacket; -use crate::scene_renderer::SceneRenderer; use crate::views::aspect_ratio::HasAspectRatio; +use crate::views::interactions::orbit_interaction::OrbitalInteraction; use crate::views::View; use crate::ViewerRenderState; pub(crate) struct View3d { - pub(crate) scene: SceneRenderer, - // At the moment, the pixel renderer is only used for the interaction marker - pub(crate) pixel_for_interaction_marker: PixelRenderer, - pub(crate) intrinsics: DynCamera, - pub(crate) offscreen: Option, + pub(crate) renderer: OffscreenRenderer, + //pub(crate) intrinsics: DynCamera, + pub(crate) orbit_interaction: OrbitalInteraction, } impl View3d { @@ -28,35 +21,15 @@ impl View3d { state: &ViewerRenderState, ) { if !views.contains_key(&packet.view_label) { - let depth_stencil = Some(wgpu::DepthStencilState { - format: wgpu::TextureFormat::Depth32Float, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilState::default(), - bias: wgpu::DepthBiasState::default(), - }); views.insert( packet.view_label.clone(), View::View3d(View3d { - offscreen: None, - scene: SceneRenderer::new( - state, - &packet.initial_camera.intrinsics, - depth_stencil.clone(), - InteractionEnum::OrbitalInteraction(OrbitalInteraction { - maybe_pointer_state: None, - maybe_scroll_state: None, - maybe_scene_focus: None, - clipping_planes: packet.initial_camera.clipping_planes, - scene_from_camera: packet.initial_camera.scene_from_camera, - }), + // intrinsics: packet.initial_camera.intrinsics.clone(), + renderer: OffscreenRenderer::new(state, &packet.initial_camera.intrinsics), + orbit_interaction: OrbitalInteraction::new( + packet.initial_camera.scene_from_camera, + packet.initial_camera.clipping_planes, ), - pixel_for_interaction_marker: PixelRenderer::new( - state, - &packet.initial_camera.intrinsics.image_size(), - depth_stencil.clone(), - ), - intrinsics: packet.initial_camera.intrinsics.clone(), }), ); } @@ -74,51 +47,17 @@ impl View3d { View::View3d(view) => view, _ => panic!("View type mismatch"), }; - for m in packet.renderables3d { - match m { - Renderable3d::Lines3(lines3) => { - view.scene - .line_renderer - .line_table - .insert(lines3.name, lines3.lines); - } - Renderable3d::Points3(points3) => { - view.scene - .point_renderer - .point_table - .insert(points3.name, points3.points); - } - Renderable3d::Mesh3(mesh) => { - view.scene - .mesh_renderer - .mesh_table - .insert(mesh.name, mesh.mesh); - } - } - } + + view.renderer.update_3d_renderables(packet.renderables3d); } - pub fn update_offscreen_texture( - &mut self, - render_state: &ViewerRenderState, - view_port_size: &ImageSize, - ) { - match &mut self.offscreen { - Some(offscreen) => { - let current_view_port_size = offscreen.view_port_size(); - if current_view_port_size != view_port_size { - *offscreen = OffscreenTextures::new(render_state, view_port_size); - } - } - None => { - self.offscreen = Some(OffscreenTextures::new(render_state, view_port_size)); - } - } + pub fn intrinsics(&self) -> DynCamera { + self.renderer.intrinsics() } } impl HasAspectRatio for View3d { fn aspect_ratio(&self) -> f32 { - self.intrinsics.image_size().aspect_ratio() + self.renderer.aspect_ratio() } }