1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
10 #include "core/Dispatch.h"
11 #include "core/Dtype.h"
12 #include "core/MemoryManager.h"
13 #include "core/ParallelFor.h"
14 #include "core/SizeVector.h"
15 #include "core/Tensor.h"
16 #include "t/geometry/kernel/GeometryIndexer.h"
17 #include "t/geometry/kernel/GeometryMacros.h"
18 #include "t/geometry/kernel/PointCloud.h"
19 #include "t/geometry/kernel/PointCloudImpl.h"
21 namespace cloudViewer {
25 namespace pointcloud {
29 utility::optional<std::reference_wrapper<core::Tensor>> image_colors,
30 const core::Tensor& points,
31 utility::optional<std::reference_wrapper<const core::Tensor>> colors,
32 const core::Tensor& intrinsics,
33 const core::Tensor& extrinsics,
36 const bool has_colors = image_colors.has_value();
38 int64_t n = points.GetLength();
40 const float* points_ptr = points.GetDataPtr<float>();
41 const float* point_colors_ptr =
42 has_colors ? colors.value().get().GetDataPtr<float>() : nullptr;
44 TransformIndexer transform_indexer(intrinsics, extrinsics, 1.0f);
45 NDArrayIndexer depth_indexer(depth, 2);
49 depth.GetDevice(), n, [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
50 float x = points_ptr[3 * workload_idx + 0];
51 float y = points_ptr[3 * workload_idx + 1];
52 float z = points_ptr[3 * workload_idx + 2];
54 // coordinate in camera (in voxel -> in meter)
55 float xc, yc, zc, u, v;
56 transform_indexer.RigidTransform(x, y, z, &xc, &yc, &zc);
58 // coordinate in image (in pixel)
59 transform_indexer.Project(xc, yc, zc, &u, &v);
60 if (!depth_indexer.InBoundary(u, v) || zc <= 0 ||
65 float* depth_ptr = depth_indexer.GetDataPtr<float>(
66 static_cast<int64_t>(u), static_cast<int64_t>(v));
67 float d = zc * depth_scale;
68 float d_old = atomicExch(depth_ptr, d);
70 atomicMinf(depth_ptr, d_old);
75 if (!has_colors) return;
77 NDArrayIndexer color_indexer(image_colors.value().get(), 2);
78 float precision_bound = depth_scale * 1e-4;
80 depth.GetDevice(), n, [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
81 float x = points_ptr[3 * workload_idx + 0];
82 float y = points_ptr[3 * workload_idx + 1];
83 float z = points_ptr[3 * workload_idx + 2];
85 // coordinate in camera (in voxel -> in meter)
86 float xc, yc, zc, u, v;
87 transform_indexer.RigidTransform(x, y, z, &xc, &yc, &zc);
89 // coordinate in image (in pixel)
90 transform_indexer.Project(xc, yc, zc, &u, &v);
91 if (!depth_indexer.InBoundary(u, v) || zc <= 0 ||
96 float dmap = *depth_indexer.GetDataPtr<float>(
97 static_cast<int64_t>(u), static_cast<int64_t>(v));
98 float d = zc * depth_scale;
99 if (d < dmap + precision_bound) {
100 uint8_t* color_ptr = color_indexer.GetDataPtr<uint8_t>(
101 static_cast<int64_t>(u), static_cast<int64_t>(v));
102 color_ptr[0] = static_cast<uint8_t>(
103 point_colors_ptr[3 * workload_idx + 0] * 255.0);
104 color_ptr[1] = static_cast<uint8_t>(
105 point_colors_ptr[3 * workload_idx + 1] * 255.0);
106 color_ptr[2] = static_cast<uint8_t>(
107 point_colors_ptr[3 * workload_idx + 2] * 255.0);
112 } // namespace pointcloud
113 } // namespace kernel
114 } // namespace geometry
116 } // namespace cloudViewer