From 16281027af498e3e63ed270cfde7b826480c6885 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 21:43:10 +0400 Subject: [PATCH] resolved problem with multiple spin()/spinOnce() --- modules/viz/doc/viz3d.rst | 16 -- modules/viz/include/opencv2/viz/viz3d.hpp | 3 - modules/viz/src/interactor_style.cpp | 7 +- modules/viz/src/interactor_style.hpp | 2 - modules/viz/src/viz3d.cpp | 3 - modules/viz/src/vizimpl.cpp | 194 ++++++++++------------ modules/viz/src/vizimpl.hpp | 88 +++------- modules/viz/test/tests_simple.cpp | 21 +-- 8 files changed, 117 insertions(+), 217 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index ec5b16e71..5b361ad84 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -134,8 +134,6 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); void setRepresentation(int representation); private: @@ -425,20 +423,6 @@ Returns rendering property of a widget. * **SHADING_GOURAUD** * **SHADING_PHONG** -viz::Viz3d::setDesiredUpdateRate --------------------------------- -Sets desired update rate of the window. - -.. ocv:function:: void setDesiredUpdateRate(double rate) - - :param rate: Desired update rate. The default is 30. - -viz::Viz3d::getDesiredUpdateRate --------------------------------- -Returns desired update rate of the window. - -.. ocv:function:: double getDesiredUpdateRate() - viz::Viz3d::setRepresentation ----------------------------- Sets geometry representation of the widgets to surface, wireframe or points. diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index b9712ef3e..090c8b14e 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -113,9 +113,6 @@ namespace cv void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - void setRepresentation(int representation); private: diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 42858f105..75003a2b6 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -220,8 +220,6 @@ int cv::viz::InteractorStyle::getModifiers() void cv::viz::InteractorStyle::OnKeyDown() { CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); - CV_Assert("No renderer given! Use SetRendererCollection() before continuing." && renderer_); - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); // Save the initial windows width/height @@ -403,8 +401,8 @@ void cv::viz::InteractorStyle::OnKeyDown() vtkSmartPointer window = Interactor->GetRenderWindow(); if (!window->GetStereoRender()) { - static Vec2i default_mask(4, 3), alternative_mask(2, 5); - window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? default_mask.val : alternative_mask.val); + static Vec2i red_blue(4, 3), magenta_green(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? red_blue.val : magenta_green.val); stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; } window->SetStereoRender(!window->GetStereoRender()); @@ -637,6 +635,5 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() void cv::viz::InteractorStyle::OnTimer() { CV_Assert("Interactor style not initialized." && init_); - CV_Assert("Renderer has not been set." && renderer_); Interactor->Render(); } diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 583860911..8d01697a8 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -63,7 +63,6 @@ namespace cv virtual void Initialize(); void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } - void setRenderer(vtkSmartPointer& renderer) { renderer_ = renderer; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); @@ -73,7 +72,6 @@ namespace cv /** \brief Set to true after initialization is complete. */ bool init_; - vtkSmartPointer renderer_; Ptr widget_actor_map_; Vec2i win_size_; diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 503359f01..237ef87c9 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -145,7 +145,4 @@ void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double value) { getWidget(id).setRenderingProperty(property, value); } double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } -void cv::viz::Viz3d::setDesiredUpdateRate(double rate) { impl_->setDesiredUpdateRate(rate); } -double cv::viz::Viz3d::getDesiredUpdateRate() { return impl_->getDesiredUpdateRate(); } - void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 61a0a01f6..e66b53823 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -46,25 +46,17 @@ #include "precomp.hpp" ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) +cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); - window_ = vtkSmartPointer::New(); - // Set the window size as 1/2 of the screen size + // Create render window + window_ = vtkSmartPointer::New(); + window_name_ = VizStorage::generateWindowName(name); + cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); window_->AddRenderer(renderer_); - - // Create the interactor style - style_->Initialize(); - style_->setRenderer(renderer_); - style_->setWidgetActorMap(widget_actor_map_); - style_->UseTimersOn(); - - interactor_ = vtkSmartPointer::New(); - window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); window_->LineSmoothingOff(); @@ -72,37 +64,89 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) window_->SwapBuffersOn(); window_->SetStereoTypeToAnaglyph(); - interactor_->SetRenderWindow(window_); - interactor_->SetInteractorStyle(style_); - interactor_->SetDesiredUpdateRate(24.0); - - // Initialize and create timer, also create window - interactor_->Initialize(); - timer_id_ = interactor_->CreateRepeatingTimer(5000L); - - exit_main_loop_timer_callback_ = vtkSmartPointer::New(); - exit_main_loop_timer_callback_->viz_ = this; - exit_main_loop_timer_callback_->right_timer_id = -1; - interactor_->AddObserver(vtkCommand::TimerEvent, exit_main_loop_timer_callback_); + // Create the interactor style + style_ = vtkSmartPointer::New(); + style_->setWidgetActorMap(widget_actor_map_); + style_->UseTimersOn(); + style_->Initialize(); + timer_callback_ = vtkSmartPointer::New(); exit_callback_ = vtkSmartPointer::New(); - exit_callback_->viz_ = this; - interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); - - resetStoppedFlag(); - - ////////////////////////////// - String window_name = VizStorage::generateWindowName(name); - window_->SetWindowName(window_name.c_str()); + exit_callback_->viz = this; } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::~VizImpl() +void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie) { - if (interactor_) - interactor_->DestroyTimer(timer_id_); - if (renderer_) - renderer_->Clear(); + if (event_id == vtkCommand::TimerEvent && timer_id == *reinterpret_cast(cookie)) + { + vtkSmartPointer interactor = vtkRenderWindowInteractor::SafeDownCast(caller); + interactor->TerminateApp(); + } +} + +void cv::viz::Viz3d::VizImpl::ExitCallback::Execute(vtkObject*, unsigned long event_id, void*) +{ + if (event_id == vtkCommand::ExitEvent) + { + viz->interactor_->TerminateApp(); + viz->interactor_ = 0; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +bool cv::viz::Viz3d::VizImpl::wasStopped() const +{ + bool stopped = spin_once_state_ ? interactor_ == 0 : false; + spin_once_state_ &= !stopped; + return stopped; +} + +void cv::viz::Viz3d::VizImpl::close() +{ + if (!interactor_) + return; + interactor_->GetRenderWindow()->Finalize(); + interactor_->TerminateApp(); // This tends to close the window... +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::spin() +{ + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + interactor_->Start(); + interactor_ = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) +{ + if (interactor_ == 0) + { + spin_once_state_ = true; + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); + interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + } + + vtkSmartPointer local = interactor_; + + if (force_redraw) + local->Render(); + + timer_callback_->timer_id = local->CreateOneShotTimer(std::max(1, time)); + local->Start(); + local->DestroyTimer(timer_callback_->timer_id); + } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -208,19 +252,6 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const return Affine3d(*actor->GetUserMatrix()->Element); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate) -{ - if (interactor_) - interactor_->SetDesiredUpdateRate(rate); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate() -{ - return interactor_ ? interactor_->GetDesiredUpdateRate() : 0.0; -} - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::saveScreenshot(const String &file) { style_->saveScreenshot(file.c_str()); } @@ -231,37 +262,6 @@ void cv::viz::Viz3d::VizImpl::registerMouseCallback(MouseCallback callback, void void cv::viz::Viz3d::VizImpl::registerKeyboardCallback(KeyboardCallback callback, void* cookie) { style_->registerKeyboardCallback(callback, cookie); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spin() -{ - resetStoppedFlag(); - window_->Render(); - interactor_->Start(); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) -{ - resetStoppedFlag(); - - if (time <= 0) - time = 1; - - if (force_redraw) - interactor_->Render(); - - double s_now_ = cv::getTickCount() / cv::getTickFrequency(); - if (s_lastDone_ > s_now_) - s_lastDone_ = s_now_; - - if ((s_now_ - s_lastDone_) > (1.0 / interactor_->GetDesiredUpdateRate())) - { - exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer(time); - interactor_->Start(); - interactor_->DestroyTimer(exit_main_loop_timer_callback_->right_timer_id); - s_lastDone_ = s_now_; - } -} ////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::removeAllWidgets() @@ -282,18 +282,15 @@ void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_siz ///////////////////////////////////////////////////////////////////////////////////////////// bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) { - vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor); - vtkPropCollection* actors = renderer_->GetViewProps(); actors->InitTraversal(); vtkProp* current_actor = NULL; while ((current_actor = actors->GetNextProp()) != NULL) - { - if (current_actor != actor_to_remove) - continue; - renderer_->RemoveActor(actor); - return true; - } + if (current_actor == actor) + { + renderer_->RemoveActor(actor); + return true; + } return false; } @@ -313,11 +310,8 @@ void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Colo renderer_->GradientBackgroundOn(); } -////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ - setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); -} +{ setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) @@ -512,14 +506,8 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) -{ - if (window_) - window_->SetFullScreen(mode); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_ ? window_->GetWindowName() : ""; } +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; } +void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); } void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } -cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } +cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(Point(Vec2i(window_->GetSize()))); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 11b8490a1..1b9abea64 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -55,7 +55,13 @@ public: int ref_counter; VizImpl(const String &name); - virtual ~VizImpl(); + virtual ~VizImpl() {}; + + bool wasStopped() const; + void close(); + + void spin(); + void spinOnce(int time = 1, bool force_redraw = false); void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); @@ -68,26 +74,6 @@ public: void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - - /** \brief Returns true when the user tried to close the window */ - bool wasStopped() const { return interactor_ ? stopped_ : true; } - - /** \brief Set the stopped flag back to false */ - void resetStoppedFlag() { if (interactor_) stopped_ = false; } - - /** \brief Stop the interaction and close the visualizaton window. */ - void close() - { - stopped_ = true; - if (interactor_) - { - interactor_->GetRenderWindow()->Finalize(); - interactor_->TerminateApp(); // This tends to close the window... - } - } - void setRepresentation(int representation); void setCamera(const Camera &camera); @@ -114,72 +100,36 @@ public: void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); - void spin(); - void spinOnce(int time = 1, bool force_redraw = false); - void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); private: - vtkSmartPointer interactor_; - - struct ExitMainLoopTimerCallback : public vtkCommand + struct TimerCallback : public vtkCommand { - static ExitMainLoopTimerCallback* New() { return new ExitMainLoopTimerCallback; } - virtual void Execute(vtkObject* vtkNotUsed(caller), unsigned long event_id, void* call_data) - { - if (event_id != vtkCommand::TimerEvent) - return; - - int timer_id = *reinterpret_cast(call_data); - if (timer_id != right_timer_id) - return; - - // Stop vtk loop and send notification to app to wake it up - viz_->interactor_->TerminateApp(); - } - int right_timer_id; - VizImpl* viz_; + static TimerCallback* New() { return new TimerCallback; } + virtual void Execute(vtkObject* caller, unsigned long event_id, void* cookie); + int timer_id; }; struct ExitCallback : public vtkCommand { static ExitCallback* New() { return new ExitCallback; } - virtual void Execute(vtkObject*, unsigned long event_id, void*) - { - if (event_id == vtkCommand::ExitEvent) - { - viz_->stopped_ = true; - viz_->interactor_->GetRenderWindow()->Finalize(); - viz_->interactor_->TerminateApp(); - } - } - VizImpl* viz_; + virtual void Execute(vtkObject*, unsigned long event_id, void*); + VizImpl* viz; }; - /** \brief Set to false if the interaction loop is running. */ - bool stopped_; + mutable bool spin_once_state_; + vtkSmartPointer interactor_; - double s_lastDone_; + vtkSmartPointer window_; + String window_name_; - /** \brief Global timer ID. Used in destructor only. */ - int timer_id_; - - /** \brief Callback object enabling us to leave the main loop, when a timer fires. */ - vtkSmartPointer exit_main_loop_timer_callback_; + vtkSmartPointer timer_callback_; vtkSmartPointer exit_callback_; vtkSmartPointer renderer_; - vtkSmartPointer window_; - - /** \brief The render window interactor style. */ vtkSmartPointer style_; - - /** \brief Internal list with actor pointers and name IDs for all widget actors */ - cv::Ptr widget_actor_map_; - - /** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ - bool camera_set_; + Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); }; diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ec475580e..dad4aacca 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -236,7 +236,7 @@ TEST(Viz, show_trajectories) viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); viz.spinOnce(20, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_trajectory_reposition) @@ -299,7 +299,7 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } @@ -338,7 +338,7 @@ TEST(Viz, show_image_3d) viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_simple_widgets) @@ -365,7 +365,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); - viz.spinOnce(1500, true); + viz.spin(); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); @@ -379,18 +379,7 @@ TEST(Viz, show_follower) viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); viz.setBackgroundMeshLab(); - viz.spinOnce(1500, true); + viz.spin(); viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } - -TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) -{ - Mesh mesh = Mesh::load(get_dragon_ply_file_path()); - - Viz3d viz("spin_twice"); - viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); - viz.spin(); - viz.spin(); -}