173 index_t resolution2 = resolution * resolution;
174 index_t resolution3 = resolution2 * resolution;
176 TransformIndexer transform_indexer(depth_intrinsic, extrinsics, voxel_size);
181 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
189 if (!block_value_map.Contains(
"tsdf") ||
190 !block_value_map.Contains(
"weight")) {
192 "TSDF and/or weight not allocated in blocks, please implement "
193 "customized integration.");
195 tsdf_t* tsdf_base_ptr = block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
196 weight_t* weight_base_ptr =
197 block_value_map.at(
"weight").GetDataPtr<weight_t>();
199 bool integrate_color =
200 block_value_map.Contains(
"color") &&
color.NumElements() > 0;
201 color_t* color_base_ptr =
nullptr;
204 float color_multiplier = 1.0;
205 if (integrate_color) {
206 color_base_ptr = block_value_map.at(
"color").
GetDataPtr<color_t>();
211 color_multiplier = 255.0;
218 index_t block_idx = indices_ptr[workload_idx / resolution3];
219 index_t voxel_idx = workload_idx % resolution3;
224 block_keys_indexer.GetDataPtr<
index_t>(block_idx);
231 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
234 index_t x = xb * resolution + xv;
235 index_t y = yb * resolution + yv;
236 index_t z = zb * resolution + zv;
239 float xc, yc, zc, u, v;
241 static_cast<float>(y),
242 static_cast<float>(z), &xc, &yc, &zc);
245 transform_indexer.
Project(xc, yc, zc, &u, &v);
256 *depth_indexer.
GetDataPtr<input_depth_t>(ui, vi) / depth_scale;
258 float sdf = depth - zc;
259 if (depth <= 0 || depth > depth_max || zc <= 0 || sdf < -sdf_trunc) {
262 sdf = sdf < sdf_trunc ? sdf : sdf_trunc;
265 index_t linear_idx = block_idx * resolution3 + voxel_idx;
267 tsdf_t* tsdf_ptr = tsdf_base_ptr + linear_idx;
268 weight_t* weight_ptr = weight_base_ptr + linear_idx;
270 float inv_wsum = 1.0f / (*weight_ptr + 1);
271 float weight = *weight_ptr;
272 *tsdf_ptr = (
weight * (*tsdf_ptr) + sdf) * inv_wsum;
274 if (integrate_color) {
275 color_t* color_ptr = color_base_ptr + 3 * linear_idx;
280 transform_indexer.
Unproject(ui, vi, 1.0, &x, &y, &z);
283 colormap_indexer.
Project(x, y, z, &uf, &vf);
288 input_color_t* input_color_ptr =
289 color_indexer.
GetDataPtr<input_color_t>(ui, vi);
291 for (
index_t i = 0; i < 3; ++i) {
292 color_ptr[i] = (
weight * color_ptr[i] +
293 input_color_ptr[i] * color_multiplier) *
301#if defined(__CUDACC__)
320 int64_t block_resolution,
329 int h_down = h / down_factor;
330 int w_down = w / down_factor;
332 block_keys.GetDevice());
336 const int fragment_size = 16;
338 if (fragment_buffer.GetDataPtr() == 0 ||
339 fragment_buffer.NumElements() == 0) {
341 const int reserve_frag_buffer_size =
342 h_down * w_down / (fragment_size * fragment_size) / voxel_size;
343 fragment_buffer =
core::Tensor({reserve_frag_buffer_size, 6},
347 const int frag_buffer_size = fragment_buffer.NumElements() / 6;
352#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
354 block_keys.GetDevice());
355 int* count_ptr =
count.GetDataPtr<
int>();
357 std::atomic<int> count_atomic(0);
358 std::atomic<int>* count_ptr = &count_atomic;
361#if defined(__CUDACC__)
362#elif defined(SYCL_LANGUAGE_VERSION)
372 block_keys.GetDevice(), block_keys.GetLength(),
374 int* key = block_keys_indexer.
GetDataPtr<
int>(workload_idx);
376 int u_min = w_down - 1, v_min = h_down - 1, u_max = 0,
378 float z_min = depth_max, z_max = depth_min;
380 float xc, yc, zc, u, v;
383 for (
int i = 0; i < 8; ++i) {
384 float xw = (key[0] + ((i & 1) > 0)) * block_resolution *
386 float yw = (key[1] + ((i & 2) > 0)) * block_resolution *
388 float zw = (key[2] + ((i & 4) > 0)) * block_resolution *
393 if (zc <= 0)
continue;
396 w2c_transform_indexer.
Project(xc, yc, zc, &u, &v);
400 v_min = min(
static_cast<int>(floorf(v)), v_min);
401 v_max = max(
static_cast<int>(ceilf(v)), v_max);
403 u_min = min(
static_cast<int>(floorf(u)), u_min);
404 u_max = max(
static_cast<int>(ceilf(u)), u_max);
406 z_min = min(z_min, zc);
407 z_max = max(z_max, zc);
410 v_min = max(0, v_min);
411 v_max = min(h_down - 1, v_max);
413 u_min = max(0, u_min);
414 u_max = min(w_down - 1, u_max);
416 if (v_min >= v_max || u_min >= u_max || z_min >= z_max)
return;
420 ceilf(
float(v_max - v_min + 1) /
float(fragment_size));
422 ceilf(
float(u_max - u_min + 1) /
float(fragment_size));
424 int frag_count = frag_v_count * frag_u_count;
426 int frag_count_end = frag_count_start + frag_count;
427 if (frag_count_end >= frag_buffer_size) {
432 for (
int frag_v = 0; frag_v < frag_v_count; ++frag_v) {
433 for (
int frag_u = 0; frag_u < frag_u_count;
435 float* frag_ptr = frag_buffer_indexer.
GetDataPtr<
float>(
436 frag_count_start +
offset);
442 frag_ptr[2] = v_min + frag_v * fragment_size;
443 frag_ptr[3] = u_min + frag_u * fragment_size;
446 frag_ptr[4] = min(frag_ptr[2] + fragment_size - 1,
447 static_cast<float>(v_max));
448 frag_ptr[5] = min(frag_ptr[3] + fragment_size - 1,
449 static_cast<float>(u_max));
453#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
454 int needed_frag_count =
count[0].Item<
int>();
456 int needed_frag_count = (*count_ptr).load();
459 int frag_count = needed_frag_count;
460 if (frag_count >= frag_buffer_size) {
462 "Could not generate full range map; allocated {} fragments but "
464 frag_buffer_size, frag_count);
465 frag_count = frag_buffer_size - 1;
467 utility::LogDebug(
"EstimateRange Allocated {} fragments and needed {}",
468 frag_buffer_size, frag_count);
474 int v = workload_idx / w_down;
475 int u = workload_idx % w_down;
478 range_ptr[0] = depth_max;
479 range_ptr[1] = depth_min;
484 block_keys.GetDevice(), frag_count * fragment_size * fragment_size,
486 int frag_idx = workload_idx / (fragment_size * fragment_size);
487 int local_idx = workload_idx % (fragment_size * fragment_size);
488 int dv = local_idx / fragment_size;
489 int du = local_idx % fragment_size;
492 frag_buffer_indexer.
GetDataPtr<
float>(frag_idx);
493 int v_min =
static_cast<int>(frag_ptr[2]);
494 int u_min =
static_cast<int>(frag_ptr[3]);
495 int v_max =
static_cast<int>(frag_ptr[4]);
496 int u_max =
static_cast<int>(frag_ptr[5]);
500 if (v > v_max || u > u_max)
return;
502 float z_min = frag_ptr[0];
503 float z_max = frag_ptr[1];
504 float* range_ptr = range_map_indexer.
GetDataPtr<
float>(u, v);
505#if defined(__CUDACC__)
506 atomicMinf(&(range_ptr[0]), z_min);
507 atomicMaxf(&(range_ptr[1]), z_max);
508#elif defined(SYCL_LANGUAGE_VERSION)
509 sycl::atomic_ref<float, sycl::memory_order::acq_rel,
510 sycl::memory_scope::device,
511 sycl::access::address_space::global_space>(
514 sycl::atomic_ref<float, sycl::memory_order::acq_rel,
515 sycl::memory_scope::device,
516 sycl::access::address_space::global_space>(
520#pragma omp critical(EstimateRangeCPU)
522 range_ptr[0] = min(z_min, range_ptr[0]);
523 range_ptr[1] = max(z_max, range_ptr[1]);
528#if defined(__CUDACC__)
532 if (needed_frag_count != frag_count) {
533 utility::LogInfo(
"Reallocating {} fragments for EstimateRange (was {})",
534 needed_frag_count, frag_count);
537 block_keys.GetDevice());
570 (std::shared_ptr<core::HashMap>& hashmap,
583 float weight_threshold,
584 float trunc_voxel_multiplier,
585 int range_map_down_factor) {
590 auto device_hashmap = hashmap->GetDeviceHashBackend();
591#if defined(__CUDACC__)
593 std::dynamic_pointer_cast<core::StdGPUHashBackend<Key, Hash, Eq>>(
595 if (cuda_hashmap ==
nullptr) {
597 "Unsupported backend: CUDA raycasting only supports STDGPU.");
599 auto hashmap_impl = cuda_hashmap->GetImpl();
600#elif defined(SYCL_LANGUAGE_VERSION)
602 std::dynamic_pointer_cast<core::SYCLHashBackend<Key, Hash, Eq>>(
604 if (sycl_hashmap ==
nullptr) {
606 "Unsupported backend: SYCL raycasting requires the SYCL "
609 auto sycl_hash_lookup = sycl_hashmap->GetDeviceLookup();
612 std::dynamic_pointer_cast<core::TBBHashBackend<Key, Hash, Eq>>(
614 if (cpu_hashmap ==
nullptr) {
616 "Unsupported backend: CPU raycasting only supports TBB.");
618 auto hashmap_impl = *cpu_hashmap->GetImpl();
641 if (!block_value_map.Contains(
"tsdf") ||
642 !block_value_map.Contains(
"weight")) {
644 "TSDF and/or weight not allocated in blocks, please implement "
645 "customized integration.");
647 const tsdf_t* tsdf_base_ptr =
648 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
649 const weight_t* weight_base_ptr =
650 block_value_map.at(
"weight").GetDataPtr<weight_t>();
653 if (renderings_map.Contains(
"depth")) {
654 depth_indexer =
ArrayIndexer(renderings_map.at(
"depth"), 2);
656 if (renderings_map.Contains(
"vertex")) {
657 vertex_indexer =
ArrayIndexer(renderings_map.at(
"vertex"), 2);
659 if (renderings_map.Contains(
"normal")) {
660 normal_indexer =
ArrayIndexer(renderings_map.at(
"normal"), 2);
664 if (renderings_map.Contains(
"index")) {
665 index_indexer =
ArrayIndexer(renderings_map.at(
"index"), 2);
667 if (renderings_map.Contains(
"mask")) {
668 mask_indexer =
ArrayIndexer(renderings_map.at(
"mask"), 2);
670 if (renderings_map.Contains(
"interp_ratio")) {
671 interp_ratio_indexer =
674 if (renderings_map.Contains(
"interp_ratio_dx")) {
675 interp_ratio_dx_indexer =
678 if (renderings_map.Contains(
"interp_ratio_dy")) {
679 interp_ratio_dy_indexer =
682 if (renderings_map.Contains(
"interp_ratio_dz")) {
683 interp_ratio_dz_indexer =
688 bool render_color =
false;
689 if (block_value_map.Contains(
"color") && renderings_map.Contains(
"color")) {
691 color_indexer =
ArrayIndexer(renderings_map.at(
"color"), 2);
693 const color_t* color_base_ptr =
694 render_color ? block_value_map.at(
"color").GetDataPtr<color_t>()
697 bool visit_neighbors = render_color || normal_indexer.
GetDataPtr() ||
713 float block_size = voxel_size * block_resolution;
714 index_t resolution2 = block_resolution * block_resolution;
715 index_t resolution3 = resolution2 * block_resolution;
720#elif defined(SYCL_LANGUAGE_VERSION)
731 index_t x_vn = (x_v + block_resolution) % block_resolution;
732 index_t y_vn = (y_v + block_resolution) % block_resolution;
733 index_t z_vn = (z_v + block_resolution) % block_resolution;
739 if (dx_b == 0 && dy_b == 0 && dz_b == 0) {
740 return block_buf_idx * resolution3 + z_v * resolution2 +
741 y_v * block_resolution + x_v;
743 Key key(x_b + dx_b, y_b + dy_b, z_b + dz_b);
745 index_t block_buf_idx = cache.
Check(key[0], key[1], key[2]);
746 if (block_buf_idx < 0) {
747#if defined(__CUDACC__)
748 auto iter = hashmap_impl.find(key);
749 if (iter == hashmap_impl.end())
return -1;
750 block_buf_idx = iter->second;
751#elif defined(SYCL_LANGUAGE_VERSION)
754 block_buf_idx =
static_cast<index_t>(bi);
756 auto iter = hashmap_impl.find(key);
757 if (iter == hashmap_impl.end())
return -1;
758 block_buf_idx = iter->second;
760 cache.
Update(key[0], key[1], key[2], block_buf_idx);
763 return block_buf_idx * resolution3 + z_vn * resolution2 +
764 y_vn * block_resolution + x_vn;
769 float x_o,
float y_o,
float z_o,
770 float x_d,
float y_d,
float z_d,
float t,
772 float x_g = x_o +
t * x_d;
773 float y_g = y_o +
t * y_d;
774 float z_g = z_o +
t * z_d;
781 Key key(x_b, y_b, z_b);
783 if (block_buf_idx < 0) {
784#if defined(__CUDACC__)
785 auto iter = hashmap_impl.find(key);
786 if (iter == hashmap_impl.end())
return -1;
787 block_buf_idx = iter->second;
788#elif defined(SYCL_LANGUAGE_VERSION)
791 block_buf_idx =
static_cast<index_t>(bi);
793 auto iter = hashmap_impl.find(key);
794 if (iter == hashmap_impl.end())
return -1;
795 block_buf_idx = iter->second;
797 cache.
Update(x_b, y_b, z_b, block_buf_idx);
805 return block_buf_idx * resolution3 + z_v * resolution2 +
806 y_v * block_resolution + x_v;
809 index_t y = workload_idx / cols;
810 index_t x = workload_idx % cols;
812 const float* range = range_indexer.
GetDataPtr<
float>(
813 x / range_map_down_factor, y / range_map_down_factor);
815 float* depth_ptr =
nullptr;
816 float* vertex_ptr =
nullptr;
817 float* color_ptr =
nullptr;
818 float* normal_ptr =
nullptr;
820 int64_t* index_ptr =
nullptr;
821 bool* mask_ptr =
nullptr;
822 float* interp_ratio_ptr =
nullptr;
823 float* interp_ratio_dx_ptr =
nullptr;
824 float* interp_ratio_dy_ptr =
nullptr;
825 float* interp_ratio_dz_ptr =
nullptr;
828 vertex_ptr = vertex_indexer.
GetDataPtr<
float>(x, y);
834 depth_ptr = depth_indexer.
GetDataPtr<
float>(x, y);
838 normal_ptr = normal_indexer.
GetDataPtr<
float>(x, y);
845 mask_ptr = mask_indexer.
GetDataPtr<
bool>(x, y);
849 for (
int i = 0; i < 8; ++i) {
854 index_ptr = index_indexer.
GetDataPtr<int64_t>(x, y);
858 for (
int i = 0; i < 8; ++i) {
863 interp_ratio_ptr = interp_ratio_indexer.
GetDataPtr<
float>(x, y);
867 for (
int i = 0; i < 8; ++i) {
868 interp_ratio_ptr[i] = 0;
872 interp_ratio_dx_ptr =
873 interp_ratio_dx_indexer.
GetDataPtr<
float>(x, y);
877 for (
int i = 0; i < 8; ++i) {
878 interp_ratio_dx_ptr[i] = 0;
882 interp_ratio_dy_ptr =
883 interp_ratio_dy_indexer.
GetDataPtr<
float>(x, y);
887 for (
int i = 0; i < 8; ++i) {
888 interp_ratio_dy_ptr[i] = 0;
892 interp_ratio_dz_ptr =
893 interp_ratio_dz_indexer.
GetDataPtr<
float>(x, y);
897 for (
int i = 0; i < 8; ++i) {
898 interp_ratio_dz_ptr[i] = 0;
903 color_ptr = color_indexer.
GetDataPtr<
float>(x, y);
910 const float t_max = range[1];
911 if (
t >= t_max)
return;
914 float x_c = 0, y_c = 0, z_c = 0;
915 float x_g = 0, y_g = 0, z_g = 0;
916 float x_o = 0, y_o = 0, z_o = 0;
921 float tsdf_prev = -1.0f;
923 float sdf_trunc = voxel_size * trunc_voxel_multiplier;
930 c2w_transform_indexer.
Unproject(
static_cast<float>(x),
931 static_cast<float>(y), 1.0f, &x_c, &y_c,
933 c2w_transform_indexer.
RigidTransform(x_c, y_c, z_c, &x_g, &y_g, &z_g);
934 float x_d = (x_g - x_o);
935 float y_d = (y_g - y_o);
936 float z_d = (z_g - z_o);
939 bool surface_found =
false;
942 GetLinearIdxAtT(x_o, y_o, z_o, x_d, y_d, z_d,
t, cache);
944 if (linear_idx < 0) {
949 tsdf = tsdf_base_ptr[linear_idx];
950 w = weight_base_ptr[linear_idx];
951 if (tsdf_prev > 0 && w >= weight_threshold && tsdf <= 0) {
952 surface_found =
true;
956 float delta = tsdf * sdf_trunc;
957 t += delta < voxel_size ? voxel_size : delta;
963 (
t * tsdf_prev - t_prev * tsdf) / (tsdf_prev - tsdf);
964 x_g = x_o + t_intersect * x_d;
965 y_g = y_o + t_intersect * y_d;
966 z_g = z_o + t_intersect * z_d;
970 *depth_ptr = t_intersect * depth_scale;
974 x_g, y_g, z_g, vertex_ptr + 0, vertex_ptr + 1,
977 if (!visit_neighbors)
return;
985 float x_v = (x_g - float(x_b) * block_size) / voxel_size;
986 float y_v = (y_g - float(y_b) * block_size) / voxel_size;
987 float z_v = (z_g - float(z_b) * block_size) / voxel_size;
989 Key key(x_b, y_b, z_b);
992 if (block_buf_idx < 0) {
993#if defined(__CUDACC__)
994 auto iter = hashmap_impl.find(key);
995 if (iter == hashmap_impl.end())
return;
996 block_buf_idx = iter->second;
997#elif defined(SYCL_LANGUAGE_VERSION)
1000 block_buf_idx =
static_cast<index_t>(bi);
1002 auto iter = hashmap_impl.find(key);
1003 if (iter == hashmap_impl.end())
return;
1004 block_buf_idx = iter->second;
1006 cache.
Update(x_b, y_b, z_b, block_buf_idx);
1013 float ratio_x = x_v - float(x_v_floor);
1014 float ratio_y = y_v - float(y_v_floor);
1015 float ratio_z = z_v - float(z_v_floor);
1018 for (
index_t k = 0; k < 8; ++k) {
1019 index_t dx_v = (k & 1) > 0 ? 1 : 0;
1020 index_t dy_v = (k & 2) > 0 ? 1 : 0;
1021 index_t dz_v = (k & 4) > 0 ? 1 : 0;
1023 index_t linear_idx_k = GetLinearIdxAtP(
1024 x_b, y_b, z_b, x_v_floor + dx_v, y_v_floor + dy_v,
1025 z_v_floor + dz_v, block_buf_idx, cache);
1027 if (linear_idx_k >= 0 && weight_base_ptr[linear_idx_k] > 0) {
1028 float rx = dx_v * (ratio_x) + (1 - dx_v) * (1 - ratio_x);
1029 float ry = dy_v * (ratio_y) + (1 - dy_v) * (1 - ratio_y);
1030 float rz = dz_v * (ratio_z) + (1 - dz_v) * (1 - ratio_z);
1031 float r = rx * ry * rz;
1033 if (interp_ratio_ptr) {
1034 interp_ratio_ptr[k] = r;
1040 index_ptr[k] = linear_idx_k;
1043 float tsdf_k = tsdf_base_ptr[linear_idx_k];
1044 float interp_ratio_dx = ry * rz * (2 * dx_v - 1);
1045 float interp_ratio_dy = rx * rz * (2 * dy_v - 1);
1046 float interp_ratio_dz = rx * ry * (2 * dz_v - 1);
1048 if (interp_ratio_dx_ptr) {
1049 interp_ratio_dx_ptr[k] = interp_ratio_dx;
1051 if (interp_ratio_dy_ptr) {
1052 interp_ratio_dy_ptr[k] = interp_ratio_dy;
1054 if (interp_ratio_dz_ptr) {
1055 interp_ratio_dz_ptr[k] = interp_ratio_dz;
1059 normal_ptr[0] += interp_ratio_dx * tsdf_k;
1060 normal_ptr[1] += interp_ratio_dy * tsdf_k;
1061 normal_ptr[2] += interp_ratio_dz * tsdf_k;
1065 index_t color_linear_idx = linear_idx_k * 3;
1067 r * color_base_ptr[color_linear_idx + 0];
1069 r * color_base_ptr[color_linear_idx + 1];
1071 r * color_base_ptr[color_linear_idx + 2];
1081 color_ptr[0] /= sum_r;
1082 color_ptr[1] /= sum_r;
1083 color_ptr[2] /= sum_r;
1087 constexpr float EPSILON = 1e-5f;
1088 float norm = sqrt(normal_ptr[0] * normal_ptr[0] +
1089 normal_ptr[1] * normal_ptr[1] +
1090 normal_ptr[2] * normal_ptr[2]);
1091 norm = max(norm, EPSILON);
1092 w2c_transform_indexer.
Rotate(
1093 -normal_ptr[0] / norm, -normal_ptr[1] / norm,
1094 -normal_ptr[2] / norm, normal_ptr + 0,
1095 normal_ptr + 1, normal_ptr + 2);
1101#if defined(__CUDACC__)
1124 float weight_threshold,
1129 index_t resolution2 = resolution * resolution;
1130 index_t resolution3 = resolution2 * resolution;
1133 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
1143 if (!block_value_map.Contains(
"tsdf") ||
1144 !block_value_map.Contains(
"weight")) {
1146 "TSDF and/or weight not allocated in blocks, please implement "
1147 "customized integration.");
1149 const tsdf_t* tsdf_base_ptr =
1150 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
1151 const weight_t* weight_base_ptr =
1152 block_value_map.at(
"weight").GetDataPtr<weight_t>();
1153 const color_t* color_base_ptr =
nullptr;
1154 if (block_value_map.Contains(
"color")) {
1155 color_base_ptr = block_value_map.at(
"color").GetDataPtr<color_t>();
1159 index_t n = n_blocks * resolution3;
1162#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1164 block_keys.GetDevice());
1167 std::atomic<index_t> count_atomic(0);
1168 std::atomic<index_t>* count_ptr = &count_atomic;
1171 if (valid_size < 0) {
1173 "No estimated max point cloud size provided, using a 2-pass "
1174 "estimation. Surface extraction could be slow.");
1182 resolution, nb_block_masks_indexer,
1183 nb_block_indices_indexer);
1188 index_t workload_block_idx = workload_idx / resolution3;
1189 index_t block_idx = indices_ptr[workload_block_idx];
1190 index_t voxel_idx = workload_idx % resolution3;
1194 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1196 index_t linear_idx = block_idx * resolution3 + voxel_idx;
1197 float tsdf_o = tsdf_base_ptr[linear_idx];
1198 float weight_o = weight_base_ptr[linear_idx];
1199 if (weight_o <= weight_threshold)
return;
1202 for (
index_t i = 0; i < 3; ++i) {
1204 GetLinearIdx(xv + (i == 0), yv + (i == 1),
1205 zv + (i == 2), workload_block_idx);
1206 if (linear_idx_i < 0)
continue;
1208 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1209 float weight_i = weight_base_ptr[linear_idx_i];
1210 if (weight_i > weight_threshold && tsdf_i * tsdf_o < 0) {
1216#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1220 valid_size = (*count_ptr).load();
1225 if (
points.GetLength() == 0) {
1239 if (color_base_ptr) {
1249 nb_block_masks_indexer,
1250 nb_block_indices_indexer);
1254 index_t curr_block_idx,
float* n) {
1255 return DeviceGetNormal<tsdf_t>(
1256 tsdf_base_ptr, xo, yo, zo, curr_block_idx, n, resolution,
1257 nb_block_masks_indexer, nb_block_indices_indexer);
1261 index_t workload_block_idx = workload_idx / resolution3;
1262 index_t block_idx = indices_ptr[workload_block_idx];
1263 index_t voxel_idx = workload_idx % resolution3;
1268 block_keys_indexer.GetDataPtr<
index_t>(block_idx);
1269 index_t xb = block_key_ptr[0];
1270 index_t yb = block_key_ptr[1];
1271 index_t zb = block_key_ptr[2];
1275 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1277 index_t linear_idx = block_idx * resolution3 + voxel_idx;
1278 float tsdf_o = tsdf_base_ptr[linear_idx];
1279 float weight_o = weight_base_ptr[linear_idx];
1280 if (weight_o <= weight_threshold)
return;
1282 float no[3] = {0}, ne[3] = {0};
1285 GetNormal(xv, yv, zv, workload_block_idx, no);
1287 index_t x = xb * resolution + xv;
1288 index_t y = yb * resolution + yv;
1289 index_t z = zb * resolution + zv;
1292 for (
index_t i = 0; i < 3; ++i) {
1294 GetLinearIdx(xv + (i == 0), yv + (i == 1), zv + (i == 2),
1295 workload_block_idx);
1296 if (linear_idx_i < 0)
continue;
1298 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1299 float weight_i = weight_base_ptr[linear_idx_i];
1300 if (weight_i > weight_threshold && tsdf_i * tsdf_o < 0) {
1301 float ratio = (0 - tsdf_o) / (tsdf_i - tsdf_o);
1304 if (idx >= valid_size) {
1305#if defined(__CUDACC__)
1306 printf(
"Point cloud size larger than "
1307 "estimated, please increase the "
1313 float* point_ptr = point_indexer.
GetDataPtr<
float>(idx);
1314 point_ptr[0] = voxel_size * (x + ratio * int(i == 0));
1315 point_ptr[1] = voxel_size * (y + ratio * int(i == 1));
1316 point_ptr[2] = voxel_size * (z + ratio * int(i == 2));
1319 float* normal_ptr = normal_indexer.
GetDataPtr<
float>(idx);
1320 GetNormal(xv + (i == 0), yv + (i == 1), zv + (i == 2),
1321 workload_block_idx, ne);
1322 float nx = (1 - ratio) * no[0] + ratio * ne[0];
1323 float ny = (1 - ratio) * no[1] + ratio * ne[1];
1324 float nz = (1 - ratio) * no[2] + ratio * ne[2];
1325 float norm =
static_cast<float>(
1326 sqrt(nx * nx + ny * ny + nz * nz) + 1e-5);
1327 normal_ptr[0] = nx / norm;
1328 normal_ptr[1] = ny / norm;
1329 normal_ptr[2] = nz / norm;
1331 if (color_base_ptr) {
1332 float* color_ptr = color_indexer.
GetDataPtr<
float>(idx);
1333 const color_t* color_o_ptr =
1334 color_base_ptr + 3 * linear_idx;
1335 float r_o = color_o_ptr[0];
1336 float g_o = color_o_ptr[1];
1337 float b_o = color_o_ptr[2];
1339 const color_t* color_i_ptr =
1340 color_base_ptr + 3 * linear_idx_i;
1341 float r_i = color_i_ptr[0];
1342 float g_i = color_i_ptr[1];
1343 float b_i = color_i_ptr[2];
1345 color_ptr[0] = ((1 - ratio) * r_o + ratio * r_i) / 255.0f;
1346 color_ptr[1] = ((1 - ratio) * g_o + ratio * g_i) / 255.0f;
1347 color_ptr[2] = ((1 - ratio) * b_o + ratio * b_i) / 255.0f;
1353#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1356 index_t total_count = (*count_ptr).load();
1359 utility::LogDebug(
"{} vertices extracted", total_count);
1360 valid_size = total_count;
1362#if defined(BUILD_CUDA_MODULE) && defined(__CUDACC__)
1387 float weight_threshold,
1391 index_t resolution = block_resolution;
1392 index_t resolution3 = resolution * resolution * resolution;
1395 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
1396 index_t n_blocks =
static_cast<index_t>(block_indices.GetLength());
1404 {n_blocks, resolution, resolution, resolution, 4},
core::Int32,
1406 }
catch (
const std::runtime_error&) {
1408 "Unable to allocate assistance mesh structure for Marching "
1409 "Cubes with {} active voxel blocks. Please consider using a "
1410 "larger voxel size (currently {}) for TSDF integration, or "
1411 "using tsdf_volume.cpu() to perform mesh extraction on CPU.",
1412 n_blocks, voxel_size);
1416 ArrayIndexer mesh_structure_indexer(mesh_structure, 4);
1417 ArrayIndexer nb_block_masks_indexer(nb_block_masks, 2);
1418 ArrayIndexer nb_block_indices_indexer(nb_block_indices, 2);
1421 const index_t* indices_ptr = block_indices.GetDataPtr<
index_t>();
1422 const index_t* inv_indices_ptr = inv_block_indices.GetDataPtr<
index_t>();
1424 if (!block_value_map.Contains(
"tsdf") ||
1425 !block_value_map.Contains(
"weight")) {
1427 "TSDF and/or weight not allocated in blocks, please implement "
1428 "customized integration.");
1430 const tsdf_t* tsdf_base_ptr =
1431 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
1432 const weight_t* weight_base_ptr =
1433 block_value_map.at(
"weight").GetDataPtr<weight_t>();
1434 const color_t* color_base_ptr =
nullptr;
1435 if (block_value_map.Contains(
"color")) {
1436 color_base_ptr = block_value_map.at(
"color").GetDataPtr<color_t>();
1439 index_t n = n_blocks * resolution3;
1448 static_cast<index_t>(resolution),
1449 nb_block_masks_indexer,
1450 nb_block_indices_indexer);
1454 index_t workload_block_idx = widx / resolution3;
1455 index_t voxel_idx = widx % resolution3;
1459 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1464 for (
index_t i = 0; i < 8; ++i) {
1466 GetLinearIdx(xv + vtx_shifts[i][0], yv + vtx_shifts[i][1],
1467 zv + vtx_shifts[i][2], workload_block_idx);
1468 if (linear_idx_i < 0)
return;
1470 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1471 float weight_i = weight_base_ptr[linear_idx_i];
1472 if (weight_i <= weight_threshold)
return;
1474 table_idx |= ((tsdf_i < 0) ? (1 << i) : 0);
1478 xv, yv, zv, workload_block_idx);
1479 mesh_struct_ptr[3] = table_idx;
1481 if (table_idx == 0 || table_idx == 255)
return;
1484 index_t edges_with_vertices = edge_table[table_idx];
1485 for (
index_t i = 0; i < 12; ++i) {
1486 if (edges_with_vertices & (1 << i)) {
1487 index_t xv_i = xv + edge_shifts[i][0];
1488 index_t yv_i = yv + edge_shifts[i][1];
1489 index_t zv_i = zv + edge_shifts[i][2];
1490 index_t edge_i = edge_shifts[i][3];
1492 index_t dxb = xv_i / resolution;
1493 index_t dyb = yv_i / resolution;
1494 index_t dzb = zv_i / resolution;
1496 index_t nb_idx = (dxb + 1) + (dyb + 1) * 3 + (dzb + 1) * 9;
1500 workload_block_idx, nb_idx);
1503 xv_i - dxb * resolution,
1504 yv_i - dyb * resolution,
1505 zv_i - dzb * resolution,
1506 inv_indices_ptr[block_idx_i]);
1509 mesh_ptr_i[edge_i] = -1;
1515#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1520 std::atomic<index_t> count_atomic(0);
1521 std::atomic<index_t>* count_ptr = &count_atomic;
1524 if (vertex_count < 0) {
1527 index_t workload_block_idx = widx / resolution3;
1528 index_t voxel_idx = widx % resolution3;
1532 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1537 xv, yv, zv, workload_block_idx);
1540 if (mesh_struct_ptr[0] != -1 && mesh_struct_ptr[1] != -1 &&
1541 mesh_struct_ptr[2] != -1) {
1546 for (
index_t e = 0; e < 3; ++e) {
1547 index_t vertex_idx = mesh_struct_ptr[e];
1548 if (vertex_idx != -1)
continue;
1554#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1557 vertex_count = (*count_ptr).load();
1561 utility::LogDebug(
"Total vertex count = {}", vertex_count);
1568 if (color_base_ptr) {
1576#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1590 nb_block_masks_indexer,
1591 nb_block_indices_indexer);
1595 index_t curr_block_idx,
float* n) {
1596 return DeviceGetNormal<tsdf_t>(
1597 tsdf_base_ptr, xo, yo, zo, curr_block_idx, n, resolution,
1598 nb_block_masks_indexer, nb_block_indices_indexer);
1602 index_t workload_block_idx = widx / resolution3;
1603 index_t block_idx = indices_ptr[workload_block_idx];
1604 index_t voxel_idx = widx % resolution3;
1609 index_t xb = block_key_ptr[0];
1610 index_t yb = block_key_ptr[1];
1611 index_t zb = block_key_ptr[2];
1615 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1618 index_t x = xb * resolution + xv;
1619 index_t y = yb * resolution + yv;
1620 index_t z = zb * resolution + zv;
1624 xv, yv, zv, workload_block_idx);
1627 if (mesh_struct_ptr[0] != -1 && mesh_struct_ptr[1] != -1 &&
1628 mesh_struct_ptr[2] != -1) {
1633 index_t linear_idx = resolution3 * block_idx + voxel_idx;
1634 float tsdf_o = tsdf_base_ptr[linear_idx];
1636 float no[3] = {0}, ne[3] = {0};
1639 GetNormal(xv, yv, zv, workload_block_idx, no);
1642 for (
index_t e = 0; e < 3; ++e) {
1643 index_t vertex_idx = mesh_struct_ptr[e];
1644 if (vertex_idx != -1)
continue;
1647 GetLinearIdx(xv + (e == 0), yv + (e == 1), zv + (e == 2),
1648 workload_block_idx);
1650 "Internal error: GetVoxelAt returns nullptr.");
1651 float tsdf_e = tsdf_base_ptr[linear_idx_e];
1652 float ratio = (0 - tsdf_o) / (tsdf_e - tsdf_o);
1655 mesh_struct_ptr[e] = idx;
1657 float ratio_x = ratio *
index_t(e == 0);
1658 float ratio_y = ratio *
index_t(e == 1);
1659 float ratio_z = ratio *
index_t(e == 2);
1661 float* vertex_ptr = vertex_indexer.
GetDataPtr<
float>(idx);
1662 vertex_ptr[0] = voxel_size * (x + ratio_x);
1663 vertex_ptr[1] = voxel_size * (y + ratio_y);
1664 vertex_ptr[2] = voxel_size * (z + ratio_z);
1667 float* normal_ptr = normal_indexer.GetDataPtr<
float>(idx);
1668 GetNormal(xv + (e == 0), yv + (e == 1), zv + (e == 2),
1669 workload_block_idx, ne);
1670 float nx = (1 - ratio) * no[0] + ratio * ne[0];
1671 float ny = (1 - ratio) * no[1] + ratio * ne[1];
1672 float nz = (1 - ratio) * no[2] + ratio * ne[2];
1673 float norm =
static_cast<float>(sqrt(nx * nx + ny * ny + nz * nz) +
1675 normal_ptr[0] = nx / norm;
1676 normal_ptr[1] = ny / norm;
1677 normal_ptr[2] = nz / norm;
1679 if (color_base_ptr) {
1680 float* color_ptr = color_indexer.
GetDataPtr<
float>(idx);
1681 float r_o = color_base_ptr[linear_idx * 3 + 0];
1682 float g_o = color_base_ptr[linear_idx * 3 + 1];
1683 float b_o = color_base_ptr[linear_idx * 3 + 2];
1685 float r_e = color_base_ptr[linear_idx_e * 3 + 0];
1686 float g_e = color_base_ptr[linear_idx_e * 3 + 1];
1687 float b_e = color_base_ptr[linear_idx_e * 3 + 2];
1689 color_ptr[0] = ((1 - ratio) * r_o + ratio * r_e) / 255.0f;
1690 color_ptr[1] = ((1 - ratio) * g_o + ratio * g_e) / 255.0f;
1691 color_ptr[2] = ((1 - ratio) * b_o + ratio * b_e) / 255.0f;
1697 index_t triangle_count = vertex_count * 3;
1701#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1709 index_t workload_block_idx = widx / resolution3;
1710 index_t voxel_idx = widx % resolution3;
1714 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1718 xv, yv, zv, workload_block_idx);
1720 index_t table_idx = mesh_struct_ptr[3];
1721 if (tri_count[table_idx] == 0)
return;
1723 for (
index_t tri = 0; tri < 16; tri += 3) {
1724 if (tri_table[table_idx][tri] == -1)
return;
1728 for (
index_t vertex = 0; vertex < 3; ++vertex) {
1729 index_t edge = tri_table[table_idx][tri + vertex];
1731 index_t xv_i = xv + edge_shifts[edge][0];
1732 index_t yv_i = yv + edge_shifts[edge][1];
1733 index_t zv_i = zv + edge_shifts[edge][2];
1734 index_t edge_i = edge_shifts[edge][3];
1736 index_t dxb = xv_i / resolution;
1737 index_t dyb = yv_i / resolution;
1738 index_t dzb = zv_i / resolution;
1740 index_t nb_idx = (dxb + 1) + (dyb + 1) * 3 + (dzb + 1) * 9;
1744 workload_block_idx, nb_idx);
1747 xv_i - dxb * resolution,
1748 yv_i - dyb * resolution,
1749 zv_i - dzb * resolution,
1750 inv_indices_ptr[block_idx_i]);
1753 triangle_indexer.GetDataPtr<
index_t>(tri_idx);
1754 triangle_ptr[2 - vertex] = mesh_struct_ptr_i[edge_i];
1759#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1762 triangle_count = (*count_ptr).load();
1764 utility::LogDebug(
"Total triangle count = {}", triangle_count);
1765 triangles = triangles.Slice(0, 0, triangle_count);