conquer3d 0.7.6__tar.gz → 0.7.8__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 (158) hide show
  1. conquer3d-0.7.8/PKG-INFO +189 -0
  2. conquer3d-0.7.8/README.md +156 -0
  3. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/_C.so +0 -0
  4. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/bvh.cu +40 -101
  5. conquer3d-0.7.8/conquer3d/csrc/data_structure/bvh_traverse.cuh +82 -0
  6. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/mesh_bvh.cu +42 -131
  7. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/triangle_mesh.cu +78 -142
  8. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/flood_fill.cu +5 -126
  9. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/flood_fill_cf.cu +35 -178
  10. conquer3d-0.7.8/conquer3d/csrc/ops/flood_fill_common.cuh +129 -0
  11. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mc.cu +4 -108
  12. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mtg.cu +4 -103
  13. conquer3d-0.7.8/conquer3d/csrc/ops/voxel_classify.cuh +136 -0
  14. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/gs_aabb.cu +125 -181
  15. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/pgs_aabb.cu +79 -114
  16. conquer3d-0.7.8/conquer3d.egg-info/PKG-INFO +189 -0
  17. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d.egg-info/SOURCES.txt +3 -0
  18. {conquer3d-0.7.6 → conquer3d-0.7.8}/pyproject.toml +1 -1
  19. conquer3d-0.7.6/PKG-INFO +0 -374
  20. conquer3d-0.7.6/README.md +0 -341
  21. conquer3d-0.7.6/conquer3d.egg-info/PKG-INFO +0 -374
  22. {conquer3d-0.7.6 → conquer3d-0.7.8}/LICENSE +0 -0
  23. {conquer3d-0.7.6 → conquer3d-0.7.8}/MANIFEST.in +0 -0
  24. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/_C.pyi +0 -0
  25. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/__init__.py +0 -0
  26. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/conversion/__init__.py +0 -0
  27. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/conversion/grid.py +0 -0
  28. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/conversion/mesh.py +0 -0
  29. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/conversion/tmesh.py +0 -0
  30. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/creation/__init__.py +0 -0
  31. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/creation/triangle_creation.py +0 -0
  32. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
  33. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
  34. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/grid.cpp +0 -0
  35. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
  36. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
  37. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
  38. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
  39. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
  40. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/data_structure/zcurve.cpp +0 -0
  41. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
  42. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/dc.cpp +0 -0
  43. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/dmc.cpp +0 -0
  44. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/flood_fill.cpp +0 -0
  45. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/flood_fill_cf.cpp +0 -0
  46. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/mc.cpp +0 -0
  47. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/mca.cpp +0 -0
  48. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/mt.cpp +0 -0
  49. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/mtg.cpp +0 -0
  50. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/ops/volint.cpp +0 -0
  51. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
  52. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
  53. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/primitive/ray.cpp +0 -0
  54. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/binds/primitive/triangle.cpp +0 -0
  55. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/check.h +0 -0
  56. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/constants.h +0 -0
  57. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/creation/triangle_creation.h +0 -0
  58. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/bvh.h +0 -0
  59. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/grid.cu +0 -0
  60. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/grid.h +0 -0
  61. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
  62. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
  63. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/kdtree.h +0 -0
  64. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
  65. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
  66. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
  67. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/zcurve.cu +0 -0
  68. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/data_structure/zcurve.h +0 -0
  69. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f2x2.h +0 -0
  70. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f3x1.h +0 -0
  71. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f3x3.h +0 -0
  72. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f3x4.h +0 -0
  73. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f4x1.h +0 -0
  74. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/f4x4.h +0 -0
  75. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/maths.h +0 -0
  76. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/ops.h +0 -0
  77. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/maths/qef.h +0 -0
  78. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/chamfer.cu +0 -0
  79. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/chamfer.h +0 -0
  80. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dc.cu +0 -0
  81. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dc.h +0 -0
  82. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dc_data.h +0 -0
  83. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dmc.cu +0 -0
  84. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dmc.h +0 -0
  85. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/dmc_data.h +0 -0
  86. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/flood_fill.h +0 -0
  87. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/flood_fill_cf.h +0 -0
  88. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mc.h +0 -0
  89. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mc_data.h +0 -0
  90. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mca.cu +0 -0
  91. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mca.h +0 -0
  92. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mca_data.h +0 -0
  93. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mt.cu +0 -0
  94. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mt.h +0 -0
  95. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mt_data.h +0 -0
  96. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mtg.h +0 -0
  97. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/mtg_data.h +0 -0
  98. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/volint.cu +0 -0
  99. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/ops/volint.h +0 -0
  100. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/aabb.h +0 -0
  101. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/edge.h +0 -0
  102. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/gs.cu +0 -0
  103. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/gs.h +0 -0
  104. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
  105. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/pgs.cu +0 -0
  106. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/pgs.h +0 -0
  107. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
  108. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/ray.h +0 -0
  109. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/primitive/triangle.h +0 -0
  110. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/csrc/pybind.cpp +0 -0
  111. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/__init__.py +0 -0
  112. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/assets/__init__.py +0 -0
  113. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/assets/common.py +0 -0
  114. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/assets/iphigenia.py +0 -0
  115. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/collate/__init__.py +0 -0
  116. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/collate/mesh.py +0 -0
  117. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/collate/sparse_tensor.py +0 -0
  118. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/__init__.py +0 -0
  119. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/base_mesh.py +0 -0
  120. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/digit3d.py +0 -0
  121. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/digit3dmv.py +0 -0
  122. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/mesh.py +0 -0
  123. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/dataset/redwood.py +0 -0
  124. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/transform/__init__.py +0 -0
  125. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/transform/base.py +0 -0
  126. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/transform/ops.py +0 -0
  127. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data/transform/vertex.py +0 -0
  128. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data_structure/__init__.py +0 -0
  129. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data_structure/bmesh.py +0 -0
  130. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data_structure/grid.py +0 -0
  131. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/data_structure/sort.py +0 -0
  132. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/io/__init__.py +0 -0
  133. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/io/obj.py +0 -0
  134. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/io/off.py +0 -0
  135. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/io/ply.py +0 -0
  136. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/__init__.py +0 -0
  137. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/delaunay_triangulation.py +0 -0
  138. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/diff_marching_cubes.py +0 -0
  139. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/diff_marching_tetrahedra_grid.py +0 -0
  140. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/distance.py +0 -0
  141. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/dpsr.py +0 -0
  142. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/dual_contouring.py +0 -0
  143. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/dual_marching_cubes.py +0 -0
  144. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/hermite.py +0 -0
  145. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/marching_cubes.py +0 -0
  146. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/marching_cubes_asymptotic.py +0 -0
  147. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/marching_tetrahedra.py +0 -0
  148. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/marching_tetrahedra_grid.py +0 -0
  149. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/ops/volint.py +0 -0
  150. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/primitive/__init__.py +0 -0
  151. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/primitive/gs.py +0 -0
  152. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d/primitive/pgs.py +0 -0
  153. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d.egg-info/dependency_links.txt +0 -0
  154. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d.egg-info/not-zip-safe +0 -0
  155. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d.egg-info/requires.txt +0 -0
  156. {conquer3d-0.7.6 → conquer3d-0.7.8}/conquer3d.egg-info/top_level.txt +0 -0
  157. {conquer3d-0.7.6 → conquer3d-0.7.8}/setup.cfg +0 -0
  158. {conquer3d-0.7.6 → conquer3d-0.7.8}/setup.py +0 -0
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: conquer3d
3
+ Version: 0.7.8
4
+ Summary: Geometric Cuda Tool Box
5
+ Author-email: Do Hoang Khoi <khoido8899@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/KhoiDOO/conquer3d
8
+ Project-URL: Repository, https://github.com/KhoiDOO/conquer3d.git
9
+ Project-URL: Documentation, https://github.com/KhoiDOO/conquer3d#readme
10
+ Project-URL: Issues, https://github.com/KhoiDOO/conquer3d/issues
11
+ Keywords: geometry
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: torch>=2.0.0
16
+ Requires-Dist: numpy
17
+ Requires-Dist: scipy
18
+ Requires-Dist: trimesh
19
+ Requires-Dist: tqdm
20
+ Requires-Dist: gdown
21
+ Provides-Extra: cuda
22
+ Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Requires-Dist: black>=23.0; extra == "dev"
26
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
27
+ Requires-Dist: mypy>=1.0; extra == "dev"
28
+ Provides-Extra: docs
29
+ Requires-Dist: mkdocs-material; extra == "docs"
30
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
31
+ Requires-Dist: mkdocs-jupyter; extra == "docs"
32
+ Dynamic: license-file
33
+
34
+ <div align="center">
35
+
36
+ # ⚡ Conquer3D
37
+
38
+ ### *High-Performance GPU-Accelerated Differentiable Geometry, Spatial Computing & Neural Rendering Toolbox*
39
+
40
+ [![Documentation](https://img.shields.io/badge/📖_Documentation-conquer3d-76B900?style=for-the-badge)](https://khoidoo.github.io/conquer3d/)
41
+ [![PyPI Version](https://img.shields.io/pypi/v/conquer3d.svg?color=blue&style=for-the-badge)](https://pypi.org/project/conquer3d/)
42
+ [![Docker Image](https://img.shields.io/badge/Docker-kohido%2Fconquer3d-2496ED?logo=docker&logoColor=white&style=for-the-badge)](https://hub.docker.com/r/kohido/conquer3d)
43
+ [![License](https://img.shields.io/badge/License-MIT-green.svg?style=for-the-badge)](LICENSE)
44
+
45
+ [![Python Version](https://img.shields.io/badge/Python-3.9%2B-3776AB?logo=python&logoColor=white&style=for-the-badge)](https://www.python.org/)
46
+ [![CUDA](https://img.shields.io/badge/CUDA-12.0%2B-76B900?logo=nvidia&logoColor=white&style=for-the-badge)](https://developer.nvidia.com/cuda-toolkit)
47
+ [![PyTorch](https://img.shields.io/badge/PyTorch-2.0%2B-EE4C2C?logo=pytorch&logoColor=white&style=for-the-badge)](https://pytorch.org/)
48
+ [![API Coverage](https://img.shields.io/badge/API_docs-1020_symbols_·_100%25-76B900?style=for-the-badge)](https://khoidoo.github.io/conquer3d/api/index.html)
49
+
50
+ <p align="center">
51
+ <b><a href="https://khoidoo.github.io/conquer3d/">🌐 Website</a></b> •
52
+ <a href="https://khoidoo.github.io/conquer3d/documentation.html">Guide</a> •
53
+ <a href="https://khoidoo.github.io/conquer3d/api/index.html">API Reference</a> •
54
+ <a href="https://khoidoo.github.io/conquer3d/benchmarks.html">Benchmarks</a> •
55
+ <a href="#-qualitative-results">Results</a> •
56
+ <a href="#-installation">Installation</a>
57
+ </p>
58
+
59
+ </div>
60
+
61
+ ---
62
+
63
+ > [!NOTE]
64
+ > The API documentation and the [documentation website](https://khoidoo.github.io/conquer3d/)
65
+ > were written with [Claude](https://claude.ai/code). The library itself — every CUDA kernel,
66
+ > data structure and operator — is the author's own work.
67
+
68
+ ---
69
+
70
+ ## 🌟 Overview
71
+
72
+ **Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.3 Billion faces/second** isosurface extraction, exact CAD sharp crease preservation, and memory-efficient spatial acceleration structures.
73
+
74
+ Every operator consumes and produces PyTorch tensors **in place** — no host round-trip, no format conversion — so meshing a field is an operation *inside* a training step rather than a preprocessing stage around it.
75
+
76
+ ```bash
77
+ pip install -U conquer3d
78
+ ```
79
+
80
+ ```python
81
+ import torch
82
+ from conquer3d.data_structure import create_voxel_grid
83
+ from conquer3d.ops import dmc
84
+
85
+ grid_vertices, voxels, _ = create_voxel_grid(
86
+ grid_min=[-1.0] * 3, grid_max=[1.0] * 3, res=[64, 64, 64], device="cuda"
87
+ )
88
+
89
+ sdf = (torch.norm(grid_vertices, dim=-1) - 0.6).requires_grad_(True)
90
+ verts, faces = dmc(grid_vertices, voxels, sdf, iso=0.0)
91
+
92
+ verts.sum().backward() # gradients flow back into the field
93
+ ```
94
+
95
+ ---
96
+
97
+ ## 🔬 Qualitative Results
98
+
99
+ Every figure below is real library output on the bundled benchmark assets, regenerated
100
+ by `docs/_figures/make_figures.py` — nothing is mocked or hand-drawn. More, at full size,
101
+ on the **[showcase](https://khoidoo.github.io/conquer3d/)**.
102
+
103
+ ### Isosurface extraction
104
+
105
+ <img src="docs/assets/img/fig-algorithms.webp" alt="Five extractors on one signed distance field" width="100%">
106
+
107
+ One signed distance field on a 64³ narrow-band grid of 19,329 cells, meshed by five
108
+ extractors, with the source mesh on the left. The lower row crops the crease where
109
+ Marching Cubes and Dual Contouring disagree most.
110
+
111
+ ### Sharp features from Hermite data
112
+
113
+ <img src="docs/assets/img/fig-hermite.webp" alt="Dual methods with and without Hermite data" width="100%">
114
+
115
+ Dual Contouring and Dual Marching Cubes run twice each: once with normals interpolated
116
+ from the grid, once with exact Hermite data from `compute_hermite_from_mesh`, which
117
+ ray-casts all 25,832 sign-crossing edges for the true intersection and face normal.
118
+ The crease is reconstructed rather than rounded.
119
+
120
+ ### Detail is a resolution dial
121
+
122
+ <img src="docs/assets/img/fig-resolution.webp" alt="Resolution ladder from 64 to 2048 cubed" width="100%">
123
+
124
+ Dual Marching Cubes on the Armadillo at seven grid resolutions from 64³ to 2048³.
125
+ Face count runs from 12,076 to 13,294,500, with Chamfer and Hausdorff distance to the
126
+ source measured at every step.
127
+
128
+ ### From mesh to surface, step by step
129
+
130
+ <img src="docs/assets/img/fig-pipeline.webp" alt="Sparse grid construction and extraction" width="100%">
131
+
132
+ The input mesh, the narrow-band cells allocated around it (7,863 of a possible 64,000
133
+ at 40³), the signed distance shown as a cutaway, the 2,646 bipolar cells, and the
134
+ extracted surface. No dense volume is ever held.
135
+
136
+ ### Six ways to decide inside
137
+
138
+ <img src="docs/assets/img/fig-sign-modes.webp" alt="Six sign determination modes" width="100%">
139
+
140
+ One axial slice signed by each of the six sign modes and contoured at zero — ray parity,
141
+ pseudonormal, winding number, flood fill, hybrid consensus, and coarse-fine fill.
142
+
143
+ ### Ray queries against the hierarchies
144
+
145
+ <img src="docs/assets/img/fig-meshbvh.webp" alt="Ray-triangle and ray-voxel queries" width="100%">
146
+
147
+ `MeshBVH.get_ray_intersection` returns the triangles a ray pierces; `BVH.query_ray`
148
+ returns the narrow-band cells it crosses. Five rays from five origins, each drawn as far
149
+ as its own first hit.
150
+
151
+ ---
152
+
153
+ ## ⚡ Benchmarks
154
+
155
+ *RTX 4090, torch 2.8.0+cu128, CUDA 12.8. Fandisk at $1024^3$ (5.15M active cells).
156
+ CUDA events around the operator alone, median of 7 runs after 2 warm-ups.*
157
+
158
+ | Algorithm | Output | Vertices | Faces | Latency | Throughput |
159
+ | :--- | :--- | ---: | ---: | ---: | ---: |
160
+ | **Dual Marching Cubes** | Triangles | 1,716,384 | 3,432,764 | **2.62 ms** | **1,311M faces/s** |
161
+ | DMC (pure quads) | Quads | 1,716,384 | 1,716,382 | 2.51 ms | 684M quads/s |
162
+ | MC Asymptotic | Triangles | 1,716,382 | 3,432,760 | 2.71 ms | 1,267M faces/s |
163
+ | Dual Contouring | Triangles | 1,716,384 | 3,432,764 | 3.88 ms | 884M faces/s |
164
+ | Marching Cubes | Triangles | 1,716,382 | 3,432,760 | 7.90 ms | 434M faces/s |
165
+ | Marching Tetrahedra | Triangles | 6,113,918 | 12,227,832 | 44.90 ms | 272M faces/s |
166
+
167
+ Sign-mode costs, distance-operator throughput, pipeline breakdown and memory scaling are
168
+ on the **[benchmarks page](https://khoidoo.github.io/conquer3d/benchmarks.html)**.
169
+
170
+ ---
171
+
172
+ ## 📦 Installation
173
+
174
+ ```bash
175
+ pip install -U conquer3d
176
+ ```
177
+
178
+ Building from source, the full feature list, worked pipelines and the 1,020-symbol API
179
+ reference are on the **[documentation site](https://khoidoo.github.io/conquer3d/documentation.html)**.
180
+
181
+ ---
182
+
183
+ ## 📄 License
184
+
185
+ Conquer3D is licensed under the [MIT License](LICENSE).
186
+
187
+ <div align="center">
188
+ <sub>Built with CUDA and PyTorch · <a href="https://khoidoo.github.io/conquer3d/">khoidoo.github.io/conquer3d</a></sub>
189
+ </div>
@@ -0,0 +1,156 @@
1
+ <div align="center">
2
+
3
+ # ⚡ Conquer3D
4
+
5
+ ### *High-Performance GPU-Accelerated Differentiable Geometry, Spatial Computing & Neural Rendering Toolbox*
6
+
7
+ [![Documentation](https://img.shields.io/badge/📖_Documentation-conquer3d-76B900?style=for-the-badge)](https://khoidoo.github.io/conquer3d/)
8
+ [![PyPI Version](https://img.shields.io/pypi/v/conquer3d.svg?color=blue&style=for-the-badge)](https://pypi.org/project/conquer3d/)
9
+ [![Docker Image](https://img.shields.io/badge/Docker-kohido%2Fconquer3d-2496ED?logo=docker&logoColor=white&style=for-the-badge)](https://hub.docker.com/r/kohido/conquer3d)
10
+ [![License](https://img.shields.io/badge/License-MIT-green.svg?style=for-the-badge)](LICENSE)
11
+
12
+ [![Python Version](https://img.shields.io/badge/Python-3.9%2B-3776AB?logo=python&logoColor=white&style=for-the-badge)](https://www.python.org/)
13
+ [![CUDA](https://img.shields.io/badge/CUDA-12.0%2B-76B900?logo=nvidia&logoColor=white&style=for-the-badge)](https://developer.nvidia.com/cuda-toolkit)
14
+ [![PyTorch](https://img.shields.io/badge/PyTorch-2.0%2B-EE4C2C?logo=pytorch&logoColor=white&style=for-the-badge)](https://pytorch.org/)
15
+ [![API Coverage](https://img.shields.io/badge/API_docs-1020_symbols_·_100%25-76B900?style=for-the-badge)](https://khoidoo.github.io/conquer3d/api/index.html)
16
+
17
+ <p align="center">
18
+ <b><a href="https://khoidoo.github.io/conquer3d/">🌐 Website</a></b> •
19
+ <a href="https://khoidoo.github.io/conquer3d/documentation.html">Guide</a> •
20
+ <a href="https://khoidoo.github.io/conquer3d/api/index.html">API Reference</a> •
21
+ <a href="https://khoidoo.github.io/conquer3d/benchmarks.html">Benchmarks</a> •
22
+ <a href="#-qualitative-results">Results</a> •
23
+ <a href="#-installation">Installation</a>
24
+ </p>
25
+
26
+ </div>
27
+
28
+ ---
29
+
30
+ > [!NOTE]
31
+ > The API documentation and the [documentation website](https://khoidoo.github.io/conquer3d/)
32
+ > were written with [Claude](https://claude.ai/code). The library itself — every CUDA kernel,
33
+ > data structure and operator — is the author's own work.
34
+
35
+ ---
36
+
37
+ ## 🌟 Overview
38
+
39
+ **Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.3 Billion faces/second** isosurface extraction, exact CAD sharp crease preservation, and memory-efficient spatial acceleration structures.
40
+
41
+ Every operator consumes and produces PyTorch tensors **in place** — no host round-trip, no format conversion — so meshing a field is an operation *inside* a training step rather than a preprocessing stage around it.
42
+
43
+ ```bash
44
+ pip install -U conquer3d
45
+ ```
46
+
47
+ ```python
48
+ import torch
49
+ from conquer3d.data_structure import create_voxel_grid
50
+ from conquer3d.ops import dmc
51
+
52
+ grid_vertices, voxels, _ = create_voxel_grid(
53
+ grid_min=[-1.0] * 3, grid_max=[1.0] * 3, res=[64, 64, 64], device="cuda"
54
+ )
55
+
56
+ sdf = (torch.norm(grid_vertices, dim=-1) - 0.6).requires_grad_(True)
57
+ verts, faces = dmc(grid_vertices, voxels, sdf, iso=0.0)
58
+
59
+ verts.sum().backward() # gradients flow back into the field
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 🔬 Qualitative Results
65
+
66
+ Every figure below is real library output on the bundled benchmark assets, regenerated
67
+ by `docs/_figures/make_figures.py` — nothing is mocked or hand-drawn. More, at full size,
68
+ on the **[showcase](https://khoidoo.github.io/conquer3d/)**.
69
+
70
+ ### Isosurface extraction
71
+
72
+ <img src="docs/assets/img/fig-algorithms.webp" alt="Five extractors on one signed distance field" width="100%">
73
+
74
+ One signed distance field on a 64³ narrow-band grid of 19,329 cells, meshed by five
75
+ extractors, with the source mesh on the left. The lower row crops the crease where
76
+ Marching Cubes and Dual Contouring disagree most.
77
+
78
+ ### Sharp features from Hermite data
79
+
80
+ <img src="docs/assets/img/fig-hermite.webp" alt="Dual methods with and without Hermite data" width="100%">
81
+
82
+ Dual Contouring and Dual Marching Cubes run twice each: once with normals interpolated
83
+ from the grid, once with exact Hermite data from `compute_hermite_from_mesh`, which
84
+ ray-casts all 25,832 sign-crossing edges for the true intersection and face normal.
85
+ The crease is reconstructed rather than rounded.
86
+
87
+ ### Detail is a resolution dial
88
+
89
+ <img src="docs/assets/img/fig-resolution.webp" alt="Resolution ladder from 64 to 2048 cubed" width="100%">
90
+
91
+ Dual Marching Cubes on the Armadillo at seven grid resolutions from 64³ to 2048³.
92
+ Face count runs from 12,076 to 13,294,500, with Chamfer and Hausdorff distance to the
93
+ source measured at every step.
94
+
95
+ ### From mesh to surface, step by step
96
+
97
+ <img src="docs/assets/img/fig-pipeline.webp" alt="Sparse grid construction and extraction" width="100%">
98
+
99
+ The input mesh, the narrow-band cells allocated around it (7,863 of a possible 64,000
100
+ at 40³), the signed distance shown as a cutaway, the 2,646 bipolar cells, and the
101
+ extracted surface. No dense volume is ever held.
102
+
103
+ ### Six ways to decide inside
104
+
105
+ <img src="docs/assets/img/fig-sign-modes.webp" alt="Six sign determination modes" width="100%">
106
+
107
+ One axial slice signed by each of the six sign modes and contoured at zero — ray parity,
108
+ pseudonormal, winding number, flood fill, hybrid consensus, and coarse-fine fill.
109
+
110
+ ### Ray queries against the hierarchies
111
+
112
+ <img src="docs/assets/img/fig-meshbvh.webp" alt="Ray-triangle and ray-voxel queries" width="100%">
113
+
114
+ `MeshBVH.get_ray_intersection` returns the triangles a ray pierces; `BVH.query_ray`
115
+ returns the narrow-band cells it crosses. Five rays from five origins, each drawn as far
116
+ as its own first hit.
117
+
118
+ ---
119
+
120
+ ## ⚡ Benchmarks
121
+
122
+ *RTX 4090, torch 2.8.0+cu128, CUDA 12.8. Fandisk at $1024^3$ (5.15M active cells).
123
+ CUDA events around the operator alone, median of 7 runs after 2 warm-ups.*
124
+
125
+ | Algorithm | Output | Vertices | Faces | Latency | Throughput |
126
+ | :--- | :--- | ---: | ---: | ---: | ---: |
127
+ | **Dual Marching Cubes** | Triangles | 1,716,384 | 3,432,764 | **2.62 ms** | **1,311M faces/s** |
128
+ | DMC (pure quads) | Quads | 1,716,384 | 1,716,382 | 2.51 ms | 684M quads/s |
129
+ | MC Asymptotic | Triangles | 1,716,382 | 3,432,760 | 2.71 ms | 1,267M faces/s |
130
+ | Dual Contouring | Triangles | 1,716,384 | 3,432,764 | 3.88 ms | 884M faces/s |
131
+ | Marching Cubes | Triangles | 1,716,382 | 3,432,760 | 7.90 ms | 434M faces/s |
132
+ | Marching Tetrahedra | Triangles | 6,113,918 | 12,227,832 | 44.90 ms | 272M faces/s |
133
+
134
+ Sign-mode costs, distance-operator throughput, pipeline breakdown and memory scaling are
135
+ on the **[benchmarks page](https://khoidoo.github.io/conquer3d/benchmarks.html)**.
136
+
137
+ ---
138
+
139
+ ## 📦 Installation
140
+
141
+ ```bash
142
+ pip install -U conquer3d
143
+ ```
144
+
145
+ Building from source, the full feature list, worked pipelines and the 1,020-symbol API
146
+ reference are on the **[documentation site](https://khoidoo.github.io/conquer3d/documentation.html)**.
147
+
148
+ ---
149
+
150
+ ## 📄 License
151
+
152
+ Conquer3D is licensed under the [MIT License](LICENSE).
153
+
154
+ <div align="center">
155
+ <sub>Built with CUDA and PyTorch · <a href="https://khoidoo.github.io/conquer3d/">khoidoo.github.io/conquer3d</a></sub>
156
+ </div>
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "bvh.h"
7
7
  #include "zcurve.h"
8
+ #include "bvh_traverse.cuh"
8
9
  #include "../primitive/ray.h"
9
10
 
10
11
  #include <thrust/device_vector.h>
@@ -434,41 +435,19 @@ __global__ void query_bvh_kernel(
434
435
  float3 q_max = query_maxs[q_idx];
435
436
 
436
437
  // The local thread stack
437
- int stack[BVH_STACK_SIZE];
438
- int stack_ptr = 0;
439
-
440
- // Push the Root Node (Index 0) to start
441
- stack[0] = 0;
442
-
443
- while (stack_ptr >= 0)
444
- {
445
- int node_idx = stack[stack_ptr--];
446
-
447
- if (aabb::test_aabb_overlap(q_min, q_max, bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx]))
448
- {
449
- if (node_idx >= num_objects - 1)
450
- {
451
- int leaf_idx = node_idx - (num_objects - 1);
452
- int original_obj_id = object_ids[leaf_idx];
453
-
454
- uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
455
-
456
- if (write_idx < max_capacity) {
457
- out_query_ids[write_idx] = q_idx;
458
- out_object_ids[write_idx] = original_obj_id;
459
- }
460
- }
461
- else
462
- {
463
- if (stack_ptr + 2 < BVH_STACK_SIZE)
464
- {
465
- int2 children = bvh_children[node_idx];
466
- stack[++stack_ptr] = children.x;
467
- stack[++stack_ptr] = children.y;
468
- }
438
+ bvh::traverse(num_objects, bvh_children,
439
+ [&] (int node_idx) {
440
+ return aabb::test_aabb_overlap(q_min, q_max,
441
+ bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx]);
442
+ },
443
+ [&] (int leaf_idx) {
444
+ uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
445
+ if (write_idx < max_capacity) {
446
+ out_query_ids[write_idx] = q_idx;
447
+ out_object_ids[write_idx] = object_ids[leaf_idx];
469
448
  }
470
- }
471
- }
449
+ return true;
450
+ });
472
451
  }
473
452
 
474
453
  void query(
@@ -545,42 +524,22 @@ __global__ void query_self_bvh_kernel(
545
524
  float3 q_max = bvh_aabb_maxs[node_offset + leaf_idx];
546
525
  int original_q_id = object_ids[leaf_idx];
547
526
 
548
- int stack[BVH_STACK_SIZE];
549
- int stack_ptr = 0;
550
- stack[0] = 0;
551
-
552
- while (stack_ptr >= 0)
553
- {
554
- int node_idx = stack[stack_ptr--];
555
-
556
- if (aabb::test_aabb_overlap(q_min, q_max, bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx]))
557
- {
558
- if (node_idx >= num_objects - 1)
559
- {
560
- int other_leaf_idx = node_idx - (num_objects - 1);
561
- int original_obj_id = object_ids[other_leaf_idx];
562
-
563
- if (original_q_id < original_obj_id)
564
- {
565
- uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
566
-
567
- if (write_idx < max_capacity) {
568
- out_query_ids[write_idx] = original_q_id;
569
- out_object_ids[write_idx] = original_obj_id;
570
- }
571
- }
572
- }
573
- else
574
- {
575
- if (stack_ptr + 2 < BVH_STACK_SIZE)
576
- {
577
- int2 children = bvh_children[node_idx];
578
- stack[++stack_ptr] = children.x;
579
- stack[++stack_ptr] = children.y;
527
+ bvh::traverse(num_objects, bvh_children,
528
+ [&] (int node_idx) {
529
+ return aabb::test_aabb_overlap(q_min, q_max,
530
+ bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx]);
531
+ },
532
+ [&] (int other_leaf_idx) {
533
+ int original_obj_id = object_ids[other_leaf_idx];
534
+ if (original_q_id < original_obj_id) {
535
+ uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
536
+ if (write_idx < max_capacity) {
537
+ out_query_ids[write_idx] = original_q_id;
538
+ out_object_ids[write_idx] = original_obj_id;
580
539
  }
581
540
  }
582
- }
583
- }
541
+ return true;
542
+ });
584
543
  }
585
544
 
586
545
  void query_self(
@@ -655,40 +614,20 @@ __global__ void query_ray_bvh_kernel(
655
614
 
656
615
  Ray ray(ray_origins[q_idx], ray_dirs[q_idx]);
657
616
 
658
- int stack[BVH_STACK_SIZE];
659
- int stack_ptr = 0;
660
- stack[0] = 0;
661
-
662
- while (stack_ptr >= 0)
663
- {
664
- int node_idx = stack[stack_ptr--];
665
- float t_hit;
666
-
667
- if (ray.is_intersect_aabb(bvh_aabb_mins[node_idx], bvh_aabb_maxs[node_idx], t_hit))
668
- {
669
- if (node_idx >= num_objects - 1)
670
- {
671
- int leaf_idx = node_idx - (num_objects - 1);
672
- int original_obj_id = object_ids[leaf_idx];
673
-
674
- uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
675
-
676
- if (write_idx < max_capacity) {
677
- out_query_ids[write_idx] = q_idx;
678
- out_object_ids[write_idx] = original_obj_id;
679
- }
680
- }
681
- else
682
- {
683
- if (stack_ptr + 2 < BVH_STACK_SIZE)
684
- {
685
- int2 children = bvh_children[node_idx];
686
- stack[++stack_ptr] = children.x;
687
- stack[++stack_ptr] = children.y;
688
- }
617
+ bvh::traverse(num_objects, bvh_children,
618
+ [&] (int node_idx) {
619
+ float t_hit;
620
+ return ray.is_intersect_aabb(bvh_aabb_mins[node_idx],
621
+ bvh_aabb_maxs[node_idx], t_hit);
622
+ },
623
+ [&] (int leaf_idx) {
624
+ uint64_t write_idx = (uint64_t)atomicAdd((unsigned long long int*)hit_counter, 1ULL);
625
+ if (write_idx < max_capacity) {
626
+ out_query_ids[write_idx] = q_idx;
627
+ out_object_ids[write_idx] = object_ids[leaf_idx];
689
628
  }
690
- }
691
- }
629
+ return true;
630
+ });
692
631
  }
693
632
 
694
633
  void query_ray(
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @file bvh_traverse.cuh
3
+ * @brief Shared stack-based descent over a Linear BVH.
4
+ *
5
+ * @details Every query in the library walks the hierarchy the same way: pop a node, ask
6
+ * whether it is worth entering, and either visit it as a leaf or push its two children.
7
+ * Only the node test and the leaf action differ. Writing that loop once and passing those
8
+ * two steps as functors keeps the traversal -- including the stack bound, the leaf index
9
+ * arithmetic and the overflow guard -- in a single place, so a fix lands everywhere rather
10
+ * than in one of eighteen copies.
11
+ *
12
+ * The functors are device lambdas and are fully inlined, so the generated code matches the
13
+ * hand-written loop it replaces.
14
+ *
15
+ * @note Two query shapes are deliberately *not* expressed here and remain hand-written:
16
+ * nearest-point search, which pushes the closer child last and prunes each child against
17
+ * the running best distance, and the Fast Winding Number descent, which does work on the
18
+ * branch where the node test *fails* rather than skipping it. Forcing either into this
19
+ * interface would obscure it for no gain.
20
+ */
21
+
22
+ #ifndef BVH_TRAVERSE_CUH
23
+ #define BVH_TRAVERSE_CUH
24
+
25
+ #include "../constants.h"
26
+ #include <cuda_runtime.h>
27
+
28
+ namespace bvh
29
+ {
30
+ /**
31
+ * @brief Walks the hierarchy, visiting every leaf the node test admits.
32
+ *
33
+ * @tparam NodeTest Callable `bool(int node_idx)`; return false to prune the subtree.
34
+ * @tparam LeafVisit Callable `bool(int leaf_idx)` receiving the leaf's slot in
35
+ * `object_ids`; return false to abandon the traversal, which is how
36
+ * any-hit queries stop at their first result.
37
+ *
38
+ * @param[in] num_objects Number of primitives $N$; internal nodes occupy $[0, N-1)$ and
39
+ * leaves $[N-1, 2N-1)$.
40
+ * @param[in] children Device array of $N - 1$ child index pairs.
41
+ * @param[in] node_test Predicate deciding whether to enter a node.
42
+ * @param[in] leaf_visit Action performed at an admitted leaf.
43
+ *
44
+ * @warning The stack holds `BVH_STACK_SIZE` entries in local memory. A hierarchy deeper
45
+ * than that silently drops the remaining children rather than failing, so a
46
+ * pathologically unbalanced tree can under-report. Morton ordering keeps real trees
47
+ * far shallower than the bound.
48
+ */
49
+ template <class NodeTest, class LeafVisit>
50
+ __device__ __forceinline__ void traverse(
51
+ const int num_objects,
52
+ const int2 *__restrict__ children,
53
+ NodeTest node_test,
54
+ LeafVisit leaf_visit)
55
+ {
56
+ int stack[BVH_STACK_SIZE];
57
+ int stack_ptr = 0;
58
+ stack[0] = 0;
59
+
60
+ while (stack_ptr >= 0)
61
+ {
62
+ const int node_idx = stack[stack_ptr--];
63
+
64
+ if (!node_test(node_idx))
65
+ continue;
66
+
67
+ if (node_idx >= num_objects - 1)
68
+ {
69
+ if (!leaf_visit(node_idx - (num_objects - 1)))
70
+ return;
71
+ }
72
+ else if (stack_ptr + 2 < BVH_STACK_SIZE)
73
+ {
74
+ const int2 c = children[node_idx];
75
+ if (c.x >= 0) stack[++stack_ptr] = c.x;
76
+ if (c.y >= 0) stack[++stack_ptr] = c.y;
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ #endif // BVH_TRAVERSE_CUH