conquer3d 0.5.2__tar.gz → 0.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. {conquer3d-0.5.2/conquer3d.egg-info → conquer3d-0.5.4}/PKG-INFO +1 -1
  2. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/_C.so +0 -0
  3. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/grid.cpp +149 -14
  4. conquer3d-0.5.4/conquer3d/csrc/binds/ops/volint.cpp +96 -0
  5. conquer3d-0.5.4/conquer3d/csrc/data_structure/grid.cu +109 -0
  6. conquer3d-0.5.4/conquer3d/csrc/data_structure/grid.h +22 -0
  7. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f4x4.h +1 -0
  8. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mc.cu +50 -44
  9. conquer3d-0.5.4/conquer3d/csrc/ops/volint.cu +121 -0
  10. conquer3d-0.5.4/conquer3d/csrc/ops/volint.h +23 -0
  11. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/pybind.cpp +2 -0
  12. conquer3d-0.5.4/conquer3d/data/dataset/__init__.py +14 -0
  13. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/dataset/digit3d.py +42 -10
  14. conquer3d-0.5.4/conquer3d/data/dataset/redwood.py +138 -0
  15. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data_structure/__init__.py +5 -1
  16. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data_structure/grid.py +43 -8
  17. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/__init__.py +3 -1
  18. conquer3d-0.5.4/conquer3d/ops/volint.py +55 -0
  19. {conquer3d-0.5.2 → conquer3d-0.5.4/conquer3d.egg-info}/PKG-INFO +1 -1
  20. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d.egg-info/SOURCES.txt +7 -0
  21. {conquer3d-0.5.2 → conquer3d-0.5.4}/pyproject.toml +1 -1
  22. {conquer3d-0.5.2 → conquer3d-0.5.4}/setup.py +5 -0
  23. conquer3d-0.5.2/conquer3d/data/dataset/__init__.py +0 -5
  24. {conquer3d-0.5.2 → conquer3d-0.5.4}/LICENSE +0 -0
  25. {conquer3d-0.5.2 → conquer3d-0.5.4}/MANIFEST.in +0 -0
  26. {conquer3d-0.5.2 → conquer3d-0.5.4}/README.md +0 -0
  27. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/_C.pyi +0 -0
  28. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/__init__.py +0 -0
  29. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/conversion/__init__.py +0 -0
  30. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/conversion/grid.py +0 -0
  31. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/conversion/mesh.py +0 -0
  32. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/conversion/tmesh.py +0 -0
  33. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/creation/__init__.py +0 -0
  34. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/creation/triangle_creation.py +0 -0
  35. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
  36. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
  37. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
  38. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
  39. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
  40. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
  41. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
  42. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/data_structure/zcurve.cpp +0 -0
  43. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
  44. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/ops/flood_fill.cpp +0 -0
  45. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/ops/mc.cpp +0 -0
  46. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/ops/mtg.cpp +0 -0
  47. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
  48. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
  49. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/primitive/ray.cpp +0 -0
  50. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/binds/primitive/triangle.cpp +0 -0
  51. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/check.h +0 -0
  52. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/constants.h +0 -0
  53. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/creation/triangle_creation.h +0 -0
  54. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/bvh.cu +0 -0
  55. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/bvh.h +0 -0
  56. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
  57. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
  58. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/kdtree.h +0 -0
  59. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
  60. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
  61. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
  62. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
  63. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
  64. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/zcurve.cu +0 -0
  65. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/data_structure/zcurve.h +0 -0
  66. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f2x2.h +0 -0
  67. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f3x1.h +0 -0
  68. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f3x3.h +0 -0
  69. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f3x4.h +0 -0
  70. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/f4x1.h +0 -0
  71. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/maths.h +0 -0
  72. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/maths/ops.h +0 -0
  73. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/chamfer.cu +0 -0
  74. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/chamfer.h +0 -0
  75. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/flood_fill.cu +0 -0
  76. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/flood_fill.h +0 -0
  77. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mc.h +0 -0
  78. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mc_data.h +0 -0
  79. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mtg.cu +0 -0
  80. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mtg.h +0 -0
  81. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/ops/mtg_data.h +0 -0
  82. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/aabb.h +0 -0
  83. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/edge.h +0 -0
  84. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/gs.cu +0 -0
  85. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/gs.h +0 -0
  86. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
  87. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
  88. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/pgs.cu +0 -0
  89. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/pgs.h +0 -0
  90. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
  91. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
  92. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/ray.h +0 -0
  93. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/csrc/primitive/triangle.h +0 -0
  94. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/__init__.py +0 -0
  95. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/assets/__init__.py +0 -0
  96. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/assets/common.py +0 -0
  97. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/assets/iphigenia.py +0 -0
  98. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/collate/__init__.py +0 -0
  99. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/collate/mesh.py +0 -0
  100. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/collate/sparse_tensor.py +0 -0
  101. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/dataset/base_mesh.py +0 -0
  102. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/dataset/mesh.py +0 -0
  103. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/transform/__init__.py +0 -0
  104. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/transform/base.py +0 -0
  105. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/transform/ops.py +0 -0
  106. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data/transform/vertex.py +0 -0
  107. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data_structure/bmesh.py +0 -0
  108. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/data_structure/sort.py +0 -0
  109. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/io/__init__.py +0 -0
  110. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/io/obj.py +0 -0
  111. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/io/off.py +0 -0
  112. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/delaunay_triangulation.py +0 -0
  113. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/diff_marching_cubes.py +0 -0
  114. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/diff_marching_tetrahedra_grid.py +0 -0
  115. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/distance.py +0 -0
  116. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/marching_cubes.py +0 -0
  117. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/marching_tetrahedra.py +0 -0
  118. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/ops/marching_tetrahedra_grid.py +0 -0
  119. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/primitive/__init__.py +0 -0
  120. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/primitive/gs.py +0 -0
  121. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d/primitive/pgs.py +0 -0
  122. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d.egg-info/dependency_links.txt +0 -0
  123. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d.egg-info/not-zip-safe +0 -0
  124. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d.egg-info/requires.txt +0 -0
  125. {conquer3d-0.5.2 → conquer3d-0.5.4}/conquer3d.egg-info/top_level.txt +0 -0
  126. {conquer3d-0.5.2 → conquer3d-0.5.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conquer3d
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: Geometric Cuda Tool Box
5
5
  Author-email: Do Hoang Khoi <khoido8899@gmail.com>
6
6
  License-Expression: MIT
@@ -6,14 +6,17 @@
6
6
  #include <vector>
7
7
  #include "../../data_structure/mesh_bvh.h"
8
8
  #include "../../data_structure/triangle_mesh.h"
9
+ #include "../../data_structure/grid.h"
10
+ #include <cuda_runtime.h>
9
11
 
10
12
  namespace py = pybind11;
11
13
 
12
- std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid(
14
+ std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>> create_voxel_grid(
13
15
  std::vector<float> grid_min,
14
16
  std::vector<float> grid_max,
15
17
  std::vector<int64_t> res,
16
- std::string device_str
18
+ std::string device_str,
19
+ bool return_idx_grids
17
20
  ) {
18
21
  TORCH_CHECK(grid_min.size() == 3, "grid_min must have 3 elements.");
19
22
  TORCH_CHECK(grid_max.size() == 3, "grid_max must have 3 elements.");
@@ -59,13 +62,16 @@ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid(
59
62
 
60
63
  auto voxels = torch::stack({v0, v1, v2, v3, v4, v5, v6, v7}, -1).view({-1, 8}).contiguous().to(torch::kInt32);
61
64
 
62
- auto i_v = torch::arange(rx, options_int);
63
- auto j_v = torch::arange(ry, options_int);
64
- auto k_v = torch::arange(rz, options_int);
65
- auto idx_grids_v = torch::meshgrid({i_v, j_v, k_v}, "ij");
66
- auto out_idx_grids = torch::stack({idx_grids_v[0].flatten(), idx_grids_v[1].flatten(), idx_grids_v[2].flatten()}, -1).contiguous();
65
+ std::optional<torch::Tensor> opt_idx_grids = std::nullopt;
66
+ if (return_idx_grids) {
67
+ auto i_v = torch::arange(rx, options_int);
68
+ auto j_v = torch::arange(ry, options_int);
69
+ auto k_v = torch::arange(rz, options_int);
70
+ auto idx_grids_v = torch::meshgrid({i_v, j_v, k_v}, "ij");
71
+ opt_idx_grids = torch::stack({idx_grids_v[0].flatten(), idx_grids_v[1].flatten(), idx_grids_v[2].flatten()}, -1).contiguous();
72
+ }
67
73
 
68
- return std::make_tuple(grid_vertices, voxels, out_idx_grids);
74
+ return std::make_tuple(grid_vertices, voxels, opt_idx_grids);
69
75
  }
70
76
 
71
77
  torch::Tensor compute_grid_normal(torch::Tensor sdf, torch::Tensor grid_vertices, torch::Tensor idx_grids, std::vector<int64_t> res) {
@@ -141,11 +147,12 @@ torch::Tensor compute_active_voxels(torch::Tensor voxels, torch::Tensor sdf, flo
141
147
  return active_indices;
142
148
  }
143
149
 
144
- std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid_from_tmesh(
150
+ std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>> create_voxel_grid_from_tmesh(
145
151
  std::vector<float> grid_min,
146
152
  std::vector<float> grid_max,
147
153
  std::vector<int64_t> res,
148
- TriangleMesh &tmesh
154
+ TriangleMesh &tmesh,
155
+ bool return_unique_vert_ids = true
149
156
  ) {
150
157
  TORCH_CHECK(grid_min.size() == 3, "grid_min must have 3 elements.");
151
158
  TORCH_CHECK(grid_max.size() == 3, "grid_max must have 3 elements.");
@@ -165,7 +172,131 @@ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid_from_t
165
172
  return std::make_tuple(
166
173
  torch::empty({0, 3}, torch::TensorOptions().dtype(torch::kFloat32).device(vertices.device())),
167
174
  torch::empty({0, 8}, torch::TensorOptions().dtype(torch::kInt32).device(vertices.device())),
168
- torch::empty({0}, torch::TensorOptions().dtype(torch::kInt64).device(vertices.device()))
175
+ return_unique_vert_ids ? std::make_optional(torch::empty({0}, torch::TensorOptions().dtype(torch::kInt64).device(vertices.device()))) : std::nullopt
176
+ );
177
+ }
178
+
179
+ auto vi = active_voxel_ids.div((ry - 1) * (rz - 1), "trunc");
180
+ auto rem = active_voxel_ids.remainder((ry - 1) * (rz - 1));
181
+ auto vj = rem.div(rz - 1, "trunc");
182
+ auto vk = rem.remainder(rz - 1);
183
+
184
+ auto v0 = vi * ry * rz + vj * rz + vk;
185
+ auto v1 = (vi + 1) * ry * rz + vj * rz + vk;
186
+ auto v2 = (vi + 1) * ry * rz + (vj + 1) * rz + vk;
187
+ auto v3 = vi * ry * rz + (vj + 1) * rz + vk;
188
+ auto v4 = vi * ry * rz + vj * rz + (vk + 1);
189
+ auto v5 = (vi + 1) * ry * rz + vj * rz + (vk + 1);
190
+ auto v6 = (vi + 1) * ry * rz + (vj + 1) * rz + (vk + 1);
191
+ auto v7 = vi * ry * rz + (vj + 1) * rz + (vk + 1);
192
+
193
+ auto active_voxels = torch::stack({v0, v1, v2, v3, v4, v5, v6, v7}, -1);
194
+
195
+ torch::Tensor unique_vert_ids, inverse_indices, counts;
196
+ std::tie(unique_vert_ids, inverse_indices, counts) = torch::_unique2(active_voxels.flatten(), true, true, false);
197
+
198
+ auto remapped_voxels = inverse_indices.view({-1, 8}).to(torch::kInt32);
199
+
200
+ auto u_i = unique_vert_ids.div(ry * rz, "trunc");
201
+ auto u_rem = unique_vert_ids.remainder(ry * rz);
202
+ auto u_j = u_rem.div(rz, "trunc");
203
+ auto u_k = u_rem.remainder(rz);
204
+
205
+ float spacing_x = (grid_max[0] - grid_min[0]) / (rx - 1);
206
+ float spacing_y = (grid_max[1] - grid_min[1]) / (ry - 1);
207
+ float spacing_z = (grid_max[2] - grid_min[2]) / (rz - 1);
208
+
209
+ auto x = grid_min[0] + u_i.to(torch::kFloat32) * spacing_x;
210
+ auto y = grid_min[1] + u_j.to(torch::kFloat32) * spacing_y;
211
+ auto z = grid_min[2] + u_k.to(torch::kFloat32) * spacing_z;
212
+
213
+ auto sparse_grid_vertices = torch::stack({x, y, z}, 1).contiguous();
214
+
215
+ return std::make_tuple(sparse_grid_vertices, remapped_voxels, return_unique_vert_ids ? std::make_optional(unique_vert_ids) : std::nullopt);
216
+ }
217
+
218
+ torch::Tensor get_active_voxel_ids_from_depth_py(
219
+ torch::Tensor depth_image,
220
+ torch::Tensor c2w_tensor,
221
+ torch::Tensor intrinsics_inv_tensor,
222
+ std::vector<float> grid_min,
223
+ std::vector<float> grid_max,
224
+ std::vector<int64_t> res,
225
+ bool activate_neighbor = false,
226
+ float trunc_margin = 0.0f
227
+ ) {
228
+ TORCH_CHECK(depth_image.is_cuda(), "depth_image must be a CUDA tensor");
229
+ TORCH_CHECK(depth_image.dim() == 2, "depth_image must be 2D (H, W)");
230
+
231
+ int image_height = depth_image.size(0);
232
+ int image_width = depth_image.size(1);
233
+ int num_pixels = image_height * image_width;
234
+
235
+ float4x4 c2w;
236
+ auto c2w_cpu = c2w_tensor.to(torch::kFloat32).cpu().contiguous();
237
+ auto c2w_a = c2w_cpu.accessor<float, 2>();
238
+ for(int r=0; r<4; ++r) for(int c=0; c<4; ++c) c2w.m[r][c] = c2w_a[r][c];
239
+
240
+ float3x3 intrinsics_inv;
241
+ auto int_cpu = intrinsics_inv_tensor.to(torch::kFloat32).cpu().contiguous();
242
+ auto int_a = int_cpu.accessor<float, 2>();
243
+ for(int r=0; r<3; ++r) for(int c=0; c<3; ++c) intrinsics_inv.m[r][c] = int_a[r][c];
244
+
245
+ float3 g_min; g_min.x = grid_min[0]; g_min.y = grid_min[1]; g_min.z = grid_min[2];
246
+ float3 g_max; g_max.x = grid_max[0]; g_max.y = grid_max[1]; g_max.z = grid_max[2];
247
+ int3 g_res; g_res.x = res[0]; g_res.y = res[1]; g_res.z = res[2];
248
+
249
+ int max_pad_x = std::ceil(trunc_margin / ((grid_max[0] - grid_min[0]) / (res[0] - 1)));
250
+ int max_pad_y = std::ceil(trunc_margin / ((grid_max[1] - grid_min[1]) / (res[1] - 1)));
251
+ int max_pad_z = std::ceil(trunc_margin / ((grid_max[2] - grid_min[2]) / (res[2] - 1)));
252
+ int max_neighbors = activate_neighbor ? ((2 * max_pad_x + 1) * (2 * max_pad_y + 1) * (2 * max_pad_z + 1)) : 1;
253
+
254
+ int64_t max_voxels = (int64_t)num_pixels * max_neighbors;
255
+ auto options = torch::TensorOptions().device(torch::kCUDA).dtype(torch::kInt64);
256
+ auto out_voxel_ids = torch::empty({max_voxels}, options);
257
+
258
+ auto valid_counter_tensor = torch::zeros({1}, options);
259
+
260
+ grid::get_active_voxel_ids_from_depth(
261
+ num_pixels,
262
+ depth_image.data_ptr<float>(),
263
+ c2w,
264
+ intrinsics_inv,
265
+ image_width,
266
+ image_height,
267
+ g_min,
268
+ g_max,
269
+ g_res,
270
+ out_voxel_ids.data_ptr<int64_t>(),
271
+ reinterpret_cast<unsigned long long*>(valid_counter_tensor.data_ptr<int64_t>()),
272
+ activate_neighbor,
273
+ trunc_margin
274
+ );
275
+
276
+ int64_t valid_count = valid_counter_tensor.item<int64_t>();
277
+ return out_voxel_ids.slice(0, 0, valid_count);
278
+ }
279
+
280
+ std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>> build_sparse_grid_from_active_voxels(
281
+ torch::Tensor active_voxel_ids,
282
+ std::vector<float> grid_min,
283
+ std::vector<float> grid_max,
284
+ std::vector<int64_t> res,
285
+ bool return_unique_vert_ids = true
286
+ ) {
287
+ TORCH_CHECK(grid_min.size() == 3, "grid_min must have 3 elements.");
288
+ TORCH_CHECK(grid_max.size() == 3, "grid_max must have 3 elements.");
289
+ TORCH_CHECK(res.size() == 3, "res must have 3 elements.");
290
+
291
+ int64_t rx = res[0];
292
+ int64_t ry = res[1];
293
+ int64_t rz = res[2];
294
+
295
+ if (active_voxel_ids.size(0) == 0) {
296
+ return std::make_tuple(
297
+ torch::empty({0, 3}, torch::TensorOptions().dtype(torch::kFloat32).device(active_voxel_ids.device())),
298
+ torch::empty({0, 8}, torch::TensorOptions().dtype(torch::kInt32).device(active_voxel_ids.device())),
299
+ return_unique_vert_ids ? std::make_optional(torch::empty({0}, torch::TensorOptions().dtype(torch::kInt64).device(active_voxel_ids.device()))) : std::nullopt
169
300
  );
170
301
  }
171
302
 
@@ -205,16 +336,20 @@ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid_from_t
205
336
 
206
337
  auto sparse_grid_vertices = torch::stack({x, y, z}, 1).contiguous();
207
338
 
208
- return std::make_tuple(sparse_grid_vertices, remapped_voxels, unique_vert_ids);
339
+ return std::make_tuple(sparse_grid_vertices, remapped_voxels, return_unique_vert_ids ? std::make_optional(unique_vert_ids) : std::nullopt);
209
340
  }
210
341
 
211
342
  void bind_ds_grid(py::module_& m) {
212
343
  m.def("create_voxel_grid", &create_voxel_grid, "Creates a structured 3D voxel grid.",
213
- py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("device_str") = "cuda");
344
+ py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("device_str") = "cuda", py::arg("return_idx_grids") = true);
214
345
  m.def("create_voxel_grid_from_tmesh", &create_voxel_grid_from_tmesh, "Creates a sparse 3D voxel grid strictly around the surface.",
215
- py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("tmesh"));
346
+ py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("tmesh"), py::arg("return_unique_vert_ids") = true);
216
347
  m.def("compute_grid_normal", &compute_grid_normal, "Computes surface normals for a grid.",
217
348
  py::arg("sdf"), py::arg("grid_vertices"), py::arg("idx_grids"), py::arg("res"));
218
349
  m.def("compute_active_voxels", &compute_active_voxels, "Computes active voxels intersecting the surface",
219
350
  py::arg("voxels"), py::arg("sdf"), py::arg("iso"));
351
+ m.def("get_active_voxel_ids_from_depth", &get_active_voxel_ids_from_depth_py, "Extracts active voxel IDs from a single depth map.",
352
+ py::arg("depth_image"), py::arg("c2w_tensor"), py::arg("intrinsics_inv_tensor"), py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("activate_neighbor") = false, py::arg("trunc_margin") = 0.0f);
353
+ m.def("build_sparse_grid_from_active_voxels", &build_sparse_grid_from_active_voxels, "Builds sparse grid from unique voxel IDs.",
354
+ py::arg("active_voxel_ids"), py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("return_unique_vert_ids") = true);
220
355
  }
@@ -0,0 +1,96 @@
1
+ #include <torch/extension.h>
2
+ #include <pybind11/pybind11.h>
3
+ #include "../../ops/volint.h"
4
+ #include "../../maths/maths.h"
5
+
6
+ namespace py = pybind11;
7
+
8
+ void single_view_volume_integral_bind(
9
+ torch::Tensor grid_vertices,
10
+ torch::Tensor sdf,
11
+ torch::Tensor weight,
12
+ std::optional<torch::Tensor> color_opt,
13
+ torch::Tensor depth_image,
14
+ std::optional<torch::Tensor> color_image_opt,
15
+ torch::Tensor extrinsics,
16
+ torch::Tensor intrinsics,
17
+ float trunc_margin,
18
+ int mode
19
+ ) {
20
+ TORCH_CHECK(grid_vertices.is_cuda() && grid_vertices.is_contiguous(), "grid_vertices must be CUDA and contiguous");
21
+ TORCH_CHECK(sdf.is_cuda() && sdf.is_contiguous(), "sdf must be CUDA and contiguous");
22
+ TORCH_CHECK(weight.is_cuda() && weight.is_contiguous(), "weight must be CUDA and contiguous");
23
+ TORCH_CHECK(depth_image.is_cuda() && depth_image.is_contiguous(), "depth_image must be CUDA and contiguous");
24
+
25
+ int num_vertices = grid_vertices.size(0);
26
+ int image_height = depth_image.size(0);
27
+ int image_width = depth_image.size(1);
28
+
29
+ const float3* grid_vertices_ptr = reinterpret_cast<const float3*>(grid_vertices.data_ptr<float>());
30
+ float* sdf_ptr = sdf.data_ptr<float>();
31
+ float* weight_ptr = weight.data_ptr<float>();
32
+ const float* depth_image_ptr = depth_image.data_ptr<float>();
33
+
34
+ float3* color_ptr = nullptr;
35
+ if (color_opt.has_value() && color_opt.value().defined() && color_opt.value().numel() > 0) {
36
+ auto color = color_opt.value();
37
+ TORCH_CHECK(color.is_cuda() && color.is_contiguous(), "color must be CUDA and contiguous");
38
+ color_ptr = reinterpret_cast<float3*>(color.data_ptr<float>());
39
+ }
40
+
41
+ const float3* color_image_ptr = nullptr;
42
+ if (color_image_opt.has_value() && color_image_opt.value().defined() && color_image_opt.value().numel() > 0) {
43
+ auto color_image = color_image_opt.value();
44
+ TORCH_CHECK(color_image.is_cuda() && color_image.is_contiguous(), "color_image must be CUDA and contiguous");
45
+ color_image_ptr = reinterpret_cast<const float3*>(color_image.data_ptr<float>());
46
+ }
47
+
48
+ torch::Tensor ex_cpu = extrinsics.cpu().contiguous();
49
+ torch::Tensor in_cpu = intrinsics.cpu().contiguous();
50
+
51
+ const float* ex_data = ex_cpu.data_ptr<float>();
52
+ float4x4 ex = make_float4x4(
53
+ ex_data[0], ex_data[1], ex_data[2], ex_data[3],
54
+ ex_data[4], ex_data[5], ex_data[6], ex_data[7],
55
+ ex_data[8], ex_data[9], ex_data[10], ex_data[11],
56
+ ex_data[12], ex_data[13], ex_data[14], ex_data[15]
57
+ );
58
+
59
+ const float* in_data = in_cpu.data_ptr<float>();
60
+ float3x3 in = make_float3x3(
61
+ in_data[0], in_data[1], in_data[2],
62
+ in_data[3], in_data[4], in_data[5],
63
+ in_data[6], in_data[7], in_data[8]
64
+ );
65
+
66
+ single_view_volume_integral(
67
+ num_vertices,
68
+ grid_vertices_ptr,
69
+ sdf_ptr,
70
+ weight_ptr,
71
+ color_ptr,
72
+ depth_image_ptr,
73
+ color_image_ptr,
74
+ image_width,
75
+ image_height,
76
+ ex,
77
+ in,
78
+ trunc_margin,
79
+ mode
80
+ );
81
+ }
82
+
83
+ void bind_ops_volint(py::module_& m) {
84
+ m.def("single_view_volume_integral", &single_view_volume_integral_bind,
85
+ py::arg("grid_vertices"),
86
+ py::arg("sdf"),
87
+ py::arg("weight"),
88
+ py::arg("color"),
89
+ py::arg("depth_image"),
90
+ py::arg("color_image"),
91
+ py::arg("extrinsics"),
92
+ py::arg("intrinsics"),
93
+ py::arg("trunc_margin"),
94
+ py::arg("mode") = 1,
95
+ "Single view TSDF volume integration");
96
+ }
@@ -0,0 +1,109 @@
1
+ #include "grid.h"
2
+ #include <stdio.h>
3
+ #include <math.h>
4
+
5
+ namespace grid {
6
+
7
+ __global__ void get_active_voxel_ids_from_depth_kernel(
8
+ const int num_pixels,
9
+ const float* depth_image,
10
+ const float4x4 c2w,
11
+ const float3x3 intrinsics_inv,
12
+ const int image_width,
13
+ const int image_height,
14
+ const float3 grid_min,
15
+ const float3 grid_max,
16
+ const int3 res,
17
+ int64_t* out_voxel_ids,
18
+ unsigned long long* valid_counter,
19
+ bool activate_neighbor,
20
+ float trunc_margin
21
+ ) {
22
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
23
+ if (idx >= num_pixels) return;
24
+
25
+ float d = depth_image[idx];
26
+ if (d <= 0.0f) return; // Ignore invalid depths
27
+
28
+ int ui = idx % image_width;
29
+ int vi = idx / image_width;
30
+
31
+ // 1. Unproject to camera coordinates using inverse intrinsics
32
+ float3 p_cam;
33
+ p_cam.x = d * (intrinsics_inv.m[0][0] * ui + intrinsics_inv.m[0][1] * vi + intrinsics_inv.m[0][2]);
34
+ p_cam.y = d * (intrinsics_inv.m[1][0] * ui + intrinsics_inv.m[1][1] * vi + intrinsics_inv.m[1][2]);
35
+ p_cam.z = d;
36
+
37
+ // 2. Transform to world coordinates using Camera-To-World matrix
38
+ float4 p_cam4 = make_float4(p_cam.x, p_cam.y, p_cam.z, 1.0f);
39
+ float4 p_world4 = c2w * p_cam4;
40
+
41
+ // 3. Compute 3D grid cell indices (0-indexed)
42
+ float spacing_x = (grid_max.x - grid_min.x) / fmaxf(1.0f, (float)(res.x - 1));
43
+ float spacing_y = (grid_max.y - grid_min.y) / fmaxf(1.0f, (float)(res.y - 1));
44
+ float spacing_z = (grid_max.z - grid_min.z) / fmaxf(1.0f, (float)(res.z - 1));
45
+
46
+ int i_min = floorf((p_world4.x - grid_min.x) / spacing_x);
47
+ int i_max = i_min;
48
+ int j_min = floorf((p_world4.y - grid_min.y) / spacing_y);
49
+ int j_max = j_min;
50
+ int k_min = floorf((p_world4.z - grid_min.z) / spacing_z);
51
+ int k_max = k_min;
52
+
53
+ if (activate_neighbor) {
54
+ i_min = floorf((p_world4.x - trunc_margin - grid_min.x) / spacing_x);
55
+ i_max = floorf((p_world4.x + trunc_margin - grid_min.x) / spacing_x);
56
+ j_min = floorf((p_world4.y - trunc_margin - grid_min.y) / spacing_y);
57
+ j_max = floorf((p_world4.y + trunc_margin - grid_min.y) / spacing_y);
58
+ k_min = floorf((p_world4.z - trunc_margin - grid_min.z) / spacing_z);
59
+ k_max = floorf((p_world4.z + trunc_margin - grid_min.z) / spacing_z);
60
+ }
61
+
62
+ for (int i = i_min; i <= i_max; ++i) {
63
+ for (int j = j_min; j <= j_max; ++j) {
64
+ for (int k = k_min; k <= k_max; ++k) {
65
+ if (i >= 0 && i < res.x - 1 && j >= 0 && j < res.y - 1 && k >= 0 && k < res.z - 1) {
66
+ int64_t voxel_id = (int64_t)i * (res.y - 1) * (res.z - 1) + (int64_t)j * (res.z - 1) + (int64_t)k;
67
+ unsigned long long write_idx = atomicAdd(valid_counter, 1ULL);
68
+ out_voxel_ids[write_idx] = voxel_id;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ void get_active_voxel_ids_from_depth(
76
+ const int num_pixels,
77
+ const float* depth_image,
78
+ const float4x4 c2w,
79
+ const float3x3 intrinsics_inv,
80
+ const int image_width,
81
+ const int image_height,
82
+ const float3 grid_min,
83
+ const float3 grid_max,
84
+ const int3 res,
85
+ int64_t* out_voxel_ids,
86
+ unsigned long long* valid_counter,
87
+ bool activate_neighbor,
88
+ float trunc_margin
89
+ ) {
90
+ int block_size = 256;
91
+ int grid_size = (num_pixels + block_size - 1) / block_size;
92
+
93
+ get_active_voxel_ids_from_depth_kernel<<<grid_size, block_size>>>(
94
+ num_pixels,
95
+ depth_image,
96
+ c2w,
97
+ intrinsics_inv,
98
+ image_width,
99
+ image_height,
100
+ grid_min,
101
+ grid_max,
102
+ res,
103
+ out_voxel_ids,
104
+ valid_counter,
105
+ activate_neighbor,
106
+ trunc_margin
107
+ );
108
+ }
109
+ }
@@ -0,0 +1,22 @@
1
+ #pragma once
2
+ #include <vector>
3
+ #include <torch/extension.h>
4
+ #include "../maths/maths.h"
5
+
6
+ namespace grid {
7
+ void get_active_voxel_ids_from_depth(
8
+ const int num_pixels,
9
+ const float* depth_image,
10
+ const float4x4 c2w,
11
+ const float3x3 intrinsics_inv,
12
+ const int image_width,
13
+ const int image_height,
14
+ const float3 grid_min,
15
+ const float3 grid_max,
16
+ const int3 res,
17
+ int64_t* out_voxel_ids,
18
+ unsigned long long* valid_counter,
19
+ bool activate_neighbor,
20
+ float trunc_margin
21
+ );
22
+ }
@@ -66,6 +66,7 @@ static __inline__ __host__ __device__ float4 operator* (const float4& a, const f
66
66
  );
67
67
  }
68
68
 
69
+ // [4, 4] x [4, 1] = [4, 1]
69
70
  static __inline__ __host__ __device__ float4 operator* (const float4x4& m, const float4& a)
70
71
  {
71
72
  return make_float4(