conquer3d 0.2.9__tar.gz → 0.3.1__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.9/conquer3d.egg-info → conquer3d-0.3.1}/PKG-INFO +8 -2
- {conquer3d-0.2.9 → conquer3d-0.3.1}/README.md +6 -1
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/_C.so +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/grid.cpp +20 -0
- conquer3d-0.3.1/conquer3d/csrc/binds/ops/mc.cpp +118 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/ops/mc.cu +152 -8
- conquer3d-0.3.1/conquer3d/csrc/ops/mc.h +39 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/aabb.h +15 -0
- conquer3d-0.3.1/conquer3d/data/collate/__init__.py +0 -0
- conquer3d-0.3.1/conquer3d/data/collate/sparse_tensor.py +43 -0
- conquer3d-0.3.1/conquer3d/data/dataset/__init__.py +0 -0
- conquer3d-0.3.1/conquer3d/data/dataset/base_mesh.py +17 -0
- conquer3d-0.3.1/conquer3d/data/dataset/digit3d.py +136 -0
- conquer3d-0.3.1/conquer3d/data/transform/__init__.py +0 -0
- conquer3d-0.3.1/conquer3d/data_structure/__init__.py +29 -0
- conquer3d-0.3.1/conquer3d/data_structure/grid.py +195 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/ops/__init__.py +2 -3
- conquer3d-0.3.1/conquer3d/ops/diff_marching_cubes.py +135 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/ops/marching_cubes.py +16 -5
- conquer3d-0.3.1/conquer3d/primitive/__init__.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1/conquer3d.egg-info}/PKG-INFO +8 -2
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d.egg-info/SOURCES.txt +9 -1
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d.egg-info/requires.txt +1 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/pyproject.toml +2 -1
- conquer3d-0.2.9/conquer3d/csrc/binds/ops/mc.cpp +0 -47
- conquer3d-0.2.9/conquer3d/csrc/ops/mc.h +0 -25
- conquer3d-0.2.9/conquer3d/data_structure/__init__.py +0 -13
- conquer3d-0.2.9/conquer3d/ops/grid.py +0 -47
- {conquer3d-0.2.9 → conquer3d-0.3.1}/LICENSE +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/MANIFEST.in +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/_C.pyi +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/__init__.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/creation/__init__.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/creation/triangle_creation.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/check.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/constants.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/creation/triangle_creation.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/bvh.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/bvh.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/kdtree.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/data_structure/zcurve.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f2x2.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f3x1.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f3x3.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f3x4.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f4x1.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/f4x4.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/maths.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/maths/ops.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/ops/chamfer.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/ops/chamfer.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/ops/mc_data.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/edge.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/gs.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/gs.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/pgs.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/pgs.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/ray.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/primitive/triangles.h +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/csrc/pybind.cpp +0 -0
- {conquer3d-0.2.9/conquer3d/primitive → conquer3d-0.3.1/conquer3d/data}/__init__.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/ops/distance.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/primitive/gs.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d/primitive/pgs.py +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d.egg-info/dependency_links.txt +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d.egg-info/not-zip-safe +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/conquer3d.egg-info/top_level.txt +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/setup.cfg +0 -0
- {conquer3d-0.2.9 → conquer3d-0.3.1}/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.1
|
|
4
4
|
Summary: Geometric Cuda Tool Box
|
|
5
5
|
Author-email: Do Hoang Khoi <khoido8899@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.9
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: torch>=2.0.0
|
|
16
|
+
Requires-Dist: gdown
|
|
16
17
|
Provides-Extra: cuda
|
|
17
18
|
Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
|
|
18
19
|
Provides-Extra: dev
|
|
@@ -51,12 +52,17 @@ conda activate geocutool
|
|
|
51
52
|
|
|
52
53
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
53
54
|
|
|
55
|
+
pip install setuptools wheel ninja
|
|
54
56
|
pip install torch==2.8.0 torchvision==0.23.0 torchaudio==2.8.0 --index-url https://download.pytorch.org/whl/cu128
|
|
55
57
|
|
|
58
|
+
pip install git+https://github.com/mit-han-lab/torchsparse.git
|
|
59
|
+
|
|
60
|
+
pip install kaolin==0.18.0 -f https://nvidia-kaolin.s3.us-east-2.amazonaws.com/torch-2.8.0_cu128.html
|
|
61
|
+
|
|
56
62
|
pip install pybind11-stubgen
|
|
57
63
|
pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
58
64
|
|
|
59
|
-
pip install plotly open3d jupyter trimesh point-cloud-utils
|
|
65
|
+
pip install plotly open3d jupyter trimesh point-cloud-utils meshlib
|
|
60
66
|
```
|
|
61
67
|
|
|
62
68
|
# 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 point-cloud-utils
|
|
36
|
+
pip install plotly open3d jupyter trimesh point-cloud-utils meshlib
|
|
32
37
|
```
|
|
33
38
|
|
|
34
39
|
# Development
|
|
Binary file
|
|
@@ -121,9 +121,29 @@ torch::Tensor compute_grid_normal(torch::Tensor sdf, torch::Tensor grid_vertices
|
|
|
121
121
|
return torch::nn::functional::normalize(normals, torch::nn::functional::NormalizeFuncOptions().p(2).dim(1));
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
torch::Tensor compute_active_voxels(torch::Tensor voxels, torch::Tensor sdf, float iso) {
|
|
125
|
+
TORCH_CHECK(voxels.device() == sdf.device(), "voxels and sdf must be on the same device.");
|
|
126
|
+
TORCH_CHECK(voxels.dtype() == torch::kInt32, "voxels must be int32.");
|
|
127
|
+
TORCH_CHECK(sdf.dtype() == torch::kFloat32, "sdf must be float32.");
|
|
128
|
+
|
|
129
|
+
auto voxels_flat = voxels.flatten().to(torch::kInt64);
|
|
130
|
+
auto voxel_sdfs = sdf.index_select(0, voxels_flat).view({-1, 8});
|
|
131
|
+
|
|
132
|
+
auto below_iso = voxel_sdfs < iso;
|
|
133
|
+
auto any_below = below_iso.any(1);
|
|
134
|
+
auto any_above = (~below_iso).any(1);
|
|
135
|
+
|
|
136
|
+
auto active_mask = any_below & any_above;
|
|
137
|
+
auto active_indices = torch::nonzero(active_mask).squeeze(1);
|
|
138
|
+
|
|
139
|
+
return active_indices;
|
|
140
|
+
}
|
|
141
|
+
|
|
124
142
|
void bind_ds_grid(py::module_& m) {
|
|
125
143
|
m.def("create_voxel_grid", &create_voxel_grid, "Creates a structured 3D voxel grid.",
|
|
126
144
|
py::arg("grid_min"), py::arg("grid_max"), py::arg("res"), py::arg("device_str") = "cuda");
|
|
127
145
|
m.def("compute_grid_normal", &compute_grid_normal, "Computes surface normals for a grid.",
|
|
128
146
|
py::arg("sdf"), py::arg("grid_vertices"), py::arg("idx_grids"), py::arg("res"));
|
|
147
|
+
m.def("compute_active_voxels", &compute_active_voxels, "Computes active voxels intersecting the surface",
|
|
148
|
+
py::arg("voxels"), py::arg("sdf"), py::arg("iso"));
|
|
129
149
|
}
|
|
@@ -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
|
+
}
|
|
@@ -176,9 +176,11 @@ namespace mc
|
|
|
176
176
|
const float3* grid_vertices,
|
|
177
177
|
const float* values,
|
|
178
178
|
const float3* grid_normals,
|
|
179
|
+
const float3* grid_colors,
|
|
179
180
|
const float iso,
|
|
180
181
|
float3* out_verts,
|
|
181
|
-
float3* out_normals
|
|
182
|
+
float3* out_normals,
|
|
183
|
+
float3* out_colors
|
|
182
184
|
)
|
|
183
185
|
{
|
|
184
186
|
uint32_t v_idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -199,24 +201,31 @@ namespace mc
|
|
|
199
201
|
// 3. Interpolate (Differentiable formula)
|
|
200
202
|
float3 p;
|
|
201
203
|
float3 n;
|
|
204
|
+
float3 c;
|
|
202
205
|
bool has_normals = grid_normals != nullptr;
|
|
206
|
+
bool has_colors = grid_colors != nullptr;
|
|
203
207
|
float3 n0 = has_normals ? grid_normals[v0_idx] : make_float3(0, 0, 0);
|
|
204
208
|
float3 n1 = has_normals ? grid_normals[v1_idx] : make_float3(0, 0, 0);
|
|
209
|
+
float3 c0 = has_colors ? grid_colors[v0_idx] : make_float3(0, 0, 0);
|
|
210
|
+
float3 c1 = has_colors ? grid_colors[v1_idx] : make_float3(0, 0, 0);
|
|
205
211
|
|
|
206
212
|
if (fabsf(iso - val0) < EPS)
|
|
207
213
|
{
|
|
208
214
|
p = p0;
|
|
209
215
|
if (has_normals) n = n0;
|
|
216
|
+
if (has_colors) c = c0;
|
|
210
217
|
}
|
|
211
218
|
else if (fabsf(iso - val1) < EPS)
|
|
212
219
|
{
|
|
213
220
|
p = p1;
|
|
214
221
|
if (has_normals) n = n1;
|
|
222
|
+
if (has_colors) c = c1;
|
|
215
223
|
}
|
|
216
224
|
else if (fabsf(val0 - val1) < EPS)
|
|
217
225
|
{
|
|
218
226
|
p = p0;
|
|
219
227
|
if (has_normals) n = n0;
|
|
228
|
+
if (has_colors) c = c0;
|
|
220
229
|
}
|
|
221
230
|
else
|
|
222
231
|
{
|
|
@@ -228,12 +237,18 @@ namespace mc
|
|
|
228
237
|
n = n0 + (n1 - n0) * t;
|
|
229
238
|
n = maths::normalize(n);
|
|
230
239
|
}
|
|
240
|
+
if (has_colors) {
|
|
241
|
+
c = c0 + (c1 - c0) * t;
|
|
242
|
+
}
|
|
231
243
|
}
|
|
232
244
|
|
|
233
245
|
out_verts[v_idx] = p;
|
|
234
246
|
if (has_normals) {
|
|
235
247
|
out_normals[v_idx] = n;
|
|
236
248
|
}
|
|
249
|
+
if (has_colors) {
|
|
250
|
+
out_colors[v_idx] = c;
|
|
251
|
+
}
|
|
237
252
|
}
|
|
238
253
|
|
|
239
254
|
void compute_active_voxels(
|
|
@@ -357,16 +372,18 @@ namespace mc
|
|
|
357
372
|
const float3* grid_vertices,
|
|
358
373
|
const float* values,
|
|
359
374
|
const float3* grid_normals,
|
|
375
|
+
const float3* grid_colors,
|
|
360
376
|
const float iso,
|
|
361
377
|
float3* out_verts,
|
|
362
|
-
float3* out_normals
|
|
378
|
+
float3* out_normals,
|
|
379
|
+
float3* out_colors
|
|
363
380
|
)
|
|
364
381
|
{
|
|
365
382
|
if (num_unique_edges == 0) return;
|
|
366
383
|
int block_size = NTHREADS;
|
|
367
384
|
int grid_size = (num_unique_edges + block_size - 1) / block_size;
|
|
368
385
|
interpolate_vertices_kernel<<<grid_size, block_size>>>(
|
|
369
|
-
num_unique_edges, unique_edges, grid_vertices, values, grid_normals, iso, out_verts, out_normals);
|
|
386
|
+
num_unique_edges, unique_edges, grid_vertices, values, grid_normals, grid_colors, iso, out_verts, out_normals, out_colors);
|
|
370
387
|
}
|
|
371
388
|
|
|
372
389
|
void compute_number_triangles(
|
|
@@ -435,15 +452,17 @@ namespace mc
|
|
|
435
452
|
num_active_voxels, used_voxel_codes, voxel_edge_to_vert_idx, voxel_triangle_prefix_sums, out_triangles);
|
|
436
453
|
}
|
|
437
454
|
|
|
438
|
-
std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>> marching_cubes(
|
|
455
|
+
std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>, std::optional<torch::Tensor>, std::optional<torch::Tensor>> marching_cubes(
|
|
439
456
|
const uint32_t num_voxels,
|
|
440
457
|
const float3* __restrict__ grid_vertices,
|
|
441
458
|
const uint32_t* __restrict__ voxels,
|
|
442
459
|
const float* __restrict__ voxel_values,
|
|
443
460
|
const float3* __restrict__ grid_normals,
|
|
461
|
+
const float3* __restrict__ grid_colors,
|
|
444
462
|
const float iso,
|
|
445
463
|
torch::TensorOptions vert_options,
|
|
446
|
-
torch::TensorOptions tri_options
|
|
464
|
+
torch::TensorOptions tri_options,
|
|
465
|
+
bool return_unique_edges
|
|
447
466
|
)
|
|
448
467
|
{
|
|
449
468
|
uint8_t *__restrict__ voxel_codes;
|
|
@@ -457,11 +476,15 @@ namespace mc
|
|
|
457
476
|
if (num_active_voxels == 0) {
|
|
458
477
|
CHECK_CUDA_INTERNAL(cudaFree(voxel_codes));
|
|
459
478
|
std::optional<torch::Tensor> out_n = std::nullopt;
|
|
479
|
+
std::optional<torch::Tensor> out_c = std::nullopt;
|
|
460
480
|
if (grid_normals != nullptr) out_n = torch::empty({0, 3}, vert_options);
|
|
481
|
+
if (grid_colors != nullptr) out_c = torch::empty({0, 3}, vert_options);
|
|
461
482
|
return std::make_tuple(
|
|
462
483
|
torch::empty({0, 3}, vert_options),
|
|
463
484
|
torch::empty({0, 3}, tri_options),
|
|
464
|
-
out_n
|
|
485
|
+
out_n,
|
|
486
|
+
out_c,
|
|
487
|
+
std::nullopt
|
|
465
488
|
);
|
|
466
489
|
}
|
|
467
490
|
|
|
@@ -493,7 +516,15 @@ namespace mc
|
|
|
493
516
|
out_normals_opt = out_normals;
|
|
494
517
|
}
|
|
495
518
|
|
|
496
|
-
|
|
519
|
+
std::optional<torch::Tensor> out_colors_opt = std::nullopt;
|
|
520
|
+
float3* __restrict__ p_out_colors = nullptr;
|
|
521
|
+
if (grid_colors != nullptr) {
|
|
522
|
+
torch::Tensor out_colors = torch::empty({out_num_vertices, 3}, vert_options);
|
|
523
|
+
p_out_colors = (float3*)out_colors.data_ptr<float>();
|
|
524
|
+
out_colors_opt = out_colors;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
interpolate_vertices(out_num_vertices, unique_edges, grid_vertices, voxel_values, grid_normals, grid_colors, iso, p_out_vertices, p_out_normals, p_out_colors);
|
|
497
528
|
|
|
498
529
|
uint32_t out_num_triangles;
|
|
499
530
|
uint32_t *__restrict__ voxel_triangle_prefix_sums;
|
|
@@ -505,6 +536,13 @@ namespace mc
|
|
|
505
536
|
|
|
506
537
|
assemble_triangles(num_active_voxels, used_voxel_codes, voxel_edge_to_vert_idx, voxel_triangle_prefix_sums, p_out_triangles);
|
|
507
538
|
|
|
539
|
+
std::optional<torch::Tensor> out_unique_edges_opt = std::nullopt;
|
|
540
|
+
if (return_unique_edges) {
|
|
541
|
+
torch::Tensor out_unique_edges = torch::empty({out_num_vertices, 2}, torch::dtype(torch::kInt32).device(vert_options.device()));
|
|
542
|
+
CHECK_CUDA_INTERNAL(cudaMemcpy(out_unique_edges.data_ptr(), unique_edges, out_num_vertices * sizeof(Edge), cudaMemcpyDeviceToDevice));
|
|
543
|
+
out_unique_edges_opt = out_unique_edges;
|
|
544
|
+
}
|
|
545
|
+
|
|
508
546
|
// Cleanup
|
|
509
547
|
CHECK_CUDA_INTERNAL(cudaFree(voxel_codes));
|
|
510
548
|
CHECK_CUDA_INTERNAL(cudaFree(used_voxel_index));
|
|
@@ -514,6 +552,112 @@ namespace mc
|
|
|
514
552
|
CHECK_CUDA_INTERNAL(cudaFree(voxel_edge_to_vert_idx));
|
|
515
553
|
CHECK_CUDA_INTERNAL(cudaFree(voxel_triangle_prefix_sums));
|
|
516
554
|
|
|
517
|
-
return std::make_tuple(out_vertices, out_triangles, out_normals_opt);
|
|
555
|
+
return std::make_tuple(out_vertices, out_triangles, out_normals_opt, out_colors_opt, out_unique_edges_opt);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
__global__ void backward_dmc_kernel(
|
|
559
|
+
const uint32_t n_verts,
|
|
560
|
+
const Edge *unique_edges,
|
|
561
|
+
const float *grid_values,
|
|
562
|
+
const float3 *grid_coords,
|
|
563
|
+
const float3 *grid_colors,
|
|
564
|
+
const float3 *adj_verts,
|
|
565
|
+
const float3 *adj_colors,
|
|
566
|
+
const float iso,
|
|
567
|
+
float *adj_values,
|
|
568
|
+
float3 *adj_grid_colors,
|
|
569
|
+
bool with_colors)
|
|
570
|
+
{
|
|
571
|
+
uint32_t v_idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
572
|
+
if (v_idx >= n_verts)
|
|
573
|
+
return;
|
|
574
|
+
|
|
575
|
+
Edge edge_sig = unique_edges[v_idx];
|
|
576
|
+
uint32_t v0_idx = edge_sig.v0;
|
|
577
|
+
uint32_t v1_idx = edge_sig.v1;
|
|
578
|
+
|
|
579
|
+
float v0_val = grid_values[v0_idx];
|
|
580
|
+
float v1_val = grid_values[v1_idx];
|
|
581
|
+
float3 p0 = grid_coords[v0_idx];
|
|
582
|
+
float3 p1 = grid_coords[v1_idx];
|
|
583
|
+
|
|
584
|
+
float3 grad_p_out = adj_verts[v_idx];
|
|
585
|
+
|
|
586
|
+
float3 c0, c1, grad_c_out;
|
|
587
|
+
if (with_colors)
|
|
588
|
+
{
|
|
589
|
+
c0 = grid_colors[v0_idx];
|
|
590
|
+
c1 = grid_colors[v1_idx];
|
|
591
|
+
grad_c_out = adj_colors[v_idx];
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
float diff = v1_val - v0_val;
|
|
595
|
+
|
|
596
|
+
if (with_colors)
|
|
597
|
+
{
|
|
598
|
+
float t = 0.5f;
|
|
599
|
+
if (fabsf(iso - v0_val) < EPS)
|
|
600
|
+
t = 0.0f;
|
|
601
|
+
else if (fabsf(iso - v1_val) < EPS)
|
|
602
|
+
t = 1.0f;
|
|
603
|
+
else if (fabsf(diff) >= EPS)
|
|
604
|
+
{
|
|
605
|
+
t = fmaxf(0.0f, fminf(1.0f, (iso - v0_val) / diff));
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
float t0 = 1.0f - t;
|
|
609
|
+
float t1 = t;
|
|
610
|
+
|
|
611
|
+
atomicAdd(&(adj_grid_colors[v0_idx].x), grad_c_out.x * t0);
|
|
612
|
+
atomicAdd(&(adj_grid_colors[v0_idx].y), grad_c_out.y * t0);
|
|
613
|
+
atomicAdd(&(adj_grid_colors[v0_idx].z), grad_c_out.z * t0);
|
|
614
|
+
|
|
615
|
+
atomicAdd(&(adj_grid_colors[v1_idx].x), grad_c_out.x * t1);
|
|
616
|
+
atomicAdd(&(adj_grid_colors[v1_idx].y), grad_c_out.y * t1);
|
|
617
|
+
atomicAdd(&(adj_grid_colors[v1_idx].z), grad_c_out.z * t1);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (diff * diff < 1e-14f)
|
|
621
|
+
return;
|
|
622
|
+
|
|
623
|
+
float dot_prod = (p1.x - p0.x) * grad_p_out.x + (p1.y - p0.y) * grad_p_out.y + (p1.z - p0.z) * grad_p_out.z;
|
|
624
|
+
float common = dot_prod / (diff * diff);
|
|
625
|
+
float grad_v0 = common * (iso - v1_val);
|
|
626
|
+
float grad_v1 = common * (v0_val - iso);
|
|
627
|
+
|
|
628
|
+
atomicAdd(&adj_values[v0_idx], grad_v0);
|
|
629
|
+
atomicAdd(&adj_values[v1_idx], grad_v1);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
void backward(
|
|
633
|
+
const uint32_t n_verts,
|
|
634
|
+
const Edge *unique_edges,
|
|
635
|
+
const float3 *grid_vertices,
|
|
636
|
+
const float3 *grid_colors,
|
|
637
|
+
const float *values,
|
|
638
|
+
const float3 *adj_verts,
|
|
639
|
+
const float3 *adj_colors,
|
|
640
|
+
float *adj_values,
|
|
641
|
+
float3 *adj_grid_colors,
|
|
642
|
+
const float iso)
|
|
643
|
+
{
|
|
644
|
+
if (n_verts == 0) return;
|
|
645
|
+
|
|
646
|
+
bool with_colors = (grid_colors != nullptr && adj_colors != nullptr && adj_grid_colors != nullptr);
|
|
647
|
+
int block_size = NTHREADS;
|
|
648
|
+
int grid_size = (n_verts + block_size - 1) / block_size;
|
|
649
|
+
|
|
650
|
+
backward_dmc_kernel<<<grid_size, block_size>>>(
|
|
651
|
+
n_verts,
|
|
652
|
+
unique_edges,
|
|
653
|
+
values,
|
|
654
|
+
grid_vertices,
|
|
655
|
+
grid_colors,
|
|
656
|
+
adj_verts,
|
|
657
|
+
adj_colors,
|
|
658
|
+
iso,
|
|
659
|
+
adj_values,
|
|
660
|
+
adj_grid_colors,
|
|
661
|
+
with_colors);
|
|
518
662
|
}
|
|
519
663
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#ifndef MC_H
|
|
2
|
+
#define MC_H
|
|
3
|
+
|
|
4
|
+
#include <torch/extension.h>
|
|
5
|
+
#include "mc_data.h"
|
|
6
|
+
#include "../check.h"
|
|
7
|
+
#include "../constants.h"
|
|
8
|
+
#include "../primitive/edge.h"
|
|
9
|
+
|
|
10
|
+
#include <optional>
|
|
11
|
+
|
|
12
|
+
namespace mc{
|
|
13
|
+
std::tuple<torch::Tensor, torch::Tensor, std::optional<torch::Tensor>, std::optional<torch::Tensor>, std::optional<torch::Tensor>> marching_cubes(
|
|
14
|
+
const uint32_t num_voxels,
|
|
15
|
+
const float3* __restrict__ grid_vertices,
|
|
16
|
+
const uint32_t* __restrict__ voxels,
|
|
17
|
+
const float* __restrict__ voxel_values,
|
|
18
|
+
const float3* __restrict__ grid_normals,
|
|
19
|
+
const float3* __restrict__ grid_colors,
|
|
20
|
+
const float iso,
|
|
21
|
+
torch::TensorOptions vert_options,
|
|
22
|
+
torch::TensorOptions tri_options,
|
|
23
|
+
bool return_unique_edges = false
|
|
24
|
+
);
|
|
25
|
+
void backward(
|
|
26
|
+
const uint32_t n_verts,
|
|
27
|
+
const Edge *unique_edges,
|
|
28
|
+
const float3 *grid_vertices,
|
|
29
|
+
const float3 *grid_colors,
|
|
30
|
+
const float *values,
|
|
31
|
+
const float3 *adj_verts,
|
|
32
|
+
const float3 *adj_colors,
|
|
33
|
+
float *adj_values,
|
|
34
|
+
float3 *adj_grid_colors,
|
|
35
|
+
const float iso
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#endif // MC_H
|
|
@@ -167,6 +167,21 @@ namespace aabb
|
|
|
167
167
|
(target_aabb_max.y) >= query_aabb_max.y &&
|
|
168
168
|
(target_aabb_max.z) >= query_aabb_max.z);
|
|
169
169
|
}
|
|
170
|
+
|
|
171
|
+
__device__ __forceinline__ bool test_point_inside_aabb(
|
|
172
|
+
const float3 &point,
|
|
173
|
+
const float3 &aabb_min,
|
|
174
|
+
const float3 &aabb_max
|
|
175
|
+
)
|
|
176
|
+
{
|
|
177
|
+
return (
|
|
178
|
+
aabb_min.x <= point.x &&
|
|
179
|
+
aabb_min.y <= point.y &&
|
|
180
|
+
aabb_min.z <= point.z &&
|
|
181
|
+
(aabb_max.x) >= point.x &&
|
|
182
|
+
(aabb_max.y) >= point.y &&
|
|
183
|
+
(aabb_max.z) >= point.z);
|
|
184
|
+
}
|
|
170
185
|
}
|
|
171
186
|
|
|
172
187
|
#endif // AABB_H
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
|
|
3
|
+
def sparse_collate_fn(batch):
|
|
4
|
+
"""
|
|
5
|
+
Collate function for sparse tensor dataloaders (e.g., MinkowskiEngine, spconv, torchsparse).
|
|
6
|
+
Takes a batch of samples where each sample is (idx_grids, features, ...).
|
|
7
|
+
Appends the batch index to the idx_grids to create (batch_idx, x, y, z).
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
batch (list): A list of tuples (idx_grids, features, label)
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
tuple: (batched_coords, batched_features, batched_labels)
|
|
14
|
+
batched_coords (torch.Tensor): Shape (Total_N, 4)
|
|
15
|
+
batched_features (torch.Tensor): Shape (Total_N, ...)
|
|
16
|
+
batched_labels (torch.Tensor): Shape (Batch_Size,)
|
|
17
|
+
"""
|
|
18
|
+
batched_coords = []
|
|
19
|
+
batched_features = []
|
|
20
|
+
batched_labels = []
|
|
21
|
+
|
|
22
|
+
for batch_idx, item in enumerate(batch):
|
|
23
|
+
idx_grids, features, label = item
|
|
24
|
+
|
|
25
|
+
# Create a batch index column of shape [N, 1]
|
|
26
|
+
b_col = torch.full((idx_grids.shape[0], 1), batch_idx, dtype=idx_grids.dtype, device=idx_grids.device)
|
|
27
|
+
|
|
28
|
+
# Concatenate to get [N, 4] formatted as (batch_idx, x, y, z)
|
|
29
|
+
coords_with_batch = torch.cat([b_col, idx_grids], dim=1)
|
|
30
|
+
|
|
31
|
+
batched_coords.append(coords_with_batch)
|
|
32
|
+
batched_features.append(features)
|
|
33
|
+
batched_labels.append(label)
|
|
34
|
+
|
|
35
|
+
batched_coords = torch.cat(batched_coords, dim=0)
|
|
36
|
+
batched_features = torch.cat(batched_features, dim=0)
|
|
37
|
+
|
|
38
|
+
if isinstance(batched_labels[0], torch.Tensor):
|
|
39
|
+
batched_labels = torch.stack(batched_labels, dim=0)
|
|
40
|
+
else:
|
|
41
|
+
batched_labels = torch.tensor(batched_labels)
|
|
42
|
+
|
|
43
|
+
return batched_coords, batched_features, batched_labels
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from torch.utils.data import Dataset
|
|
2
|
+
from typing import Callable, Optional
|
|
3
|
+
|
|
4
|
+
class BaseMeshDataset(Dataset):
|
|
5
|
+
"""
|
|
6
|
+
Base PyTorch Dataset class for Mesh datasets.
|
|
7
|
+
"""
|
|
8
|
+
def __init__(self, root: str, transform: Optional[Callable] = None):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.root = root
|
|
11
|
+
self.transform = transform
|
|
12
|
+
|
|
13
|
+
def __len__(self) -> int:
|
|
14
|
+
raise NotImplementedError("Subclasses must implement __len__")
|
|
15
|
+
|
|
16
|
+
def __getitem__(self, idx: int):
|
|
17
|
+
raise NotImplementedError("Subclasses must implement __getitem__")
|