ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ModelInteractorLogic.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 <Eigen/src/Core/Transpose.h>
11 
14 
15 namespace cloudViewer {
16 namespace visualization {
17 namespace rendering {
18 
20  Camera* camera,
21  double min_far_plane)
22  : RotationInteractorLogic(camera, min_far_plane), scene_(scene) {}
23 
25 
27  Super::SetBoundingBox(bounds);
28  // Initialize parent's matrix_ (in case we do a mouse wheel, which
29  // doesn't involve a mouse down) and the center of rotation.
30  SetMouseDownInfo(Camera::Transform::Identity(),
31  bounds.GetCenter().cast<float>());
32 }
33 
35  GeometryHandle axes, const std::vector<GeometryHandle>& objects) {}
36 
37 void ModelInteractorLogic::Rotate(int dx, int dy) {
38  Eigen::Vector3f x_axis = -camera_->GetLeftVector();
39  Eigen::Vector3f y_axis = camera_->GetUpVector();
40 
41  Eigen::Vector3f axis = -dy * x_axis + dx * y_axis;
42  axis = axis.normalized();
43  float theta = float(CalcRotateRadians(dx, dy));
44  Eigen::AngleAxisf rot_matrix(theta, axis);
45 
46  // Rotations about a point using a world axis do not produce
47  // a matrix that can be applied to any matrix; each individual
48  // matrix must be rotated around the point.
49  for (auto o : transforms_at_mouse_down_) {
50  Camera::Transform t = o.second; // copy
51  t.translate(center_of_rotation_);
52  t.fromPositionOrientationScale(t.translation(),
53  rot_matrix * t.rotation(),
54  Eigen::Vector3f(1, 1, 1));
55  t.translate(-center_of_rotation_);
56  scene_->GetScene()->SetGeometryTransform(o.first, t);
57  }
58  UpdateBoundingBox(Camera::Transform(rot_matrix));
59 }
60 
61 void ModelInteractorLogic::RotateZ(int dx, int dy) {
62  auto rad = CalcRotateZRadians(dx, dy);
63  Eigen::AngleAxisf rot_matrix(rad, camera_->GetForwardVector());
64 
65  for (auto o : transforms_at_mouse_down_) {
66  Camera::Transform t = o.second; // copy
67  t.translate(center_of_rotation_);
68  t.fromPositionOrientationScale(t.translation(),
69  rot_matrix * t.rotation(),
70  Eigen::Vector3f(1, 1, 1));
71  t.translate(-center_of_rotation_);
72  scene_->GetScene()->SetGeometryTransform(o.first, t);
73  }
74  UpdateBoundingBox(Camera::Transform(rot_matrix));
75 }
76 
77 void ModelInteractorLogic::Dolly(float dy, DragType drag_type) {
78  float z_dist = CalcDollyDist(dy, drag_type, matrix_at_mouse_down_);
79  Eigen::Vector3f world_move = -z_dist * camera_->GetForwardVector();
80 
81  for (auto o : transforms_at_mouse_down_) {
83  if (drag_type == DragType::MOUSE) {
84  t = o.second; // copy
85  } else {
86  t = scene_->GetScene()->GetGeometryTransform(o.first);
87  }
88  Eigen::Vector3f new_trans = t.translation() + world_move;
89  t.fromPositionOrientationScale(new_trans, t.rotation(),
90  Eigen::Vector3f(1, 1, 1));
91  scene_->GetScene()->SetGeometryTransform(o.first, t);
92  }
93 
94  Camera::Transform t = Camera::Transform::Identity();
95  t.translate(world_move);
96  UpdateBoundingBox(t);
97 
99 }
100 
101 void ModelInteractorLogic::Pan(int dx, int dy) {
102  Eigen::Vector3f world_move = CalcPanVectorWorld(-dx, -dy);
104 
105  for (auto o : transforms_at_mouse_down_) {
106  Camera::Transform t = o.second; // copy
107  Eigen::Vector3f new_trans = t.translation() + world_move;
108  t.fromPositionOrientationScale(new_trans, t.rotation(),
109  Eigen::Vector3f(1, 1, 1));
110  scene_->GetScene()->SetGeometryTransform(o.first, t);
111  }
112  Camera::Transform t = Camera::Transform::Identity();
113  t.translate(world_move);
114  UpdateBoundingBox(t);
115 }
116 
117 void ModelInteractorLogic::UpdateBoundingBox(const Camera::Transform& t) {
118  using Transform4 = Eigen::Transform<double, 3, Eigen::Affine>;
119  Transform4 change = t.cast<double>();
120  Eigen::Vector3d new_min = change * model_bounds_.GetMinBound();
121  Eigen::Vector3d new_max = change * model_bounds_.GetMaxBound();
122  // Call super's not our SetBoundingBox(): we also update the
123  // center of rotation, because normally this call is not done during
124  // mouse movement, but rather, once to initalize the interactor.
125  Super::SetBoundingBox(ccBBox(new_min, new_max));
126 }
127 
128 const std::string kAxisObjectName("__axis__");
129 
131  SetMouseDownInfo(Camera::Transform::Identity(), center_of_rotation_);
132 
133  transforms_at_mouse_down_.clear();
134  auto models = scene_->GetGeometries();
135  auto* scene = scene_->GetScene();
136 
137  for (const auto& m : models) {
138  transforms_at_mouse_down_[m] = scene->GetGeometryTransform(m);
139  }
140 
141  // Show axes while user is dragging
142  is_axes_visible_ = scene_->GetScene()->GeometryIsVisible(kAxisObjectName);
143  if (!is_axes_visible_)
144  scene_->GetScene()->ShowGeometry(kAxisObjectName, true);
145 
146  // Fix far plane if the center of the model is offset from origin
148 }
149 
151 
153  if (!is_axes_visible_)
154  scene_->GetScene()->ShowGeometry(kAxisObjectName, false);
155 }
156 
157 } // namespace rendering
158 } // namespace visualization
159 } // namespace cloudViewer
Bounding box structure.
Definition: ecvBBox.h:25
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
Definition: ecvBBox.h:84
virtual Eigen::Vector3d GetMinBound() const override
Returns min bounds for geometry coordinates.
Definition: ecvBBox.h:81
virtual Eigen::Vector3d GetCenter() const override
Returns the center of the geometry coordinates.
Definition: ecvBBox.h:87
virtual Eigen::Vector3f GetUpVector() const =0
virtual Eigen::Vector3f GetLeftVector() const =0
Eigen::Transform< float, 3, Eigen::Affine > Transform
Definition: Camera.h:29
virtual Eigen::Vector3f GetForwardVector() const =0
void SetMouseDownInfo(const Camera::Transform &matrix, const Eigen::Vector3f &center_of_rotation)
float CalcDollyDist(float dy, DragType drag_type, const Camera::Transform &matrix)
void SetModel(GeometryHandle axes, const std::vector< GeometryHandle > &objects)
void RotateZ(int dx, int dy) override
Rotates about the forward axis of the matrix.
ModelInteractorLogic(CloudViewerScene *scene, Camera *camera, double min_far_plane)
virtual bool GeometryIsVisible(const std::string &object_name)=0
virtual Transform GetGeometryTransform(const std::string &object_name)=0
virtual void SetGeometryTransform(const std::string &object_name, const Transform &transform)=0
virtual void ShowGeometry(const std::string &object_name, bool show)=0
const std::string kAxisObjectName("__axis__")
Generic file read and write utility for python interface.