332 lines
13 KiB
C
332 lines
13 KiB
C
![]() |
// ----------------------------------------------------------------------------
|
||
|
// - 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 <windows.h>
|
||
|
#endif
|
||
|
|
||
|
#include <GL/glew.h>
|
||
|
#include <GLFW/glfw3.h>
|
||
|
|
||
|
#include <Eigen/Core>
|
||
|
#include <memory>
|
||
|
#include <string>
|
||
|
#include <unordered_map>
|
||
|
#include <unordered_set>
|
||
|
|
||
|
#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<bool(Visualizer *)> 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<const geometry::Geometry> 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<const geometry::Geometry> 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<const geometry::Geometry> 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<geometry::Image> 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<geometry::Image> 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<GLFWContext> glfw_context_ = nullptr;
|
||
|
|
||
|
Eigen::Vector2i saved_window_size_ = Eigen::Vector2i::Zero();
|
||
|
Eigen::Vector2i saved_window_pos_ = Eigen::Vector2i::Zero();
|
||
|
std::function<bool(Visualizer *)> 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<bool(Visualizer *)> 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<ViewControl> view_control_ptr_;
|
||
|
|
||
|
// rendering properties
|
||
|
std::unique_ptr<RenderOption> render_option_ptr_;
|
||
|
|
||
|
// geometry to be rendered
|
||
|
std::unordered_set<std::shared_ptr<const geometry::Geometry>>
|
||
|
geometry_ptrs_;
|
||
|
|
||
|
// geometry renderers
|
||
|
std::unordered_set<std::shared_ptr<glsl::GeometryRenderer>>
|
||
|
geometry_renderer_ptrs_;
|
||
|
|
||
|
// utilities owned by the Visualizer
|
||
|
std::vector<std::shared_ptr<const geometry::Geometry>> utility_ptrs_;
|
||
|
|
||
|
// utility renderers
|
||
|
std::vector<std::shared_ptr<glsl::GeometryRenderer>> utility_renderer_ptrs_;
|
||
|
// map's key is the renderer for which the RenderOption applies
|
||
|
// (should be something in utility_renderer_ptrs_)
|
||
|
std::unordered_map<std::shared_ptr<glsl::GeometryRenderer>, RenderOption>
|
||
|
utility_renderer_opts_;
|
||
|
|
||
|
// coordinate frame
|
||
|
std::shared_ptr<geometry::TriangleMesh> coordinate_frame_mesh_ptr_;
|
||
|
std::shared_ptr<glsl::CoordinateFrameRenderer>
|
||
|
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
|