ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
TriangleMeshImpl.h
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 
8 #include <Logging.h>
9 
12 #include "cloudViewer/core/Dtype.h"
18 
19 namespace cloudViewer {
20 namespace t {
21 namespace geometry {
22 namespace kernel {
23 namespace trianglemesh {
24 
25 #ifndef __CUDACC__
26 using std::isnan;
27 #endif
28 
29 #if defined(__CUDACC__)
30 void NormalizeNormalsCUDA
31 #else
33 #endif
35  const core::Dtype dtype = normals.GetDtype();
36  const int64_t n = normals.GetLength();
37 
39  scalar_t* ptr = normals.GetDataPtr<scalar_t>();
40 
41  core::ParallelFor(normals.GetDevice(), n,
42  [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
43  int64_t idx = 3 * workload_idx;
44  scalar_t x = ptr[idx];
45  scalar_t y = ptr[idx + 1];
46  scalar_t z = ptr[idx + 2];
47  if (isnan(x)) {
48  x = 0.0;
49  y = 0.0;
50  z = 1.0;
51  } else {
52  scalar_t norm = sqrt(x * x + y * y + z * z);
53  if (norm > 0) {
54  x /= norm;
55  y /= norm;
56  z /= norm;
57  }
58  ptr[idx] = x;
59  ptr[idx + 1] = y;
60  ptr[idx + 2] = z;
61  }
62  });
63  });
64 }
65 
66 #if defined(__CUDACC__)
67 void ComputeTriangleNormalsCUDA
68 #else
70 #endif
71  (const core::Tensor& vertices,
72  const core::Tensor& triangles,
74  const core::Dtype dtype = normals.GetDtype();
75  const int64_t n = normals.GetLength();
76  const core::Tensor triangles_d = triangles.To(core::Int64);
77 
79  scalar_t* normal_ptr = normals.GetDataPtr<scalar_t>();
80  const int64_t* triangle_ptr = triangles_d.GetDataPtr<int64_t>();
81  const scalar_t* vertex_ptr = vertices.GetDataPtr<scalar_t>();
82 
83  core::ParallelFor(normals.GetDevice(), n,
84  [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
85  int64_t idx = 3 * workload_idx;
86 
87  int64_t triangle_id1 = triangle_ptr[idx];
88  int64_t triangle_id2 = triangle_ptr[idx + 1];
89  int64_t triangle_id3 = triangle_ptr[idx + 2];
90 
91  scalar_t v01[3], v02[3];
92  v01[0] = vertex_ptr[3 * triangle_id2] -
93  vertex_ptr[3 * triangle_id1];
94  v01[1] = vertex_ptr[3 * triangle_id2 + 1] -
95  vertex_ptr[3 * triangle_id1 + 1];
96  v01[2] = vertex_ptr[3 * triangle_id2 + 2] -
97  vertex_ptr[3 * triangle_id1 + 2];
98  v02[0] = vertex_ptr[3 * triangle_id3] -
99  vertex_ptr[3 * triangle_id1];
100  v02[1] = vertex_ptr[3 * triangle_id3 + 1] -
101  vertex_ptr[3 * triangle_id1 + 1];
102  v02[2] = vertex_ptr[3 * triangle_id3 + 2] -
103  vertex_ptr[3 * triangle_id1 + 2];
104 
106  &normal_ptr[idx]);
107  });
108  });
109 }
110 
111 #if defined(__CUDACC__)
112 void ComputeTriangleAreasCUDA
113 #else
115 #endif
116  (const core::Tensor& vertices,
117  const core::Tensor& triangles,
118  core::Tensor& triangle_areas) {
119  const int64_t n = triangle_areas.GetLength();
120  const core::Dtype dtype = triangle_areas.GetDtype();
121  const core::Tensor triangles_d = triangles.To(core::Int64);
122 
123  DISPATCH_FLOAT_DTYPE_TO_TEMPLATE(dtype, [&]() {
124  scalar_t* area_ptr = triangle_areas.GetDataPtr<scalar_t>();
125  const int64_t* triangle_ptr = triangles_d.GetDataPtr<int64_t>();
126  const scalar_t* vertex_ptr = vertices.GetDataPtr<scalar_t>();
127 
128  core::ParallelFor(triangle_areas.GetDevice(), n,
129  [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
130  int64_t idx = 3 * workload_idx;
131 
132  int64_t triangle_id1 = triangle_ptr[idx];
133  int64_t triangle_id2 = triangle_ptr[idx + 1];
134  int64_t triangle_id3 = triangle_ptr[idx + 2];
135 
136  scalar_t v01[3], v02[3];
137  v01[0] = vertex_ptr[3 * triangle_id2] -
138  vertex_ptr[3 * triangle_id1];
139  v01[1] = vertex_ptr[3 * triangle_id2 + 1] -
140  vertex_ptr[3 * triangle_id1 + 1];
141  v01[2] = vertex_ptr[3 * triangle_id2 + 2] -
142  vertex_ptr[3 * triangle_id1 + 2];
143  v02[0] = vertex_ptr[3 * triangle_id3] -
144  vertex_ptr[3 * triangle_id1];
145  v02[1] = vertex_ptr[3 * triangle_id3 + 1] -
146  vertex_ptr[3 * triangle_id1 + 1];
147  v02[2] = vertex_ptr[3 * triangle_id3 + 2] -
148  vertex_ptr[3 * triangle_id1 + 2];
149 
150  area_ptr[workload_idx] =
152  v01, v02);
153  });
154  });
155 }
156 
157 } // namespace trianglemesh
158 } // namespace kernel
159 } // namespace geometry
160 } // namespace t
161 } // namespace cloudViewer
Common CUDA utilities.
#define CLOUDVIEWER_DEVICE
Definition: CUDAUtils.h:45
#define DISPATCH_FLOAT_DTYPE_TO_TEMPLATE(DTYPE,...)
Definition: Dispatch.h:78
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
double normals[3]
CLOUDVIEWER_HOST_DEVICE CLOUDVIEWER_FORCE_INLINE void cross_3x1(const scalar_t *A_3x1_input, const scalar_t *B_3x1_input, scalar_t *C_3x1_output)
Definition: Matrix.h:62
CLOUDVIEWER_HOST_DEVICE CLOUDVIEWER_FORCE_INLINE scalar_t cross_mag_3x1(const scalar_t *A_3x1_input, const scalar_t *B_3x1_input)
Definition: Matrix.h:76
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition: ParallelFor.h:111
const Dtype Int64
Definition: Dtype.cpp:47
void ComputeTriangleNormalsCPU(const core::Tensor &vertices, const core::Tensor &triangles, core::Tensor &normals)
void NormalizeNormalsCPU(core::Tensor &normals)
void ComputeTriangleAreasCPU(const core::Tensor &vertices, const core::Tensor &triangles, core::Tensor &triangle_areas)
Generic file read and write utility for python interface.