// ---------------------------------------------------------------------------- // - Open3D: www.open3d.org - // ---------------------------------------------------------------------------- // Copyright (c) 2018-2023 www.open3d.org // SPDX-License-Identifier: MIT // ---------------------------------------------------------------------------- #pragma once // Avoid warning caused by redefinition of APIENTRY macro // defined also in glfw3.h #ifdef _WIN32 #include #endif #include #include #include #include #include #include #include #include "open3d/geometry/Geometry.h" #include "open3d/visualization/shader/GeometryRenderer.h" #include "open3d/visualization/utility/ColorMap.h" #include "open3d/visualization/visualizer/RenderOption.h" #include "open3d/visualization/visualizer/ViewControl.h" namespace open3d { namespace geometry { class TriangleMesh; class Image; } // namespace geometry namespace visualization { class GLFWContext; /// \class Visualizer /// /// \brief The main Visualizer class. class Visualizer { public: struct MouseControl { public: bool is_mouse_left_button_down = false; bool is_mouse_middle_button_down = false; bool is_control_key_down = false; bool is_shift_key_down = false; bool is_alt_key_down = false; bool is_super_key_down = false; double mouse_position_x = 0.0; double mouse_position_y = 0.0; }; public: Visualizer(); virtual ~Visualizer(); Visualizer(Visualizer &&) = delete; Visualizer(const Visualizer &) = delete; Visualizer &operator=(const Visualizer &) = delete; public: /// \brief Function to create a window and initialize GLFW. /// /// This function MUST be called from the main thread. /// /// \param window_name Window title name. /// \param width Width of the window. /// \param height Height of window. /// \param left Left margin of the window to the screen. /// \param top Top margin of the window to the screen. /// \param visible Whether the window is visible. bool CreateVisualizerWindow(const std::string &window_name = "Open3D", const int width = 640, const int height = 480, const int left = 50, const int top = 50, const bool visible = true); /// \brief Function to destroy a window. /// /// This function MUST be called from the main thread. void DestroyVisualizerWindow(); /// \brief Function to register a callback function for animation. /// /// The callback function returns if UpdateGeometry() needs to be run. /// /// \param callback_func The call back function. void RegisterAnimationCallback( std::function callback_func); /// \brief Function to activate the window. /// /// This function will block the current thread until the window is closed. void Run(); /// Function to to notify the window to be closed void Close(); /// \brief Function to process the event queue and return if the window is /// closed. /// /// Use this function if you want to manage the while loop yourself. This /// function will block the thread. bool WaitEvents(); /// Function to process the event queue and return if the window is closed. /// /// Use this function if you want to manage the while loop yourself. This /// function will NOT block the thread. Thus it is suitable for computation /// heavy task behind the scene. bool PollEvents(); /// \brief Function to add geometry to the scene and create corresponding /// shaders. /// /// 1. After calling this function, the Visualizer owns the geometry object. /// 2. This function MUST be called after CreateVisualizerWindow(). /// 3. This function returns FALSE when the geometry is of an unsupported /// type. /// 4. If an added geometry is changed, the behavior of Visualizer is /// undefined. Programmers are responsible for calling Geometry() to /// notify the Visualizer that the geometry has been changed and the /// Visualizer should be updated accordingly. /// /// \param geometry_ptr The Geometry object. /// \param reset_bounding_box Reset viewpoint to view all geometries. virtual bool AddGeometry( std::shared_ptr geometry_ptr, bool reset_bounding_box = true); /// \brief Function to remove geometry from the scene. /// /// 1. After calling this function, the Visualizer releases the pointer of /// the geometry object. /// 2. This function MUST be called after CreateVisualizerWindow(). /// 3. This function returns FALSE if the geometry to be removed is not /// added by AddGeometry /// /// \param geometry_ptr The Geometry object. /// \param reset_bounding_box Reset viewpoint to view all geometries. virtual bool RemoveGeometry( std::shared_ptr geometry_ptr, bool reset_bounding_box = true); /// Function to remove all geometries from the scene. /// After calling this function, the Visualizer releases the pointer of /// all geometry objects. virtual bool ClearGeometries(); /// \brief Function to update geometry. /// /// This function must be called when geometry has been changed. Otherwise /// the behavior of Visualizer is undefined. /// If called without an argument, updates all geometries, otherwise only /// updates the geometry specified. virtual bool UpdateGeometry( std::shared_ptr geometry_ptr = nullptr); virtual bool HasGeometry() const; /// Function to inform render needed to be updated. virtual void UpdateRender(); /// Functions to change between fullscreen and windowed modes virtual void SetFullScreen(bool fullscreen); virtual void ToggleFullScreen(); virtual bool IsFullScreen(); virtual void PrintVisualizerHelp(); virtual void UpdateWindowTitle(); virtual void BuildUtilities(); /// Function to retrieve the associated ViewControl ViewControl &GetViewControl() { return *view_control_ptr_; } /// Function to retrieve the associated RenderOption. RenderOption &GetRenderOption() { return *render_option_ptr_; } /// \brief Function to capture screen and store RGB in a float buffer. /// /// \param do_render Set to `true` to do render. std::shared_ptr CaptureScreenFloatBuffer( bool do_render = true); /// \brief Function to capture and save a screen image. /// /// \param filename Path to file. /// \param do_render Set to `true` to do render. void CaptureScreenImage(const std::string &filename = "", bool do_render = true); /// Function to capture depth in a float buffer. /// /// \param do_render Set to `true` to do render. std::shared_ptr CaptureDepthFloatBuffer( bool do_render = true); /// Function to capture and save a depth image. /// /// \param filename Path to file. /// \param do_render Set to `true` to do render. /// \param depth_scale Scale depth value when capturing the depth image. void CaptureDepthImage(const std::string &filename = "", bool do_render = true, double depth_scale = 1000.0); /// \brief Function to capture and save local point cloud. /// /// \param filename Path to file. /// \param do_render Set to `true` to do render. /// \param convert_to_world_coordinate Set to `true` to convert to world /// coordinates. void CaptureDepthPointCloud(const std::string &filename = "", bool do_render = true, bool convert_to_world_coordinate = false); void CaptureRenderOption(const std::string &filename = ""); /// Function to reset view point. void ResetViewPoint(bool reset_bounding_box = false); const std::string &GetWindowName() const { return window_name_; } /// Get the current view status as a json string of ViewTrajectory. std::string GetViewStatus(); /// Set the current view status from a json string of ViewTrajectory. void SetViewStatus(const std::string &view_status_str); protected: /// Function to initialize OpenGL virtual bool InitOpenGL(); /// Function to initialize ViewControl virtual bool InitViewControl(); /// Function to initialize RenderOption virtual bool InitRenderOption(); /// Function to do the main rendering /// The function first sets view point, then draw geometry (pointclouds and /// meshes individually). virtual void Render(bool render_screen = false); /// Copy the current view status to clipboard. void CopyViewStatusToClipboard(); /// Apply the view point from clipboard. void CopyViewStatusFromClipboard(); /// Callback functions virtual void WindowRefreshCallback(GLFWwindow *window); virtual void WindowResizeCallback(GLFWwindow *window, int w, int h); virtual void MouseMoveCallback(GLFWwindow *window, double x, double y); virtual void MouseScrollCallback(GLFWwindow *window, double x, double y); virtual void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); virtual void KeyPressCallback( GLFWwindow *window, int key, int scancode, int action, int mods); /// \brief Function to notify the window to be closed. virtual void WindowCloseCallback(GLFWwindow *window); protected: // window GLFWwindow *window_ = NULL; std::string window_name_ = "Open3D"; /// \brief Shared GLFW context. std::shared_ptr glfw_context_ = nullptr; Eigen::Vector2i saved_window_size_ = Eigen::Vector2i::Zero(); Eigen::Vector2i saved_window_pos_ = Eigen::Vector2i::Zero(); std::function animation_callback_func_ = nullptr; // Auxiliary internal backup of the callback function. // It copies animation_callback_func_ in each PollEvent() or WaitEvent() // so that even if user calls RegisterAnimationCallback() within the // callback function it is still safe. std::function animation_callback_func_in_loop_ = nullptr; // control MouseControl mouse_control_; bool is_redraw_required_ = true; bool is_initialized_ = false; GLuint vao_id_ = 0; // render targets for "capture_screen_float_buffer" and // "capture_screen_image" in offscreen render mode GLuint render_fbo_ = 0; GLuint render_rgb_tex_ = 0; GLuint render_depth_stencil_rbo_ = 0; // view control std::unique_ptr view_control_ptr_; // rendering properties std::unique_ptr render_option_ptr_; // geometry to be rendered std::unordered_set> geometry_ptrs_; // geometry renderers std::unordered_set> geometry_renderer_ptrs_; // utilities owned by the Visualizer std::vector> utility_ptrs_; // utility renderers std::vector> utility_renderer_ptrs_; // map's key is the renderer for which the RenderOption applies // (should be something in utility_renderer_ptrs_) std::unordered_map, RenderOption> utility_renderer_opts_; // coordinate frame std::shared_ptr coordinate_frame_mesh_ptr_; std::shared_ptr coordinate_frame_mesh_renderer_ptr_; #ifdef __APPLE__ // MacBook with Retina display does not have a 1:1 mapping from screen // coordinates to pixels. Thus we hack it back. // http://www.glfw.org/faq.html#why-is-my-output-in-the-lower-left-corner-of-the-window double pixel_to_screen_coordinate_ = 1.0; #endif //__APPLE__ }; } // namespace visualization } // namespace open3d