conquer3d 0.2.4__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {conquer3d-0.2.4/conquer3d.egg-info → conquer3d-0.2.6}/PKG-INFO +49 -12
  2. {conquer3d-0.2.4 → conquer3d-0.2.6}/README.md +48 -11
  3. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/_C.pyi +30 -2
  4. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/_C.so +0 -0
  5. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/data_structure/bvh.cpp +89 -1
  6. conquer3d-0.2.6/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +44 -0
  7. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +47 -2
  8. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/bvh.cu +182 -0
  9. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/bvh.h +35 -0
  10. conquer3d-0.2.6/conquer3d/csrc/data_structure/mesh_bvh.cu +413 -0
  11. conquer3d-0.2.6/conquer3d/csrc/data_structure/mesh_bvh.h +41 -0
  12. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/triangle_mesh.cu +1 -0
  13. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/triangle_mesh.h +12 -0
  14. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/aabb.h +18 -0
  15. conquer3d-0.2.6/conquer3d/csrc/primitive/ray.h +62 -0
  16. conquer3d-0.2.6/conquer3d/csrc/primitive/triangles.h +200 -0
  17. {conquer3d-0.2.4 → conquer3d-0.2.6/conquer3d.egg-info}/PKG-INFO +49 -12
  18. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d.egg-info/SOURCES.txt +1 -0
  19. {conquer3d-0.2.4 → conquer3d-0.2.6}/pyproject.toml +1 -1
  20. {conquer3d-0.2.4 → conquer3d-0.2.6}/setup.py +0 -10
  21. conquer3d-0.2.4/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -22
  22. conquer3d-0.2.4/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -98
  23. conquer3d-0.2.4/conquer3d/csrc/data_structure/mesh_bvh.h +0 -24
  24. conquer3d-0.2.4/conquer3d/csrc/primitive/triangles.h +0 -106
  25. {conquer3d-0.2.4 → conquer3d-0.2.6}/LICENSE +0 -0
  26. {conquer3d-0.2.4 → conquer3d-0.2.6}/MANIFEST.in +0 -0
  27. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/__init__.py +0 -0
  28. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/creation/__init__.py +0 -0
  29. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/creation/triangle_creation.py +0 -0
  30. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
  31. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
  32. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
  33. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
  34. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
  35. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
  36. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/check.h +0 -0
  37. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/constants.h +0 -0
  38. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/creation/triangle_creation.h +0 -0
  39. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
  40. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
  41. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/kdtree.h +0 -0
  42. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
  43. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/data_structure/zcurve.h +0 -0
  44. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f2x2.h +0 -0
  45. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f3x1.h +0 -0
  46. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f3x3.h +0 -0
  47. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f3x4.h +0 -0
  48. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f4x1.h +0 -0
  49. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/f4x4.h +0 -0
  50. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/maths.h +0 -0
  51. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/maths/ops.h +0 -0
  52. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/edge.h +0 -0
  53. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/gs.cu +0 -0
  54. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/gs.h +0 -0
  55. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
  56. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
  57. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/pgs.cu +0 -0
  58. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/pgs.h +0 -0
  59. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
  60. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
  61. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/csrc/pybind.cpp +0 -0
  62. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/data_structure/__init__.py +0 -0
  63. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/primitive/__init__.py +0 -0
  64. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/primitive/gs.py +0 -0
  65. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d/primitive/pgs.py +0 -0
  66. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d.egg-info/dependency_links.txt +0 -0
  67. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d.egg-info/not-zip-safe +0 -0
  68. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d.egg-info/requires.txt +0 -0
  69. {conquer3d-0.2.4 → conquer3d-0.2.6}/conquer3d.egg-info/top_level.txt +0 -0
  70. {conquer3d-0.2.4 → conquer3d-0.2.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conquer3d
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Geometric Cuda Tool Box
5
5
  Author-email: Do Hoang Khoi <khoido8899@gmail.com>
6
6
  License-Expression: MIT
@@ -68,17 +68,54 @@ twine upload dist/* --verbose
68
68
  ## Research Paper
69
69
  ```bibtex
70
70
  @inproceedings{2383795.2383801,
71
- author = {Karras, Tero},
72
- title = {Maximizing parallelism in the construction of BVHs, octrees, and k-d trees},
73
- year = {2012},
74
- isbn = {9783905674415},
75
- publisher = {Eurographics Association},
76
- address = {Goslar, DEU},
77
- booktitle = {Proceedings of the Fourth ACM SIGGRAPH / Eurographics Conference on High-Performance Graphics},
78
- pages = {33–37},
79
- numpages = {5},
80
- location = {Paris, France},
81
- series = {EGGH-HPG'12}
71
+ author = {Karras, Tero},
72
+ title = {Maximizing parallelism in the construction of BVHs, octrees, and k-d trees},
73
+ year = {2012},
74
+ isbn = {9783905674415},
75
+ publisher = {Eurographics Association},
76
+ address = {Goslar, DEU},
77
+ booktitle = {Proceedings of the Fourth ACM SIGGRAPH / Eurographics Conference on High-Performance Graphics},
78
+ pages = {33–37},
79
+ numpages = {5},
80
+ location = {Paris, France},
81
+ series = {EGGH-HPG'12}
82
+ }
83
+ ```
84
+
85
+ ```bibtex
86
+ @article{10.1080/10867651.1997.10487472,
87
+ author = {M\"{o}ller, Tomas},
88
+ title = {A fast triangle-triangle intersection test},
89
+ year = {1997},
90
+ issue_date = {1997},
91
+ publisher = {A. K. Peters, Ltd.},
92
+ address = {USA},
93
+ volume = {2},
94
+ number = {2},
95
+ issn = {1086-7651},
96
+ url = {https://doi.org/10.1080/10867651.1997.10487472},
97
+ doi = {10.1080/10867651.1997.10487472},
98
+ journal = {J. Graph. Tools},
99
+ month = nov,
100
+ pages = {25–30},
101
+ numpages = {6}
102
+ }
103
+ ```
104
+
105
+ ```bibtex
106
+ @inproceedings{10.1145/1198555.1198746,
107
+ author = {M\"{o}ller, Tomas and Trumbore, Ben},
108
+ title = {Fast, minimum storage ray/triangle intersection},
109
+ year = {2005},
110
+ isbn = {9781450378338},
111
+ publisher = {Association for Computing Machinery},
112
+ address = {New York, NY, USA},
113
+ url = {https://doi.org/10.1145/1198555.1198746},
114
+ doi = {10.1145/1198555.1198746},
115
+ pages = {7–es},
116
+ keywords = {base transformation, intersection, ray tracing, ray/triangle-intersection},
117
+ location = {Los Angeles, California},
118
+ series = {SIGGRAPH '05}
82
119
  }
83
120
  ```
84
121
 
@@ -44,17 +44,54 @@ twine upload dist/* --verbose
44
44
  ## Research Paper
45
45
  ```bibtex
46
46
  @inproceedings{2383795.2383801,
47
- author = {Karras, Tero},
48
- title = {Maximizing parallelism in the construction of BVHs, octrees, and k-d trees},
49
- year = {2012},
50
- isbn = {9783905674415},
51
- publisher = {Eurographics Association},
52
- address = {Goslar, DEU},
53
- booktitle = {Proceedings of the Fourth ACM SIGGRAPH / Eurographics Conference on High-Performance Graphics},
54
- pages = {33–37},
55
- numpages = {5},
56
- location = {Paris, France},
57
- series = {EGGH-HPG'12}
47
+ author = {Karras, Tero},
48
+ title = {Maximizing parallelism in the construction of BVHs, octrees, and k-d trees},
49
+ year = {2012},
50
+ isbn = {9783905674415},
51
+ publisher = {Eurographics Association},
52
+ address = {Goslar, DEU},
53
+ booktitle = {Proceedings of the Fourth ACM SIGGRAPH / Eurographics Conference on High-Performance Graphics},
54
+ pages = {33–37},
55
+ numpages = {5},
56
+ location = {Paris, France},
57
+ series = {EGGH-HPG'12}
58
+ }
59
+ ```
60
+
61
+ ```bibtex
62
+ @article{10.1080/10867651.1997.10487472,
63
+ author = {M\"{o}ller, Tomas},
64
+ title = {A fast triangle-triangle intersection test},
65
+ year = {1997},
66
+ issue_date = {1997},
67
+ publisher = {A. K. Peters, Ltd.},
68
+ address = {USA},
69
+ volume = {2},
70
+ number = {2},
71
+ issn = {1086-7651},
72
+ url = {https://doi.org/10.1080/10867651.1997.10487472},
73
+ doi = {10.1080/10867651.1997.10487472},
74
+ journal = {J. Graph. Tools},
75
+ month = nov,
76
+ pages = {25–30},
77
+ numpages = {6}
78
+ }
79
+ ```
80
+
81
+ ```bibtex
82
+ @inproceedings{10.1145/1198555.1198746,
83
+ author = {M\"{o}ller, Tomas and Trumbore, Ben},
84
+ title = {Fast, minimum storage ray/triangle intersection},
85
+ year = {2005},
86
+ isbn = {9781450378338},
87
+ publisher = {Association for Computing Machinery},
88
+ address = {New York, NY, USA},
89
+ url = {https://doi.org/10.1145/1198555.1198746},
90
+ doi = {10.1145/1198555.1198746},
91
+ pages = {7–es},
92
+ keywords = {base transformation, intersection, ray tracing, ray/triangle-intersection},
93
+ location = {Los Angeles, California},
94
+ series = {SIGGRAPH '05}
58
95
  }
59
96
  ```
60
97
 
@@ -14,6 +14,14 @@ class BVH:
14
14
  """
15
15
  Query the BVH with bounding boxes or segments. Returns (query_ids, object_ids).
16
16
  """
17
+ def query_point(self, query_points: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
18
+ """
19
+ Find the closest leaf AABB to each query point. Returns (query_ids, object_ids, distances)
20
+ """
21
+ def query_ray(self, ray_origins: torch.Tensor, ray_dirs: torch.Tensor, max_capacity: int = 10000000) -> tuple[torch.Tensor, torch.Tensor]:
22
+ """
23
+ Find all ray-AABB intersections. Returns (ray_ids, object_ids)
24
+ """
17
25
  def query_self(self) -> tuple[torch.Tensor, torch.Tensor]:
18
26
  """
19
27
  Query the BVH against itself. Returns unique overlapping (query_ids, object_ids).
@@ -49,6 +57,10 @@ class MeshBVH(BVH):
49
57
  """
50
58
  Construct MeshBVH from Triangle AABBs.
51
59
  """
60
+ def get_ray_intersection(self, ray_origins: torch.Tensor, ray_dirs: torch.Tensor, vertices: torch.Tensor, triangles: torch.Tensor, return_distance: bool = False) -> typing.Any:
61
+ """
62
+ Find all ray-triangle intersections. Returns (ray_ids, triangle_ids, intersect_points, [distances])
63
+ """
52
64
  def get_self_intersection(self, vertices: torch.Tensor, triangles: torch.Tensor) -> torch.Tensor:
53
65
  """
54
66
  Find all self-intersecting triangle pairs
@@ -57,6 +69,10 @@ class MeshBVH(BVH):
57
69
  """
58
70
  Check if there are any self-intersecting triangle pairs
59
71
  """
72
+ def query_point(self, query_points: torch.Tensor, vertices: torch.Tensor, triangles: torch.Tensor, return_sdf: bool = False, return_prj_pts: bool = True, sign_mode: int = 0) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
73
+ """
74
+ Find the closest triangle to each query point. Returns (query_ids, triangle_ids, projected_points, distances)
75
+ """
60
76
  class PGSBVH(BVH):
61
77
  def __init__(self, in_aabb_mins: torch.Tensor, in_aabb_maxs: torch.Tensor) -> None:
62
78
  """
@@ -87,8 +103,14 @@ class TriangleMesh:
87
103
  ...
88
104
  def get_non_manifold_vertices(self) -> torch.Tensor:
89
105
  ...
106
+ def get_ray_intersection(self, ray_origins: torch.Tensor, ray_dirs: torch.Tensor, return_distance: bool = False) -> typing.Any:
107
+ """
108
+ Find all ray-triangle intersections. Returns (ray_ids, triangle_ids, intersect_points, [distances])
109
+ """
90
110
  def get_self_intersection(self) -> torch.Tensor:
91
- ...
111
+ """
112
+ Find all self-intersecting triangle pairs
113
+ """
92
114
  def get_vertices_to_triangle_map(self) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
93
115
  ...
94
116
  def is_edge_manifold(self, allow_boundary_edge: bool = True) -> bool:
@@ -96,9 +118,15 @@ class TriangleMesh:
96
118
  def is_manifold(self, allow_boundary_edge: bool = True) -> bool:
97
119
  ...
98
120
  def is_self_intersection(self) -> bool:
99
- ...
121
+ """
122
+ Check if there are any self-intersecting triangle pairs
123
+ """
100
124
  def is_vertex_manifold(self) -> bool:
101
125
  ...
126
+ def query_points(self, query_pts: torch.Tensor, return_sdf: bool = False, return_prj_pts: bool = True, sign_mode: int = 0, distance_mode: int = 0) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
127
+ """
128
+ Query points against the mesh. Returns (query_ids, triangle_ids, projected_points, distances)
129
+ """
102
130
  def remove_triangles_by_mask(self, keep_mask: torch.Tensor) -> None:
103
131
  ...
104
132
  @property
@@ -153,6 +153,85 @@ std::tuple<torch::Tensor, torch::Tensor> BVH::query_self()
153
153
  );
154
154
  }
155
155
 
156
+ std::tuple<torch::Tensor, torch::Tensor> BVH::query_ray(
157
+ const torch::Tensor &ray_origins,
158
+ const torch::Tensor &ray_dirs,
159
+ int64_t max_capacity)
160
+ {
161
+ CHECK_INPUT(ray_origins);
162
+ CHECK_INPUT(ray_dirs);
163
+ TORCH_CHECK(ray_origins.size(0) == ray_dirs.size(0), "ray_origins and ray_dirs must have the same number of rays");
164
+
165
+ int num_queries = ray_origins.size(0);
166
+
167
+ auto options_i64 = torch::TensorOptions().dtype(torch::kInt64).device(ray_origins.device());
168
+ torch::Tensor out_query_ids = torch::empty({max_capacity}, options_i64);
169
+ torch::Tensor out_object_ids = torch::empty({max_capacity}, options_i64);
170
+ torch::Tensor hit_counter = torch::zeros({1}, options_i64);
171
+
172
+ bvh::query_ray(
173
+ num_queries,
174
+ this->num_objects,
175
+ (const float3 *)ray_origins.data_ptr<float>(),
176
+ (const float3 *)ray_dirs.data_ptr<float>(),
177
+ (const float3 *)this->aabb_mins.data_ptr<float>(),
178
+ (const float3 *)this->aabb_maxs.data_ptr<float>(),
179
+ (const int2 *)this->bvh_children.data_ptr<int>(),
180
+ this->object_ids.data_ptr<int>(),
181
+ out_query_ids.data_ptr<int64_t>(),
182
+ out_object_ids.data_ptr<int64_t>(),
183
+ hit_counter.data_ptr<int64_t>(),
184
+ max_capacity);
185
+
186
+ int64_t h_hit_counter = hit_counter.item<int64_t>();
187
+
188
+ if (h_hit_counter >= max_capacity)
189
+ {
190
+ TORCH_WARN("BVH ray query capacity exceeded. Some hits were dropped.");
191
+ h_hit_counter = max_capacity;
192
+ }
193
+
194
+ if (h_hit_counter == 0) {
195
+ return std::make_tuple(
196
+ torch::empty({0}, options_i64),
197
+ torch::empty({0}, options_i64)
198
+ );
199
+ }
200
+
201
+ return std::make_tuple(
202
+ out_query_ids.slice(0, 0, h_hit_counter),
203
+ out_object_ids.slice(0, 0, h_hit_counter));
204
+ }
205
+
206
+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> BVH::query_point(
207
+ const torch::Tensor &query_points)
208
+ {
209
+ CHECK_INPUT(query_points);
210
+
211
+ int num_queries = query_points.size(0);
212
+
213
+ auto options_i64 = torch::TensorOptions().dtype(torch::kInt64).device(query_points.device());
214
+ auto options_f32 = torch::TensorOptions().dtype(torch::kFloat32).device(query_points.device());
215
+
216
+ torch::Tensor out_query_ids = torch::empty({num_queries}, options_i64);
217
+ torch::Tensor out_object_ids = torch::empty({num_queries}, options_i64);
218
+ torch::Tensor out_distances = torch::empty({num_queries}, options_f32);
219
+
220
+ bvh::query_point(
221
+ num_queries,
222
+ this->num_objects,
223
+ (const float3 *)query_points.data_ptr<float>(),
224
+ (const float3 *)this->aabb_mins.data_ptr<float>(),
225
+ (const float3 *)this->aabb_maxs.data_ptr<float>(),
226
+ (const int2 *)this->bvh_children.data_ptr<int>(),
227
+ this->object_ids.data_ptr<int>(),
228
+ out_query_ids.data_ptr<int64_t>(),
229
+ out_object_ids.data_ptr<int64_t>(),
230
+ out_distances.data_ptr<float>());
231
+
232
+ return std::make_tuple(out_query_ids, out_object_ids, out_distances);
233
+ }
234
+
156
235
  void bind_ds_bvh(py::module_& m)
157
236
  {
158
237
  py::class_<BVH>(m, "BVH")
@@ -167,5 +246,14 @@ void bind_ds_bvh(py::module_& m)
167
246
  "Query the BVH with bounding boxes or segments. Returns (query_ids, object_ids).")
168
247
 
169
248
  .def("query_self", &BVH::query_self,
170
- "Query the BVH against itself. Returns unique overlapping (query_ids, object_ids).");
249
+ "Query the BVH against itself. Returns unique overlapping (query_ids, object_ids).")
250
+
251
+ .def("query_ray", &BVH::query_ray,
252
+ py::arg("ray_origins"),
253
+ py::arg("ray_dirs"),
254
+ py::arg("max_capacity") = BVH_MAX_CAPACITY,
255
+ "Find all ray-AABB intersections. Returns (ray_ids, object_ids)")
256
+ .def("query_point", &BVH::query_point,
257
+ py::arg("query_points"),
258
+ "Find the closest leaf AABB to each query point. Returns (query_ids, object_ids, distances)");
171
259
  }
@@ -0,0 +1,44 @@
1
+ #include <torch/extension.h>
2
+ #include "../../data_structure/mesh_bvh.h"
3
+ #include <pybind11/pybind11.h>
4
+
5
+ namespace py = pybind11;
6
+
7
+ void bind_ds_mesh_bvh(py::module_& m)
8
+ {
9
+ py::class_<MeshBVH, BVH>(m, "MeshBVH")
10
+ .def(py::init<const torch::Tensor &, const torch::Tensor &>(),
11
+ py::arg("in_aabb_mins"),
12
+ py::arg("in_aabb_maxs"),
13
+ "Construct MeshBVH from Triangle AABBs.")
14
+ .def("get_self_intersection", &MeshBVH::get_self_intersection,
15
+ py::arg("vertices"),
16
+ py::arg("triangles"),
17
+ "Find all self-intersecting triangle pairs")
18
+ .def("is_self_intersection", &MeshBVH::is_self_intersection,
19
+ py::arg("vertices"),
20
+ py::arg("triangles"),
21
+ "Check if there are any self-intersecting triangle pairs")
22
+ .def("get_ray_intersection", [](MeshBVH& self, const torch::Tensor& ray_origins, const torch::Tensor& ray_dirs, const torch::Tensor& vertices, const torch::Tensor& triangles, bool return_distance) -> py::object {
23
+ auto result = self.get_ray_intersection(ray_origins, ray_dirs, vertices, triangles, return_distance);
24
+ if (return_distance) {
25
+ return py::cast(result);
26
+ } else {
27
+ return py::cast(std::make_tuple(std::get<0>(result), std::get<1>(result), std::get<2>(result)));
28
+ }
29
+ },
30
+ py::arg("ray_origins"),
31
+ py::arg("ray_dirs"),
32
+ py::arg("vertices"),
33
+ py::arg("triangles"),
34
+ py::arg("return_distance") = false,
35
+ "Find all ray-triangle intersections. Returns (ray_ids, triangle_ids, intersect_points, [distances])")
36
+ .def("query_point", &MeshBVH::query_point,
37
+ py::arg("query_points"),
38
+ py::arg("vertices"),
39
+ py::arg("triangles"),
40
+ py::arg("return_sdf") = false,
41
+ py::arg("return_prj_pts") = true,
42
+ py::arg("sign_mode") = 0,
43
+ "Find the closest triangle to each query point. Returns (query_ids, triangle_ids, projected_points, distances)");
44
+ }
@@ -97,6 +97,30 @@ bool TriangleMesh::is_self_intersection()
97
97
  return this->bvh.value().is_self_intersection(this->vertices, this->triangles);
98
98
  }
99
99
 
100
+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor> TriangleMesh::query_points(
101
+ const torch::Tensor &query_pts,
102
+ bool return_sdf,
103
+ bool return_prj_pts,
104
+ int sign_mode,
105
+ int distance_mode)
106
+ {
107
+ if (distance_mode == 0) {
108
+ this->build_bvh();
109
+ return this->bvh.value().query_point(query_pts, this->vertices, this->triangles, return_sdf, return_prj_pts, sign_mode);
110
+ } else {
111
+ throw std::runtime_error("distance_mode != 0 not implemented yet");
112
+ }
113
+ }
114
+
115
+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor> TriangleMesh::get_ray_intersection(
116
+ const torch::Tensor &ray_origins,
117
+ const torch::Tensor &ray_dirs,
118
+ bool return_distance)
119
+ {
120
+ this->build_bvh();
121
+ return this->bvh.value().get_ray_intersection(ray_origins, ray_dirs, this->vertices, this->triangles, return_distance);
122
+ }
123
+
100
124
  torch::Tensor TriangleMesh::get_triangle_areas()
101
125
  {
102
126
  if (!this->triangle_areas.defined())
@@ -313,8 +337,29 @@ void bind_ds_triangle_mesh(py::module_ &m)
313
337
  .def_property_readonly("surface_area", &TriangleMesh::get_surface_area)
314
338
  .def_property_readonly("bvh", &TriangleMesh::build_bvh)
315
339
  .def("build_bvh", &TriangleMesh::build_bvh)
316
- .def("get_self_intersection", &TriangleMesh::get_self_intersection)
317
- .def("is_self_intersection", &TriangleMesh::is_self_intersection)
340
+ .def("get_self_intersection", &TriangleMesh::get_self_intersection,
341
+ "Find all self-intersecting triangle pairs")
342
+ .def("is_self_intersection", &TriangleMesh::is_self_intersection,
343
+ "Check if there are any self-intersecting triangle pairs")
344
+ .def("get_ray_intersection", [](TriangleMesh& self, const torch::Tensor& ray_origins, const torch::Tensor& ray_dirs, bool return_distance) -> py::object {
345
+ auto result = self.get_ray_intersection(ray_origins, ray_dirs, return_distance);
346
+ if (return_distance) {
347
+ return py::cast(result);
348
+ } else {
349
+ return py::cast(std::make_tuple(std::get<0>(result), std::get<1>(result), std::get<2>(result)));
350
+ }
351
+ },
352
+ py::arg("ray_origins"),
353
+ py::arg("ray_dirs"),
354
+ py::arg("return_distance") = false,
355
+ "Find all ray-triangle intersections. Returns (ray_ids, triangle_ids, intersect_points, [distances])")
356
+ .def("query_points", &TriangleMesh::query_points,
357
+ py::arg("query_pts"),
358
+ py::arg("return_sdf") = false,
359
+ py::arg("return_prj_pts") = true,
360
+ py::arg("sign_mode") = 0,
361
+ py::arg("distance_mode") = 0,
362
+ "Query points against the mesh. Returns (query_ids, triangle_ids, projected_points, distances)")
318
363
  .def_property_readonly("edges", &TriangleMesh::get_edges)
319
364
  .def_property_readonly("edge_to_triangle_offsets", &TriangleMesh::get_edge_to_triangle_offsets)
320
365
  .def_property_readonly("edge_to_triangle_counts", &TriangleMesh::get_edge_to_triangle_counts)
@@ -1,5 +1,6 @@
1
1
  #include "bvh.h"
2
2
  #include "zcurve.h"
3
+ #include "../primitive/ray.h"
3
4
 
4
5
  #include <thrust/device_vector.h>
5
6
  #include <thrust/device_ptr.h>
@@ -453,4 +454,185 @@ namespace bvh
453
454
  max_capacity
454
455
  );
455
456
  }
457
+
458
+ __global__ void query_ray_bvh_kernel(
459
+ const uint32_t num_queries,
460
+ const uint32_t num_objects,
461
+ const float3* __restrict__ ray_origins,
462
+ const float3* __restrict__ ray_dirs,
463
+ const float3* __restrict__ bvh_aabb_mins,
464
+ const float3* __restrict__ bvh_aabb_maxs,
465
+ const int2* __restrict__ bvh_children,
466
+ const int* __restrict__ object_ids,
467
+ int64_t* __restrict__ out_query_ids,
468
+ int64_t* __restrict__ out_object_ids,
469
+ int64_t* __restrict__ hit_counter,
470
+ const int64_t max_capacity)
471
+ {
472
+ uint32_t q_idx = blockIdx.x * blockDim.x + threadIdx.x;
473
+ if (q_idx >= num_queries) return;
474
+
475
+ Ray ray(ray_origins[q_idx], ray_dirs[q_idx]);
476
+
477
+ int stack[BVH_STACK_SIZE];
478
+ int stack_ptr = 0;
479
+ stack[0] = 0;
480
+
481
+ while (stack_ptr >= 0)
482
+ {
483
+ int node_idx = stack[stack_ptr--];
484
+ float t_hit;
485
+
486
+ if (ray.is_intersect_aabb(bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx], t_hit))
487
+ {
488
+ if (node_idx >= num_objects - 1)
489
+ {
490
+ int leaf_idx = node_idx - (num_objects - 1);
491
+ int original_obj_id = object_ids[leaf_idx];
492
+
493
+ uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
494
+
495
+ if (write_idx < max_capacity) {
496
+ out_query_ids[write_idx] = q_idx;
497
+ out_object_ids[write_idx] = original_obj_id;
498
+ }
499
+ }
500
+ else
501
+ {
502
+ if (stack_ptr + 2 < BVH_STACK_SIZE)
503
+ {
504
+ int2 children = bvh_children[node_idx];
505
+ stack[++stack_ptr] = children.x;
506
+ stack[++stack_ptr] = children.y;
507
+ }
508
+ }
509
+ }
510
+ }
511
+ }
512
+
513
+ void query_ray(
514
+ const uint32_t num_queries,
515
+ const uint32_t num_objects,
516
+ const float3* __restrict__ ray_origins,
517
+ const float3* __restrict__ ray_dirs,
518
+ const float3* __restrict__ bvh_aabb_mins,
519
+ const float3* __restrict__ bvh_aabb_maxs,
520
+ const int2* __restrict__ bvh_children,
521
+ const int* __restrict__ object_ids,
522
+ int64_t* __restrict__ out_query_ids,
523
+ int64_t* __restrict__ out_object_ids,
524
+ int64_t* __restrict__ hit_counter,
525
+ const int64_t max_capacity)
526
+ {
527
+ uint32_t threads = NTHREADS;
528
+ uint32_t blocks = (num_queries + threads - 1) / threads;
529
+
530
+ query_ray_bvh_kernel<<<blocks, threads>>>(
531
+ num_queries,
532
+ num_objects,
533
+ ray_origins,
534
+ ray_dirs,
535
+ bvh_aabb_mins,
536
+ bvh_aabb_maxs,
537
+ bvh_children,
538
+ object_ids,
539
+ out_query_ids,
540
+ out_object_ids,
541
+ hit_counter,
542
+ max_capacity
543
+ );
544
+ }
545
+
546
+ __global__ void query_point_bvh_kernel(
547
+ const uint32_t num_queries,
548
+ const uint32_t num_objects,
549
+ const float3* __restrict__ query_points,
550
+ const float3* __restrict__ bvh_aabb_mins,
551
+ const float3* __restrict__ bvh_aabb_maxs,
552
+ const int2* __restrict__ bvh_children,
553
+ const int* __restrict__ object_ids,
554
+ int64_t* __restrict__ out_query_ids,
555
+ int64_t* __restrict__ out_object_ids,
556
+ float* __restrict__ out_distances)
557
+ {
558
+ uint32_t q_idx = blockIdx.x * blockDim.x + threadIdx.x;
559
+ if (q_idx >= num_queries) return;
560
+
561
+ float3 p = query_points[q_idx];
562
+
563
+ int stack[BVH_STACK_SIZE];
564
+ int stack_ptr = 0;
565
+ stack[0] = 0;
566
+
567
+ float best_dist_sq = FLT_MAX;
568
+ int best_leaf_original_id = -1;
569
+
570
+ while (stack_ptr >= 0)
571
+ {
572
+ int node_idx = stack[stack_ptr--];
573
+
574
+ float dist_sq = aabb::compute_squared_distance(p, bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx]);
575
+
576
+ if (dist_sq > best_dist_sq) continue; // Prune branch
577
+
578
+ if (node_idx >= num_objects - 1)
579
+ {
580
+ if (dist_sq < best_dist_sq) {
581
+ best_dist_sq = dist_sq;
582
+ best_leaf_original_id = object_ids[node_idx - (num_objects - 1)];
583
+ }
584
+ }
585
+ else
586
+ {
587
+ if (stack_ptr + 2 < BVH_STACK_SIZE)
588
+ {
589
+ int2 children = bvh_children[node_idx];
590
+
591
+ float dist_l = aabb::compute_squared_distance(p, bvh_aabb_mins[children.x], bvh_aabb_maxs[children.x]);
592
+ float dist_r = aabb::compute_squared_distance(p, bvh_aabb_mins[children.y], bvh_aabb_maxs[children.y]);
593
+
594
+ if (dist_l > dist_r) {
595
+ stack[++stack_ptr] = children.x;
596
+ stack[++stack_ptr] = children.y;
597
+ } else {
598
+ stack[++stack_ptr] = children.y;
599
+ stack[++stack_ptr] = children.x;
600
+ }
601
+ }
602
+ }
603
+ }
604
+
605
+ out_query_ids[q_idx] = q_idx;
606
+ out_object_ids[q_idx] = best_leaf_original_id;
607
+ out_distances[q_idx] = sqrtf(best_dist_sq);
608
+ }
609
+
610
+ void query_point(
611
+ const uint32_t num_queries,
612
+ const uint32_t num_objects,
613
+ const float3* __restrict__ query_points,
614
+ const float3* __restrict__ bvh_aabb_mins,
615
+ const float3* __restrict__ bvh_aabb_maxs,
616
+ const int2* __restrict__ bvh_children,
617
+ const int* __restrict__ object_ids,
618
+ int64_t* __restrict__ out_query_ids,
619
+ int64_t* __restrict__ out_object_ids,
620
+ float* __restrict__ out_distances)
621
+ {
622
+ uint32_t threads = NTHREADS;
623
+ uint32_t blocks = (num_queries + threads - 1) / threads;
624
+
625
+ query_point_bvh_kernel<<<blocks, threads>>>(
626
+ num_queries,
627
+ num_objects,
628
+ query_points,
629
+ bvh_aabb_mins,
630
+ bvh_aabb_maxs,
631
+ bvh_children,
632
+ object_ids,
633
+ out_query_ids,
634
+ out_object_ids,
635
+ out_distances
636
+ );
637
+ }
456
638
  }
@@ -4,6 +4,7 @@
4
4
  #include "../maths/maths.h"
5
5
  #include "../constants.h"
6
6
  #include "../primitive/aabb.h"
7
+ #include "../primitive/ray.h"
7
8
 
8
9
  #include <torch/extension.h>
9
10
  #include <cuda_runtime.h>
@@ -29,6 +30,14 @@ public:
29
30
  const torch::Tensor &query_aabb_maxs);
30
31
 
31
32
  std::tuple<torch::Tensor, torch::Tensor> query_self();
33
+
34
+ std::tuple<torch::Tensor, torch::Tensor> query_ray(
35
+ const torch::Tensor &ray_origins,
36
+ const torch::Tensor &ray_dirs,
37
+ int64_t max_capacity = BVH_MAX_CAPACITY);
38
+
39
+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> query_point(
40
+ const torch::Tensor &query_points);
32
41
  };
33
42
 
34
43
  namespace bvh
@@ -69,6 +78,32 @@ namespace bvh
69
78
  int64_t *__restrict__ out_object_ids,
70
79
  int64_t *__restrict__ hit_counter,
71
80
  const int64_t max_capacity);
81
+
82
+ __host__ void query_ray(
83
+ const uint32_t num_queries,
84
+ const uint32_t num_objects,
85
+ const float3 *__restrict__ ray_origins,
86
+ const float3 *__restrict__ ray_dirs,
87
+ const float3 *__restrict__ bvh_aabb_mins,
88
+ const float3 *__restrict__ bvh_aabb_maxs,
89
+ const int2 *__restrict__ bvh_children,
90
+ const int *__restrict__ object_ids,
91
+ int64_t *__restrict__ out_query_ids,
92
+ int64_t *__restrict__ out_object_ids,
93
+ int64_t *__restrict__ hit_counter,
94
+ const int64_t max_capacity);
95
+
96
+ __host__ void query_point(
97
+ const uint32_t num_queries,
98
+ const uint32_t num_objects,
99
+ const float3 *__restrict__ query_points,
100
+ const float3 *__restrict__ bvh_aabb_mins,
101
+ const float3 *__restrict__ bvh_aabb_maxs,
102
+ const int2 *__restrict__ bvh_children,
103
+ const int *__restrict__ object_ids,
104
+ int64_t *__restrict__ out_query_ids,
105
+ int64_t *__restrict__ out_object_ids,
106
+ float *__restrict__ out_distances);
72
107
  }
73
108
 
74
109
  #endif // BVH_H