ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
LightDirectionInteractorLogic.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 <LineSet.h>
11 #include <ecvMesh.h>
12 #include <ecvPointCloud.h>
13 
17 
18 namespace cloudViewer {
19 namespace visualization {
20 namespace rendering {
21 
22 namespace {
23 
24 void CreateCircle(const Eigen::Vector3d& center,
25  const Eigen::Vector3d& u,
26  const Eigen::Vector3d& v,
27  double radius,
28  int n_segs,
29  ccPointCloud& cloud) {
30  for (int i = 0; i <= n_segs; ++i) {
31  double theta = 2.0 * M_PI * double(i) / double(n_segs);
32  double cosT = std::cos(theta);
33  double sinT = std::sin(theta);
34  Eigen::Vector3d p = center + radius * cosT * u + radius * sinT * v;
35  Eigen::Vector3d n = (cosT * u + sinT * v).normalized();
36  cloud.addEigenPoint(p);
37  cloud.addEigenNorm(n);
38  }
39 }
40 
41 std::shared_ptr<ccMesh> CreateArrow(const Eigen::Vector3d& dir,
42  double radius,
43  double length,
44  double head_length,
45  int n_segs = 20) {
46  Eigen::Vector3d tmp(dir.y(), dir.z(), dir.x());
47  Eigen::Vector3d u = dir.cross(tmp).normalized();
48  Eigen::Vector3d v = dir.cross(u);
49 
50  Eigen::Vector3d start(0, 0, 0);
51  Eigen::Vector3d head_start((length - head_length) * dir.x(),
52  (length - head_length) * dir.y(),
53  (length - head_length) * dir.z());
54  Eigen::Vector3d end(length * dir.x(), length * dir.y(), length * dir.z());
55 
56  ccPointCloud* baseVertices = new ccPointCloud("vertices");
57  assert(baseVertices);
58  auto arrow = std::make_shared<ccMesh>(baseVertices);
59  if (!arrow->reserveAssociatedCloud(n_segs + 1, false, true)) {
60  return nullptr;
61  }
62 
63  // Cylinder
64  CreateCircle(start, u, v, radius, n_segs, *baseVertices);
65  int n_verts_in_circle = n_segs + 1;
66  CreateCircle(head_start, u, v, radius, n_segs, *baseVertices);
67  for (int i = 0; i < n_segs; ++i) {
68  arrow->addTriangle(
69  Eigen::Vector3i(i, i + 1, n_verts_in_circle + i + 1));
70  arrow->addTriangle(Eigen::Vector3i(n_verts_in_circle + i + 1,
71  n_verts_in_circle + i, i));
72  }
73 
74  // End of cone
75  int start_idx = int(baseVertices->size());
76  CreateCircle(head_start, u, v, 2.0 * radius, n_segs, *baseVertices);
77 
78  for (int i = start_idx; i < int(baseVertices->size()); ++i) {
79  baseVertices->addEigenNorm(-dir);
80  }
81 
82  int center_idx = int(baseVertices->size());
83  baseVertices->addEigenPoint(head_start);
84  baseVertices->addEigenNorm(-dir);
85  for (int i = 0; i < n_segs; ++i) {
86  arrow->addTriangle(
87  Eigen::Vector3i(start_idx + i, start_idx + i + 1, center_idx));
88  }
89 
90  // Cone
91  start_idx = int(baseVertices->size());
92  CreateCircle(head_start, u, v, 2.0 * radius, n_segs, *baseVertices);
93  for (int i = 0; i < n_segs; ++i) {
94  int pointIdx = int(baseVertices->size());
95  baseVertices->addEigenPoint(end);
96  baseVertices->addEigenNorm(baseVertices->getEigenNormal(
97  static_cast<size_t>(start_idx + i)));
98  arrow->addTriangle(
99  Eigen::Vector3i(start_idx + i, start_idx + i + 1, pointIdx));
100  }
101 
102  // do some cleaning
103  {
104  baseVertices->shrinkToFit();
105  arrow->shrinkToFit();
106  NormsIndexesTableType* normals = arrow->getTriNormsTable();
107  if (normals) {
108  normals->shrink_to_fit();
109  }
110  }
111 
112  baseVertices->setEnabled(false);
113  // DGM: no need to lock it as it is only used by one mesh!
114  baseVertices->setLocked(false);
115  arrow->addChild(baseVertices);
116 
117  return arrow;
118 }
119 
120 } // namespace
121 
122 static const Eigen::Vector3d kSkyColor(0.0f, 0.0f, 1.0f);
123 static const Eigen::Vector3d kSunColor(1.0f, 0.9f, 0.0f);
124 
126  Camera* camera)
127  : scene_(scene), camera_(camera) {}
128 
130  Eigen::Vector3f up = camera_->GetUpVector();
131  Eigen::Vector3f right = -camera_->GetLeftVector();
132  RotateWorld(-dx, -dy, up, right);
134 }
135 
137  light_dir_at_mouse_down_ = scene_->GetSunLightDirection();
138  auto identity = Camera::Transform::Identity();
139  Super::SetMouseDownInfo(identity, {0.0f, 0.0f, 0.0f});
140 
141  ClearUI();
142 
143  Eigen::Vector3f dir = scene_->GetSunLightDirection();
144 
145  double size = model_size_;
146  if (size <= 0.001) {
147  size = 10;
148  }
149  double sphere_size = 0.5 * size; // size is a diameter
150  auto sphere_tris = ccMesh::CreateSphere(sphere_size, 20);
151  // NOTE: Line set doesn't support UVs. With defaultUnlit shader which
152  // requires UVs, filament will print out a warning about the missing vertex
153  // attribute. If/when we have a shader specifically for line sets we can use
154  // it to avoid the warning.
155  auto sphere = geometry::LineSet::CreateFromTriangleMesh(*sphere_tris);
156  sphere->PaintUniformColor(kSkyColor);
157  auto t0 = Camera::Transform::Identity();
158  MaterialRecord mat;
159  mat.shader = "defaultUnlit";
160  scene_->AddGeometry("__suncagesphere__", *sphere, mat);
161  scene_->SetGeometryTransform("__suncagesphere__", t0);
162  scene_->GeometryShadows("__suncagesphere__", false, false);
163  ui_objs_.push_back({"__suncagesphere__", t0});
164 
165  auto sun_radius = 0.05 * size;
166  auto sun = ccMesh::CreateSphere(sun_radius, 20);
167  sun->PaintUniformColor(kSunColor);
168  sun->ComputeVertexNormals();
169  sun->triangle_uvs_.resize(sun->size() * 3, {0.f, 0.f});
170  auto t1 = Camera::Transform::Identity();
171  t1.translate(-sphere_size * dir);
172  scene_->AddGeometry("__sunsphere__", *sun, mat);
173  scene_->SetGeometryTransform("__sunsphere__", t1);
174  scene_->GeometryShadows("__sunsphere__", false, false);
175  ui_objs_.push_back({"__sunsphere__", t1});
176 
177  const double arrow_radius = 0.075 * sun_radius;
178  const double arrow_length = 0.333 * size;
179  auto sun_dir = CreateArrow(dir.cast<double>(), arrow_radius, arrow_length,
180  0.1 * arrow_length, 20);
181  sun_dir->PaintUniformColor(kSunColor);
182  sun_dir->ComputeVertexNormals();
183  sun_dir->triangle_uvs_.resize(sun_dir->size() * 3, {0.f, 0.f});
184  auto t2 = Camera::Transform::Identity();
185  t2.translate(-sphere_size * dir);
186  scene_->AddGeometry("__sunarrow__", *sun_dir, mat);
187  scene_->SetGeometryTransform("__sunarrow__", t2);
188  scene_->GeometryShadows("__sunarrow__", false, false);
189  ui_objs_.push_back({"__sunarrow__", t2});
190 
192 }
193 
195  Eigen::Vector3f model_center = model_bounds_.GetCenter().cast<float>();
196  for (auto& o : ui_objs_) {
197  Camera::Transform t = GetMatrix() * o.transform;
198  t.pretranslate(model_center);
199  scene_->SetGeometryTransform(o.name, t);
200  }
201 }
202 
204 
205 void LightDirectionInteractorLogic::ClearUI() {
206  for (auto& o : ui_objs_) {
207  scene_->RemoveGeometry(o.name);
208  }
209  ui_objs_.clear();
210 }
211 
213  return GetMatrix() * light_dir_at_mouse_down_;
214 }
215 
216 } // namespace rendering
217 } // namespace visualization
218 } // namespace cloudViewer
constexpr double M_PI
Pi.
Definition: CVConst.h:19
int size
Array of compressed 3D normals (single index)
virtual Eigen::Vector3d GetCenter() const override
Returns the center of the geometry coordinates.
Definition: ecvBBox.h:87
static std::shared_ptr< ccMesh > CreateSphere(double radius=1.0, int resolution=20, bool create_uv_map=false)
virtual void setLocked(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:117
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addEigenNorm(const Eigen::Vector3d &N)
Eigen::Vector3d getEigenNormal(size_t index) const
void shrinkToFit()
Removes unused capacity.
void addEigenPoint(const Eigen::Vector3d &point)
unsigned size() const override
Definition: PointCloudTpl.h:38
static std::shared_ptr< LineSet > CreateFromTriangleMesh(const ccMesh &mesh)
virtual Eigen::Vector3f GetUpVector() const =0
virtual Eigen::Vector3f GetLeftVector() const =0
Eigen::Transform< float, 3, Eigen::Affine > Transform
Definition: Camera.h:29
void SetMouseDownInfo(const Camera::Transform &matrix, const Eigen::Vector3f &center_of_rotation)
virtual void RotateWorld(int dx, int dy, const Eigen::Vector3f &x_axis, const Eigen::Vector3f &y_axis)
virtual void GeometryShadows(const std::string &object_name, bool cast_shadows, bool receive_shadows)=0
virtual void RemoveGeometry(const std::string &object_name)=0
virtual void SetGeometryTransform(const std::string &object_name, const Transform &transform)=0
virtual bool AddGeometry(const std::string &object_name, const ccHObject &geometry, const MaterialRecord &material, const std::string &downsampled_name="", size_t downsample_threshold=SIZE_MAX)=0
virtual Eigen::Vector3f GetSunLightDirection()=0
double normals[3]
__host__ __device__ float length(float2 v)
Definition: cutil_math.h:1162
static const Eigen::Vector3d kSkyColor(0.0f, 0.0f, 1.0f)
static const Eigen::Vector3d kSunColor(1.0f, 0.9f, 0.0f)
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 3, 1 > Vector3i
Definition: knncpp.h:30