ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VisualizerWithEditing.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <FileSystem.h>
11 #include <HalfEdgeTriangleMesh.h>
12 #include <IJsonConvertibleIO.h>
13 #include <Image.h>
14 #include <LineSet.h>
15 #include <Logging.h>
16 #include <ecvMesh.h>
17 #include <ecvPointCloud.h>
18 #include <tinyfiledialogs/tinyfiledialogs.h>
19 
20 #include "io/PointCloudIO.h"
21 #include "io/TriangleMeshIO.h"
28 
29 namespace cloudViewer {
30 namespace visualization {
31 
33  std::shared_ptr<const ccHObject> geometry_ptr,
34  bool reset_bounding_box) {
35  if (!is_initialized_ || !geometry_ptrs_.empty()) {
36  return false;
37  }
38 
39  glfwMakeContextCurrent(window_);
40  original_geometry_ptr_ = geometry_ptr;
41  if (geometry_ptr->isKindOf(CV_TYPES::CUSTOM_H_OBJECT)) {
42  return false;
43  } else if (geometry_ptr->isKindOf(CV_TYPES::POINT_CLOUD)) {
44  auto ptr = std::make_shared<ccPointCloud>();
45  *ptr = (const ccPointCloud &)*original_geometry_ptr_;
48  std::make_shared<glsl::PointCloudRenderer>();
49  if (!editing_geometry_renderer_ptr_->AddGeometry(
51  return false;
52  }
53  } else if (geometry_ptr->isKindOf(CV_TYPES::LINESET)) {
54  auto ptr = std::make_shared<geometry::LineSet>();
58  std::make_shared<glsl::LineSetRenderer>();
59  if (!editing_geometry_renderer_ptr_->AddGeometry(
61  return false;
62  }
63  } else if (geometry_ptr->isKindOf(CV_TYPES::MESH)) {
64  auto ptr = std::make_shared<ccMesh>(nullptr);
65  *ptr = (const ccMesh &)*original_geometry_ptr_;
68  std::make_shared<glsl::TriangleMeshRenderer>();
69  if (!editing_geometry_renderer_ptr_->AddGeometry(
71  return false;
72  }
73  } else if (geometry_ptr->isKindOf(CV_TYPES::HALF_EDGE_MESH)) {
74  auto ptr = std::make_shared<geometry::HalfEdgeTriangleMesh>();
78  std::make_shared<glsl::HalfEdgeMeshRenderer>();
79  if (!editing_geometry_renderer_ptr_->AddGeometry(
81  return false;
82  }
83  } else if (geometry_ptr->isKindOf(CV_TYPES::IMAGE2)) {
84  auto ptr = std::make_shared<geometry::Image>();
85  *ptr = (const geometry::Image &)*original_geometry_ptr_;
88  std::make_shared<glsl::ImageRenderer>();
89  if (!editing_geometry_renderer_ptr_->AddGeometry(
91  return false;
92  }
93  } else {
94  return false;
95  }
98  if (reset_bounding_box) {
99  ResetViewPoint(true);
100  }
102  "Add geometry and update bounding box to {}",
103  view_control_ptr_->GetBoundingBox().GetPrintInfo().c_str());
104  return UpdateGeometry();
105 }
106 
109  // clang-format off
110  utility::LogInfo(" -- Editing control --");
111  utility::LogInfo(" F : Enter free view mode.");
112  utility::LogInfo(" X : Enter orthogonal view along X axis, press again to flip.");
113  utility::LogInfo(" Y : Enter orthogonal view along Y axis, press again to flip.");
114  utility::LogInfo(" Z : Enter orthogonal view along Z axis, press again to flip.");
115  utility::LogInfo(" K : Lock / unlock camera.");
116  utility::LogInfo(" Ctrl + D : Downsample point cloud with a voxel grid.");
117  utility::LogInfo(" Ctrl + R : reset geometry to its initial state.");
118  utility::LogInfo(" Shift + +/- : Increase/decrease picked point size..");
119  utility::LogInfo(" Shift + mouse left button : Pick a point and add in queue.");
120  utility::LogInfo(" Shift + mouse right button : Remove last picked point from queue.");
121  utility::LogInfo("");
122  utility::LogInfo(" -- When camera is locked --");
123  utility::LogInfo(" Mouse left button + drag : Create a selection rectangle.");
124  utility::LogInfo(" Ctrl + mouse buttons + drag : Hold Ctrl key to draw a selection polygon.");
125  utility::LogInfo(" Left mouse button to add point. Right mouse");
126  utility::LogInfo(" button to remove point. Release Ctrl key to");
127  utility::LogInfo(" close the polygon.");
128  utility::LogInfo(" C : Crop the geometry with selection region.");
129  utility::LogInfo("");
130  // clang-format on
131 }
132 
134  if (window_) {
135  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
136  std::string new_window_title =
137  window_name_ + " - " + view_control.GetStatusString();
138  glfwSetWindowTitle(window_, new_window_title.c_str());
139  }
140 }
141 
144  bool success;
145 
146  // 1. Build selection polygon
147  success = true;
148  selection_polygon_ptr_ = std::make_shared<SelectionPolygon>();
150  std::make_shared<glsl::SelectionPolygonRenderer>();
152  success = false;
153  }
154  if (success) {
157  }
158 
159  // 2. Build pointcloud picker
160  success = true;
161  pointcloud_picker_ptr_ = std::make_shared<PointCloudPicker>();
162  if (geometry_ptrs_.empty() ||
164  success = false;
165  }
167  std::make_shared<glsl::PointCloudPickerRenderer>();
169  success = false;
170  }
171  if (success) {
174  }
175 }
176 
177 int VisualizerWithEditing::PickPoint(double x, double y) {
178  auto renderer_ptr = std::make_shared<glsl::PointCloudPickingRenderer>();
179  if (!renderer_ptr->AddGeometry(editing_geometry_ptr_)) {
180  return -1;
181  }
182  const auto &view = GetViewControl();
183  // Render to FBO and disable anti-aliasing
184  glDisable(GL_MULTISAMPLE);
185  GLuint frame_buffer_name = 0;
186  glGenFramebuffers(1, &frame_buffer_name);
187  glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_name);
188  GLuint fbo_texture;
189  glGenTextures(1, &fbo_texture);
190  glBindTexture(GL_TEXTURE_2D, fbo_texture);
191  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.GetWindowWidth(),
192  view.GetWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
193  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
194  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
195  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
196  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
197  if (!GLEW_ARB_framebuffer_object) {
198  // OpenGL 2.1 doesn't require this, 3.1+ does
200  "[PickPoint] Your GPU does not provide framebuffer objects. "
201  "Use a texture instead.");
202  glBindFramebuffer(GL_FRAMEBUFFER, 0);
203  glEnable(GL_MULTISAMPLE);
204  return -1;
205  }
206  GLuint depth_render_buffer;
207  glGenRenderbuffers(1, &depth_render_buffer);
208  glBindRenderbuffer(GL_RENDERBUFFER, depth_render_buffer);
209  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
210  view.GetWindowWidth(), view.GetWindowHeight());
211  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
212  GL_RENDERBUFFER, depth_render_buffer);
213  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
214  fbo_texture, 0);
215  GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
216  glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
217  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
218  utility::LogWarning("[PickPoint] Something is wrong with FBO.");
219  glBindFramebuffer(GL_FRAMEBUFFER, 0);
220  glEnable(GL_MULTISAMPLE);
221  return -1;
222  }
223  glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_name);
224  view_control_ptr_->SetViewMatrices();
225  glDisable(GL_BLEND);
226  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
227  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
228  glClearDepth(1.0f);
229  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
230  renderer_ptr->Render(GetRenderOption(), GetViewControl());
231  glFinish();
232  uint8_t rgba[4];
233  glReadPixels((int)(x + 0.5), (int)(view.GetWindowHeight() - y + 0.5), 1, 1,
234  GL_RGBA, GL_UNSIGNED_BYTE, rgba);
235  int index = gl_util::ColorCodeToPickIndex(
236  Eigen::Vector4i(rgba[0], rgba[1], rgba[2], rgba[3]));
237  // Recover rendering state
238  glBindFramebuffer(GL_FRAMEBUFFER, 0);
239  glEnable(GL_MULTISAMPLE);
240  return index;
241 }
242 
244  return pointcloud_picker_ptr_->picked_indices_;
245 }
246 
249  std::unique_ptr<ViewControlWithEditing>(new ViewControlWithEditing);
250  ResetViewPoint();
251  return true;
252 }
253 
255  render_option_ptr_ = std::unique_ptr<RenderOptionWithEditing>(
257  return true;
258 }
259 
261  GLFWwindow *window, int key, int scancode, int action, int mods) {
262  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
263  auto &option = (RenderOptionWithEditing &)(*render_option_ptr_);
264  if (action == GLFW_RELEASE) {
265  if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL) {
266  if (view_control.IsLocked() &&
269  selection_polygon_ptr_->polygon_.pop_back();
270  if (selection_polygon_ptr_->IsEmpty()) {
271  selection_polygon_ptr_->Clear();
272  } else {
273  selection_polygon_ptr_->FillPolygon(
274  view_control.GetWindowWidth(),
275  view_control.GetWindowHeight());
276  selection_polygon_ptr_->polygon_type_ =
278  }
279  selection_polygon_renderer_ptr_->UpdateGeometry();
280  is_redraw_required_ = true;
281  }
282  }
283  return;
284  }
285 
286  switch (key) {
287  case GLFW_KEY_F:
288  view_control.SetEditingMode(
289  ViewControlWithEditing::EditingMode::FreeMode);
290  utility::LogDebug("[Visualizer] Enter freeview mode.");
291  break;
292  case GLFW_KEY_X:
293  view_control.ToggleEditingX();
294  utility::LogDebug("[Visualizer] Enter orthogonal X editing mode.");
295  break;
296  case GLFW_KEY_Y:
297  view_control.ToggleEditingY();
298  utility::LogDebug("[Visualizer] Enter orthogonal Y editing mode.");
299  break;
300  case GLFW_KEY_Z:
301  view_control.ToggleEditingZ();
302  utility::LogDebug("[Visualizer] Enter orthogonal Z editing mode.");
303  break;
304  case GLFW_KEY_K:
305  view_control.ToggleLocking();
307  utility::LogDebug("[Visualizer] Camera {:s}.",
308  view_control.IsLocked() ? "Lock" : "Unlock");
309  break;
310  case GLFW_KEY_R:
311  if (mods & GLFW_MOD_CONTROL) {
314  editing_geometry_renderer_ptr_->UpdateGeometry();
315  } else {
316  Visualizer::KeyPressCallback(window, key, scancode, action,
317  mods);
318  }
319  break;
320  case GLFW_KEY_D:
321  if (mods & GLFW_MOD_CONTROL) {
322  if (use_dialog_) {
323  std::string buff;
324  buff = fmt::format("{:.4f}", voxel_size_);
325  const char *str = tinyfd_inputBox(
326  "Set voxel size",
327  "Set voxel size (ignored if it is non-positive)",
328  buff.c_str());
329  if (str == NULL) {
331  "Illegal input, using default voxel size.");
332  } else {
333  char *end;
334  errno = 0;
335  double l = std::strtod(str, &end);
336  if (errno == ERANGE &&
337  (l == HUGE_VAL || l == -HUGE_VAL)) {
339  "Illegal input, using default voxel "
340  "size.");
341  } else {
342  voxel_size_ = l;
343  }
344  }
345  }
346  if (voxel_size_ > 0.0 && editing_geometry_ptr_ &&
348  utility::LogInfo("Voxel downsample with voxel size {:.4f}.",
349  voxel_size_);
351  pcd = *pcd.VoxelDownSample(voxel_size_);
352  UpdateGeometry();
353  } else {
355  "No voxel downsample performed due to illegal "
356  "voxel size.");
357  }
358  } else {
359  Visualizer::KeyPressCallback(window, key, scancode, action,
360  mods);
361  }
362  break;
363  case GLFW_KEY_C:
364  if (view_control.IsLocked() && selection_polygon_ptr_) {
365  if (editing_geometry_ptr_ &&
367  glfwMakeContextCurrent(window_);
369  if (std::shared_ptr<ccPointCloud> pcd_ptr =
370  selection_polygon_ptr_->CropPointCloud(
371  pcd, view_control)) {
372  pcd = *pcd_ptr;
373  } else {
375  "Internal error: CropPointCloud returned "
376  "nullptr.");
377  }
378  editing_geometry_renderer_ptr_->UpdateGeometry();
379  const char *filename;
380  const char *pattern[1] = {"*.ply"};
381  std::string default_filename =
382  default_directory_ + "cropped_" +
383  std::to_string(crop_action_count_ + 1) + ".ply";
384  if (use_dialog_) {
385  filename = tinyfd_saveFileDialog(
386  "ccPointCloud file", default_filename.c_str(),
387  1, pattern, "Polygon File Format (*.ply)");
388  } else {
389  filename = default_filename.c_str();
390  }
391  if (!filename) {
393  "No filename is given. Abort saving.");
394  } else {
397  }
398  view_control.ToggleLocking();
401  } else if (editing_geometry_ptr_ &&
403  glfwMakeContextCurrent(window_);
404  ccMesh &mesh = (ccMesh &)*editing_geometry_ptr_;
405  if (std::shared_ptr<ccMesh> mesh_ptr =
406  selection_polygon_ptr_->CropTriangleMesh(
407  mesh, view_control)) {
408  mesh = *mesh_ptr;
409  } else {
411  "Internal error: CropTriangleMesh returned "
412  "nullptr.");
413  }
414  editing_geometry_renderer_ptr_->UpdateGeometry();
415  const char *filename;
416  const char *pattern[1] = {"*.ply"};
417  std::string default_filename =
418  default_directory_ + "cropped_" +
419  std::to_string(crop_action_count_ + 1) + ".ply";
420  if (use_dialog_) {
421  filename = tinyfd_saveFileDialog(
422  "Mesh file", default_filename.c_str(), 1,
423  pattern, "Polygon File Format (*.ply)");
424  } else {
425  filename = default_filename.c_str();
426  }
427  if (!filename) {
429  "No filename is given. Abort saving.");
430  } else {
433  }
434  view_control.ToggleLocking();
437  }
438  } else {
439  Visualizer::KeyPressCallback(window, key, scancode, action,
440  mods);
441  }
442  break;
443  case GLFW_KEY_MINUS:
444  if (mods & GLFW_MOD_SHIFT) {
445  option.DecreaseSphereSize();
446  } else {
447  Visualizer::KeyPressCallback(window, key, scancode, action,
448  mods);
449  }
450  break;
451  case GLFW_KEY_EQUAL:
452  if (mods & GLFW_MOD_SHIFT) {
453  option.IncreaseSphereSize();
454  } else {
455  Visualizer::KeyPressCallback(window, key, scancode, action,
456  mods);
457  }
458  break;
459  default:
460  Visualizer::KeyPressCallback(window, key, scancode, action, mods);
461  break;
462  }
463  is_redraw_required_ = true;
465 }
466 
468  int w,
469  int h) {
471  Visualizer::WindowResizeCallback(window, w, h);
472 }
473 
475  double x,
476  double y) {
477  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
478  if (view_control.IsLocked()) {
479 #ifdef __APPLE__
480  x /= pixel_to_screen_coordinate_;
481  y /= pixel_to_screen_coordinate_;
482 #endif
483  double y_inv = view_control.GetWindowHeight() - y;
486  selection_polygon_ptr_->polygon_[1](0) = x;
487  selection_polygon_ptr_->polygon_[2](0) = x;
488  selection_polygon_ptr_->polygon_[2](1) = y_inv;
489  selection_polygon_ptr_->polygon_[3](1) = y_inv;
490  selection_polygon_renderer_ptr_->UpdateGeometry();
491  is_redraw_required_ = true;
492  } else if (selection_mode_ == SelectionMode::Polygon) {
493  selection_polygon_ptr_->polygon_.back() = Eigen::Vector2d(x, y_inv);
494  selection_polygon_renderer_ptr_->UpdateGeometry();
495  is_redraw_required_ = true;
496  }
497  } else {
498  Visualizer::MouseMoveCallback(window, x, y);
499  }
500 }
501 
503  double x,
504  double y) {
505  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
506  if (view_control.IsLocked()) {
507  } else {
508  Visualizer::MouseScrollCallback(window, x, y);
509  }
510 }
511 
513  int button,
514  int action,
515  int mods) {
516  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
517  if (view_control.IsLocked() && selection_polygon_ptr_ &&
519  if (button == GLFW_MOUSE_BUTTON_LEFT) {
520  double x, y;
521  glfwGetCursorPos(window, &x, &y);
522 #ifdef __APPLE__
523  x /= pixel_to_screen_coordinate_;
524  y /= pixel_to_screen_coordinate_;
525 #endif
526  if (action == GLFW_PRESS) {
527  double y_inv = view_control.GetWindowHeight() - y;
530  if (mods & GLFW_MOD_CONTROL) {
532  selection_polygon_ptr_->polygon_.push_back(
533  Eigen::Vector2d(x, y_inv));
534  selection_polygon_ptr_->polygon_.push_back(
535  Eigen::Vector2d(x, y_inv));
536  } else {
538  selection_polygon_ptr_->is_closed_ = true;
539  selection_polygon_ptr_->polygon_.push_back(
540  Eigen::Vector2d(x, y_inv));
541  selection_polygon_ptr_->polygon_.push_back(
542  Eigen::Vector2d(x, y_inv));
543  selection_polygon_ptr_->polygon_.push_back(
544  Eigen::Vector2d(x, y_inv));
545  selection_polygon_ptr_->polygon_.push_back(
546  Eigen::Vector2d(x, y_inv));
547  }
548  selection_polygon_renderer_ptr_->UpdateGeometry();
550  } else if (selection_mode_ == SelectionMode::Polygon) {
551  if (mods & GLFW_MOD_CONTROL) {
552  selection_polygon_ptr_->polygon_.back() =
553  Eigen::Vector2d(x, y_inv);
554  selection_polygon_ptr_->polygon_.push_back(
555  Eigen::Vector2d(x, y_inv));
556  selection_polygon_renderer_ptr_->UpdateGeometry();
557  }
558  }
559  } else if (action == GLFW_RELEASE) {
563  selection_polygon_ptr_->FillPolygon(
564  view_control.GetWindowWidth(),
565  view_control.GetWindowHeight());
566  selection_polygon_ptr_->polygon_type_ =
568  selection_polygon_renderer_ptr_->UpdateGeometry();
569  } else if (selection_mode_ == SelectionMode::Polygon) {
570  }
571  }
572  is_redraw_required_ = true;
573  } else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
574  if (action == GLFW_PRESS &&
576  (mods & GLFW_MOD_CONTROL)) {
577  if (selection_polygon_ptr_->polygon_.size() > 2) {
579  ->polygon_[selection_polygon_ptr_->polygon_.size() -
580  2] =
581  selection_polygon_ptr_->polygon_
582  [selection_polygon_ptr_->polygon_.size() -
583  1];
584  selection_polygon_ptr_->polygon_.pop_back();
585  selection_polygon_renderer_ptr_->UpdateGeometry();
586  is_redraw_required_ = true;
587  }
588  }
589  }
590  } else {
591  if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE &&
592  (mods & GLFW_MOD_SHIFT)) {
593  double x, y;
594  glfwGetCursorPos(window, &x, &y);
595 #ifdef __APPLE__
596  x /= pixel_to_screen_coordinate_;
597  y /= pixel_to_screen_coordinate_;
598 #endif
599  int index = PickPoint(x, y);
600  if (index == -1) {
601  utility::LogInfo("No point has been picked.");
602  } else {
603  const auto &point =
604  ((const ccPointCloud &)(*editing_geometry_ptr_))
605  .getEigenPoint(
606  static_cast<unsigned int>(index));
608  "Picked point #{:d} ({:.2}, {:.2}, {:.2}) to add in "
609  "queue.",
610  index, point(0), point(1), point(2));
611  pointcloud_picker_ptr_->picked_indices_.push_back(
612  (size_t)index);
613  is_redraw_required_ = true;
614  }
615  } else if (button == GLFW_MOUSE_BUTTON_RIGHT &&
616  action == GLFW_RELEASE && (mods & GLFW_MOD_SHIFT)) {
617  if (!pointcloud_picker_ptr_->picked_indices_.empty()) {
619  "Remove picked point #{} from pick queue.",
620  pointcloud_picker_ptr_->picked_indices_.back());
621  pointcloud_picker_ptr_->picked_indices_.pop_back();
622  is_redraw_required_ = true;
623  }
624  }
625  Visualizer::MouseButtonCallback(window, button, action, mods);
626  }
627 }
628 
632  selection_polygon_renderer_ptr_->UpdateGeometry();
633  }
635 }
636 
640  pointcloud_picker_renderer_ptr_->UpdateGeometry();
641  }
642 }
643 
645  const std::string &filename /* = ""*/) {
646  std::string ply_filename = filename;
647  if (ply_filename.empty()) {
648  ply_filename = "CroppedGeometry.ply";
649  }
650  std::string volume_filename =
652  ".json";
654  io::WritePointCloud(ply_filename,
655  (const ccPointCloud &)(*editing_geometry_ptr_), {});
656  else if (editing_geometry_ptr_->isKindOf(CV_TYPES::MESH))
657  io::WriteTriangleMesh(ply_filename,
658  (const ccMesh &)(*editing_geometry_ptr_));
660  volume_filename,
661  *selection_polygon_ptr_->CreateSelectionPolygonVolume(
662  GetViewControl()));
663 }
664 
665 } // namespace visualization
666 } // namespace cloudViewer
std::string filename
filament::Texture::InternalFormat format
#define NULL
Triangular mesh.
Definition: ecvMesh.h:35
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
std::shared_ptr< ccPointCloud > VoxelDownSample(double voxel_size)
Function to downsample input ccPointCloud into output ccPointCloud with a voxel.
HalfEdgeTriangleMesh inherits TriangleMesh class with the addition of HalfEdge data structure for eac...
The Image class stores image with customizable width, height, num of channels and bytes per channel.
Definition: Image.h:33
LineSet define a sets of lines in 3D. A typical application is to display the point cloud corresponde...
Definition: LineSet.h:29
void WindowResizeCallback(GLFWwindow *window, int w, int h) override
void SaveCroppingResult(const std::string &filename="")
void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) override
void KeyPressCallback(GLFWwindow *window, int key, int scancode, int action, int mods) override
std::shared_ptr< glsl::GeometryRenderer > editing_geometry_renderer_ptr_
bool InitRenderOption() override
Function to initialize RenderOption.
void MouseScrollCallback(GLFWwindow *window, double x, double y) override
bool InitViewControl() override
Function to initialize ViewControl.
std::shared_ptr< PointCloudPicker > pointcloud_picker_ptr_
std::shared_ptr< const ccHObject > original_geometry_ptr_
std::shared_ptr< glsl::SelectionPolygonRenderer > selection_polygon_renderer_ptr_
std::shared_ptr< SelectionPolygon > selection_polygon_ptr_
void MouseMoveCallback(GLFWwindow *window, double x, double y) override
bool AddGeometry(std::shared_ptr< const ccHObject > geometry_ptr, bool reset_bounding_box=true) override
Function to add geometry to the scene and create corresponding shaders.
std::shared_ptr< glsl::PointCloudPickerRenderer > pointcloud_picker_renderer_ptr_
virtual bool UpdateGeometry(std::shared_ptr< const ccHObject > geometry_ptr=nullptr)
Function to update geometry.
Definition: Visualizer.cpp:466
virtual void KeyPressCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
std::vector< std::shared_ptr< glsl::GeometryRenderer > > utility_renderer_ptrs_
Definition: Visualizer.h:297
RenderOption & GetRenderOption()
Function to retrieve the associated RenderOption.
Definition: Visualizer.h:177
virtual void MouseScrollCallback(GLFWwindow *window, double x, double y)
std::unordered_set< std::shared_ptr< const ccHObject > > geometry_ptrs_
Definition: Visualizer.h:287
virtual void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
std::unique_ptr< RenderOption > render_option_ptr_
Definition: Visualizer.h:284
virtual void MouseMoveCallback(GLFWwindow *window, double x, double y)
void ResetViewPoint(bool reset_bounding_box=false)
Function to reset view point.
std::unordered_set< std::shared_ptr< glsl::GeometryRenderer > > geometry_renderer_ptrs_
Definition: Visualizer.h:291
std::unique_ptr< ViewControl > view_control_ptr_
Definition: Visualizer.h:281
ViewControl & GetViewControl()
Function to retrieve the associated ViewControl.
Definition: Visualizer.h:175
virtual void WindowResizeCallback(GLFWwindow *window, int w, int h)
std::vector< std::shared_ptr< const ccHObject > > utility_ptrs_
Definition: Visualizer.h:294
ccMesh * mesh_ptr
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
#define LogError(...)
Definition: Logging.h:60
#define LogDebug(...)
Definition: Logging.h:90
@ CUSTOM_H_OBJECT
Definition: CVTypes.h:179
@ HALF_EDGE_MESH
Definition: CVTypes.h:150
@ MESH
Definition: CVTypes.h:105
@ POINT_CLOUD
Definition: CVTypes.h:104
@ LINESET
Definition: CVTypes.h:152
@ IMAGE2
Definition: CVTypes.h:156
bool WriteIJsonConvertible(const std::string &filename, const cloudViewer::utility::IJsonConvertible &object)
bool WriteTriangleMesh(const std::string &filename, const ccMesh &mesh, bool write_ascii, bool compressed, bool write_vertex_normals, bool write_vertex_colors, bool write_triangle_uvs, bool print_progress)
bool WritePointCloud(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption &params)
std::string GetFileNameWithoutExtension(const std::string &filename)
Definition: FileSystem.cpp:295
int ColorCodeToPickIndex(const Eigen::Vector4i &color)
Definition: GLHelper.cpp:113
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 4, 1 > Vector4i
Definition: knncpp.h:31
std::string to_string(const T &n)
Definition: Common.h:20
Definition: lsd.c:149