177 index_t resolution2 = resolution * resolution;
178 index_t resolution3 = resolution2 * resolution;
180 TransformIndexer transform_indexer(depth_intrinsic, extrinsics, voxel_size);
185 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
193 if (!block_value_map.Contains(
"tsdf") ||
194 !block_value_map.Contains(
"weight")) {
196 "TSDF and/or weight not allocated in blocks, please implement "
197 "customized integration.");
199 tsdf_t* tsdf_base_ptr = block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
200 weight_t* weight_base_ptr =
201 block_value_map.at(
"weight").GetDataPtr<weight_t>();
203 bool integrate_color =
204 block_value_map.Contains(
"color") &&
color.NumElements() > 0;
205 color_t* color_base_ptr =
nullptr;
208 float color_multiplier = 1.0;
209 if (integrate_color) {
210 color_base_ptr = block_value_map.at(
"color").
GetDataPtr<color_t>();
215 color_multiplier = 255.0;
222 index_t block_idx = indices_ptr[workload_idx / resolution3];
223 index_t voxel_idx = workload_idx % resolution3;
228 block_keys_indexer.GetDataPtr<
index_t>(block_idx);
235 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
243 float xc, yc, zc, u, v;
245 static_cast<float>(
y),
246 static_cast<float>(
z), &xc, &yc, &zc);
249 transform_indexer.
Project(xc, yc, zc, &u, &v);
260 *depth_indexer.
GetDataPtr<input_depth_t>(ui, vi) / depth_scale;
262 float sdf = depth - zc;
263 if (depth <= 0 || depth > depth_max || zc <= 0 || sdf < -sdf_trunc) {
266 sdf = sdf < sdf_trunc ? sdf : sdf_trunc;
269 index_t linear_idx = block_idx * resolution3 + voxel_idx;
271 tsdf_t* tsdf_ptr = tsdf_base_ptr + linear_idx;
272 weight_t* weight_ptr = weight_base_ptr + linear_idx;
274 float inv_wsum = 1.0f / (*weight_ptr + 1);
275 float weight = *weight_ptr;
276 *tsdf_ptr = (
weight * (*tsdf_ptr) + sdf) * inv_wsum;
278 if (integrate_color) {
279 color_t* color_ptr = color_base_ptr + 3 * linear_idx;
292 input_color_t* input_color_ptr =
293 color_indexer.
GetDataPtr<input_color_t>(ui, vi);
295 for (
index_t i = 0; i < 3; ++i) {
296 color_ptr[i] = (
weight * color_ptr[i] +
297 input_color_ptr[i] * color_multiplier) *
305#if defined(__CUDACC__)
324 int64_t block_resolution,
333 int h_down = h / down_factor;
334 int w_down = w / down_factor;
336 block_keys.GetDevice());
340 const int fragment_size = 16;
342 if (fragment_buffer.GetDataPtr() == 0 ||
343 fragment_buffer.NumElements() == 0) {
345 const int reserve_frag_buffer_size =
346 h_down * w_down / (fragment_size * fragment_size) / voxel_size;
347 fragment_buffer =
core::Tensor({reserve_frag_buffer_size, 6},
351 const int frag_buffer_size = fragment_buffer.NumElements() / 6;
356#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
358 block_keys.GetDevice());
359 int* count_ptr =
count.GetDataPtr<
int>();
361 std::atomic<int> count_atomic(0);
362 std::atomic<int>* count_ptr = &count_atomic;
365#if defined(__CUDACC__)
366#elif defined(SYCL_LANGUAGE_VERSION)
376 block_keys.GetDevice(), block_keys.GetLength(),
378 int* key = block_keys_indexer.
GetDataPtr<
int>(workload_idx);
380 int u_min = w_down - 1, v_min = h_down - 1, u_max = 0,
382 float z_min = depth_max, z_max = depth_min;
384 float xc, yc, zc, u, v;
387 for (
int i = 0; i < 8; ++i) {
388 float xw = (key[0] + ((i & 1) > 0)) * block_resolution *
390 float yw = (key[1] + ((i & 2) > 0)) * block_resolution *
392 float zw = (key[2] + ((i & 4) > 0)) * block_resolution *
397 if (zc <= 0)
continue;
400 w2c_transform_indexer.
Project(xc, yc, zc, &u, &v);
404 v_min = min(
static_cast<int>(floorf(v)), v_min);
405 v_max = max(
static_cast<int>(ceilf(v)), v_max);
407 u_min = min(
static_cast<int>(floorf(u)), u_min);
408 u_max = max(
static_cast<int>(ceilf(u)), u_max);
410 z_min = min(z_min, zc);
411 z_max = max(z_max, zc);
414 v_min = max(0, v_min);
415 v_max = min(h_down - 1, v_max);
417 u_min = max(0, u_min);
418 u_max = min(w_down - 1, u_max);
420 if (v_min >= v_max || u_min >= u_max || z_min >= z_max)
return;
424 ceilf(
float(v_max - v_min + 1) /
float(fragment_size));
426 ceilf(
float(u_max - u_min + 1) /
float(fragment_size));
428 int frag_count = frag_v_count * frag_u_count;
430 int frag_count_end = frag_count_start + frag_count;
431 if (frag_count_end >= frag_buffer_size) {
436 for (
int frag_v = 0; frag_v < frag_v_count; ++frag_v) {
437 for (
int frag_u = 0; frag_u < frag_u_count;
439 float* frag_ptr = frag_buffer_indexer.
GetDataPtr<
float>(
440 frag_count_start +
offset);
446 frag_ptr[2] = v_min + frag_v * fragment_size;
447 frag_ptr[3] = u_min + frag_u * fragment_size;
450 frag_ptr[4] = min(frag_ptr[2] + fragment_size - 1,
451 static_cast<float>(v_max));
452 frag_ptr[5] = min(frag_ptr[3] + fragment_size - 1,
453 static_cast<float>(u_max));
457#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
458 int needed_frag_count =
count[0].Item<
int>();
460 int needed_frag_count = (*count_ptr).load();
463 int frag_count = needed_frag_count;
464 if (frag_count >= frag_buffer_size) {
466 "Could not generate full range map; allocated {} fragments but "
468 frag_buffer_size, frag_count);
469 frag_count = frag_buffer_size - 1;
471 utility::LogDebug(
"EstimateRange Allocated {} fragments and needed {}",
472 frag_buffer_size, frag_count);
478 int v = workload_idx / w_down;
479 int u = workload_idx % w_down;
482 range_ptr[0] = depth_max;
483 range_ptr[1] = depth_min;
490#if !defined(__CUDACC__) && !defined(SYCL_LANGUAGE_VERSION)
491 tbb::spin_mutex estimate_range_mutex;
492 tbb::profiling::set_name(estimate_range_mutex,
"EstimateRangeCPU");
493#define LOCAL_LAMBDA_CAPTURE =, &estimate_range_mutex
495#define LOCAL_LAMBDA_CAPTURE =
499 block_keys.GetDevice(), frag_count * fragment_size * fragment_size,
501 int frag_idx = workload_idx / (fragment_size * fragment_size);
502 int local_idx = workload_idx % (fragment_size * fragment_size);
503 int dv = local_idx / fragment_size;
504 int du = local_idx % fragment_size;
507 frag_buffer_indexer.
GetDataPtr<
float>(frag_idx);
508 int v_min =
static_cast<int>(frag_ptr[2]);
509 int u_min =
static_cast<int>(frag_ptr[3]);
510 int v_max =
static_cast<int>(frag_ptr[4]);
511 int u_max =
static_cast<int>(frag_ptr[5]);
515 if (v > v_max || u > u_max)
return;
517 float z_min = frag_ptr[0];
518 float z_max = frag_ptr[1];
519 float* range_ptr = range_map_indexer.
GetDataPtr<
float>(u, v);
520#if defined(__CUDACC__)
521 atomicMinf(&(range_ptr[0]), z_min);
522 atomicMaxf(&(range_ptr[1]), z_max);
523#elif defined(SYCL_LANGUAGE_VERSION)
524 sycl::atomic_ref<float, sycl::memory_order::acq_rel,
525 sycl::memory_scope::device,
526 sycl::access::address_space::global_space>(
529 sycl::atomic_ref<float, sycl::memory_order::acq_rel,
530 sycl::memory_scope::device,
531 sycl::access::address_space::global_space>(
536 tbb::spin_mutex::scoped_lock lock(estimate_range_mutex);
537 range_ptr[0] = min(z_min, range_ptr[0]);
538 range_ptr[1] = max(z_max, range_ptr[1]);
543#if defined(__CUDACC__)
546#undef LOCAL_LAMBDA_CAPTURE
548 if (needed_frag_count != frag_count) {
549 utility::LogInfo(
"Reallocating {} fragments for EstimateRange (was {})",
550 needed_frag_count, frag_count);
553 block_keys.GetDevice());
586 (std::shared_ptr<core::HashMap>& hashmap,
599 float weight_threshold,
600 float trunc_voxel_multiplier,
601 int range_map_down_factor) {
606 auto device_hashmap = hashmap->GetDeviceHashBackend();
607#if defined(__CUDACC__)
609 std::dynamic_pointer_cast<core::StdGPUHashBackend<Key, Hash, Eq>>(
611 if (cuda_hashmap ==
nullptr) {
613 "Unsupported backend: CUDA raycasting only supports STDGPU.");
615 auto hashmap_impl = cuda_hashmap->GetImpl();
616#elif defined(SYCL_LANGUAGE_VERSION)
618 std::dynamic_pointer_cast<core::SYCLHashBackend<Key, Hash, Eq>>(
620 if (sycl_hashmap ==
nullptr) {
622 "Unsupported backend: SYCL raycasting requires the SYCL "
625 auto sycl_hash_lookup = sycl_hashmap->GetDeviceLookup();
628 std::dynamic_pointer_cast<core::TBBHashBackend<Key, Hash, Eq>>(
630 if (cpu_hashmap ==
nullptr) {
632 "Unsupported backend: CPU raycasting only supports TBB.");
634 auto hashmap_impl = *cpu_hashmap->GetImpl();
657 if (!block_value_map.Contains(
"tsdf") ||
658 !block_value_map.Contains(
"weight")) {
660 "TSDF and/or weight not allocated in blocks, please implement "
661 "customized integration.");
663 const tsdf_t* tsdf_base_ptr =
664 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
665 const weight_t* weight_base_ptr =
666 block_value_map.at(
"weight").GetDataPtr<weight_t>();
669 if (renderings_map.Contains(
"depth")) {
670 depth_indexer =
ArrayIndexer(renderings_map.at(
"depth"), 2);
672 if (renderings_map.Contains(
"vertex")) {
673 vertex_indexer =
ArrayIndexer(renderings_map.at(
"vertex"), 2);
675 if (renderings_map.Contains(
"normal")) {
676 normal_indexer =
ArrayIndexer(renderings_map.at(
"normal"), 2);
680 if (renderings_map.Contains(
"index")) {
681 index_indexer =
ArrayIndexer(renderings_map.at(
"index"), 2);
683 if (renderings_map.Contains(
"mask")) {
684 mask_indexer =
ArrayIndexer(renderings_map.at(
"mask"), 2);
686 if (renderings_map.Contains(
"interp_ratio")) {
687 interp_ratio_indexer =
690 if (renderings_map.Contains(
"interp_ratio_dx")) {
691 interp_ratio_dx_indexer =
694 if (renderings_map.Contains(
"interp_ratio_dy")) {
695 interp_ratio_dy_indexer =
698 if (renderings_map.Contains(
"interp_ratio_dz")) {
699 interp_ratio_dz_indexer =
704 bool render_color =
false;
705 if (block_value_map.Contains(
"color") && renderings_map.Contains(
"color")) {
707 color_indexer =
ArrayIndexer(renderings_map.at(
"color"), 2);
709 const color_t* color_base_ptr =
710 render_color ? block_value_map.at(
"color").GetDataPtr<color_t>()
713 bool visit_neighbors = render_color || normal_indexer.
GetDataPtr() ||
729 float block_size = voxel_size * block_resolution;
730 index_t resolution2 = block_resolution * block_resolution;
731 index_t resolution3 = resolution2 * block_resolution;
736#elif defined(SYCL_LANGUAGE_VERSION)
747 index_t x_vn = (x_v + block_resolution) % block_resolution;
748 index_t y_vn = (y_v + block_resolution) % block_resolution;
749 index_t z_vn = (z_v + block_resolution) % block_resolution;
755 if (dx_b == 0 && dy_b == 0 && dz_b == 0) {
756 return block_buf_idx * resolution3 + z_v * resolution2 +
757 y_v * block_resolution + x_v;
759 Key key(x_b + dx_b, y_b + dy_b, z_b + dz_b);
761 index_t block_buf_idx = cache.
Check(key[0], key[1], key[2]);
762 if (block_buf_idx < 0) {
763#if defined(__CUDACC__)
764 auto iter = hashmap_impl.find(key);
765 if (iter == hashmap_impl.end())
return -1;
766 block_buf_idx = iter->second;
767#elif defined(SYCL_LANGUAGE_VERSION)
770 block_buf_idx =
static_cast<index_t>(bi);
772 auto iter = hashmap_impl.find(key);
773 if (iter == hashmap_impl.end())
return -1;
774 block_buf_idx = iter->second;
776 cache.
Update(key[0], key[1], key[2], block_buf_idx);
779 return block_buf_idx * resolution3 + z_vn * resolution2 +
780 y_vn * block_resolution + x_vn;
785 float x_o,
float y_o,
float z_o,
786 float x_d,
float y_d,
float z_d,
float t,
788 float x_g = x_o +
t * x_d;
789 float y_g = y_o +
t * y_d;
790 float z_g = z_o +
t * z_d;
797 Key key(x_b, y_b, z_b);
799 if (block_buf_idx < 0) {
800#if defined(__CUDACC__)
801 auto iter = hashmap_impl.find(key);
802 if (iter == hashmap_impl.end())
return -1;
803 block_buf_idx = iter->second;
804#elif defined(SYCL_LANGUAGE_VERSION)
807 block_buf_idx =
static_cast<index_t>(bi);
809 auto iter = hashmap_impl.find(key);
810 if (iter == hashmap_impl.end())
return -1;
811 block_buf_idx = iter->second;
813 cache.
Update(x_b, y_b, z_b, block_buf_idx);
821 return block_buf_idx * resolution3 + z_v * resolution2 +
822 y_v * block_resolution + x_v;
828 const float* range = range_indexer.
GetDataPtr<
float>(
829 x / range_map_down_factor,
y / range_map_down_factor);
831 float* depth_ptr =
nullptr;
832 float* vertex_ptr =
nullptr;
833 float* color_ptr =
nullptr;
834 float* normal_ptr =
nullptr;
836 int64_t* index_ptr =
nullptr;
837 bool* mask_ptr =
nullptr;
838 float* interp_ratio_ptr =
nullptr;
839 float* interp_ratio_dx_ptr =
nullptr;
840 float* interp_ratio_dy_ptr =
nullptr;
841 float* interp_ratio_dz_ptr =
nullptr;
865 for (
int i = 0; i < 8; ++i) {
874 for (
int i = 0; i < 8; ++i) {
879 interp_ratio_ptr = interp_ratio_indexer.
GetDataPtr<
float>(
x,
y);
883 for (
int i = 0; i < 8; ++i) {
884 interp_ratio_ptr[i] = 0;
888 interp_ratio_dx_ptr =
893 for (
int i = 0; i < 8; ++i) {
894 interp_ratio_dx_ptr[i] = 0;
898 interp_ratio_dy_ptr =
903 for (
int i = 0; i < 8; ++i) {
904 interp_ratio_dy_ptr[i] = 0;
908 interp_ratio_dz_ptr =
913 for (
int i = 0; i < 8; ++i) {
914 interp_ratio_dz_ptr[i] = 0;
926 const float t_max = range[1];
927 if (
t >= t_max)
return;
930 float x_c = 0, y_c = 0, z_c = 0;
931 float x_g = 0, y_g = 0, z_g = 0;
932 float x_o = 0, y_o = 0, z_o = 0;
937 float tsdf_prev = -1.0f;
939 float sdf_trunc = voxel_size * trunc_voxel_multiplier;
946 c2w_transform_indexer.
Unproject(
static_cast<float>(
x),
947 static_cast<float>(
y), 1.0f, &x_c, &y_c,
949 c2w_transform_indexer.
RigidTransform(x_c, y_c, z_c, &x_g, &y_g, &z_g);
950 float x_d = (x_g - x_o);
951 float y_d = (y_g - y_o);
952 float z_d = (z_g - z_o);
955 bool surface_found =
false;
958 GetLinearIdxAtT(x_o, y_o, z_o, x_d, y_d, z_d,
t, cache);
960 if (linear_idx < 0) {
965 tsdf = tsdf_base_ptr[linear_idx];
966 w = weight_base_ptr[linear_idx];
967 if (tsdf_prev > 0 && w >= weight_threshold && tsdf <= 0) {
968 surface_found =
true;
972 float delta = tsdf * sdf_trunc;
973 t += delta < voxel_size ? voxel_size : delta;
979 (
t * tsdf_prev - t_prev * tsdf) / (tsdf_prev - tsdf);
980 x_g = x_o + t_intersect * x_d;
981 y_g = y_o + t_intersect * y_d;
982 z_g = z_o + t_intersect * z_d;
986 *depth_ptr = t_intersect * depth_scale;
990 x_g, y_g, z_g, vertex_ptr + 0, vertex_ptr + 1,
993 if (!visit_neighbors)
return;
1001 float x_v = (x_g - float(x_b) * block_size) / voxel_size;
1002 float y_v = (y_g - float(y_b) * block_size) / voxel_size;
1003 float z_v = (z_g - float(z_b) * block_size) / voxel_size;
1005 Key key(x_b, y_b, z_b);
1008 if (block_buf_idx < 0) {
1009#if defined(__CUDACC__)
1010 auto iter = hashmap_impl.find(key);
1011 if (iter == hashmap_impl.end())
return;
1012 block_buf_idx = iter->second;
1013#elif defined(SYCL_LANGUAGE_VERSION)
1016 block_buf_idx =
static_cast<index_t>(bi);
1018 auto iter = hashmap_impl.find(key);
1019 if (iter == hashmap_impl.end())
return;
1020 block_buf_idx = iter->second;
1022 cache.
Update(x_b, y_b, z_b, block_buf_idx);
1029 float ratio_x = x_v - float(x_v_floor);
1030 float ratio_y = y_v - float(y_v_floor);
1031 float ratio_z = z_v - float(z_v_floor);
1034 for (
index_t k = 0; k < 8; ++k) {
1035 index_t dx_v = (k & 1) > 0 ? 1 : 0;
1036 index_t dy_v = (k & 2) > 0 ? 1 : 0;
1037 index_t dz_v = (k & 4) > 0 ? 1 : 0;
1039 index_t linear_idx_k = GetLinearIdxAtP(
1040 x_b, y_b, z_b, x_v_floor + dx_v, y_v_floor + dy_v,
1041 z_v_floor + dz_v, block_buf_idx, cache);
1043 if (linear_idx_k >= 0 && weight_base_ptr[linear_idx_k] > 0) {
1044 float rx = dx_v * (ratio_x) + (1 - dx_v) * (1 - ratio_x);
1045 float ry = dy_v * (ratio_y) + (1 - dy_v) * (1 - ratio_y);
1046 float rz = dz_v * (ratio_z) + (1 - dz_v) * (1 - ratio_z);
1047 float r = rx * ry * rz;
1049 if (interp_ratio_ptr) {
1050 interp_ratio_ptr[k] = r;
1056 index_ptr[k] = linear_idx_k;
1059 float tsdf_k = tsdf_base_ptr[linear_idx_k];
1060 float interp_ratio_dx = ry * rz * (2 * dx_v - 1);
1061 float interp_ratio_dy = rx * rz * (2 * dy_v - 1);
1062 float interp_ratio_dz = rx * ry * (2 * dz_v - 1);
1064 if (interp_ratio_dx_ptr) {
1065 interp_ratio_dx_ptr[k] = interp_ratio_dx;
1067 if (interp_ratio_dy_ptr) {
1068 interp_ratio_dy_ptr[k] = interp_ratio_dy;
1070 if (interp_ratio_dz_ptr) {
1071 interp_ratio_dz_ptr[k] = interp_ratio_dz;
1075 normal_ptr[0] += interp_ratio_dx * tsdf_k;
1076 normal_ptr[1] += interp_ratio_dy * tsdf_k;
1077 normal_ptr[2] += interp_ratio_dz * tsdf_k;
1081 index_t color_linear_idx = linear_idx_k * 3;
1083 r * color_base_ptr[color_linear_idx + 0];
1085 r * color_base_ptr[color_linear_idx + 1];
1087 r * color_base_ptr[color_linear_idx + 2];
1097 color_ptr[0] /= sum_r;
1098 color_ptr[1] /= sum_r;
1099 color_ptr[2] /= sum_r;
1103 constexpr float EPSILON = 1e-5f;
1104 float norm = sqrt(normal_ptr[0] * normal_ptr[0] +
1105 normal_ptr[1] * normal_ptr[1] +
1106 normal_ptr[2] * normal_ptr[2]);
1107 norm = max(norm, EPSILON);
1108 w2c_transform_indexer.
Rotate(
1109 -normal_ptr[0] / norm, -normal_ptr[1] / norm,
1110 -normal_ptr[2] / norm, normal_ptr + 0,
1111 normal_ptr + 1, normal_ptr + 2);
1117#if defined(__CUDACC__)
1140 float weight_threshold,
1145 index_t resolution2 = resolution * resolution;
1146 index_t resolution3 = resolution2 * resolution;
1149 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
1159 if (!block_value_map.Contains(
"tsdf") ||
1160 !block_value_map.Contains(
"weight")) {
1162 "TSDF and/or weight not allocated in blocks, please implement "
1163 "customized integration.");
1165 const tsdf_t* tsdf_base_ptr =
1166 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
1167 const weight_t* weight_base_ptr =
1168 block_value_map.at(
"weight").GetDataPtr<weight_t>();
1169 const color_t* color_base_ptr =
nullptr;
1170 if (block_value_map.Contains(
"color")) {
1171 color_base_ptr = block_value_map.at(
"color").GetDataPtr<color_t>();
1175 index_t n = n_blocks * resolution3;
1178#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1180 block_keys.GetDevice());
1183 std::atomic<index_t> count_atomic(0);
1184 std::atomic<index_t>* count_ptr = &count_atomic;
1187 if (valid_size < 0) {
1189 "No estimated max point cloud size provided, using a 2-pass "
1190 "estimation. Surface extraction could be slow.");
1198 resolution, nb_block_masks_indexer,
1199 nb_block_indices_indexer);
1204 index_t workload_block_idx = workload_idx / resolution3;
1205 index_t block_idx = indices_ptr[workload_block_idx];
1206 index_t voxel_idx = workload_idx % resolution3;
1210 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1212 index_t linear_idx = block_idx * resolution3 + voxel_idx;
1213 float tsdf_o = tsdf_base_ptr[linear_idx];
1214 float weight_o = weight_base_ptr[linear_idx];
1215 if (weight_o <= weight_threshold)
return;
1218 for (
index_t i = 0; i < 3; ++i) {
1220 GetLinearIdx(xv + (i == 0), yv + (i == 1),
1221 zv + (i == 2), workload_block_idx);
1222 if (linear_idx_i < 0)
continue;
1224 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1225 float weight_i = weight_base_ptr[linear_idx_i];
1226 if (weight_i > weight_threshold && tsdf_i * tsdf_o < 0) {
1232#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1236 valid_size = (*count_ptr).load();
1241 if (
points.GetLength() == 0) {
1255 if (color_base_ptr) {
1265 nb_block_masks_indexer,
1266 nb_block_indices_indexer);
1270 index_t curr_block_idx,
float* n) {
1271 return DeviceGetNormal<tsdf_t>(
1272 tsdf_base_ptr, xo, yo, zo, curr_block_idx, n, resolution,
1273 nb_block_masks_indexer, nb_block_indices_indexer);
1277 index_t workload_block_idx = workload_idx / resolution3;
1278 index_t block_idx = indices_ptr[workload_block_idx];
1279 index_t voxel_idx = workload_idx % resolution3;
1284 block_keys_indexer.GetDataPtr<
index_t>(block_idx);
1285 index_t xb = block_key_ptr[0];
1286 index_t yb = block_key_ptr[1];
1287 index_t zb = block_key_ptr[2];
1291 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1293 index_t linear_idx = block_idx * resolution3 + voxel_idx;
1294 float tsdf_o = tsdf_base_ptr[linear_idx];
1295 float weight_o = weight_base_ptr[linear_idx];
1296 if (weight_o <= weight_threshold)
return;
1298 float no[3] = {0}, ne[3] = {0};
1301 GetNormal(xv, yv, zv, workload_block_idx, no);
1308 for (
index_t i = 0; i < 3; ++i) {
1310 GetLinearIdx(xv + (i == 0), yv + (i == 1), zv + (i == 2),
1311 workload_block_idx);
1312 if (linear_idx_i < 0)
continue;
1314 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1315 float weight_i = weight_base_ptr[linear_idx_i];
1316 if (weight_i > weight_threshold && tsdf_i * tsdf_o < 0) {
1317 float ratio = (0 - tsdf_o) / (tsdf_i - tsdf_o);
1320 if (idx >= valid_size) {
1321#if defined(__CUDACC__)
1322 printf(
"Point cloud size larger than "
1323 "estimated, please increase the "
1329 float* point_ptr = point_indexer.
GetDataPtr<
float>(idx);
1330 point_ptr[0] = voxel_size * (
x + ratio * int(i == 0));
1331 point_ptr[1] = voxel_size * (
y + ratio * int(i == 1));
1332 point_ptr[2] = voxel_size * (
z + ratio * int(i == 2));
1335 float* normal_ptr = normal_indexer.
GetDataPtr<
float>(idx);
1336 GetNormal(xv + (i == 0), yv + (i == 1), zv + (i == 2),
1337 workload_block_idx, ne);
1338 float nx = (1 - ratio) * no[0] + ratio * ne[0];
1339 float ny = (1 - ratio) * no[1] + ratio * ne[1];
1340 float nz = (1 - ratio) * no[2] + ratio * ne[2];
1341 float norm =
static_cast<float>(
1342 sqrt(nx * nx + ny * ny + nz * nz) + 1e-5);
1343 normal_ptr[0] = nx / norm;
1344 normal_ptr[1] = ny / norm;
1345 normal_ptr[2] = nz / norm;
1347 if (color_base_ptr) {
1348 float* color_ptr = color_indexer.
GetDataPtr<
float>(idx);
1349 const color_t* color_o_ptr =
1350 color_base_ptr + 3 * linear_idx;
1351 float r_o = color_o_ptr[0];
1352 float g_o = color_o_ptr[1];
1353 float b_o = color_o_ptr[2];
1355 const color_t* color_i_ptr =
1356 color_base_ptr + 3 * linear_idx_i;
1357 float r_i = color_i_ptr[0];
1358 float g_i = color_i_ptr[1];
1359 float b_i = color_i_ptr[2];
1361 color_ptr[0] = ((1 - ratio) * r_o + ratio * r_i) / 255.0f;
1362 color_ptr[1] = ((1 - ratio) * g_o + ratio * g_i) / 255.0f;
1363 color_ptr[2] = ((1 - ratio) * b_o + ratio * b_i) / 255.0f;
1369#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1372 index_t total_count = (*count_ptr).load();
1375 utility::LogDebug(
"{} vertices extracted", total_count);
1376 valid_size = total_count;
1378#if defined(BUILD_CUDA_MODULE) && defined(__CUDACC__)
1403 float weight_threshold,
1407 index_t resolution = block_resolution;
1408 index_t resolution3 = resolution * resolution * resolution;
1411 ArrayIndexer voxel_indexer({resolution, resolution, resolution});
1412 index_t n_blocks =
static_cast<index_t>(block_indices.GetLength());
1420 {n_blocks, resolution, resolution, resolution, 4},
core::Int32,
1422 }
catch (
const std::runtime_error&) {
1424 "Unable to allocate assistance mesh structure for Marching "
1425 "Cubes with {} active voxel blocks. Please consider using a "
1426 "larger voxel size (currently {}) for TSDF integration, or "
1427 "using tsdf_volume.cpu() to perform mesh extraction on CPU.",
1428 n_blocks, voxel_size);
1432 ArrayIndexer mesh_structure_indexer(mesh_structure, 4);
1433 ArrayIndexer nb_block_masks_indexer(nb_block_masks, 2);
1434 ArrayIndexer nb_block_indices_indexer(nb_block_indices, 2);
1437 const index_t* indices_ptr = block_indices.GetDataPtr<
index_t>();
1438 const index_t* inv_indices_ptr = inv_block_indices.GetDataPtr<
index_t>();
1440 if (!block_value_map.Contains(
"tsdf") ||
1441 !block_value_map.Contains(
"weight")) {
1443 "TSDF and/or weight not allocated in blocks, please implement "
1444 "customized integration.");
1446 const tsdf_t* tsdf_base_ptr =
1447 block_value_map.at(
"tsdf").GetDataPtr<tsdf_t>();
1448 const weight_t* weight_base_ptr =
1449 block_value_map.at(
"weight").GetDataPtr<weight_t>();
1450 const color_t* color_base_ptr =
nullptr;
1451 if (block_value_map.Contains(
"color")) {
1452 color_base_ptr = block_value_map.at(
"color").GetDataPtr<color_t>();
1455 index_t n = n_blocks * resolution3;
1464 static_cast<index_t>(resolution),
1465 nb_block_masks_indexer,
1466 nb_block_indices_indexer);
1470 index_t workload_block_idx = widx / resolution3;
1471 index_t voxel_idx = widx % resolution3;
1475 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1480 for (
index_t i = 0; i < 8; ++i) {
1482 GetLinearIdx(xv + vtx_shifts[i][0], yv + vtx_shifts[i][1],
1483 zv + vtx_shifts[i][2], workload_block_idx);
1484 if (linear_idx_i < 0)
return;
1486 float tsdf_i = tsdf_base_ptr[linear_idx_i];
1487 float weight_i = weight_base_ptr[linear_idx_i];
1488 if (weight_i <= weight_threshold)
return;
1490 table_idx |= ((tsdf_i < 0) ? (1 << i) : 0);
1494 xv, yv, zv, workload_block_idx);
1495 mesh_struct_ptr[3] = table_idx;
1497 if (table_idx == 0 || table_idx == 255)
return;
1500 index_t edges_with_vertices = edge_table[table_idx];
1501 for (
index_t i = 0; i < 12; ++i) {
1502 if (edges_with_vertices & (1 << i)) {
1503 index_t xv_i = xv + edge_shifts[i][0];
1504 index_t yv_i = yv + edge_shifts[i][1];
1505 index_t zv_i = zv + edge_shifts[i][2];
1506 index_t edge_i = edge_shifts[i][3];
1508 index_t dxb = xv_i / resolution;
1509 index_t dyb = yv_i / resolution;
1510 index_t dzb = zv_i / resolution;
1512 index_t nb_idx = (dxb + 1) + (dyb + 1) * 3 + (dzb + 1) * 9;
1516 workload_block_idx, nb_idx);
1519 xv_i - dxb * resolution,
1520 yv_i - dyb * resolution,
1521 zv_i - dzb * resolution,
1522 inv_indices_ptr[block_idx_i]);
1525 mesh_ptr_i[edge_i] = -1;
1531#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1536 std::atomic<index_t> count_atomic(0);
1537 std::atomic<index_t>* count_ptr = &count_atomic;
1540 if (vertex_count < 0) {
1543 index_t workload_block_idx = widx / resolution3;
1544 index_t voxel_idx = widx % resolution3;
1548 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1553 xv, yv, zv, workload_block_idx);
1556 if (mesh_struct_ptr[0] != -1 && mesh_struct_ptr[1] != -1 &&
1557 mesh_struct_ptr[2] != -1) {
1562 for (
index_t e = 0; e < 3; ++e) {
1563 index_t vertex_idx = mesh_struct_ptr[e];
1564 if (vertex_idx != -1)
continue;
1570#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1573 vertex_count = (*count_ptr).load();
1577 utility::LogDebug(
"Total vertex count = {}", vertex_count);
1584 if (color_base_ptr) {
1592#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1606 nb_block_masks_indexer,
1607 nb_block_indices_indexer);
1611 index_t curr_block_idx,
float* n) {
1612 return DeviceGetNormal<tsdf_t>(
1613 tsdf_base_ptr, xo, yo, zo, curr_block_idx, n, resolution,
1614 nb_block_masks_indexer, nb_block_indices_indexer);
1618 index_t workload_block_idx = widx / resolution3;
1619 index_t block_idx = indices_ptr[workload_block_idx];
1620 index_t voxel_idx = widx % resolution3;
1625 index_t xb = block_key_ptr[0];
1626 index_t yb = block_key_ptr[1];
1627 index_t zb = block_key_ptr[2];
1631 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1640 xv, yv, zv, workload_block_idx);
1643 if (mesh_struct_ptr[0] != -1 && mesh_struct_ptr[1] != -1 &&
1644 mesh_struct_ptr[2] != -1) {
1649 index_t linear_idx = resolution3 * block_idx + voxel_idx;
1650 float tsdf_o = tsdf_base_ptr[linear_idx];
1652 float no[3] = {0}, ne[3] = {0};
1655 GetNormal(xv, yv, zv, workload_block_idx, no);
1658 for (
index_t e = 0; e < 3; ++e) {
1659 index_t vertex_idx = mesh_struct_ptr[e];
1660 if (vertex_idx != -1)
continue;
1663 GetLinearIdx(xv + (e == 0), yv + (e == 1), zv + (e == 2),
1664 workload_block_idx);
1668 "Internal error: GetVoxelAt returns nullptr.");
1669 float tsdf_e = tsdf_base_ptr[linear_idx_e];
1670 float ratio = (0 - tsdf_o) / (tsdf_e - tsdf_o);
1673 mesh_struct_ptr[e] = idx;
1675 float ratio_x = ratio *
index_t(e == 0);
1676 float ratio_y = ratio *
index_t(e == 1);
1677 float ratio_z = ratio *
index_t(e == 2);
1679 float* vertex_ptr = vertex_indexer.
GetDataPtr<
float>(idx);
1680 vertex_ptr[0] = voxel_size * (
x + ratio_x);
1681 vertex_ptr[1] = voxel_size * (
y + ratio_y);
1682 vertex_ptr[2] = voxel_size * (
z + ratio_z);
1685 float* normal_ptr = normal_indexer.GetDataPtr<
float>(idx);
1686 GetNormal(xv + (e == 0), yv + (e == 1), zv + (e == 2),
1687 workload_block_idx, ne);
1688 float nx = (1 - ratio) * no[0] + ratio * ne[0];
1689 float ny = (1 - ratio) * no[1] + ratio * ne[1];
1690 float nz = (1 - ratio) * no[2] + ratio * ne[2];
1691 float norm =
static_cast<float>(sqrt(nx * nx + ny * ny + nz * nz) +
1693 normal_ptr[0] = nx / norm;
1694 normal_ptr[1] = ny / norm;
1695 normal_ptr[2] = nz / norm;
1697 if (color_base_ptr) {
1698 float* color_ptr = color_indexer.
GetDataPtr<
float>(idx);
1699 float r_o = color_base_ptr[linear_idx * 3 + 0];
1700 float g_o = color_base_ptr[linear_idx * 3 + 1];
1701 float b_o = color_base_ptr[linear_idx * 3 + 2];
1703 float r_e = color_base_ptr[linear_idx_e * 3 + 0];
1704 float g_e = color_base_ptr[linear_idx_e * 3 + 1];
1705 float b_e = color_base_ptr[linear_idx_e * 3 + 2];
1707 color_ptr[0] = ((1 - ratio) * r_o + ratio * r_e) / 255.0f;
1708 color_ptr[1] = ((1 - ratio) * g_o + ratio * g_e) / 255.0f;
1709 color_ptr[2] = ((1 - ratio) * b_o + ratio * b_e) / 255.0f;
1715 index_t triangle_count = vertex_count * 3;
1719#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1727 index_t workload_block_idx = widx / resolution3;
1728 index_t voxel_idx = widx % resolution3;
1732 voxel_indexer.WorkloadToCoord(voxel_idx, &xv, &yv, &zv);
1736 xv, yv, zv, workload_block_idx);
1738 index_t table_idx = mesh_struct_ptr[3];
1739 if (tri_count[table_idx] == 0)
return;
1741 for (
index_t tri = 0; tri < 16; tri += 3) {
1742 if (tri_table[table_idx][tri] == -1)
return;
1746 for (
index_t vertex = 0; vertex < 3; ++vertex) {
1747 index_t edge = tri_table[table_idx][tri + vertex];
1749 index_t xv_i = xv + edge_shifts[edge][0];
1750 index_t yv_i = yv + edge_shifts[edge][1];
1751 index_t zv_i = zv + edge_shifts[edge][2];
1752 index_t edge_i = edge_shifts[edge][3];
1754 index_t dxb = xv_i / resolution;
1755 index_t dyb = yv_i / resolution;
1756 index_t dzb = zv_i / resolution;
1758 index_t nb_idx = (dxb + 1) + (dyb + 1) * 3 + (dzb + 1) * 9;
1762 workload_block_idx, nb_idx);
1765 xv_i - dxb * resolution,
1766 yv_i - dyb * resolution,
1767 zv_i - dzb * resolution,
1768 inv_indices_ptr[block_idx_i]);
1771 triangle_indexer.GetDataPtr<
index_t>(tri_idx);
1772 triangle_ptr[2 - vertex] = mesh_struct_ptr_i[edge_i];
1777#if defined(__CUDACC__) || defined(SYCL_LANGUAGE_VERSION)
1780 triangle_count = (*count_ptr).load();
1782 utility::LogDebug(
"Total triangle count = {}", triangle_count);
1783 triangles = triangles.Slice(0, 0, triangle_count);