conquer3d 0.2.8__tar.gz → 0.3.0__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 (86) hide show
  1. {conquer3d-0.2.8/conquer3d.egg-info → conquer3d-0.3.0}/PKG-INFO +7 -2
  2. {conquer3d-0.2.8 → conquer3d-0.3.0}/README.md +6 -1
  3. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/_C.so +0 -0
  4. conquer3d-0.3.0/conquer3d/csrc/binds/data_structure/grid.cpp +150 -0
  5. conquer3d-0.3.0/conquer3d/csrc/binds/ops/chamfer.cpp +42 -0
  6. conquer3d-0.3.0/conquer3d/csrc/binds/ops/mc.cpp +118 -0
  7. conquer3d-0.3.0/conquer3d/csrc/ops/chamfer.cu +73 -0
  8. conquer3d-0.3.0/conquer3d/csrc/ops/chamfer.h +18 -0
  9. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/ops/mc.cu +187 -13
  10. conquer3d-0.3.0/conquer3d/csrc/ops/mc.h +39 -0
  11. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/pybind.cpp +2 -0
  12. conquer3d-0.3.0/conquer3d/data_structure/__init__.py +15 -0
  13. conquer3d-0.3.0/conquer3d/data_structure/grid.py +114 -0
  14. conquer3d-0.3.0/conquer3d/ops/__init__.py +10 -0
  15. conquer3d-0.3.0/conquer3d/ops/diff_marching_cubes.py +135 -0
  16. conquer3d-0.3.0/conquer3d/ops/distance.py +28 -0
  17. conquer3d-0.3.0/conquer3d/ops/marching_cubes.py +64 -0
  18. {conquer3d-0.2.8 → conquer3d-0.3.0/conquer3d.egg-info}/PKG-INFO +7 -2
  19. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/SOURCES.txt +6 -1
  20. {conquer3d-0.2.8 → conquer3d-0.3.0}/pyproject.toml +1 -1
  21. conquer3d-0.2.8/conquer3d/csrc/binds/data_structure/grid.cpp +0 -66
  22. conquer3d-0.2.8/conquer3d/csrc/binds/ops/mc.cpp +0 -37
  23. conquer3d-0.2.8/conquer3d/csrc/ops/mc.h +0 -24
  24. conquer3d-0.2.8/conquer3d/data_structure/__init__.py +0 -13
  25. conquer3d-0.2.8/conquer3d/ops/__init__.py +0 -7
  26. conquer3d-0.2.8/conquer3d/ops/grid.py +0 -26
  27. conquer3d-0.2.8/conquer3d/ops/marching_cubes.py +0 -42
  28. {conquer3d-0.2.8 → conquer3d-0.3.0}/LICENSE +0 -0
  29. {conquer3d-0.2.8 → conquer3d-0.3.0}/MANIFEST.in +0 -0
  30. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/_C.pyi +0 -0
  31. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/__init__.py +0 -0
  32. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/creation/__init__.py +0 -0
  33. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/creation/triangle_creation.py +0 -0
  34. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
  35. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
  36. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
  37. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
  38. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
  39. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
  40. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
  41. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
  42. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
  43. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/check.h +0 -0
  44. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/constants.h +0 -0
  45. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/creation/triangle_creation.h +0 -0
  46. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/bvh.cu +0 -0
  47. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/bvh.h +0 -0
  48. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
  49. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
  50. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/kdtree.h +0 -0
  51. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
  52. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
  53. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
  54. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
  55. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
  56. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/zcurve.h +0 -0
  57. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f2x2.h +0 -0
  58. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x1.h +0 -0
  59. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x3.h +0 -0
  60. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x4.h +0 -0
  61. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f4x1.h +0 -0
  62. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f4x4.h +0 -0
  63. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/maths.h +0 -0
  64. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/ops.h +0 -0
  65. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/ops/mc_data.h +0 -0
  66. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/aabb.h +0 -0
  67. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/edge.h +0 -0
  68. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs.cu +0 -0
  69. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs.h +0 -0
  70. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
  71. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
  72. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs.cu +0 -0
  73. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs.h +0 -0
  74. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
  75. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
  76. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/ray.h +0 -0
  77. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/triangles.h +0 -0
  78. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/__init__.py +0 -0
  79. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/gs.py +0 -0
  80. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/pgs.py +0 -0
  81. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/dependency_links.txt +0 -0
  82. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/not-zip-safe +0 -0
  83. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/requires.txt +0 -0
  84. {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/top_level.txt +0 -0
  85. {conquer3d-0.2.8 → conquer3d-0.3.0}/setup.cfg +0 -0
  86. {conquer3d-0.2.8 → conquer3d-0.3.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conquer3d
3
- Version: 0.2.8
3
+ Version: 0.3.0
4
4
  Summary: Geometric Cuda Tool Box
5
5
  Author-email: Do Hoang Khoi <khoido8899@gmail.com>
6
6
  License-Expression: MIT
@@ -51,12 +51,17 @@ conda activate geocutool
51
51
 
52
52
  conda install nvidia::cuda-toolkit==12.8.2 -y
53
53
 
54
+ pip install setuptools wheel ninja
54
55
  pip install torch==2.8.0 torchvision==0.23.0 torchaudio==2.8.0 --index-url https://download.pytorch.org/whl/cu128
55
56
 
57
+ pip install git+https://github.com/mit-han-lab/torchsparse.git
58
+
59
+ pip install kaolin==0.18.0 -f https://nvidia-kaolin.s3.us-east-2.amazonaws.com/torch-2.8.0_cu128.html
60
+
56
61
  pip install pybind11-stubgen
57
62
  pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
58
63
 
59
- pip install plotly open3d jupyter trimesh
64
+ pip install plotly open3d jupyter trimesh point-cloud-utils
60
65
  ```
61
66
 
62
67
  # Development
@@ -23,12 +23,17 @@ conda activate geocutool
23
23
 
24
24
  conda install nvidia::cuda-toolkit==12.8.2 -y
25
25
 
26
+ pip install setuptools wheel ninja
26
27
  pip install torch==2.8.0 torchvision==0.23.0 torchaudio==2.8.0 --index-url https://download.pytorch.org/whl/cu128
27
28
 
29
+ pip install git+https://github.com/mit-han-lab/torchsparse.git
30
+
31
+ pip install kaolin==0.18.0 -f https://nvidia-kaolin.s3.us-east-2.amazonaws.com/torch-2.8.0_cu128.html
32
+
28
33
  pip install pybind11-stubgen
29
34
  pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
30
35
 
31
- pip install plotly open3d jupyter trimesh
36
+ pip install plotly open3d jupyter trimesh point-cloud-utils
32
37
  ```
33
38
 
34
39
  # Development
@@ -0,0 +1,150 @@
1
+ #include <torch/extension.h>
2
+ #include <pybind11/pybind11.h>
3
+ #include <pybind11/stl.h>
4
+ #include <tuple>
5
+ #include <string>
6
+ #include <vector>
7
+
8
+ namespace py = pybind11;
9
+
10
+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> create_voxel_grid(
11
+ std::vector<float> grid_min,
12
+ std::vector<float> grid_max,
13
+ std::vector<int64_t> res,
14
+ std::string device_str
15
+ ) {
16
+ TORCH_CHECK(grid_min.size() == 3, "grid_min must have 3 elements.");
17
+ TORCH_CHECK(grid_max.size() == 3, "grid_max must have 3 elements.");
18
+ TORCH_CHECK(res.size() == 3, "res must have 3 elements.");
19
+
20
+ c10::Device device(device_str);
21
+ auto options = torch::TensorOptions().device(device).dtype(torch::kFloat32);
22
+
23
+ int64_t rx = res[0];
24
+ int64_t ry = res[1];
25
+ int64_t rz = res[2];
26
+
27
+ auto x = torch::linspace(grid_min[0], grid_max[0], rx, options);
28
+ auto y = torch::linspace(grid_min[1], grid_max[1], ry, options);
29
+ auto z = torch::linspace(grid_min[2], grid_max[2], rz, options);
30
+
31
+ auto grids = torch::meshgrid({x, y, z}, "ij");
32
+ auto grid_x = grids[0].flatten();
33
+ auto grid_y = grids[1].flatten();
34
+ auto grid_z = grids[2].flatten();
35
+
36
+ auto grid_vertices = torch::stack({grid_x, grid_y, grid_z}, 1).contiguous();
37
+
38
+ auto options_int = options.dtype(torch::kInt64);
39
+ auto i = torch::arange(rx - 1, options_int);
40
+ auto j = torch::arange(ry - 1, options_int);
41
+ auto k = torch::arange(rz - 1, options_int);
42
+
43
+ auto idx_grids = torch::meshgrid({i, j, k}, "ij");
44
+ auto vi = idx_grids[0];
45
+ auto vj = idx_grids[1];
46
+ auto vk = idx_grids[2];
47
+
48
+ // Voxel connectivity indexing mapping matching mc.cu
49
+ auto v0 = vi * ry * rz + vj * rz + vk;
50
+ auto v1 = (vi + 1) * ry * rz + vj * rz + vk;
51
+ auto v2 = (vi + 1) * ry * rz + (vj + 1) * rz + vk;
52
+ auto v3 = vi * ry * rz + (vj + 1) * rz + vk;
53
+ auto v4 = vi * ry * rz + vj * rz + (vk + 1);
54
+ auto v5 = (vi + 1) * ry * rz + vj * rz + (vk + 1);
55
+ auto v6 = (vi + 1) * ry * rz + (vj + 1) * rz + (vk + 1);
56
+ auto v7 = vi * ry * rz + (vj + 1) * rz + (vk + 1);
57
+
58
+ auto voxels = torch::stack({v0, v1, v2, v3, v4, v5, v6, v7}, -1).view({-1, 8}).contiguous().to(torch::kInt32);
59
+
60
+ auto i_v = torch::arange(rx, options_int);
61
+ auto j_v = torch::arange(ry, options_int);
62
+ auto k_v = torch::arange(rz, options_int);
63
+ auto idx_grids_v = torch::meshgrid({i_v, j_v, k_v}, "ij");
64
+ auto out_idx_grids = torch::stack({idx_grids_v[0].flatten(), idx_grids_v[1].flatten(), idx_grids_v[2].flatten()}, -1).contiguous();
65
+
66
+ return std::make_tuple(grid_vertices, voxels, out_idx_grids);
67
+ }
68
+
69
+ torch::Tensor compute_grid_normal(torch::Tensor sdf, torch::Tensor grid_vertices, torch::Tensor idx_grids, std::vector<int64_t> res) {
70
+ TORCH_CHECK(res.size() == 3, "res must have 3 elements.");
71
+
72
+ auto i = idx_grids.select(1, 0);
73
+ auto j = idx_grids.select(1, 1);
74
+ auto k = idx_grids.select(1, 2);
75
+
76
+ auto rx = res[0];
77
+ auto ry = res[1];
78
+ auto rz = res[2];
79
+
80
+ auto i_prev = torch::clamp(i - 1, 0, rx - 1);
81
+ auto i_next = torch::clamp(i + 1, 0, rx - 1);
82
+
83
+ auto j_prev = torch::clamp(j - 1, 0, ry - 1);
84
+ auto j_next = torch::clamp(j + 1, 0, ry - 1);
85
+
86
+ auto k_prev = torch::clamp(k - 1, 0, rz - 1);
87
+ auto k_next = torch::clamp(k + 1, 0, rz - 1);
88
+
89
+ auto idx_x_prev = i_prev * ry * rz + j * rz + k;
90
+ auto idx_x_next = i_next * ry * rz + j * rz + k;
91
+
92
+ auto idx_y_prev = i * ry * rz + j_prev * rz + k;
93
+ auto idx_y_next = i * ry * rz + j_next * rz + k;
94
+
95
+ auto idx_z_prev = i * ry * rz + j * rz + k_prev;
96
+ auto idx_z_next = i * ry * rz + j * rz + k_next;
97
+
98
+ auto sdf_flat = sdf.flatten();
99
+
100
+ auto diff_x = sdf_flat.index_select(0, idx_x_next) - sdf_flat.index_select(0, idx_x_prev);
101
+ auto diff_y = sdf_flat.index_select(0, idx_y_next) - sdf_flat.index_select(0, idx_y_prev);
102
+ auto diff_z = sdf_flat.index_select(0, idx_z_next) - sdf_flat.index_select(0, idx_z_prev);
103
+
104
+ auto vx = grid_vertices.select(1, 0);
105
+ auto vy = grid_vertices.select(1, 1);
106
+ auto vz = grid_vertices.select(1, 2);
107
+
108
+ auto dx = vx.index_select(0, idx_x_next) - vx.index_select(0, idx_x_prev);
109
+ auto dy = vy.index_select(0, idx_y_next) - vy.index_select(0, idx_y_prev);
110
+ auto dz = vz.index_select(0, idx_z_next) - vz.index_select(0, idx_z_prev);
111
+
112
+ dx = torch::where(dx == 0, torch::tensor(1e-5f, dx.options()), dx);
113
+ dy = torch::where(dy == 0, torch::tensor(1e-5f, dy.options()), dy);
114
+ dz = torch::where(dz == 0, torch::tensor(1e-5f, dz.options()), dz);
115
+
116
+ auto grad_x = diff_x / dx;
117
+ auto grad_y = diff_y / dy;
118
+ auto grad_z = diff_z / dz;
119
+
120
+ auto normals = torch::stack({grad_x, grad_y, grad_z}, 1);
121
+ return torch::nn::functional::normalize(normals, torch::nn::functional::NormalizeFuncOptions().p(2).dim(1));
122
+ }
123
+
124
+ torch::Tensor compute_active_voxels(torch::Tensor voxels, torch::Tensor sdf, float iso) {
125
+ TORCH_CHECK(voxels.is_cuda(), "voxels must be a CUDA tensor.");
126
+ TORCH_CHECK(sdf.is_cuda(), "sdf must be a CUDA tensor.");
127
+ TORCH_CHECK(voxels.dtype() == torch::kInt32, "voxels must be int32.");
128
+ TORCH_CHECK(sdf.dtype() == torch::kFloat32, "sdf must be float32.");
129
+
130
+ auto voxels_flat = voxels.flatten().to(torch::kInt64);
131
+ auto voxel_sdfs = sdf.index_select(0, voxels_flat).view({-1, 8});
132
+
133
+ auto below_iso = voxel_sdfs < iso;
134
+ auto any_below = below_iso.any(1);
135
+ auto any_above = (~below_iso).any(1);
136
+
137
+ auto active_mask = any_below & any_above;
138
+ auto active_indices = torch::nonzero(active_mask).squeeze(1);
139
+
140
+ return active_indices;
141
+ }
142
+
143
+ void bind_ds_grid(py::module_& m) {
144
+ m.def("create_voxel_grid", &create_voxel_grid, "Creates a structured 3D voxel grid.",
145
+ py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("device_str") = "cuda");
146
+ m.def("compute_grid_normal", &compute_grid_normal, "Computes surface normals for a grid.",
147
+ py::arg("sdf"), py::arg("grid_vertices"), py::arg("idx_grids"), py::arg("res"));
148
+ m.def("compute_active_voxels", &compute_active_voxels, "Computes active voxels intersecting the surface",
149
+ py::arg("voxels"), py::arg("sdf"), py::arg("iso"));
150
+ }
@@ -0,0 +1,42 @@
1
+ #include <torch/extension.h>
2
+ #include <pybind11/pybind11.h>
3
+ #include "../../ops/chamfer.h"
4
+ #include "../../check.h"
5
+
6
+ namespace py = pybind11;
7
+
8
+ std::tuple<torch::Tensor, torch::Tensor> one_sided_chamfer_distance_wrapper(
9
+ torch::Tensor query_points,
10
+ torch::Tensor reference_points
11
+ ) {
12
+ CHECK_INPUT(query_points);
13
+ CHECK_INPUT(reference_points);
14
+
15
+ uint32_t num_query_points = query_points.size(0);
16
+ uint32_t num_reference_points = reference_points.size(0);
17
+
18
+ const float3* __restrict__ p_query_points = (float3*)query_points.data_ptr<float>();
19
+ const float3* __restrict__ p_reference_points = (float3*)reference_points.data_ptr<float>();
20
+
21
+ torch::Tensor distances = torch::empty({num_query_points}, query_points.options());
22
+ torch::Tensor indices = torch::empty({num_query_points}, query_points.options().dtype(torch::kInt64));
23
+
24
+ float* __restrict__ p_distances = distances.data_ptr<float>();
25
+ int64_t* __restrict__ p_indices = indices.data_ptr<int64_t>();
26
+
27
+ one_sided_chamfer_distance(
28
+ num_query_points,
29
+ p_query_points,
30
+ num_reference_points,
31
+ p_reference_points,
32
+ p_distances,
33
+ p_indices
34
+ );
35
+
36
+ return std::make_tuple(distances, indices);
37
+ }
38
+
39
+ void bind_ops_chamfer(py::module_& m) {
40
+ m.def("one_sided_chamfer_distance", &one_sided_chamfer_distance_wrapper, "One Sided Chamfer Distance",
41
+ py::arg("query_points"), py::arg("reference_points"));
42
+ }
@@ -0,0 +1,118 @@
1
+ #include <torch/extension.h>
2
+ #include <pybind11/pybind11.h>
3
+ #include "../../ops/mc.h"
4
+ #include "../../check.h"
5
+
6
+ namespace py = pybind11;
7
+
8
+ std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>, std::optional<torch::Tensor>, std::optional<torch::Tensor>> marching_cubes_wrapper(
9
+ torch::Tensor grid_vertices,
10
+ torch::Tensor voxels,
11
+ torch::Tensor voxel_values,
12
+ std::optional<torch::Tensor> grid_normals,
13
+ std::optional<torch::Tensor> grid_colors,
14
+ float iso,
15
+ bool return_unique_edges
16
+ ) {
17
+ CHECK_INPUT(grid_vertices);
18
+ CHECK_INPUT(voxels);
19
+ CHECK_INPUT(voxel_values);
20
+
21
+ uint32_t num_voxels = voxels.size(0);
22
+
23
+ const float3* __restrict__ p_grid_vertices = (float3*)grid_vertices.data_ptr<float>();
24
+ const uint32_t* __restrict__ p_voxels = (uint32_t*)voxels.data_ptr<int32_t>();
25
+ const float* __restrict__ p_voxel_values = voxel_values.data_ptr<float>();
26
+
27
+ const float3* __restrict__ p_grid_normals = nullptr;
28
+ if (grid_normals.has_value()) {
29
+ CHECK_INPUT(grid_normals.value());
30
+ p_grid_normals = (float3*)grid_normals.value().data_ptr<float>();
31
+ }
32
+
33
+ const float3* __restrict__ p_grid_colors = nullptr;
34
+ if (grid_colors.has_value()) {
35
+ CHECK_INPUT(grid_colors.value());
36
+ p_grid_colors = (float3*)grid_colors.value().data_ptr<float>();
37
+ }
38
+
39
+ return mc::marching_cubes(
40
+ num_voxels,
41
+ p_grid_vertices,
42
+ p_voxels,
43
+ p_voxel_values,
44
+ p_grid_normals,
45
+ p_grid_colors,
46
+ iso,
47
+ grid_vertices.options(),
48
+ voxels.options(),
49
+ return_unique_edges
50
+ );
51
+ }
52
+
53
+ void marching_cubes_backward_wrapper(
54
+ torch::Tensor unique_edges,
55
+ torch::Tensor grid_vertices,
56
+ std::optional<torch::Tensor> grid_colors,
57
+ torch::Tensor values,
58
+ torch::Tensor adj_verts,
59
+ std::optional<torch::Tensor> adj_colors,
60
+ torch::Tensor adj_values,
61
+ std::optional<torch::Tensor> adj_grid_colors,
62
+ float iso
63
+ ) {
64
+ CHECK_INPUT(unique_edges);
65
+ CHECK_INPUT(grid_vertices);
66
+ CHECK_INPUT(values);
67
+ CHECK_INPUT(adj_verts);
68
+ CHECK_INPUT(adj_values);
69
+
70
+ uint32_t n_verts = unique_edges.size(0);
71
+
72
+ const Edge* p_unique_edges = (const Edge*)unique_edges.data_ptr<int32_t>();
73
+ const float3* p_grid_vertices = (const float3*)grid_vertices.data_ptr<float>();
74
+ const float* p_values = values.data_ptr<float>();
75
+ const float3* p_adj_verts = (const float3*)adj_verts.data_ptr<float>();
76
+ float* p_adj_values = adj_values.data_ptr<float>();
77
+
78
+ const float3* p_grid_colors = nullptr;
79
+ if (grid_colors.has_value()) {
80
+ CHECK_INPUT(grid_colors.value());
81
+ p_grid_colors = (const float3*)grid_colors.value().data_ptr<float>();
82
+ }
83
+
84
+ const float3* p_adj_colors = nullptr;
85
+ if (adj_colors.has_value()) {
86
+ CHECK_INPUT(adj_colors.value());
87
+ p_adj_colors = (const float3*)adj_colors.value().data_ptr<float>();
88
+ }
89
+
90
+ float3* p_adj_grid_colors = nullptr;
91
+ if (adj_grid_colors.has_value()) {
92
+ CHECK_INPUT(adj_grid_colors.value());
93
+ p_adj_grid_colors = (float3*)adj_grid_colors.value().data_ptr<float>();
94
+ }
95
+
96
+ mc::backward(
97
+ n_verts,
98
+ p_unique_edges,
99
+ p_grid_vertices,
100
+ p_grid_colors,
101
+ p_values,
102
+ p_adj_verts,
103
+ p_adj_colors,
104
+ p_adj_values,
105
+ p_adj_grid_colors,
106
+ iso
107
+ );
108
+ }
109
+
110
+ void bind_ops_mc(py::module_& m) {
111
+ m.def("marching_cubes", &marching_cubes_wrapper, "Marching Cubes",
112
+ py::arg("grid_vertices"), py::arg("voxels"), py::arg("voxel_values"),
113
+ py::arg("grid_normals") = std::nullopt, py::arg("grid_colors") = std::nullopt, py::arg("iso") = 0.0f, py::arg("return_unique_edges") = false);
114
+
115
+ m.def("marching_cubes_backward", &marching_cubes_backward_wrapper, "Marching Cubes Backward",
116
+ py::arg("unique_edges"), py::arg("grid_vertices"), py::arg("grid_colors"), py::arg("values"),
117
+ py::arg("adj_verts"), py::arg("adj_colors"), py::arg("adj_values"), py::arg("adj_grid_colors"), py::arg("iso"));
118
+ }
@@ -0,0 +1,73 @@
1
+ #include "../data_structure/kdtree.h"
2
+
3
+ #include <cstdint>
4
+ #include <thrust/device_vector.h>
5
+ #include <thrust/sequence.h>
6
+
7
+ __global__ void one_sided_chamfer_distance_kernel(
8
+ const uint32_t num_query_points,
9
+ const float3 *__restrict__ query_points,
10
+ const uint32_t num_reference_points,
11
+ const float3 *__restrict__ tree_points,
12
+ const int64_t *__restrict__ tree_inds,
13
+ float *__restrict__ distances,
14
+ int64_t *__restrict__ indices)
15
+ {
16
+ uint32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
17
+ if (idx >= num_query_points)
18
+ return;
19
+
20
+ float3 query_point = query_points[idx];
21
+
22
+ float best_dists[MAX_K];
23
+ int64_t best_inds[MAX_K];
24
+
25
+ #pragma unroll
26
+ for (int i = 0; i < MAX_K; i++)
27
+ {
28
+ best_dists[i] = FLT_MAX;
29
+ best_inds[i] = -1;
30
+ }
31
+
32
+ kdtree::query_kdtree_loop(
33
+ query_point,
34
+ num_reference_points,
35
+ tree_points,
36
+ tree_inds,
37
+ 1,
38
+ best_dists,
39
+ best_inds);
40
+
41
+ distances[idx] = best_dists[0];
42
+ indices[idx] = best_inds[0];
43
+ }
44
+
45
+ void one_sided_chamfer_distance(
46
+ const uint32_t num_query_points,
47
+ const float3 *__restrict__ query_points,
48
+ const uint32_t num_reference_points,
49
+ const float3 *__restrict__ reference_points,
50
+ float *__restrict__ distances,
51
+ int64_t *__restrict__ indices)
52
+ {
53
+ thrust::device_vector<float3> cloned_ref_points(reference_points, reference_points + num_reference_points);
54
+ thrust::device_vector<int64_t> reference_indices(num_reference_points);
55
+ thrust::sequence(reference_indices.begin(), reference_indices.end());
56
+
57
+ kdtree::build(
58
+ num_reference_points,
59
+ thrust::raw_pointer_cast(cloned_ref_points.data()),
60
+ thrust::raw_pointer_cast(reference_indices.data()));
61
+
62
+ uint32_t threads = NTHREADS;
63
+ uint32_t blocks = (num_query_points + threads - 1) / threads;
64
+
65
+ one_sided_chamfer_distance_kernel<<<blocks, threads>>>(
66
+ num_query_points,
67
+ query_points,
68
+ num_reference_points,
69
+ thrust::raw_pointer_cast(cloned_ref_points.data()),
70
+ thrust::raw_pointer_cast(reference_indices.data()),
71
+ distances,
72
+ indices);
73
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef CHAMFER_H
2
+ #define CHAMFER_H
3
+
4
+ #include "../constants.h"
5
+ #include "../maths/maths.h"
6
+
7
+ #include <cuda_runtime.h>
8
+
9
+ void one_sided_chamfer_distance(
10
+ const uint32_t num_query_points,
11
+ const float3* __restrict__ query_points,
12
+ const uint32_t num_reference_points,
13
+ const float3* __restrict__ reference_points,
14
+ float* __restrict__ distances,
15
+ int64_t* __restrict__ indices
16
+ );
17
+
18
+ #endif // CHAMFER_H