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.
- {conquer3d-0.2.8/conquer3d.egg-info → conquer3d-0.3.0}/PKG-INFO +7 -2
- {conquer3d-0.2.8 → conquer3d-0.3.0}/README.md +6 -1
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/_C.so +0 -0
- conquer3d-0.3.0/conquer3d/csrc/binds/data_structure/grid.cpp +150 -0
- conquer3d-0.3.0/conquer3d/csrc/binds/ops/chamfer.cpp +42 -0
- conquer3d-0.3.0/conquer3d/csrc/binds/ops/mc.cpp +118 -0
- conquer3d-0.3.0/conquer3d/csrc/ops/chamfer.cu +73 -0
- conquer3d-0.3.0/conquer3d/csrc/ops/chamfer.h +18 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/ops/mc.cu +187 -13
- conquer3d-0.3.0/conquer3d/csrc/ops/mc.h +39 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/pybind.cpp +2 -0
- conquer3d-0.3.0/conquer3d/data_structure/__init__.py +15 -0
- conquer3d-0.3.0/conquer3d/data_structure/grid.py +114 -0
- conquer3d-0.3.0/conquer3d/ops/__init__.py +10 -0
- conquer3d-0.3.0/conquer3d/ops/diff_marching_cubes.py +135 -0
- conquer3d-0.3.0/conquer3d/ops/distance.py +28 -0
- conquer3d-0.3.0/conquer3d/ops/marching_cubes.py +64 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0/conquer3d.egg-info}/PKG-INFO +7 -2
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/SOURCES.txt +6 -1
- {conquer3d-0.2.8 → conquer3d-0.3.0}/pyproject.toml +1 -1
- conquer3d-0.2.8/conquer3d/csrc/binds/data_structure/grid.cpp +0 -66
- conquer3d-0.2.8/conquer3d/csrc/binds/ops/mc.cpp +0 -37
- conquer3d-0.2.8/conquer3d/csrc/ops/mc.h +0 -24
- conquer3d-0.2.8/conquer3d/data_structure/__init__.py +0 -13
- conquer3d-0.2.8/conquer3d/ops/__init__.py +0 -7
- conquer3d-0.2.8/conquer3d/ops/grid.py +0 -26
- conquer3d-0.2.8/conquer3d/ops/marching_cubes.py +0 -42
- {conquer3d-0.2.8 → conquer3d-0.3.0}/LICENSE +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/MANIFEST.in +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/_C.pyi +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/__init__.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/creation/__init__.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/creation/triangle_creation.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/check.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/constants.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/creation/triangle_creation.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/bvh.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/bvh.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/kdtree.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/data_structure/zcurve.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f2x2.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x1.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x3.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f3x4.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f4x1.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/f4x4.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/maths.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/maths/ops.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/ops/mc_data.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/aabb.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/edge.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/ray.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/csrc/primitive/triangles.h +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/__init__.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/gs.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d/primitive/pgs.py +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/dependency_links.txt +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/not-zip-safe +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/requires.txt +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/conquer3d.egg-info/top_level.txt +0 -0
- {conquer3d-0.2.8 → conquer3d-0.3.0}/setup.cfg +0 -0
- {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.
|
|
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
|
|
Binary file
|
|
@@ -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
|