ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VisualizerWithCustomAnimation.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 <IJsonConvertibleIO.h>
12 #include <Logging.h>
13 
14 #include <thread>
15 
18 
19 namespace cloudViewer {
20 namespace visualization {
21 using namespace cloudViewer;
23 
25 
28  // clang-format off
29  utility::LogInfo(" -- Animation control --");
30  utility::LogInfo(" Ctrl + F : Enter freeview (editing) mode.");
31  utility::LogInfo(" Ctrl + W : Enter preview mode.");
32  utility::LogInfo(" Ctrl + P : Enter animation mode and play animation from beginning.");
33  utility::LogInfo(" Ctrl + R : Enter animation mode, play animation, and record screen.");
34  utility::LogInfo(" Ctrl + G : Enter animation mode, play animation, and record depth.");
35  utility::LogInfo(" Ctrl + S : Save the camera path into a json file.");
36  utility::LogInfo("");
37  utility::LogInfo(" -- In free view mode --");
38  utility::LogInfo(" Ctrl + <-/-> : Go backward/forward a keyframe.");
39  utility::LogInfo(" Ctrl + Wheel : Same as Ctrl + <-/->.");
40  utility::LogInfo(" Ctrl + [/] : Go to the first/last keyframe.");
41  utility::LogInfo(" Ctrl + +/- : Increase/decrease interval between keyframes.");
42  utility::LogInfo(" Ctrl + L : Turn on/off camera path as a loop.");
43  utility::LogInfo(" Ctrl + A : Add a keyframe right after the current keyframe.");
44  utility::LogInfo(" Ctrl + U : Update the current keyframe.");
45  utility::LogInfo(" Ctrl + D : Delete the current keyframe.");
46  utility::LogInfo(" Ctrl + N : Add 360 spin right after the current keyframe.");
47  utility::LogInfo(" Ctrl + E : Erase the entire camera path.");
48  utility::LogInfo("");
49  utility::LogInfo(" -- In preview mode --");
50  utility::LogInfo(" Ctrl + <-/-> : Go backward/forward a frame.");
51  utility::LogInfo(" Ctrl + Wheel : Same as Ctrl + <-/->.");
52  utility::LogInfo(" Ctrl + [/] : Go to beginning/end of the camera path.");
53  utility::LogInfo("");
54  // clang-format on
55 }
56 
58  if (window_) {
59  auto &view_control =
61  std::string new_window_title =
62  window_name_ + " - " + view_control.GetStatusString();
63  glfwSetWindowTitle(window_, new_window_title.c_str());
64  }
65 }
66 
68  bool recording /* = false*/,
69  bool recording_depth /* = false*/,
70  bool close_window_when_animation_ends /* = false*/) {
71  auto &view_control = (ViewControlWithCustomAnimation &)(*view_control_ptr_);
72  if (view_control.NumOfFrames() == 0) {
73  utility::LogWarning("Abort playing due to empty trajectory.");
74  return;
75  }
76  view_control.SetAnimationMode(
77  ViewControlWithCustomAnimation::AnimationMode::PlayMode);
78  is_redraw_required_ = true;
81  utility::ConsoleProgressBar progress_bar(view_control.NumOfFrames(),
82  "Play animation: ");
83  auto trajectory_ptr = std::make_shared<camera::PinholeCameraTrajectory>();
84  bool recording_trajectory = view_control.IsValidPinholeCameraTrajectory();
85  if (recording) {
86  if (recording_depth) {
89  } else {
92  }
93  }
94  RegisterAnimationCallback([this, recording, recording_depth,
95  close_window_when_animation_ends,
96  recording_trajectory, trajectory_ptr,
97  &progress_bar](Visualizer *vis) {
98  // The lambda function captures no references to avoid dangling
99  // references
100  auto &view_control =
102  std::this_thread::sleep_for(std::chrono::milliseconds(10));
104  if (recording) {
105  if (recording_trajectory) {
106  auto parameter = camera::PinholeCameraParameters();
107  view_control.ConvertToPinholeCameraParameters(parameter);
108  trajectory_ptr->parameters_.push_back(parameter);
109  }
110  std::string buffer;
111  if (recording_depth) {
115  recording_depth_basedir_ + std::string(buffer), false);
116  } else {
120  recording_image_basedir_ + std::string(buffer), false);
121  }
122  }
123  view_control.Step(1.0);
124  ++progress_bar;
125  if (view_control.IsPlayingEnd(recording_file_index_)) {
126  view_control.SetAnimationMode(
127  ViewControlWithCustomAnimation::AnimationMode::FreeMode);
128  RegisterAnimationCallback(nullptr);
129  if (recording && recording_trajectory) {
130  if (recording_depth) {
134  *trajectory_ptr);
135  } else {
139  *trajectory_ptr);
140  }
141  }
142  if (close_window_when_animation_ends) {
143  Close();
144  }
145  }
147  return false;
148  });
149 }
150 
152  view_control_ptr_ = std::unique_ptr<ViewControlWithCustomAnimation>(
154  ResetViewPoint();
155  return true;
156 }
157 
159  GLFWwindow *window, int key, int scancode, int action, int mods) {
160  auto &view_control = (ViewControlWithCustomAnimation &)(*view_control_ptr_);
161  if (action == GLFW_RELEASE || view_control.IsPlaying()) {
162  return;
163  }
164 
165  if (mods & GLFW_MOD_CONTROL) {
166  switch (key) {
167  case GLFW_KEY_F:
168  view_control.SetAnimationMode(ViewControlWithCustomAnimation::
169  AnimationMode::FreeMode);
171  "[Visualizer] Enter freeview (editing) mode.");
172  break;
173  case GLFW_KEY_W:
174  view_control.SetAnimationMode(
176  PreviewMode);
177  utility::LogDebug("[Visualizer] Enter preview mode.");
178  break;
179  case GLFW_KEY_P:
180  Play(false);
181  break;
182  case GLFW_KEY_R:
183  Play(true, false);
184  break;
185  case GLFW_KEY_G:
186  Play(true, true);
187  break;
188  case GLFW_KEY_S:
189  view_control.CaptureTrajectory();
190  break;
191  case GLFW_KEY_LEFT:
192  view_control.Step(-1.0);
193  break;
194  case GLFW_KEY_RIGHT:
195  view_control.Step(1.0);
196  break;
197  case GLFW_KEY_LEFT_BRACKET:
198  view_control.GoToFirst();
199  break;
200  case GLFW_KEY_RIGHT_BRACKET:
201  view_control.GoToLast();
202  break;
203  case GLFW_KEY_EQUAL:
204  view_control.ChangeTrajectoryInterval(1);
205  utility::LogDebug("[Visualizer] Trajectory interval set to {}.",
206  view_control.GetTrajectoryInterval());
207  break;
208  case GLFW_KEY_MINUS:
209  view_control.ChangeTrajectoryInterval(-1);
210  utility::LogDebug("[Visualizer] Trajectory interval set to {}.",
211  view_control.GetTrajectoryInterval());
212  break;
213  case GLFW_KEY_L:
214  view_control.ToggleTrajectoryLoop();
215  break;
216  case GLFW_KEY_A:
217  view_control.AddKeyFrame();
219  "[Visualizer] Insert key frame; {} remaining.",
220  view_control.NumOfKeyFrames());
221  break;
222  case GLFW_KEY_U:
223  view_control.UpdateKeyFrame();
225  "[Visualizer] Update key frame; {} remaining.",
226  view_control.NumOfKeyFrames());
227  break;
228  case GLFW_KEY_D:
229  view_control.DeleteKeyFrame();
231  "[Visualizer] Delete last key frame; {} remaining.",
232  view_control.NumOfKeyFrames());
233  break;
234  case GLFW_KEY_N:
235  view_control.AddSpinKeyFrames();
237  "[Visualizer] Insert spin key frames; {} remaining.",
238  view_control.NumOfKeyFrames());
239  break;
240  case GLFW_KEY_E:
241  view_control.ClearAllKeyFrames();
243  "[Visualizer] Clear key frames; {} remaining.",
244  view_control.NumOfKeyFrames());
245  break;
246  default:
247  Visualizer::KeyPressCallback(window, key, scancode, action,
248  mods);
249  break;
250  }
251  is_redraw_required_ = true;
253  } else {
254  Visualizer::KeyPressCallback(window, key, scancode, action, mods);
255  }
256 }
257 
259  double x,
260  double y) {
261  auto &view_control = (ViewControlWithCustomAnimation &)(*view_control_ptr_);
262  if (view_control.IsPreviewing()) {
263  } else if (view_control.IsPlaying()) {
264  } else {
265  Visualizer::MouseMoveCallback(window, x, y);
266  }
267 }
268 
270  double x,
271  double y) {
272  auto &view_control = (ViewControlWithCustomAnimation &)(*view_control_ptr_);
273  if (view_control.IsPreviewing()) {
274  if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
275  glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
276  view_control.Step(y);
277  is_redraw_required_ = true;
279  }
280  } else if (view_control.IsPlaying()) {
281  } else {
282  Visualizer::MouseScrollCallback(window, x, y);
283  }
284 }
285 
287  int button,
288  int action,
289  int mods) {
290  auto &view_control = (ViewControlWithCustomAnimation &)(*view_control_ptr_);
291  if (view_control.IsPreviewing()) {
292  } else if (view_control.IsPlaying()) {
293  } else {
294  Visualizer::MouseButtonCallback(window, button, action, mods);
295  }
296 }
297 
298 } // namespace visualization
299 } // namespace cloudViewer
filament::Texture::InternalFormat format
utility::CountingProgressReporter * progress_bar
Contains both intrinsic and extrinsic pinhole camera parameters.
void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) override
void KeyPressCallback(GLFWwindow *window, int key, int scancode, int action, int mods) override
void MouseMoveCallback(GLFWwindow *window, double x, double y) override
bool InitViewControl() override
Function to initialize ViewControl.
void Play(bool recording=false, bool recording_depth=false, bool close_window_when_animation_ends=false)
void MouseScrollCallback(GLFWwindow *window, double x, double y) override
The main Visualizer class.
Definition: Visualizer.h:45
virtual void KeyPressCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
void CaptureScreenImage(const std::string &filename="", bool do_render=true)
Function to capture and save a screen image.
virtual void MouseScrollCallback(GLFWwindow *window, double x, double y)
virtual void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
virtual void MouseMoveCallback(GLFWwindow *window, double x, double y)
void ResetViewPoint(bool reset_bounding_box=false)
Function to reset view point.
void Close()
Function to to notify the window to be closed.
Definition: Visualizer.cpp:305
void RegisterAnimationCallback(std::function< bool(Visualizer *)> callback_func)
Function to register a callback function for animation.
Definition: Visualizer.cpp:249
std::unique_ptr< ViewControl > view_control_ptr_
Definition: Visualizer.h:281
void CaptureDepthImage(const std::string &filename="", bool do_render=true, double depth_scale=1000.0)
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
#define LogDebug(...)
Definition: Logging.h:90
bool WriteIJsonConvertible(const std::string &filename, const cloudViewer::utility::IJsonConvertible &object)
bool MakeDirectoryHierarchy(const std::string &directory)
Definition: FileSystem.cpp:499
Generic file read and write utility for python interface.