ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VisualizerWithVertexSelection.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 <ecvHObjectCaster.h>
17 #include <ecvMesh.h>
18 #include <ecvPointCloud.h>
19 #include <ecvTetraMesh.h>
20 #include <tinyfiledialogs/tinyfiledialogs.h>
21 
22 #include "io/PointCloudIO.h"
23 #include "io/TriangleMeshIO.h"
30 
31 namespace cloudViewer {
32 namespace visualization {
33 
34 namespace {
35 static const double POINT_SIZE = 9.0;
36 static const double MIN_POINT_SIZE = 3.0;
37 static const Eigen::Vector3d CHOOSE_POINTS_COLOR(1, 0, 1);
38 static const Eigen::Vector3d SELECTED_POINTS_COLOR(0, 1, 0);
39 static const int START_RECT_DIST = 3;
40 
41 bool BindFramebuffer(int width, int height) {
42  GLuint frame_buffer_name = 0;
43  glGenFramebuffers(1, &frame_buffer_name);
44  glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_name);
45  GLuint fbo_texture;
46  glGenTextures(1, &fbo_texture);
47  glBindTexture(GL_TEXTURE_2D, fbo_texture);
48  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
49  GL_UNSIGNED_BYTE, 0);
50  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
51  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
52  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
53  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
54  if (!GLEW_ARB_framebuffer_object) {
55  // OpenGL 2.1 doesn't require this, 3.1+ does
57  "[BindFramebuffwer] Your GPU does not provide framebuffer "
58  "objects. "
59  "Use a texture instead.");
60  return false;
61  }
62  GLuint depth_render_buffer;
63  glGenRenderbuffers(1, &depth_render_buffer);
64  glBindRenderbuffer(GL_RENDERBUFFER, depth_render_buffer);
65  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
66  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
67  GL_RENDERBUFFER, depth_render_buffer);
68  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
69  fbo_texture, 0);
70  GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
71  glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
72  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
73  utility::LogWarning("[BindFramebuffer] Something is wrong with FBO.");
74  return false;
75  }
76  return true;
77 }
78 
79 } // namespace
80 
81 using namespace cloudViewer;
83  std::shared_ptr<const ccHObject> geometry_in_ptr,
84  bool reset_bounding_box) {
85  if (!is_initialized_ || !geometry_ptrs_.empty()) {
87  "VisualizerWithVertexSelection only supports one geometry");
88  return false;
89  }
90  glfwMakeContextCurrent(window_);
91 
92  // Add the geometry/renderer
93  geometry_ptr_ = geometry_in_ptr;
94  switch (geometry_ptr_->getClassID()) {
97  std::make_shared<glsl::PointCloudRenderer>();
98  break;
99  case CV_TYPES::LINESET:
100  geometry_renderer_ptr_ = std::make_shared<glsl::LineSetRenderer>();
101  break;
102  case CV_TYPES::MESH: // fall-through
104  std::make_shared<glsl::TriangleMeshRenderer>();
105  break;
108  std::make_shared<glsl::HalfEdgeMeshRenderer>();
109  break;
112  std::make_shared<glsl::TetraMeshRenderer>();
113  break;
114  case CV_TYPES::IMAGE2:
115  geometry_renderer_ptr_ = std::make_shared<glsl::ImageRenderer>();
116  break;
118  // MeshBase is too general, can't render. Fall-through.
123  case CV_TYPES::BBOX:
124  case CV_TYPES::MESH_BASE:
125  // MeshBase is too general, can't render. Fall-through.
127  return false;
128  }
129 
130  if (!geometry_renderer_ptr_->AddGeometry(geometry_ptr_)) {
131  return false;
132  }
135 
136  // Add the point selection renderers
137  ui_points_geometry_ptr_ = std::make_shared<ccPointCloud>();
138  ui_points_renderer_ptr_ = std::make_shared<glsl::PointCloudRenderer>();
140  ui_selected_points_geometry_ptr_ = std::make_shared<ccPointCloud>();
142  std::make_shared<glsl::PointCloudRenderer>();
146 
151  SetPointSize(POINT_SIZE);
152 
153  if (reset_bounding_box) {
154  ResetViewPoint(true);
155  }
157  "Add geometry and update bounding box to {}",
158  view_control_ptr_->GetBoundingBox().GetPrintInfo().c_str());
159  return UpdateGeometry();
160 }
161 
163  std::shared_ptr<const ccHObject> geometry_ptr /*= nullptr*/) {
164  if (geometry_ptr) {
166  "VisualizerWithVertexSelection::UpdateGeometry() does not "
167  "support "
168  "passing a new geometry. However, you may update the geometry "
169  "you"
170  "passed to AddGeometry() and call UpdateGeometry().");
171  return false;
172  }
173  geometry_ptr = geometry_ptr_;
174 
175  bool result = Visualizer::UpdateGeometry(geometry_ptr);
176 
177  switch (geometry_ptr_->getClassID()) {
178  case CV_TYPES::POINT_CLOUD: {
179  auto cloud =
180  std::static_pointer_cast<const ccPointCloud>(geometry_ptr_);
181  if (cloud->size() !=
184  }
185  ui_points_geometry_ptr_->reserveThePointsTable(cloud->size());
186  ui_points_geometry_ptr_->addPoints(cloud->getPoints());
187  if (cloud->hasNormals()) {
188  if (!ui_points_geometry_ptr_->hasNormals()) {
189  ui_points_geometry_ptr_->reserveTheNormsTable();
190  }
191  ui_points_geometry_ptr_->addNorms(cloud->getPointNormals());
192  }
193 
194  break;
195  }
196  case CV_TYPES::LINESET: {
197  auto lines = std::static_pointer_cast<const geometry::LineSet>(
198  geometry_ptr_);
199  if (lines->points_.size() !=
202  }
203  ui_points_geometry_ptr_->addPoints(lines->points_);
204  break;
205  }
206  case CV_TYPES::MESH: {
207  auto mesh = std::static_pointer_cast<const ccMesh>(geometry_ptr_);
208  ccPointCloud *cloud =
209  ccHObjectCaster::ToPointCloud(mesh->getAssociatedCloud());
210  assert(cloud);
211  if (cloud->size() !=
214  }
215  ui_points_geometry_ptr_->clear();
216  ui_points_geometry_ptr_->append(cloud, 0);
217  break;
218  }
221  auto mesh = std::static_pointer_cast<const geometry::ecvMeshBase>(
222  geometry_ptr_);
223  if (mesh->vertices_.size() !=
226  }
227  ui_points_geometry_ptr_->clear();
228  ui_points_geometry_ptr_->addPoints(mesh->vertices_);
229  ui_points_geometry_ptr_->addEigenNorms(mesh->vertex_normals_);
230  break;
231  }
232  case CV_TYPES::IMAGE2:
237  case CV_TYPES::BBOX:
239  break;
240  }
241 
242  ui_points_geometry_ptr_->PaintUniformColor(CHOOSE_POINTS_COLOR);
243  ui_points_renderer_ptr_->UpdateGeometry();
244 
245  geometry_renderer_ptr_->UpdateGeometry();
246 
247  return result;
248 }
249 
252  // clang-format off
253  utility::LogInfo(" -- Editing control --");
254  utility::LogInfo(" X : Enter orthogonal view along X axis, press again to flip.");
255  utility::LogInfo(" Y : Enter orthogonal view along Y axis, press again to flip.");
256  utility::LogInfo(" Z : Enter orthogonal view along Z axis, press again to flip.");
257  utility::LogInfo(" Ctrl + R : Clear selection.");
258  utility::LogInfo(" Shift + +/- : Increase/decrease picked point size.");
259  utility::LogInfo(" Shift + mouse left button : Pick a point and add to selection. If it is");
260  utility::LogInfo(" already in the selection it will be removed.");
261  utility::LogInfo(" Shift + mouse left drag : Defines a rectangle, which will add all the ");
262  utility::LogInfo(" points in it to the selection.");
263  utility::LogInfo(" mouse right drag : Moves selected points.");
264  utility::LogInfo(" Delete / Backspace : Removes all points in the rectangle from the");
265  utility::LogInfo(" selection.");
266  utility::LogInfo("");
267  // clang-format on
268 }
269 
271  if (window_) {
272  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
273  auto title = window_name_ + " - " + view_control.GetStatusString();
274  glfwSetWindowTitle(window_, title.c_str());
275  }
276 }
277 
280  bool success;
281 
282  // 1. Build selection polygon
283  success = true;
284  selection_polygon_ptr_ = std::make_shared<SelectionPolygon>();
286  std::make_shared<glsl::SelectionPolygonRenderer>();
288  success = false;
289  }
290  if (success) {
293  }
294 
295  // 2. Build pointcloud picker
296  success = true;
297  pointcloud_picker_ptr_ = std::make_shared<PointCloudPicker>();
298  if (geometry_ptrs_.empty() ||
299  !pointcloud_picker_ptr_->SetPointCloud(geometry_ptr_)) {
300  success = false;
301  }
303  std::make_shared<glsl::PointCloudPickerRenderer>();
305  success = false;
306  }
307  if (success) {
310  }
311 }
312 
313 float VisualizerWithVertexSelection::GetDepth(int winX, int winY) {
314  const auto &view = GetViewControl();
315 
316  // Render to FBO
317  if (!BindFramebuffer(view.GetWindowWidth(), view.GetWindowHeight())) {
318  glBindFramebuffer(GL_FRAMEBUFFER, 0);
319  return {};
320  }
321 
322  view_control_ptr_->SetViewMatrices();
323  // We only need the depth information, so reduce time rendering colors
324  glDisable(GL_MULTISAMPLE);
325  glDisable(GL_BLEND);
326  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
327  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
328  glClearDepth(1.0f);
329  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
330 
331  for (auto &renderer : geometry_renderer_ptrs_) {
332  renderer->Render(GetRenderOption(), GetViewControl());
333  }
334  glFinish();
335 
336  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
337  glEnable(GL_MULTISAMPLE);
338 
339  // glReadPixels uses GL coordinates: (x, y) is lower left and +y is up
340  int width = 1;
341  int height = 1;
342  int lowerLeftX = int(winX + 0.5);
343  int lowerLeftY = int(view.GetWindowHeight() - winY - height + 0.5);
344 
345  float depth;
346  glReadPixels(lowerLeftX, lowerLeftY, width, height, GL_DEPTH_COMPONENT,
347  GL_FLOAT, &depth);
348 
349  glBindFramebuffer(GL_FRAMEBUFFER, 0);
350  return depth;
351 }
352 
353 std::vector<int> VisualizerWithVertexSelection::PickPoints(double winX,
354  double winY,
355  double w,
356  double h) {
357  points_in_rect_.clear();
358 
359  auto renderer_ptr = std::make_shared<glsl::PointCloudPickingRenderer>();
360  if (!renderer_ptr->AddGeometry(ui_points_geometry_ptr_)) {
361  return {};
362  }
363  const auto &view = GetViewControl();
364  // Render to FBO
365  if (!BindFramebuffer(view.GetWindowWidth(), view.GetWindowHeight())) {
366  glBindFramebuffer(GL_FRAMEBUFFER, 0);
367  return {};
368  }
369 
370  view_control_ptr_->SetViewMatrices();
371  glDisable(GL_MULTISAMPLE); // we need pixelation for correct pick colors
372  glDisable(GL_BLEND);
373  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
374  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
375  glClearDepth(1.0f);
376  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
377 
378  // Render any triangle meshes to the depth buffer only (so that z-buffer
379  // prevents points that are behind them being drawn for selection)
380  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
381  for (auto &renderer : geometry_renderer_ptrs_) {
382  if (renderer->GetGeometry()->isKindOf(CV_TYPES::MESH)) {
383  renderer->Render(GetRenderOption(), GetViewControl());
384  }
385  }
386  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
387 
388  // Now render the points
389  renderer_ptr->Render(pick_point_opts_, GetViewControl());
390 
391  glFinish();
392 
393  // glReadPixels uses GL coordinates: (x, y) is lower left and +y is up
394  int width = int(std::ceil(w));
395  int height = int(std::ceil(h));
396  int lowerLeftX = int(winX + 0.5);
397  int lowerLeftY = int(view.GetWindowHeight() - winY - height + 0.5);
398  std::vector<uint8_t> rgba(4 * width * height, 0);
399 
400  glReadPixels(lowerLeftX, lowerLeftY, width, height, GL_RGBA,
401  GL_UNSIGNED_BYTE, rgba.data());
402  // Recover rendering state
403  glBindFramebuffer(GL_FRAMEBUFFER, 0);
404  glEnable(GL_MULTISAMPLE);
405 
406  std::unordered_set<int> indexSet;
407  for (int i = 0; i < width * height; ++i) {
408  const uint8_t *rgbaPtr = rgba.data() + 4 * i;
410  rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]));
411  if (index >= 0) {
412  indexSet.insert(index);
413  }
414  }
415 
416  std::vector<int> indices;
417  indices.reserve(indexSet.size());
418  for (int idx : indexSet) {
419  indices.push_back(idx);
420  }
421  points_in_rect_ = indices;
422  return indices;
423 }
424 
425 std::vector<VisualizerWithVertexSelection::PickedPoint>
427  std::vector<PickedPoint> points;
428  points.reserve(selected_points_.size());
429  for (auto &kv : selected_points_) {
430  points.push_back({kv.first, kv.second});
431  }
432  return points;
433 }
434 
437  std::unique_ptr<ViewControlWithEditing>(new ViewControlWithEditing);
438  ResetViewPoint();
439  return true;
440 }
441 
443  render_option_ptr_ = std::unique_ptr<RenderOptionWithEditing>(
445  return true;
446 }
447 
449  std::function<void()> f) {
451 }
452 
454  std::function<void()> f) {
456 }
457 
459  std::function<void()> f) {
461 }
462 
464  int w,
465  int h) {
467  Visualizer::WindowResizeCallback(window, w, h);
468 }
469 
471  GLFWwindow *window, int key, int scancode, int action, int mods) {
472  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
473  if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT) {
474  if (action == GLFW_PRESS) {
477  }
478  is_redraw_required_ = true;
479  } else if (action == GLFW_RELEASE) {
481  for (size_t i = 0; i < utility_renderer_ptrs_.size();) {
484  utility_renderer_ptrs_.begin() + i);
485  is_redraw_required_ = true;
486  } else {
487  ++i;
488  }
489  }
490  }
491  } else if ((key == GLFW_KEY_DELETE || key == GLFW_KEY_BACKSPACE) &&
492  action == GLFW_RELEASE) {
495  is_redraw_required_ = true;
496  }
497 
498  switch (key) {
499  case GLFW_KEY_X:
500  view_control.ToggleEditingX();
501  utility::LogDebug("[Visualizer] Enter orthogonal X editing mode.");
502  break;
503  case GLFW_KEY_Y:
504  view_control.ToggleEditingY();
505  utility::LogDebug("[Visualizer] Enter orthogonal Y editing mode.");
506  break;
507  case GLFW_KEY_Z:
508  view_control.ToggleEditingZ();
509  utility::LogDebug("[Visualizer] Enter orthogonal Z editing mode.");
510  break;
511  case GLFW_KEY_R:
512  if (mods & GLFW_MOD_CONTROL) {
514  ui_selected_points_geometry_ptr_->PaintUniformColor(
515  SELECTED_POINTS_COLOR);
516  ui_selected_points_renderer_ptr_->UpdateGeometry();
517  is_redraw_required_ = true;
518  } else {
519  Visualizer::KeyPressCallback(window, key, scancode, action,
520  mods);
521  }
522  break;
523  case GLFW_KEY_MINUS: {
524  if (action == GLFW_PRESS) {
526  is_redraw_required_ = true;
527  } else {
528  Visualizer::KeyPressCallback(window, key, scancode, action,
529  mods);
530  }
531  break;
532  }
533  case GLFW_KEY_EQUAL: {
534  if (action == GLFW_PRESS) {
536  is_redraw_required_ = true;
537  } else {
538  Visualizer::KeyPressCallback(window, key, scancode, action,
539  mods);
540  }
541  break;
542  }
543  default:
544  Visualizer::KeyPressCallback(window, key, scancode, action, mods);
545  break;
546  }
547  is_redraw_required_ = true;
549 }
550 
552  double x,
553  double y) {
554  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
556 #ifdef __APPLE__
557  x /= pixel_to_screen_coordinate_;
558  y /= pixel_to_screen_coordinate_;
559 #endif
560  double y_inv = view_control.GetWindowHeight() - y;
562  std::abs(x - mouse_down_pos_.x()) > START_RECT_DIST &&
563  std::abs(y - mouse_down_pos_.y()) > START_RECT_DIST) {
566  selection_polygon_ptr_->is_closed_ = true;
567  Eigen::Vector2d pt(x, y_inv);
568  selection_polygon_ptr_->polygon_.push_back(pt);
569  selection_polygon_ptr_->polygon_.push_back(pt);
570  selection_polygon_ptr_->polygon_.push_back(pt);
571  selection_polygon_ptr_->polygon_.push_back(pt);
572  selection_polygon_renderer_ptr_->UpdateGeometry();
574  selection_polygon_ptr_->polygon_[1](0) = x;
575  selection_polygon_ptr_->polygon_[2](0) = x;
576  selection_polygon_ptr_->polygon_[2](1) = y_inv;
577  selection_polygon_ptr_->polygon_[3](1) = y_inv;
578  selection_polygon_renderer_ptr_->UpdateGeometry();
579  } else if (selection_mode_ == SelectionMode::Moving) {
581  }
582  is_redraw_required_ = true;
583  } else {
584  Visualizer::MouseMoveCallback(window, x, y);
585  }
586 }
587 
589  double x,
590  double y) {
591  Visualizer::MouseScrollCallback(window, x, y);
592 }
593 
595  int button,
596  int action,
597  int mods) {
598  double x, y;
599  glfwGetCursorPos(window, &x, &y);
600 #ifdef __APPLE__
601  x /= pixel_to_screen_coordinate_;
602  y /= pixel_to_screen_coordinate_;
603 #endif
604 
605  if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
606  if (mods & GLFW_MOD_SHIFT) {
608  mouse_down_pos_ = {x, y};
609  } else {
610  Visualizer::MouseButtonCallback(window, button, action, mods);
611  }
612  } else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
614  auto indices = PickPoints(x, y, 1, 1);
615  if (indices.empty()) {
616  utility::LogInfo("No point has been picked.");
617  } else {
618  int index = indices[0];
619  if (selected_points_.find(index) == selected_points_.end()) {
620  AddPickedPoints({index});
621  } else {
622  RemovePickedPoints({index});
623  }
624  }
625  is_redraw_required_ = true;
627  auto &view_control = (ViewControlWithEditing &)(*view_control_ptr_);
628  auto winHeight = view_control.GetWindowHeight();
629  x = selection_polygon_ptr_->polygon_[0](0);
630  y = winHeight - selection_polygon_ptr_->polygon_[0](1);
631  double x2 = selection_polygon_ptr_->polygon_[2](0);
632  double y2 = winHeight - selection_polygon_ptr_->polygon_[2](1);
633  double w = x2 - x;
634  double h = y2 - y;
635  if (w < 0) {
636  x += w; // w is negative
637  w = -w;
638  }
639  if (h < 0) {
640  y += h; // h is negative
641  h = -h;
642  }
643  auto indices = PickPoints(x, y, w, h);
644  if (indices.empty()) {
645  utility::LogInfo("No points have been picked.");
646  } else {
647  AddPickedPoints(indices);
648  }
649  is_redraw_required_ = true;
650  } else {
651  Visualizer::MouseButtonCallback(window, button, action, mods);
652  }
655  }
657  } else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) {
658  mouse_down_pos_ = {x, y};
661  // The mouse moves on the viewing plane, but we want it to look like
662  // we are moving the point we clicked on. One pixel on the viewing
663  // plane is a larger distance than one pixel projected onto the
664  // viewing plane because perspective shrinks things as they get
665  // farther away.
666  auto depth = GetDepth(static_cast<int>(x), static_cast<int>(y));
667  // If we clicked on something, set the depth, otherwise keep it what
668  // it was last time, which should be about right (as good as we're
669  // going to get)
670  if (depth < 1.0) {
671  drag_depth_ = depth;
672  }
673  } else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) {
676  is_redraw_required_ = true;
677  } else {
678  Visualizer::MouseButtonCallback(window, button, action, mods);
679  }
680 }
681 
683  points_in_rect_.clear();
686  selection_polygon_renderer_ptr_->UpdateGeometry();
687  }
689 }
690 
694  pointcloud_picker_renderer_ptr_->UpdateGeometry();
695  }
696 }
697 
699  utility::LogInfo("Clearing all points from selection.");
701  selected_points_.clear();
705  ui_selected_points_renderer_ptr_->UpdateGeometry();
706  }
707 }
708 
710  const std::vector<int> indices) {
711  const std::vector<Eigen::Vector3d> *eigenPoints = nullptr;
712  const std::vector<CCVector3> *points = nullptr;
713  if (geometry_ptr_->isKindOf(CV_TYPES::POINT_CLOUD) ||
714  geometry_ptr_->isKindOf(CV_TYPES::MESH)) {
716  if (!points) {
717  return; // can't get points info, so can't add them
718  }
719  } else {
720  eigenPoints = GetGeometryEigenPoints(geometry_ptr_);
721  if (!eigenPoints) {
722  return; // can't get points info, so can't add them
723  }
724  }
725 
726  for (auto &index : indices) {
727  if (eigenPoints) {
728  const auto &point = (*eigenPoints)[index];
730  "Adding point #{:d} ({:.2f}, {:.2f}, {:.2f}) to selection.",
731  index, point(0), point(1), point(2));
732  selected_points_[index] = point;
733  ui_selected_points_geometry_ptr_->addEigenPoint(point);
734  } else if (points) {
735  const auto &point = (*points)[index];
737  "Adding point #{:d} ({:.2f}, {:.2f}, {:.2f}) to selection.",
738  index, point(0), point(1), point(2));
741  }
742  }
743 
744  ui_selected_points_geometry_ptr_->PaintUniformColor(SELECTED_POINTS_COLOR);
745  ui_selected_points_renderer_ptr_->UpdateGeometry();
746 
747  if (on_selection_changed_) {
749  }
750 }
751 
753  const std::vector<int> indices) {
754  for (auto &index : indices) {
755  utility::LogInfo("Removing point #{:d} from selection.", index);
756  selected_points_.erase(index);
757  }
759  for (auto &kv : selected_points_) {
760  ui_selected_points_geometry_ptr_->addPoint(kv.second);
761  }
762  ui_selected_points_geometry_ptr_->PaintUniformColor(SELECTED_POINTS_COLOR);
763  ui_selected_points_renderer_ptr_->UpdateGeometry();
764 
765  if (on_selection_changed_) {
767  }
768 }
769 
771  const Eigen::Vector3d &delta, DragType type) {
773  for (auto &kv : selected_points_before_drag_) {
774  auto index = kv.first;
775  auto new_coord = kv.second + delta;
776  selected_points_[index] = new_coord;
777  ui_selected_points_geometry_ptr_->addEigenPoint(new_coord);
778  }
779  ui_selected_points_geometry_ptr_->PaintUniformColor(SELECTED_POINTS_COLOR);
780  ui_selected_points_renderer_ptr_->UpdateGeometry();
781 
784  } else if (type == DRAG_END && on_selection_moved_) {
786  }
787 }
788 
789 const std::vector<Eigen::Vector3d> *
791  std::shared_ptr<const ccHObject> geometry) {
792  const std::vector<Eigen::Vector3d> *points = nullptr;
793  switch (geometry->getClassID()) {
794  case CV_TYPES::LINESET: {
795  auto lines =
796  std::static_pointer_cast<const geometry::LineSet>(geometry);
797  points = &lines->points_;
798  break;
799  }
801  case CV_TYPES::TETRA_MESH: {
802  auto mesh = std::static_pointer_cast<const geometry::ecvMeshBase>(
803  geometry);
804  points = &mesh->vertices_;
805  break;
806  }
807  case CV_TYPES::IMAGE2:
812  case CV_TYPES::BBOX:
814  points = nullptr;
815  break;
816  }
817  return points;
818 }
819 
821  std::shared_ptr<const ccHObject> geometry) {
822  const std::vector<CCVector3> *points = nullptr;
823  switch (geometry->getClassID()) {
824  case CV_TYPES::POINT_CLOUD: {
825  auto cloud = std::static_pointer_cast<const ccPointCloud>(geometry);
826  points = &cloud->getPoints();
827  break;
828  }
829  case CV_TYPES::MESH:
830  case CV_TYPES::PRIMITIVE: {
831  auto mesh = std::static_pointer_cast<const ccMesh>(geometry);
832  points = &mesh->getVertices();
833  break;
834  }
835  case CV_TYPES::IMAGE2:
840  case CV_TYPES::BBOX:
842  points = nullptr;
843  break;
844  }
845  return points;
846 }
847 
849  double winY) {
850  auto &view = (ViewControlWithEditing &)(*view_control_ptr_);
851  auto start = gl_util::Unproject(
852  Eigen::Vector3d(mouse_down_pos_.x(),
853  view.GetWindowHeight() - mouse_down_pos_.y(),
854  drag_depth_),
855  view.GetMVPMatrix(), view.GetWindowWidth(), view.GetWindowHeight());
856  auto end = gl_util::Unproject(
857  Eigen::Vector3d(winX, view.GetWindowHeight() - winY, drag_depth_),
858  view.GetMVPMatrix(), view.GetWindowWidth(), view.GetWindowHeight());
859  return end - start;
860 }
861 
863  size = std::max(size, MIN_POINT_SIZE);
866  opt->SetPointSize(size);
868  opt->SetPointSize(size);
869 }
870 
871 } // namespace visualization
872 } // namespace cloudViewer
int width
int size
int height
int points
char type
core::Tensor result
Definition: VtkUtils.cpp:76
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
unsigned size() const override
Definition: PointCloudTpl.h:38
double point_size_
Point size for PointCloud.
Definition: RenderOption.h:178
std::shared_ptr< glsl::GeometryRenderer > ui_selected_points_renderer_ptr_
std::shared_ptr< glsl::SelectionPolygonRenderer > selection_polygon_renderer_ptr_
const std::vector< Eigen::Vector3d > * GetGeometryEigenPoints(std::shared_ptr< const ccHObject > geometry)
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.
void MouseMoveCallback(GLFWwindow *window, double x, double y) override
void KeyPressCallback(GLFWwindow *window, int key, int scancode, int action, int mods) override
std::unordered_map< int, Eigen::Vector3d > selected_points_before_drag_
const std::vector< CCVector3 > * GetGeometryPoints(std::shared_ptr< const ccHObject > geometry)
bool UpdateGeometry(std::shared_ptr< const ccHObject > geometry_ptr=nullptr) override
Function to update geometry.
std::vector< int > PickPoints(double x, double y, double w, double h)
void MouseScrollCallback(GLFWwindow *window, double x, double y) override
void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) override
std::shared_ptr< glsl::PointCloudPickerRenderer > pointcloud_picker_renderer_ptr_
void WindowResizeCallback(GLFWwindow *window, int w, int h) override
bool InitViewControl() override
Function to initialize ViewControl.
bool InitRenderOption() override
Function to initialize RenderOption.
void DragSelectedPoints(const Eigen::Vector3d &delta, DragType type)
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
std::unordered_map< std::shared_ptr< glsl::GeometryRenderer >, RenderOption > utility_renderer_opts_
Definition: Visualizer.h:301
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
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
#define LogDebug(...)
Definition: Logging.h:90
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
int max(int a, int b)
Definition: cutil_math.h:48
@ HIERARCHY_OBJECT
Definition: CVTypes.h:103
@ CUSTOM_H_OBJECT
Definition: CVTypes.h:179
@ PRIMITIVE
Definition: CVTypes.h:119
@ HALF_EDGE_MESH
Definition: CVTypes.h:150
@ MESH
Definition: CVTypes.h:105
@ TETRA_MESH
Definition: CVTypes.h:149
@ POINT_CLOUD
Definition: CVTypes.h:104
@ MESH_BASE
Definition: CVTypes.h:148
@ VOXEL_GRID
Definition: CVTypes.h:151
@ LINESET
Definition: CVTypes.h:152
@ RGBD_IMAGE
Definition: CVTypes.h:158
@ IMAGE2
Definition: CVTypes.h:156
@ POINT_OCTREE2
Definition: CVTypes.h:157
@ BBOX
Definition: CVTypes.h:154
@ ORIENTED_BBOX
Definition: CVTypes.h:155
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
Eigen::Vector3d Unproject(const Eigen::Vector3d &screen_point, const GLMatrix4f &mvp_matrix, const int width, const int height)
Definition: GLHelper.cpp:97
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
Definition: lsd.c:149