conquer3d 0.3.3__tar.gz → 0.3.5__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.3.5/MANIFEST.in +1 -0
- {conquer3d-0.3.3/conquer3d.egg-info → conquer3d-0.3.5}/PKG-INFO +20 -14
- {conquer3d-0.3.3 → conquer3d-0.3.5}/README.md +19 -14
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/_C.so +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/ops/mc.cu +4 -11
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/ops/mc.h +1 -0
- conquer3d-0.3.5/conquer3d/data/assets/common.py +132 -0
- conquer3d-0.3.5/conquer3d/data/assets/iphigenia.py +43 -0
- conquer3d-0.3.5/conquer3d/data/transform/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data_structure/grid.py +18 -1
- conquer3d-0.3.5/conquer3d/io/__init__.py +2 -0
- conquer3d-0.3.5/conquer3d/io/obj.py +42 -0
- conquer3d-0.3.5/conquer3d/io/off.py +23 -0
- conquer3d-0.3.5/conquer3d/ops/delaunay_triangulation.py +71 -0
- conquer3d-0.3.5/conquer3d/ops/marching_tetrahedra.py +125 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5/conquer3d.egg-info}/PKG-INFO +20 -14
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d.egg-info/SOURCES.txt +8 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d.egg-info/requires.txt +1 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/pyproject.toml +2 -1
- {conquer3d-0.3.3 → conquer3d-0.3.5}/setup.py +4 -0
- conquer3d-0.3.3/MANIFEST.in +0 -1
- {conquer3d-0.3.3 → conquer3d-0.3.5}/LICENSE +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/_C.pyi +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/conversion/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/conversion/grid.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/conversion/mesh.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/creation/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/creation/triangle_creation.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/grid.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/ops/mc.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/primitive/ray.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/binds/primitive/triangle.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/check.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/constants.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/creation/triangle_creation.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/bvh.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/bvh.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/kdtree.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/data_structure/zcurve.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f2x2.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f3x1.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f3x3.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f3x4.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f4x1.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/f4x4.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/maths.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/maths/ops.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/ops/chamfer.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/ops/chamfer.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/ops/mc_data.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/aabb.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/edge.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/gs.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/gs.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/pgs.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/pgs.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/ray.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/primitive/triangle.h +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/csrc/pybind.cpp +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/__init__.py +0 -0
- {conquer3d-0.3.3/conquer3d/data/collate → conquer3d-0.3.5/conquer3d/data/assets}/__init__.py +0 -0
- {conquer3d-0.3.3/conquer3d/data/dataset → conquer3d-0.3.5/conquer3d/data/collate}/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/collate/mesh.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/collate/sparse_tensor.py +0 -0
- {conquer3d-0.3.3/conquer3d/data/transform → conquer3d-0.3.5/conquer3d/data/dataset}/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/dataset/base_mesh.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/dataset/digit3d.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/transform/base.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/transform/ops.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data/transform/vertex.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data_structure/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/data_structure/bmesh.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/ops/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/ops/diff_marching_cubes.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/ops/distance.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/ops/marching_cubes.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/primitive/__init__.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/primitive/gs.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d/primitive/pgs.py +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d.egg-info/dependency_links.txt +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d.egg-info/not-zip-safe +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/conquer3d.egg-info/top_level.txt +0 -0
- {conquer3d-0.3.3 → conquer3d-0.3.5}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include conquer3d/csrc *.h *.cuh *.cpp *.cu
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
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: meshio>=5.3.5
|
|
16
17
|
Requires-Dist: gdown
|
|
17
18
|
Provides-Extra: cuda
|
|
18
19
|
Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
|
|
@@ -49,6 +50,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
49
50
|
```bash
|
|
50
51
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
51
52
|
conda activate geocutool
|
|
53
|
+
conda install -c conda-forge sparsehash -y
|
|
52
54
|
|
|
53
55
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
54
56
|
|
|
@@ -77,6 +79,9 @@ twine upload dist/* --verbose
|
|
|
77
79
|
|
|
78
80
|
# Reference
|
|
79
81
|
|
|
82
|
+
## Book
|
|
83
|
+
|
|
84
|
+
|
|
80
85
|
## Research Paper
|
|
81
86
|
```bibtex
|
|
82
87
|
@inproceedings{2383795.2383801,
|
|
@@ -133,19 +138,19 @@ twine upload dist/* --verbose
|
|
|
133
138
|
|
|
134
139
|
```bibtex
|
|
135
140
|
@InProceedings{10.1007/978-3-662-05105-4_2,
|
|
136
|
-
author="Meyer, Mark
|
|
137
|
-
and Desbrun, Mathieu
|
|
138
|
-
and Schr{\"o}der, Peter
|
|
139
|
-
and Barr, Alan H.",
|
|
140
|
-
editor="Hege, Hans-Christian
|
|
141
|
-
and Polthier, Konrad",
|
|
142
|
-
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
143
|
-
booktitle="Visualization and Mathematics III",
|
|
144
|
-
year="2003",
|
|
145
|
-
publisher="Springer Berlin Heidelberg",
|
|
146
|
-
address="Berlin, Heidelberg",
|
|
147
|
-
pages="35--57",
|
|
148
|
-
isbn="978-3-662-05105-4"
|
|
141
|
+
author="Meyer, Mark
|
|
142
|
+
and Desbrun, Mathieu
|
|
143
|
+
and Schr{\"o}der, Peter
|
|
144
|
+
and Barr, Alan H.",
|
|
145
|
+
editor="Hege, Hans-Christian
|
|
146
|
+
and Polthier, Konrad",
|
|
147
|
+
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
148
|
+
booktitle="Visualization and Mathematics III",
|
|
149
|
+
year="2003",
|
|
150
|
+
publisher="Springer Berlin Heidelberg",
|
|
151
|
+
address="Berlin, Heidelberg",
|
|
152
|
+
pages="35--57",
|
|
153
|
+
isbn="978-3-662-05105-4"
|
|
149
154
|
}
|
|
150
155
|
```
|
|
151
156
|
|
|
@@ -161,3 +166,4 @@ isbn="978-3-662-05105-4"
|
|
|
161
166
|
- [Pytorch3D](https://github.com/facebookresearch/pytorch3d)
|
|
162
167
|
- [Open3D](https://www.open3d.org/)
|
|
163
168
|
- [trimesh](https://github.com/mikedh/trimesh)
|
|
169
|
+
- [TetWeave](https://github.com/AlexandreBinninger/TetWeave/tree/main)
|
|
@@ -20,6 +20,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
20
20
|
```bash
|
|
21
21
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
22
22
|
conda activate geocutool
|
|
23
|
+
conda install -c conda-forge sparsehash -y
|
|
23
24
|
|
|
24
25
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
25
26
|
|
|
@@ -48,6 +49,9 @@ twine upload dist/* --verbose
|
|
|
48
49
|
|
|
49
50
|
# Reference
|
|
50
51
|
|
|
52
|
+
## Book
|
|
53
|
+
|
|
54
|
+
|
|
51
55
|
## Research Paper
|
|
52
56
|
```bibtex
|
|
53
57
|
@inproceedings{2383795.2383801,
|
|
@@ -104,19 +108,19 @@ twine upload dist/* --verbose
|
|
|
104
108
|
|
|
105
109
|
```bibtex
|
|
106
110
|
@InProceedings{10.1007/978-3-662-05105-4_2,
|
|
107
|
-
author="Meyer, Mark
|
|
108
|
-
and Desbrun, Mathieu
|
|
109
|
-
and Schr{\"o}der, Peter
|
|
110
|
-
and Barr, Alan H.",
|
|
111
|
-
editor="Hege, Hans-Christian
|
|
112
|
-
and Polthier, Konrad",
|
|
113
|
-
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
114
|
-
booktitle="Visualization and Mathematics III",
|
|
115
|
-
year="2003",
|
|
116
|
-
publisher="Springer Berlin Heidelberg",
|
|
117
|
-
address="Berlin, Heidelberg",
|
|
118
|
-
pages="35--57",
|
|
119
|
-
isbn="978-3-662-05105-4"
|
|
111
|
+
author="Meyer, Mark
|
|
112
|
+
and Desbrun, Mathieu
|
|
113
|
+
and Schr{\"o}der, Peter
|
|
114
|
+
and Barr, Alan H.",
|
|
115
|
+
editor="Hege, Hans-Christian
|
|
116
|
+
and Polthier, Konrad",
|
|
117
|
+
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
118
|
+
booktitle="Visualization and Mathematics III",
|
|
119
|
+
year="2003",
|
|
120
|
+
publisher="Springer Berlin Heidelberg",
|
|
121
|
+
address="Berlin, Heidelberg",
|
|
122
|
+
pages="35--57",
|
|
123
|
+
isbn="978-3-662-05105-4"
|
|
120
124
|
}
|
|
121
125
|
```
|
|
122
126
|
|
|
@@ -131,4 +135,5 @@ isbn="978-3-662-05105-4"
|
|
|
131
135
|
- [Kaolin](https://github.com/NVIDIAGameWorks/kaolin)
|
|
132
136
|
- [Pytorch3D](https://github.com/facebookresearch/pytorch3d)
|
|
133
137
|
- [Open3D](https://www.open3d.org/)
|
|
134
|
-
- [trimesh](https://github.com/mikedh/trimesh)
|
|
138
|
+
- [trimesh](https://github.com/mikedh/trimesh)
|
|
139
|
+
- [TetWeave](https://github.com/AlexandreBinninger/TetWeave/tree/main)
|
|
Binary file
|
|
@@ -583,11 +583,9 @@ namespace mc
|
|
|
583
583
|
|
|
584
584
|
float3 grad_p_out = adj_verts[v_idx];
|
|
585
585
|
|
|
586
|
-
float3
|
|
586
|
+
float3 grad_c_out;
|
|
587
587
|
if (with_colors)
|
|
588
588
|
{
|
|
589
|
-
c0 = grid_colors[v0_idx];
|
|
590
|
-
c1 = grid_colors[v1_idx];
|
|
591
589
|
grad_c_out = adj_colors[v_idx];
|
|
592
590
|
}
|
|
593
591
|
|
|
@@ -608,19 +606,14 @@ namespace mc
|
|
|
608
606
|
float t0 = 1.0f - t;
|
|
609
607
|
float t1 = t;
|
|
610
608
|
|
|
611
|
-
atomicAdd(&(adj_grid_colors[v0_idx]
|
|
612
|
-
atomicAdd(&(adj_grid_colors[
|
|
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);
|
|
609
|
+
atomicAdd(&(adj_grid_colors[v0_idx]), grad_c_out * t0);
|
|
610
|
+
atomicAdd(&(adj_grid_colors[v1_idx]), grad_c_out * t1);
|
|
618
611
|
}
|
|
619
612
|
|
|
620
613
|
if (diff * diff < 1e-14f)
|
|
621
614
|
return;
|
|
622
615
|
|
|
623
|
-
float dot_prod = (p1
|
|
616
|
+
float dot_prod = maths::dot(p1 - p0, grad_p_out);
|
|
624
617
|
float common = dot_prod / (diff * diff);
|
|
625
618
|
float grad_v0 = common * (iso - v1_val);
|
|
626
619
|
float grad_v1 = common * (v0_val - iso);
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import urllib.request
|
|
3
|
+
import torch
|
|
4
|
+
from conquer3d.io.obj import read_obj
|
|
5
|
+
|
|
6
|
+
class Common3D:
|
|
7
|
+
"""
|
|
8
|
+
Base class for models from the common-3d-test-models repository.
|
|
9
|
+
Downloads the specific .obj model directly via the Raw GitHub URL
|
|
10
|
+
and loads its vertices, faces, and optional colors.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, filename, download_dir="~/.conquer3d"):
|
|
13
|
+
self.filename = filename
|
|
14
|
+
self.url = f"https://raw.githubusercontent.com/KhoiDOO/common-3d-test-models/master/data/{self.filename}"
|
|
15
|
+
self.download_dir = os.path.expanduser(download_dir)
|
|
16
|
+
self.vertices = None
|
|
17
|
+
self.faces = None
|
|
18
|
+
self.colors = None
|
|
19
|
+
|
|
20
|
+
self._load()
|
|
21
|
+
|
|
22
|
+
def _load(self):
|
|
23
|
+
os.makedirs(self.download_dir, exist_ok=True)
|
|
24
|
+
obj_path = os.path.join(self.download_dir, self.filename)
|
|
25
|
+
|
|
26
|
+
if not os.path.exists(obj_path):
|
|
27
|
+
print(f"Downloading {self.filename} from {self.url}...")
|
|
28
|
+
req = urllib.request.Request(self.url, headers={'User-Agent': 'Mozilla/5.0'})
|
|
29
|
+
with urllib.request.urlopen(req) as response, open(obj_path, 'wb') as out_file:
|
|
30
|
+
out_file.write(response.read())
|
|
31
|
+
print("Download complete.")
|
|
32
|
+
|
|
33
|
+
print(f"Reading {self.filename}...")
|
|
34
|
+
self.vertices, self.faces, self.colors = read_obj(obj_path)
|
|
35
|
+
|
|
36
|
+
# --- Child Classes ---
|
|
37
|
+
|
|
38
|
+
class Alligator(Common3D):
|
|
39
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
40
|
+
super().__init__("alligator.obj", download_dir)
|
|
41
|
+
|
|
42
|
+
class Armadillo(Common3D):
|
|
43
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
44
|
+
super().__init__("armadillo.obj", download_dir)
|
|
45
|
+
|
|
46
|
+
class Beast(Common3D):
|
|
47
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
48
|
+
super().__init__("beast.obj", download_dir)
|
|
49
|
+
|
|
50
|
+
class BeetleAlt(Common3D):
|
|
51
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
52
|
+
super().__init__("beetle-alt.obj", download_dir)
|
|
53
|
+
|
|
54
|
+
class Beetle(Common3D):
|
|
55
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
56
|
+
super().__init__("beetle.obj", download_dir)
|
|
57
|
+
|
|
58
|
+
class Bimba(Common3D):
|
|
59
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
60
|
+
super().__init__("bimba.obj", download_dir)
|
|
61
|
+
|
|
62
|
+
class Cheburashka(Common3D):
|
|
63
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
64
|
+
super().__init__("cheburashka.obj", download_dir)
|
|
65
|
+
|
|
66
|
+
class Cow(Common3D):
|
|
67
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
68
|
+
super().__init__("cow.obj", download_dir)
|
|
69
|
+
|
|
70
|
+
class Fandisk(Common3D):
|
|
71
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
72
|
+
super().__init__("fandisk.obj", download_dir)
|
|
73
|
+
|
|
74
|
+
class HappyBuddha(Common3D):
|
|
75
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
76
|
+
super().__init__("happy.obj", download_dir)
|
|
77
|
+
|
|
78
|
+
class Homer(Common3D):
|
|
79
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
80
|
+
super().__init__("homer.obj", download_dir)
|
|
81
|
+
|
|
82
|
+
class Horse(Common3D):
|
|
83
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
84
|
+
super().__init__("horse.obj", download_dir)
|
|
85
|
+
|
|
86
|
+
class Igea(Common3D):
|
|
87
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
88
|
+
super().__init__("igea.obj", download_dir)
|
|
89
|
+
|
|
90
|
+
class Lucy(Common3D):
|
|
91
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
92
|
+
super().__init__("lucy.obj", download_dir)
|
|
93
|
+
|
|
94
|
+
class MaxPlanck(Common3D):
|
|
95
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
96
|
+
super().__init__("max-planck.obj", download_dir)
|
|
97
|
+
|
|
98
|
+
class Nefertiti(Common3D):
|
|
99
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
100
|
+
super().__init__("nefertiti.obj", download_dir)
|
|
101
|
+
|
|
102
|
+
class Ogre(Common3D):
|
|
103
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
104
|
+
super().__init__("ogre.obj", download_dir)
|
|
105
|
+
|
|
106
|
+
class RockerArm(Common3D):
|
|
107
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
108
|
+
super().__init__("rocker-arm.obj", download_dir)
|
|
109
|
+
|
|
110
|
+
class Spot(Common3D):
|
|
111
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
112
|
+
super().__init__("spot.obj", download_dir)
|
|
113
|
+
|
|
114
|
+
class StanfordBunny(Common3D):
|
|
115
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
116
|
+
super().__init__("stanford-bunny.obj", download_dir)
|
|
117
|
+
|
|
118
|
+
class Suzanne(Common3D):
|
|
119
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
120
|
+
super().__init__("suzanne.obj", download_dir)
|
|
121
|
+
|
|
122
|
+
class Teapot(Common3D):
|
|
123
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
124
|
+
super().__init__("teapot.obj", download_dir)
|
|
125
|
+
|
|
126
|
+
class Woody(Common3D):
|
|
127
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
128
|
+
super().__init__("woody.obj", download_dir)
|
|
129
|
+
|
|
130
|
+
class XYZRGBDragon(Common3D):
|
|
131
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
132
|
+
super().__init__("xyzrgb_dragon.obj", download_dir)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import urllib.request
|
|
3
|
+
import zipfile
|
|
4
|
+
import torch
|
|
5
|
+
from conquer3d.io.off import read_off
|
|
6
|
+
|
|
7
|
+
class Iphiagenia:
|
|
8
|
+
"""
|
|
9
|
+
Iphigenia asset mesh from pmp-book.org.
|
|
10
|
+
Downloads the full resolution Iphigenia mesh (zip), extracts the .off file,
|
|
11
|
+
and loads the vertices and faces into PyTorch tensors.
|
|
12
|
+
"""
|
|
13
|
+
def __init__(self, download_dir="~/.conquer3d"):
|
|
14
|
+
self.url = "https://www.pmp-book.org/download/meshes/iphi_fullres.zip"
|
|
15
|
+
self.download_dir = os.path.expanduser(download_dir)
|
|
16
|
+
self.vertices = None
|
|
17
|
+
self.faces = None
|
|
18
|
+
|
|
19
|
+
self._load()
|
|
20
|
+
|
|
21
|
+
def _load(self):
|
|
22
|
+
os.makedirs(self.download_dir, exist_ok=True)
|
|
23
|
+
zip_path = os.path.join(self.download_dir, "iphi_fullres.zip")
|
|
24
|
+
|
|
25
|
+
if not os.path.exists(zip_path):
|
|
26
|
+
print(f"Downloading Iphigenia mesh from {self.url}...")
|
|
27
|
+
# We use a Request with a User-Agent to easily bypass basic checks
|
|
28
|
+
req = urllib.request.Request(self.url, headers={'User-Agent': 'Mozilla/5.0'})
|
|
29
|
+
with urllib.request.urlopen(req) as response, open(zip_path, 'wb') as out_file:
|
|
30
|
+
out_file.write(response.read())
|
|
31
|
+
print("Download complete.")
|
|
32
|
+
|
|
33
|
+
print("Extracting and reading OFF file...")
|
|
34
|
+
with zipfile.ZipFile(zip_path, 'r') as z:
|
|
35
|
+
# Find the .off file in the zip
|
|
36
|
+
off_filename = next((name for name in z.namelist() if name.lower().endswith('.off')), None)
|
|
37
|
+
if not off_filename:
|
|
38
|
+
raise FileNotFoundError("Could not find an .off file in the downloaded zip.")
|
|
39
|
+
|
|
40
|
+
with z.open(off_filename, 'r') as off_file:
|
|
41
|
+
# off_file is a file-like object of bytes.
|
|
42
|
+
# read_off will automatically decode and parse it.
|
|
43
|
+
self.vertices, self.faces = read_off(off_file)
|
|
File without changes
|
|
@@ -62,4 +62,21 @@ def compute_active_voxels(
|
|
|
62
62
|
Returns:
|
|
63
63
|
torch.Tensor: An int64 tensor containing the indices of the active voxels.
|
|
64
64
|
"""
|
|
65
|
-
return _C.compute_active_voxels(voxels.contiguous(), sdf.contiguous(), iso)
|
|
65
|
+
return _C.compute_active_voxels(voxels.contiguous(), sdf.contiguous(), iso)
|
|
66
|
+
|
|
67
|
+
def create_random_points_ball(n_points: int, radius: float = 1.0, device: str = 'cuda') -> torch.Tensor:
|
|
68
|
+
"""
|
|
69
|
+
Creates a set of random points uniformly distributed inside a sphere.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
n_points (int): Number of points to sample.
|
|
73
|
+
radius (float): Radius of the sphere. Defaults to 1.0.
|
|
74
|
+
device (str): Device to place the tensor on. Defaults to 'cuda'.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
torch.Tensor: Random points of shape (n_points, 3).
|
|
78
|
+
"""
|
|
79
|
+
points = torch.randn(n_points, 3, device=device)
|
|
80
|
+
radii = torch.rand(n_points, 1, device=device) ** (1/3) * radius
|
|
81
|
+
points = (points / points.norm(dim=-1, keepdim=True)) * radii
|
|
82
|
+
return points
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import meshio
|
|
3
|
+
|
|
4
|
+
def read_obj(file_obj):
|
|
5
|
+
"""
|
|
6
|
+
Reads an OBJ file and returns vertices, faces, and optional vertex colors using meshio.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
file_obj: A file-like object or a string path.
|
|
10
|
+
"""
|
|
11
|
+
mesh = meshio.read(file_obj, file_format="obj")
|
|
12
|
+
vertices = torch.tensor(mesh.points, dtype=torch.float32)
|
|
13
|
+
|
|
14
|
+
faces = None
|
|
15
|
+
if "triangle" in mesh.cells_dict:
|
|
16
|
+
faces = torch.tensor(mesh.cells_dict["triangle"], dtype=torch.long)
|
|
17
|
+
else:
|
|
18
|
+
faces = torch.empty((0, 3), dtype=torch.long)
|
|
19
|
+
|
|
20
|
+
# Meshio sometimes places vertex colors in point_data under 'obj:vc'
|
|
21
|
+
colors = None
|
|
22
|
+
if mesh.point_data is not None and "obj:vc" in mesh.point_data:
|
|
23
|
+
colors = torch.tensor(mesh.point_data["obj:vc"], dtype=torch.float32)
|
|
24
|
+
|
|
25
|
+
return vertices, faces, colors
|
|
26
|
+
|
|
27
|
+
def write_obj(filepath, vertices, faces, colors=None):
|
|
28
|
+
"""
|
|
29
|
+
Writes vertices, faces, and optional vertex colors to an OBJ file using meshio.
|
|
30
|
+
"""
|
|
31
|
+
point_data = {}
|
|
32
|
+
if colors is not None:
|
|
33
|
+
point_data["obj:vc"] = colors.detach().cpu().numpy()
|
|
34
|
+
|
|
35
|
+
mesh = meshio.Mesh(
|
|
36
|
+
points=vertices.detach().cpu().numpy(),
|
|
37
|
+
cells=[("triangle", faces.detach().cpu().numpy())],
|
|
38
|
+
point_data=point_data if len(point_data) > 0 else None
|
|
39
|
+
)
|
|
40
|
+
meshio.write(filepath, mesh, file_format="obj")
|
|
41
|
+
|
|
42
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import meshio
|
|
3
|
+
|
|
4
|
+
def read_off(filepath_or_filelike):
|
|
5
|
+
"""
|
|
6
|
+
Read an OFF (Object File Format) file and return vertices and faces as PyTorch tensors using meshio.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
filepath_or_filelike: A string path or a file-like object.
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
tuple: (vertices, faces) as torch.Tensor
|
|
13
|
+
"""
|
|
14
|
+
mesh = meshio.read(filepath_or_filelike, file_format="off")
|
|
15
|
+
vertices = torch.tensor(mesh.points, dtype=torch.float32)
|
|
16
|
+
|
|
17
|
+
faces = None
|
|
18
|
+
if "triangle" in mesh.cells_dict:
|
|
19
|
+
faces = torch.tensor(mesh.cells_dict["triangle"], dtype=torch.long)
|
|
20
|
+
else:
|
|
21
|
+
faces = torch.empty((0, 3), dtype=torch.long)
|
|
22
|
+
|
|
23
|
+
return vertices, faces
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import numpy as np
|
|
3
|
+
import tetgen
|
|
4
|
+
|
|
5
|
+
def find_near_duplicates_sort(points, epsilon=1e-7):
|
|
6
|
+
"""
|
|
7
|
+
Approximate detection of near-duplicate points in a point cloud using sorting.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
- points: Tensor of shape (N, 3), where N is the number of points.
|
|
11
|
+
- epsilon: Distance threshold for considering points as duplicates.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
- duplicate_indices: A tensor of shape (M,) where M is the number of points who have a near-duplicate.
|
|
15
|
+
"""
|
|
16
|
+
sorted_indices = torch.argsort(points[:, 0])
|
|
17
|
+
points_sorted = points[sorted_indices]
|
|
18
|
+
|
|
19
|
+
diffs = points_sorted[1:] - points_sorted[:-1]
|
|
20
|
+
distances = torch.norm(diffs, dim=-1)
|
|
21
|
+
|
|
22
|
+
close_mask = distances < epsilon
|
|
23
|
+
duplicate_indices_1, duplicate_indices_2 = sorted_indices[:-1][close_mask], sorted_indices[1:][close_mask]
|
|
24
|
+
duplicate_indices = torch.cat((duplicate_indices_1, duplicate_indices_2))
|
|
25
|
+
return duplicate_indices
|
|
26
|
+
|
|
27
|
+
def tet_is_inside_oriented(vertices, tets):
|
|
28
|
+
"""
|
|
29
|
+
Check if the tetrahedra are oriented correctly, i.e. if the normals of the faces point outwards.
|
|
30
|
+
This is tested by checking if the dot product of the normals and the vector from the barycenter of the tetrahedron to the barycenter of the face is negative.
|
|
31
|
+
"""
|
|
32
|
+
faces = torch.tensor([[0, 2, 1], [0, 1, 3], [0, 3, 2], [1, 2, 3]], dtype=torch.long)
|
|
33
|
+
tets_combinations = tets[:, faces]
|
|
34
|
+
normals_per_tets = torch.cross(vertices[tets_combinations[:, :, 1]] - vertices[tets_combinations[:, :, 0]], vertices[tets_combinations[:, :, 2]] - vertices[tets_combinations[:, :, 0]], dim=2)
|
|
35
|
+
tet_barycenter = vertices[tets].mean(dim=1)
|
|
36
|
+
faces_barycenter = vertices[tets_combinations].mean(dim=2)
|
|
37
|
+
faces_b_to_tet_b = faces_barycenter - tet_barycenter.unsqueeze(1)
|
|
38
|
+
dot = torch.sum(normals_per_tets * faces_b_to_tet_b, dim=2)
|
|
39
|
+
return dot < 0
|
|
40
|
+
|
|
41
|
+
def reorient_tetrahedra(vertices, tets):
|
|
42
|
+
inside_oriented_triangles = tet_is_inside_oriented(vertices, tets)
|
|
43
|
+
to_flip = inside_oriented_triangles.all(dim=1)
|
|
44
|
+
tets[to_flip] = tets[to_flip][:, [0, 2, 1, 3]]
|
|
45
|
+
return tets
|
|
46
|
+
|
|
47
|
+
import scipy.spatial
|
|
48
|
+
|
|
49
|
+
@torch.no_grad()
|
|
50
|
+
def delaunay_simplices_tetgen(points):
|
|
51
|
+
# PyVista's tetgen wrapper raises RuntimeError on point clouds without faces.
|
|
52
|
+
# We natively use scipy's Delaunay which perfectly tetrahedralizes 3D point clouds.
|
|
53
|
+
delaunay = scipy.spatial.Delaunay(points.detach().cpu().numpy())
|
|
54
|
+
return torch.tensor(delaunay.simplices.astype(np.int64), device=points.device)
|
|
55
|
+
|
|
56
|
+
def tetrahedralize(points):
|
|
57
|
+
duplicates = find_near_duplicates_sort(points)
|
|
58
|
+
if duplicates.shape[0] > 0:
|
|
59
|
+
with torch.no_grad():
|
|
60
|
+
points[duplicates] += torch.randn_like(points[duplicates]) * 1e-6
|
|
61
|
+
tetrahedra = delaunay_simplices_tetgen(points)
|
|
62
|
+
tetrahedra = reorient_tetrahedra(points, tetrahedra)
|
|
63
|
+
return tetrahedra
|
|
64
|
+
|
|
65
|
+
def get_edges(tetrahedra):
|
|
66
|
+
tet_edges = torch.tensor([
|
|
67
|
+
[0, 1], [0, 2], [0, 3],
|
|
68
|
+
[1, 2], [1, 3], [2, 3]
|
|
69
|
+
], device=tetrahedra.device)
|
|
70
|
+
edges = tetrahedra[:, tet_edges]
|
|
71
|
+
return edges
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
|
|
3
|
+
triangle_table = torch.tensor([
|
|
4
|
+
[-1, -1, -1, -1, -1, -1],
|
|
5
|
+
[1, 0, 2, -1, -1, -1],
|
|
6
|
+
[4, 0, 3, -1, -1, -1],
|
|
7
|
+
[1, 4, 2, 1, 3, 4],
|
|
8
|
+
[3, 1, 5, -1, -1, -1],
|
|
9
|
+
[2, 3, 0, 2, 5, 3],
|
|
10
|
+
[1, 4, 0, 1, 5, 4],
|
|
11
|
+
[4, 2, 5, -1, -1, -1],
|
|
12
|
+
[4, 5, 2, -1, -1, -1],
|
|
13
|
+
[4, 1, 0, 4, 5, 1],
|
|
14
|
+
[3, 2, 0, 3, 5, 2],
|
|
15
|
+
[1, 3, 5, -1, -1, -1],
|
|
16
|
+
[4, 1, 2, 4, 3, 1],
|
|
17
|
+
[3, 0, 4, -1, -1, -1],
|
|
18
|
+
[2, 0, 1, -1, -1, -1],
|
|
19
|
+
[-1, -1, -1, -1, -1, -1]
|
|
20
|
+
], dtype=torch.long)
|
|
21
|
+
|
|
22
|
+
num_triangles_table = torch.tensor([0, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0], dtype=torch.long)
|
|
23
|
+
base_tet_edges = torch.tensor([0, 1, 0, 2, 0, 3, 1, 2, 1, 3, 2, 3], dtype=torch.long)
|
|
24
|
+
v_id = torch.pow(2, torch.arange(4, dtype=torch.long))
|
|
25
|
+
|
|
26
|
+
def _sort_edges(edges):
|
|
27
|
+
"""sort last dimension of edges of shape (E, 2)"""
|
|
28
|
+
with torch.no_grad():
|
|
29
|
+
order = (edges[:, 0] > edges[:, 1]).long()
|
|
30
|
+
order = order.unsqueeze(dim=1)
|
|
31
|
+
|
|
32
|
+
a = torch.gather(input=edges, index=order, dim=1)
|
|
33
|
+
b = torch.gather(input=edges, index=1 - order, dim=1)
|
|
34
|
+
|
|
35
|
+
return torch.stack([a, b], -1)
|
|
36
|
+
|
|
37
|
+
def marching_tetrahedra(vertices, tets, sdfs, colors=None, return_tet_idx=False):
|
|
38
|
+
"""
|
|
39
|
+
Extracts a triangulated isosurface from a tetrahedral grid using the Marching Tetrahedra algorithm.
|
|
40
|
+
|
|
41
|
+
This is a pure-PyTorch, fully vectorized implementation that is mathematically differentiable.
|
|
42
|
+
It identifies tetrahedra that intersect the zero-isosurface, finds the exact intersection points
|
|
43
|
+
on the edges using linear interpolation based on SDF values, and generates the resulting triangles.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
vertices (torch.Tensor): A tensor of shape (N, 3) containing the 3D coordinates of the grid vertices.
|
|
47
|
+
tets (torch.Tensor): A tensor of shape (T, 4) containing the vertex indices for each tetrahedron.
|
|
48
|
+
sdfs (torch.Tensor): A tensor of shape (N,) containing the Signed Distance Field values at each vertex.
|
|
49
|
+
colors (torch.Tensor, optional): A tensor of shape (N, C) containing color or feature values at each vertex.
|
|
50
|
+
If provided, these features are linearly interpolated to the isosurface exactly like the geometry.
|
|
51
|
+
Defaults to None.
|
|
52
|
+
return_tet_idx (bool, optional): If True, also returns the indices of the tetrahedra that produced
|
|
53
|
+
each generated face. Defaults to False.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
tuple:
|
|
57
|
+
- verts (torch.Tensor): The extracted surface vertices of shape (V, 3). If `colors` was provided,
|
|
58
|
+
the shape will be (V, 3 + C) where the interpolated colors are concatenated to the coordinates.
|
|
59
|
+
- faces (torch.Tensor): The triangular faces of the extracted surface of shape (F, 3).
|
|
60
|
+
- tet_idx (torch.Tensor, optional): The original tetrahedron index corresponding to each face.
|
|
61
|
+
Returned only if `return_tet_idx` is True.
|
|
62
|
+
"""
|
|
63
|
+
device = vertices.device
|
|
64
|
+
with torch.no_grad():
|
|
65
|
+
occ_n = sdfs > 0
|
|
66
|
+
occ_fx4 = occ_n[tets.reshape(-1)].reshape(-1, 4)
|
|
67
|
+
occ_sum = torch.sum(occ_fx4, -1)
|
|
68
|
+
valid_tets = (occ_sum > 0) & (occ_sum < 4)
|
|
69
|
+
occ_sum = occ_sum[valid_tets]
|
|
70
|
+
|
|
71
|
+
# find all vertices
|
|
72
|
+
all_edges = tets[valid_tets][:, base_tet_edges.to(device)].reshape(-1, 2)
|
|
73
|
+
all_edges = _sort_edges(all_edges)
|
|
74
|
+
unique_edges, idx_map = torch.unique(all_edges, dim=0, return_inverse=True)
|
|
75
|
+
|
|
76
|
+
unique_edges = unique_edges.long()
|
|
77
|
+
mask_edges = occ_n[unique_edges.reshape(-1)].reshape(-1, 2).sum(-1) == 1
|
|
78
|
+
mapping = torch.ones((unique_edges.shape[0]), dtype=torch.long, device=device) * -1
|
|
79
|
+
mapping[mask_edges] = torch.arange(mask_edges.sum(), dtype=torch.long, device=device)
|
|
80
|
+
idx_map = mapping[idx_map]
|
|
81
|
+
|
|
82
|
+
interp_v = unique_edges[mask_edges].reshape(-1)
|
|
83
|
+
|
|
84
|
+
edges_to_interp = torch.index_select(vertices, 0, interp_v).reshape(-1, 2, 3)
|
|
85
|
+
edges_to_interp_sdfs = torch.index_select(sdfs, 0, interp_v).reshape(-1, 2, 1)
|
|
86
|
+
|
|
87
|
+
edges_to_interp0, edges_to_interp1 = edges_to_interp.unbind(dim=1)
|
|
88
|
+
|
|
89
|
+
edges_to_interp_sdfs0, edges_to_interp_sdfs1 = edges_to_interp_sdfs.unbind(dim=1)
|
|
90
|
+
edges_to_interp_sdfs1 = -edges_to_interp_sdfs1
|
|
91
|
+
|
|
92
|
+
verts = (edges_to_interp0 * edges_to_interp_sdfs1 + edges_to_interp1 * edges_to_interp_sdfs0)
|
|
93
|
+
verts = verts / (edges_to_interp_sdfs0 + edges_to_interp_sdfs1)
|
|
94
|
+
|
|
95
|
+
if colors is not None:
|
|
96
|
+
edges_to_interp_colors = torch.index_select(colors, 0, interp_v).reshape(-1, 2, colors.shape[-1])
|
|
97
|
+
edges_to_interp_colors0, edges_to_interp_colors1 = edges_to_interp_colors.unbind(dim=1)
|
|
98
|
+
verts_colors = (edges_to_interp_colors0 * edges_to_interp_sdfs1 + edges_to_interp_colors1 * edges_to_interp_sdfs0)
|
|
99
|
+
verts_colors = verts_colors / (edges_to_interp_sdfs0 + edges_to_interp_sdfs1)
|
|
100
|
+
|
|
101
|
+
idx_map = idx_map.reshape(-1, 6)
|
|
102
|
+
|
|
103
|
+
tetindex = (occ_fx4[valid_tets] * v_id.to(device).unsqueeze(0)).sum(-1)
|
|
104
|
+
num_triangles = num_triangles_table.to(device)[tetindex]
|
|
105
|
+
triangle_table_device = triangle_table.to(device)
|
|
106
|
+
|
|
107
|
+
# Generate triangle indices
|
|
108
|
+
faces = torch.cat((
|
|
109
|
+
torch.gather(input=idx_map[num_triangles == 1], dim=1,
|
|
110
|
+
index=triangle_table_device[tetindex[num_triangles == 1]][:, :3]).reshape(-1, 3),
|
|
111
|
+
torch.gather(input=idx_map[num_triangles == 2], dim=1,
|
|
112
|
+
index=triangle_table_device[tetindex[num_triangles == 2]][:, :6]).reshape(-1, 3),
|
|
113
|
+
), dim=0)
|
|
114
|
+
|
|
115
|
+
if return_tet_idx:
|
|
116
|
+
tet_idx = torch.arange(tets.shape[0], device=device)[valid_tets]
|
|
117
|
+
tet_idx = torch.cat((tet_idx[num_triangles == 1], tet_idx[num_triangles ==
|
|
118
|
+
2].unsqueeze(-1).expand(-1, 2).reshape(-1)), dim=0)
|
|
119
|
+
if colors is not None:
|
|
120
|
+
return verts, faces, tet_idx, verts_colors
|
|
121
|
+
return verts, faces, tet_idx
|
|
122
|
+
|
|
123
|
+
if colors is not None:
|
|
124
|
+
return verts, faces, verts_colors
|
|
125
|
+
return verts, faces
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
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: meshio>=5.3.5
|
|
16
17
|
Requires-Dist: gdown
|
|
17
18
|
Provides-Extra: cuda
|
|
18
19
|
Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
|
|
@@ -49,6 +50,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
49
50
|
```bash
|
|
50
51
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
51
52
|
conda activate geocutool
|
|
53
|
+
conda install -c conda-forge sparsehash -y
|
|
52
54
|
|
|
53
55
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
54
56
|
|
|
@@ -77,6 +79,9 @@ twine upload dist/* --verbose
|
|
|
77
79
|
|
|
78
80
|
# Reference
|
|
79
81
|
|
|
82
|
+
## Book
|
|
83
|
+
|
|
84
|
+
|
|
80
85
|
## Research Paper
|
|
81
86
|
```bibtex
|
|
82
87
|
@inproceedings{2383795.2383801,
|
|
@@ -133,19 +138,19 @@ twine upload dist/* --verbose
|
|
|
133
138
|
|
|
134
139
|
```bibtex
|
|
135
140
|
@InProceedings{10.1007/978-3-662-05105-4_2,
|
|
136
|
-
author="Meyer, Mark
|
|
137
|
-
and Desbrun, Mathieu
|
|
138
|
-
and Schr{\"o}der, Peter
|
|
139
|
-
and Barr, Alan H.",
|
|
140
|
-
editor="Hege, Hans-Christian
|
|
141
|
-
and Polthier, Konrad",
|
|
142
|
-
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
143
|
-
booktitle="Visualization and Mathematics III",
|
|
144
|
-
year="2003",
|
|
145
|
-
publisher="Springer Berlin Heidelberg",
|
|
146
|
-
address="Berlin, Heidelberg",
|
|
147
|
-
pages="35--57",
|
|
148
|
-
isbn="978-3-662-05105-4"
|
|
141
|
+
author="Meyer, Mark
|
|
142
|
+
and Desbrun, Mathieu
|
|
143
|
+
and Schr{\"o}der, Peter
|
|
144
|
+
and Barr, Alan H.",
|
|
145
|
+
editor="Hege, Hans-Christian
|
|
146
|
+
and Polthier, Konrad",
|
|
147
|
+
title="Discrete Differential-Geometry Operators for Triangulated 2-Manifolds",
|
|
148
|
+
booktitle="Visualization and Mathematics III",
|
|
149
|
+
year="2003",
|
|
150
|
+
publisher="Springer Berlin Heidelberg",
|
|
151
|
+
address="Berlin, Heidelberg",
|
|
152
|
+
pages="35--57",
|
|
153
|
+
isbn="978-3-662-05105-4"
|
|
149
154
|
}
|
|
150
155
|
```
|
|
151
156
|
|
|
@@ -161,3 +166,4 @@ isbn="978-3-662-05105-4"
|
|
|
161
166
|
- [Pytorch3D](https://github.com/facebookresearch/pytorch3d)
|
|
162
167
|
- [Open3D](https://www.open3d.org/)
|
|
163
168
|
- [trimesh](https://github.com/mikedh/trimesh)
|
|
169
|
+
- [TetWeave](https://github.com/AlexandreBinninger/TetWeave/tree/main)
|
|
@@ -72,6 +72,9 @@ conquer3d/csrc/primitive/pgs_math.cuh
|
|
|
72
72
|
conquer3d/csrc/primitive/ray.h
|
|
73
73
|
conquer3d/csrc/primitive/triangle.h
|
|
74
74
|
conquer3d/data/__init__.py
|
|
75
|
+
conquer3d/data/assets/__init__.py
|
|
76
|
+
conquer3d/data/assets/common.py
|
|
77
|
+
conquer3d/data/assets/iphigenia.py
|
|
75
78
|
conquer3d/data/collate/__init__.py
|
|
76
79
|
conquer3d/data/collate/mesh.py
|
|
77
80
|
conquer3d/data/collate/sparse_tensor.py
|
|
@@ -85,10 +88,15 @@ conquer3d/data/transform/vertex.py
|
|
|
85
88
|
conquer3d/data_structure/__init__.py
|
|
86
89
|
conquer3d/data_structure/bmesh.py
|
|
87
90
|
conquer3d/data_structure/grid.py
|
|
91
|
+
conquer3d/io/__init__.py
|
|
92
|
+
conquer3d/io/obj.py
|
|
93
|
+
conquer3d/io/off.py
|
|
88
94
|
conquer3d/ops/__init__.py
|
|
95
|
+
conquer3d/ops/delaunay_triangulation.py
|
|
89
96
|
conquer3d/ops/diff_marching_cubes.py
|
|
90
97
|
conquer3d/ops/distance.py
|
|
91
98
|
conquer3d/ops/marching_cubes.py
|
|
99
|
+
conquer3d/ops/marching_tetrahedra.py
|
|
92
100
|
conquer3d/primitive/__init__.py
|
|
93
101
|
conquer3d/primitive/gs.py
|
|
94
102
|
conquer3d/primitive/pgs.py
|
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
|
|
10
10
|
[project]
|
|
11
11
|
name = "conquer3d"
|
|
12
|
-
version = "0.3.
|
|
12
|
+
version = "0.3.5"
|
|
13
13
|
description = "Geometric Cuda Tool Box"
|
|
14
14
|
readme = "README.md"
|
|
15
15
|
license = "MIT"
|
|
@@ -20,6 +20,7 @@ requires-python = ">=3.9"
|
|
|
20
20
|
keywords = ["geometry"]
|
|
21
21
|
dependencies = [
|
|
22
22
|
"torch>=2.0.0",
|
|
23
|
+
"meshio>=5.3.5",
|
|
23
24
|
"gdown",
|
|
24
25
|
]
|
|
25
26
|
|
|
@@ -57,6 +57,10 @@ def get_extensions():
|
|
|
57
57
|
# nvcc_flags += ['-DTORCH_INDUCTOR_CPP_WRAPPER']
|
|
58
58
|
else:
|
|
59
59
|
nvcc_flags = nvcc_flags.split(" ")
|
|
60
|
+
|
|
61
|
+
# Suppress harmless nvcc warnings (like conda's compiler-bindir redefinition)
|
|
62
|
+
nvcc_flags.append("-w")
|
|
63
|
+
|
|
60
64
|
extra_compile_args = {
|
|
61
65
|
"cxx": ["-O3", "-Wno-attributes"],
|
|
62
66
|
"nvcc": nvcc_flags,
|
conquer3d-0.3.3/MANIFEST.in
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
recursive-include conquer3d/csrc *.h *.hpp *.cuh *.cpp *.cu
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conquer3d-0.3.3/conquer3d/data/collate → conquer3d-0.3.5/conquer3d/data/assets}/__init__.py
RENAMED
|
File without changes
|
{conquer3d-0.3.3/conquer3d/data/dataset → conquer3d-0.3.5/conquer3d/data/collate}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conquer3d-0.3.3/conquer3d/data/transform → conquer3d-0.3.5/conquer3d/data/dataset}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|