From e22ee7722f679e8d7b416f6b57f79fe287bcd5c8 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sat, 28 Sep 2024 16:30:11 +0200 Subject: [PATCH] camera sharing between views (#116) * camera sharing between views * camera sharing bugfix Linux compilation --- .../rendering/apps/simple_surface_viewer.cpp | 14 ++++ cgogn/ui/app.cpp | 36 +++++++++- cgogn/ui/app.h | 5 ++ cgogn/ui/gl_viewer.cpp | 71 ++++++++++--------- cgogn/ui/gl_viewer.h | 53 +++++++++----- cgogn/ui/module.h | 2 + 6 files changed, 126 insertions(+), 55 deletions(-) diff --git a/cgogn/rendering/apps/simple_surface_viewer.cpp b/cgogn/rendering/apps/simple_surface_viewer.cpp index a1605e9e7..654cc6a0f 100644 --- a/cgogn/rendering/apps/simple_surface_viewer.cpp +++ b/cgogn/rendering/apps/simple_surface_viewer.cpp @@ -94,6 +94,20 @@ int main(int argc, char** argv) v1->link_module(&sr); // v1->link_module(&str); + // test for camera sharing + cgogn::ui::View* v2 = app.add_view(); + v2->link_module(&mp); + v2->link_module(&sr); + + v2->share_camera(v1); + + cgogn::ui::View* v3 = app.add_view(); + v3->link_module(&mp); + v3->link_module(&sr); + + v3->share_camera(v1); + + app.set_views_3_columns(); if (filename.length() > 0) { diff --git a/cgogn/ui/app.cpp b/cgogn/ui/app.cpp index 9b00be4c4..a3b08bbb1 100644 --- a/cgogn/ui/app.cpp +++ b/cgogn/ui/app.cpp @@ -458,7 +458,7 @@ void App::adapt_views_geometry() case 3: views_[0]->set_view_ratio(0, 0, 0.5, 0.5); views_[1]->set_view_ratio(0.5, 0, 0.5, 0.5); - views_[2]->set_view_ratio(0, 0, 1, 0.5); + views_[2]->set_view_ratio(0, 0.5, 1, 0.5); break; case 4: views_[0]->set_view_ratio(0, 0, 0.5, 0.5); @@ -472,6 +472,35 @@ void App::adapt_views_geometry() v->resize_event(window_width_, window_height_, framebuffer_width_, framebuffer_height_); } +void App::set_views_3_columns() +{ + if (views_.size() == 3) + { + views_[0]->set_view_ratio(0, 0, 0.33, 1); + views_[1]->set_view_ratio(0.33, 0, 0.33, 1); + views_[2]->set_view_ratio(0.66, 0, 0.33, 1); + } + + for (const auto& v : views_) + v->resize_event(window_width_, window_height_, framebuffer_width_, framebuffer_height_); +} + + +void App::set_views_4_columns() +{ + if (views_.size() == 4) + { + views_[0]->set_view_ratio(0, 0, 0.25, 1); + views_[1]->set_view_ratio(0.25, 0, 0.25, 1); + views_[2]->set_view_ratio(0.5, 0, 0.25, 1); + views_[3]->set_view_ratio(0.75, 0, 0.25, 1); + } + + for (const auto& v : views_) + v->resize_event(window_width_, window_height_, framebuffer_width_, framebuffer_height_); +} + + void App::init_modules() { for (Module* m : modules_) @@ -489,6 +518,9 @@ int App::launch() boost::synapse::poll(*tlq_); glfwPollEvents(); + if (glfwWindowShouldClose(window_)) + break; + glfwMakeContextCurrent(window_); frame_time_ = glfwGetTime(); @@ -674,8 +706,8 @@ int App::launch() void App::stop() { - close_event(); glfwSetWindowShouldClose(window_, GLFW_TRUE); + close_event(); } } // namespace ui diff --git a/cgogn/ui/app.h b/cgogn/ui/app.h index 3d78f072c..d2e213d53 100644 --- a/cgogn/ui/app.h +++ b/cgogn/ui/app.h @@ -68,6 +68,11 @@ class CGOGN_UI_EXPORT App static float64 frame_time_; View* add_view(); + + void set_views_3_columns(); + + void set_views_4_columns(); + inline View* current_view() const { return current_view_; diff --git a/cgogn/ui/gl_viewer.cpp b/cgogn/ui/gl_viewer.cpp index 210d5dbd6..5244c589d 100644 --- a/cgogn/ui/gl_viewer.cpp +++ b/cgogn/ui/gl_viewer.cpp @@ -33,8 +33,9 @@ namespace ui GLViewer::GLViewer(Inputs* inputs) : viewport_width_(0), viewport_height_(0), inputs_(inputs), need_redraw_(true) { - current_frame_ = &camera_; - camera_saved_ = camera_; + camera_ = std::make_shared(); + current_frame_ = camera_.get(); + camera_saved_ = *camera_; } GLViewer::~GLViewer() @@ -46,15 +47,15 @@ void GLViewer::set_manipulated_frame(MovingFrame* frame) if (frame != nullptr) current_frame_ = frame; else - current_frame_ = &camera_; + current_frame_ = camera_.get(); } void GLViewer::resize_event(int32 viewport_width, int32 viewport_height) { viewport_width_ = viewport_width; viewport_height_ = viewport_height; - camera_.set_aspect_ratio(double(viewport_width_) / viewport_height_); - need_redraw_ = true; + camera_->set_aspect_ratio(double(viewport_width_) / viewport_height_); + request_update(); } void GLViewer::close_event() @@ -68,7 +69,7 @@ void GLViewer::mouse_press_event(int32 button, int32, int32) current_frame_->is_moving_ = false; spinning_speed_ = 0; current_frame_->spin_ = rendering::Transfo3d::Identity(); - need_redraw_ = true; + request_update(); } } @@ -82,7 +83,7 @@ void GLViewer::mouse_release_event(int32 button, int32, int32) spinning_speed_ = 0; current_frame_->spin_ = rendering::Transfo3d::Identity(); } - need_redraw_ = true; + request_update(); } } @@ -93,8 +94,8 @@ void GLViewer::mouse_dbl_click_event(int32 /*buttons*/, int32 x, int32 y) rendering::GLVec3d P; if (pixel_scene_position(x, y, P)) { - camera_.set_pivot_point(P); - need_redraw_ = true; + camera_->set_pivot_point(P); + request_update(); } } } @@ -115,9 +116,9 @@ void GLViewer::mouse_move_event(int32 x, int32 y) spinning_speed_ *= inputs_->mouse_sensitivity_; if (obj_mode()) { - rendering::Transfo3d inv_camera = camera_.frame_.inverse(); + rendering::Transfo3d inv_camera = camera_->frame_.inverse(); rendering::Transfo3d sm(Eigen::AngleAxisd(2.0 * spinning_speed_, axis)); - current_frame_->spin_ = inv_camera * sm * camera_.frame_; + current_frame_->spin_ = inv_camera * sm * camera_->frame_; auto tr = current_frame_->frame_.translation().eval(); current_frame_->frame_.translation().setZero(); current_frame_->frame_ = current_frame_->spin_ * current_frame_->frame_; @@ -130,33 +131,33 @@ void GLViewer::mouse_move_event(int32 x, int32 y) current_frame_->frame_.translation().setZero(); current_frame_->frame_ = Eigen::AngleAxisd(spinning_speed_, axis) * current_frame_->frame_; current_frame_->frame_.translation() = tr; - camera_.update_matrices(); + camera_->update_matrices(); } - need_redraw_ = true; + request_update(); } if (mouse_button_pressed(GLFW_MOUSE_BUTTON_RIGHT)) { - float64 zcam = 1.0 / std::tan(camera_.field_of_view() / 2.0); - float64 a = camera_.scene_radius() - camera_.frame_.translation().z() / zcam; + float64 zcam = 1.0 / std::tan(camera_->field_of_view() / 2.0); + float64 a = camera_->scene_radius() - camera_->frame_.translation().z() / zcam; if (obj_mode()) { - rendering::Transfo3d inv_camera = camera_.frame_.inverse(); - float64 tx = dx / viewport_width_ * camera_.width() * a; - float64 ty = -dy / viewport_height_ * camera_.height() * a; + rendering::Transfo3d inv_camera = camera_->frame_.inverse(); + float64 tx = dx / viewport_width_ * camera_->width() * a; + float64 ty = -dy / viewport_height_ * camera_->height() * a; rendering::Transfo3d ntr = - inv_camera * Eigen::Translation3d(rendering::GLVec3d(tx, ty, 0.0)) * camera_.frame_; + inv_camera * Eigen::Translation3d(rendering::GLVec3d(tx, ty, 0.0)) * camera_->frame_; current_frame_->frame_ = ntr * current_frame_->frame_; } else { - float64 nx = float64(dx) / viewport_width_ * camera_.width() * a; - float64 ny = -1.0 * float64(dy) / viewport_height_ * camera_.height() * a; - camera_.frame_.translation().x() += 2 * nx; - camera_.frame_.translation().y() += 2 * ny; - camera_.update_matrices(); + float64 nx = float64(dx) / viewport_width_ * camera_->width() * a; + float64 ny = -1.0 * float64(dy) / viewport_height_ * camera_->height() * a; + camera_->frame_.translation().x() += 2 * nx; + camera_->frame_.translation().y() += 2 * ny; + camera_->update_matrices(); } - need_redraw_ = true; + request_update(); } } @@ -166,19 +167,19 @@ void GLViewer::mouse_wheel_event(float64, float64 dy) { if (obj_mode()) { - rendering::Transfo3d inv_camera = camera_.frame_.inverse(); + rendering::Transfo3d inv_camera = camera_->frame_.inverse(); auto ntr = inv_camera * Eigen::Translation3d(rendering::GLVec3d(0, 0, -inputs_->wheel_sensitivity_ * dy)) * - camera_.frame_; + camera_->frame_; current_frame_->frame_ = ntr * current_frame_->frame_; } else { - float64 zcam = 1.0 / std::tan(camera_.field_of_view() / 2.0); - float64 a = camera_.scene_radius() - camera_.frame_.translation().z() / zcam / camera_.scene_radius(); - camera_.frame_.translation().z() -= inputs_->wheel_sensitivity_ * dy * std::max(0.1, a); - camera_.update_matrices(); + float64 zcam = 1.0 / std::tan(camera_->field_of_view() / 2.0); + float64 a = camera_->scene_radius() - camera_->frame_.translation().z() / zcam / camera_->scene_radius(); + camera_->frame_.translation().z() -= inputs_->wheel_sensitivity_ * dy * std::max(0.1, a); + camera_->update_matrices(); } - need_redraw_ = true; + request_update(); } } @@ -200,9 +201,9 @@ void GLViewer::spin() current_frame_->frame_.translation().setZero(); current_frame_->frame_ = current_frame_->spin_ * current_frame_->frame_; current_frame_->frame_.translation() = tr; - if (current_frame_ == &camera_) - camera_.update_matrices(); - need_redraw_ = true; + if (current_frame_ == camera_.get()) + camera_->update_matrices(); + request_update(); } } diff --git a/cgogn/ui/gl_viewer.h b/cgogn/ui/gl_viewer.h index 6c2f730ed..48f39b98e 100644 --- a/cgogn/ui/gl_viewer.h +++ b/cgogn/ui/gl_viewer.h @@ -30,6 +30,8 @@ #include #include +#include + #include namespace cgogn @@ -45,18 +47,30 @@ class CGOGN_UI_EXPORT GLViewer virtual ~GLViewer(); CGOGN_NOT_COPYABLE_NOR_MOVABLE(GLViewer); + inline void share_camera(GLViewer* v) + { + camera_ = v->camera_; + current_frame_ = v->current_frame_; + shared_cam_with_.push_back(v); + v->shared_cam_with_.push_back(this); + } + inline bool need_redraw() const { return need_redraw_; } + inline void request_update() { need_redraw_ = true; + for (auto* v : shared_cam_with_) + if (!v->need_redraw()) + v->request_update(); } inline const Camera& camera() const { - return camera_; + return *camera_; } inline void save_camera() { @@ -64,61 +78,62 @@ class CGOGN_UI_EXPORT GLViewer out_file.open("saved_camera"); if (out_file.is_open()) { - out_file << camera_; + out_file << *camera_; out_file.close(); } - camera_saved_ = camera_; + camera_saved_ = *camera_; } inline void restore_camera() { - camera_ = camera_saved_; + *camera_ = camera_saved_; std::ifstream in_file("saved_camera", std::ios::in); if (in_file.is_open()) { - in_file >> camera_; + in_file >> *camera_; in_file.close(); } - need_redraw_ = true; + request_update(); } inline const rendering::GLMat4& projection_matrix() const { - return camera_.projection_matrix(); + return camera_->projection_matrix(); } inline const rendering::GLMat4d& projection_matrix_d() const { - return camera_.projection_matrix_d(); + return camera_->projection_matrix_d(); } inline const rendering::GLMat4& modelview_matrix() const { - return camera_.modelview_matrix(); + return camera_->modelview_matrix(); } inline const rendering::GLMat4d& modelview_matrix_d() const { - return camera_.modelview_matrix_d(); + return camera_->modelview_matrix_d(); } + void set_manipulated_frame(MovingFrame* frame); inline void set_scene_radius(float64 radius) { - camera_.set_scene_radius(radius); + camera_->set_scene_radius(radius); } inline void set_scene_center(const rendering::GLVec3d& center) { scene_center_ = center; - if (!camera_.pivot_point_initialized()) - camera_.set_pivot_point(scene_center_); + if (!camera_->pivot_point_initialized()) + camera_->set_pivot_point(scene_center_); } inline void set_scene_center(const rendering::GLVec3& center) { scene_center_ = center.cast(); - if (!camera_.pivot_point_initialized()) - camera_.set_pivot_point(scene_center_); + if (!camera_->pivot_point_initialized()) + camera_->set_pivot_point(scene_center_); } inline void show_entire_scene() { - camera_.show_entire_scene(); + camera_->show_entire_scene(); request_update(); } @@ -201,11 +216,13 @@ class CGOGN_UI_EXPORT GLViewer inline bool obj_mode() const { - return current_frame_ != &camera_; + return current_frame_ != camera_.get(); } void spin(); - Camera camera_; + std::shared_ptr camera_; + std::vector shared_cam_with_; + Camera camera_saved_; MovingFrame* current_frame_; rendering::GLVec3d scene_center_; diff --git a/cgogn/ui/module.h b/cgogn/ui/module.h index 6c1b3ff2b..d13454688 100644 --- a/cgogn/ui/module.h +++ b/cgogn/ui/module.h @@ -82,6 +82,7 @@ class CGOGN_UI_EXPORT ViewModule : public Module return linked_views_; } + protected: virtual void mouse_press_event(View* view, int32 button, int32 x, int32 y); virtual void mouse_release_event(View* view, int32 button, int32 x, int32 y); @@ -94,6 +95,7 @@ class CGOGN_UI_EXPORT ViewModule : public Module virtual void draw(View* view); std::vector linked_views_; + }; /*****************************************************************************/