warp-lang 1.10.0__py3-none-macosx_11_0_arm64.whl

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.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (468) hide show
  1. warp/__init__.py +334 -0
  2. warp/__init__.pyi +5856 -0
  3. warp/_src/__init__.py +14 -0
  4. warp/_src/autograd.py +1077 -0
  5. warp/_src/build.py +620 -0
  6. warp/_src/build_dll.py +642 -0
  7. warp/_src/builtins.py +10555 -0
  8. warp/_src/codegen.py +4361 -0
  9. warp/_src/config.py +178 -0
  10. warp/_src/constants.py +59 -0
  11. warp/_src/context.py +8352 -0
  12. warp/_src/dlpack.py +464 -0
  13. warp/_src/fabric.py +362 -0
  14. warp/_src/fem/__init__.py +14 -0
  15. warp/_src/fem/adaptivity.py +510 -0
  16. warp/_src/fem/cache.py +689 -0
  17. warp/_src/fem/dirichlet.py +190 -0
  18. warp/_src/fem/domain.py +553 -0
  19. warp/_src/fem/field/__init__.py +131 -0
  20. warp/_src/fem/field/field.py +703 -0
  21. warp/_src/fem/field/nodal_field.py +403 -0
  22. warp/_src/fem/field/restriction.py +39 -0
  23. warp/_src/fem/field/virtual.py +1021 -0
  24. warp/_src/fem/geometry/__init__.py +32 -0
  25. warp/_src/fem/geometry/adaptive_nanogrid.py +782 -0
  26. warp/_src/fem/geometry/closest_point.py +99 -0
  27. warp/_src/fem/geometry/deformed_geometry.py +277 -0
  28. warp/_src/fem/geometry/element.py +854 -0
  29. warp/_src/fem/geometry/geometry.py +693 -0
  30. warp/_src/fem/geometry/grid_2d.py +478 -0
  31. warp/_src/fem/geometry/grid_3d.py +539 -0
  32. warp/_src/fem/geometry/hexmesh.py +956 -0
  33. warp/_src/fem/geometry/nanogrid.py +660 -0
  34. warp/_src/fem/geometry/partition.py +483 -0
  35. warp/_src/fem/geometry/quadmesh.py +597 -0
  36. warp/_src/fem/geometry/tetmesh.py +762 -0
  37. warp/_src/fem/geometry/trimesh.py +588 -0
  38. warp/_src/fem/integrate.py +2507 -0
  39. warp/_src/fem/linalg.py +385 -0
  40. warp/_src/fem/operator.py +398 -0
  41. warp/_src/fem/polynomial.py +231 -0
  42. warp/_src/fem/quadrature/__init__.py +17 -0
  43. warp/_src/fem/quadrature/pic_quadrature.py +318 -0
  44. warp/_src/fem/quadrature/quadrature.py +665 -0
  45. warp/_src/fem/space/__init__.py +248 -0
  46. warp/_src/fem/space/basis_function_space.py +499 -0
  47. warp/_src/fem/space/basis_space.py +681 -0
  48. warp/_src/fem/space/dof_mapper.py +253 -0
  49. warp/_src/fem/space/function_space.py +312 -0
  50. warp/_src/fem/space/grid_2d_function_space.py +179 -0
  51. warp/_src/fem/space/grid_3d_function_space.py +229 -0
  52. warp/_src/fem/space/hexmesh_function_space.py +255 -0
  53. warp/_src/fem/space/nanogrid_function_space.py +199 -0
  54. warp/_src/fem/space/partition.py +435 -0
  55. warp/_src/fem/space/quadmesh_function_space.py +222 -0
  56. warp/_src/fem/space/restriction.py +221 -0
  57. warp/_src/fem/space/shape/__init__.py +152 -0
  58. warp/_src/fem/space/shape/cube_shape_function.py +1107 -0
  59. warp/_src/fem/space/shape/shape_function.py +134 -0
  60. warp/_src/fem/space/shape/square_shape_function.py +928 -0
  61. warp/_src/fem/space/shape/tet_shape_function.py +829 -0
  62. warp/_src/fem/space/shape/triangle_shape_function.py +674 -0
  63. warp/_src/fem/space/tetmesh_function_space.py +270 -0
  64. warp/_src/fem/space/topology.py +461 -0
  65. warp/_src/fem/space/trimesh_function_space.py +193 -0
  66. warp/_src/fem/types.py +114 -0
  67. warp/_src/fem/utils.py +488 -0
  68. warp/_src/jax.py +188 -0
  69. warp/_src/jax_experimental/__init__.py +14 -0
  70. warp/_src/jax_experimental/custom_call.py +389 -0
  71. warp/_src/jax_experimental/ffi.py +1286 -0
  72. warp/_src/jax_experimental/xla_ffi.py +658 -0
  73. warp/_src/marching_cubes.py +710 -0
  74. warp/_src/math.py +416 -0
  75. warp/_src/optim/__init__.py +14 -0
  76. warp/_src/optim/adam.py +165 -0
  77. warp/_src/optim/linear.py +1608 -0
  78. warp/_src/optim/sgd.py +114 -0
  79. warp/_src/paddle.py +408 -0
  80. warp/_src/render/__init__.py +14 -0
  81. warp/_src/render/imgui_manager.py +291 -0
  82. warp/_src/render/render_opengl.py +3638 -0
  83. warp/_src/render/render_usd.py +939 -0
  84. warp/_src/render/utils.py +162 -0
  85. warp/_src/sparse.py +2718 -0
  86. warp/_src/tape.py +1208 -0
  87. warp/_src/thirdparty/__init__.py +0 -0
  88. warp/_src/thirdparty/appdirs.py +598 -0
  89. warp/_src/thirdparty/dlpack.py +145 -0
  90. warp/_src/thirdparty/unittest_parallel.py +676 -0
  91. warp/_src/torch.py +393 -0
  92. warp/_src/types.py +5888 -0
  93. warp/_src/utils.py +1695 -0
  94. warp/autograd.py +33 -0
  95. warp/bin/libwarp-clang.dylib +0 -0
  96. warp/bin/libwarp.dylib +0 -0
  97. warp/build.py +29 -0
  98. warp/build_dll.py +24 -0
  99. warp/codegen.py +24 -0
  100. warp/constants.py +24 -0
  101. warp/context.py +33 -0
  102. warp/dlpack.py +24 -0
  103. warp/examples/__init__.py +24 -0
  104. warp/examples/assets/bear.usd +0 -0
  105. warp/examples/assets/bunny.usd +0 -0
  106. warp/examples/assets/cube.usd +0 -0
  107. warp/examples/assets/nonuniform.usd +0 -0
  108. warp/examples/assets/nvidia_logo.png +0 -0
  109. warp/examples/assets/pixel.jpg +0 -0
  110. warp/examples/assets/rocks.nvdb +0 -0
  111. warp/examples/assets/rocks.usd +0 -0
  112. warp/examples/assets/sphere.usd +0 -0
  113. warp/examples/assets/square_cloth.usd +0 -0
  114. warp/examples/benchmarks/benchmark_api.py +389 -0
  115. warp/examples/benchmarks/benchmark_cloth.py +296 -0
  116. warp/examples/benchmarks/benchmark_cloth_cupy.py +96 -0
  117. warp/examples/benchmarks/benchmark_cloth_jax.py +105 -0
  118. warp/examples/benchmarks/benchmark_cloth_numba.py +161 -0
  119. warp/examples/benchmarks/benchmark_cloth_numpy.py +85 -0
  120. warp/examples/benchmarks/benchmark_cloth_paddle.py +94 -0
  121. warp/examples/benchmarks/benchmark_cloth_pytorch.py +94 -0
  122. warp/examples/benchmarks/benchmark_cloth_taichi.py +120 -0
  123. warp/examples/benchmarks/benchmark_cloth_warp.py +153 -0
  124. warp/examples/benchmarks/benchmark_gemm.py +164 -0
  125. warp/examples/benchmarks/benchmark_interop_paddle.py +166 -0
  126. warp/examples/benchmarks/benchmark_interop_torch.py +166 -0
  127. warp/examples/benchmarks/benchmark_launches.py +301 -0
  128. warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
  129. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  130. warp/examples/browse.py +37 -0
  131. warp/examples/core/example_cupy.py +86 -0
  132. warp/examples/core/example_dem.py +241 -0
  133. warp/examples/core/example_fluid.py +299 -0
  134. warp/examples/core/example_graph_capture.py +150 -0
  135. warp/examples/core/example_marching_cubes.py +195 -0
  136. warp/examples/core/example_mesh.py +180 -0
  137. warp/examples/core/example_mesh_intersect.py +211 -0
  138. warp/examples/core/example_nvdb.py +182 -0
  139. warp/examples/core/example_raycast.py +111 -0
  140. warp/examples/core/example_raymarch.py +205 -0
  141. warp/examples/core/example_render_opengl.py +290 -0
  142. warp/examples/core/example_sample_mesh.py +300 -0
  143. warp/examples/core/example_sph.py +411 -0
  144. warp/examples/core/example_spin_lock.py +93 -0
  145. warp/examples/core/example_torch.py +211 -0
  146. warp/examples/core/example_wave.py +269 -0
  147. warp/examples/core/example_work_queue.py +118 -0
  148. warp/examples/distributed/example_jacobi_mpi.py +506 -0
  149. warp/examples/fem/example_adaptive_grid.py +286 -0
  150. warp/examples/fem/example_apic_fluid.py +469 -0
  151. warp/examples/fem/example_burgers.py +261 -0
  152. warp/examples/fem/example_convection_diffusion.py +181 -0
  153. warp/examples/fem/example_convection_diffusion_dg.py +225 -0
  154. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  155. warp/examples/fem/example_deformed_geometry.py +172 -0
  156. warp/examples/fem/example_diffusion.py +196 -0
  157. warp/examples/fem/example_diffusion_3d.py +225 -0
  158. warp/examples/fem/example_diffusion_mgpu.py +225 -0
  159. warp/examples/fem/example_distortion_energy.py +228 -0
  160. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  161. warp/examples/fem/example_magnetostatics.py +242 -0
  162. warp/examples/fem/example_mixed_elasticity.py +293 -0
  163. warp/examples/fem/example_navier_stokes.py +263 -0
  164. warp/examples/fem/example_nonconforming_contact.py +300 -0
  165. warp/examples/fem/example_stokes.py +213 -0
  166. warp/examples/fem/example_stokes_transfer.py +262 -0
  167. warp/examples/fem/example_streamlines.py +357 -0
  168. warp/examples/fem/utils.py +1047 -0
  169. warp/examples/interop/example_jax_callable.py +146 -0
  170. warp/examples/interop/example_jax_ffi_callback.py +132 -0
  171. warp/examples/interop/example_jax_kernel.py +232 -0
  172. warp/examples/optim/example_diffray.py +561 -0
  173. warp/examples/optim/example_fluid_checkpoint.py +497 -0
  174. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  175. warp/examples/tile/example_tile_cholesky.py +88 -0
  176. warp/examples/tile/example_tile_convolution.py +66 -0
  177. warp/examples/tile/example_tile_fft.py +55 -0
  178. warp/examples/tile/example_tile_filtering.py +113 -0
  179. warp/examples/tile/example_tile_matmul.py +85 -0
  180. warp/examples/tile/example_tile_mcgp.py +191 -0
  181. warp/examples/tile/example_tile_mlp.py +385 -0
  182. warp/examples/tile/example_tile_nbody.py +199 -0
  183. warp/fabric.py +24 -0
  184. warp/fem/__init__.py +173 -0
  185. warp/fem/adaptivity.py +26 -0
  186. warp/fem/cache.py +30 -0
  187. warp/fem/dirichlet.py +24 -0
  188. warp/fem/field/__init__.py +24 -0
  189. warp/fem/field/field.py +26 -0
  190. warp/fem/geometry/__init__.py +21 -0
  191. warp/fem/geometry/closest_point.py +31 -0
  192. warp/fem/linalg.py +38 -0
  193. warp/fem/operator.py +32 -0
  194. warp/fem/polynomial.py +29 -0
  195. warp/fem/space/__init__.py +22 -0
  196. warp/fem/space/basis_space.py +24 -0
  197. warp/fem/space/shape/__init__.py +68 -0
  198. warp/fem/space/topology.py +24 -0
  199. warp/fem/types.py +24 -0
  200. warp/fem/utils.py +32 -0
  201. warp/jax.py +29 -0
  202. warp/jax_experimental/__init__.py +29 -0
  203. warp/jax_experimental/custom_call.py +29 -0
  204. warp/jax_experimental/ffi.py +39 -0
  205. warp/jax_experimental/xla_ffi.py +24 -0
  206. warp/marching_cubes.py +24 -0
  207. warp/math.py +37 -0
  208. warp/native/array.h +1687 -0
  209. warp/native/builtin.h +2327 -0
  210. warp/native/bvh.cpp +562 -0
  211. warp/native/bvh.cu +826 -0
  212. warp/native/bvh.h +555 -0
  213. warp/native/clang/clang.cpp +541 -0
  214. warp/native/coloring.cpp +622 -0
  215. warp/native/crt.cpp +51 -0
  216. warp/native/crt.h +568 -0
  217. warp/native/cuda_crt.h +1058 -0
  218. warp/native/cuda_util.cpp +677 -0
  219. warp/native/cuda_util.h +313 -0
  220. warp/native/error.cpp +77 -0
  221. warp/native/error.h +36 -0
  222. warp/native/exports.h +2023 -0
  223. warp/native/fabric.h +246 -0
  224. warp/native/hashgrid.cpp +311 -0
  225. warp/native/hashgrid.cu +89 -0
  226. warp/native/hashgrid.h +240 -0
  227. warp/native/initializer_array.h +41 -0
  228. warp/native/intersect.h +1253 -0
  229. warp/native/intersect_adj.h +375 -0
  230. warp/native/intersect_tri.h +348 -0
  231. warp/native/mat.h +5189 -0
  232. warp/native/mathdx.cpp +93 -0
  233. warp/native/matnn.h +221 -0
  234. warp/native/mesh.cpp +266 -0
  235. warp/native/mesh.cu +406 -0
  236. warp/native/mesh.h +2097 -0
  237. warp/native/nanovdb/GridHandle.h +533 -0
  238. warp/native/nanovdb/HostBuffer.h +591 -0
  239. warp/native/nanovdb/NanoVDB.h +6246 -0
  240. warp/native/nanovdb/NodeManager.h +323 -0
  241. warp/native/nanovdb/PNanoVDB.h +3390 -0
  242. warp/native/noise.h +859 -0
  243. warp/native/quat.h +1664 -0
  244. warp/native/rand.h +342 -0
  245. warp/native/range.h +145 -0
  246. warp/native/reduce.cpp +174 -0
  247. warp/native/reduce.cu +363 -0
  248. warp/native/runlength_encode.cpp +79 -0
  249. warp/native/runlength_encode.cu +61 -0
  250. warp/native/scan.cpp +47 -0
  251. warp/native/scan.cu +55 -0
  252. warp/native/scan.h +23 -0
  253. warp/native/solid_angle.h +466 -0
  254. warp/native/sort.cpp +251 -0
  255. warp/native/sort.cu +286 -0
  256. warp/native/sort.h +35 -0
  257. warp/native/sparse.cpp +241 -0
  258. warp/native/sparse.cu +435 -0
  259. warp/native/spatial.h +1306 -0
  260. warp/native/svd.h +727 -0
  261. warp/native/temp_buffer.h +46 -0
  262. warp/native/tile.h +4124 -0
  263. warp/native/tile_radix_sort.h +1112 -0
  264. warp/native/tile_reduce.h +838 -0
  265. warp/native/tile_scan.h +240 -0
  266. warp/native/tuple.h +189 -0
  267. warp/native/vec.h +2199 -0
  268. warp/native/version.h +23 -0
  269. warp/native/volume.cpp +501 -0
  270. warp/native/volume.cu +68 -0
  271. warp/native/volume.h +970 -0
  272. warp/native/volume_builder.cu +483 -0
  273. warp/native/volume_builder.h +52 -0
  274. warp/native/volume_impl.h +70 -0
  275. warp/native/warp.cpp +1143 -0
  276. warp/native/warp.cu +4604 -0
  277. warp/native/warp.h +358 -0
  278. warp/optim/__init__.py +20 -0
  279. warp/optim/adam.py +24 -0
  280. warp/optim/linear.py +35 -0
  281. warp/optim/sgd.py +24 -0
  282. warp/paddle.py +24 -0
  283. warp/py.typed +0 -0
  284. warp/render/__init__.py +22 -0
  285. warp/render/imgui_manager.py +29 -0
  286. warp/render/render_opengl.py +24 -0
  287. warp/render/render_usd.py +24 -0
  288. warp/render/utils.py +24 -0
  289. warp/sparse.py +51 -0
  290. warp/tape.py +24 -0
  291. warp/tests/__init__.py +1 -0
  292. warp/tests/__main__.py +4 -0
  293. warp/tests/assets/curlnoise_golden.npy +0 -0
  294. warp/tests/assets/mlp_golden.npy +0 -0
  295. warp/tests/assets/pixel.npy +0 -0
  296. warp/tests/assets/pnoise_golden.npy +0 -0
  297. warp/tests/assets/spiky.usd +0 -0
  298. warp/tests/assets/test_grid.nvdb +0 -0
  299. warp/tests/assets/test_index_grid.nvdb +0 -0
  300. warp/tests/assets/test_int32_grid.nvdb +0 -0
  301. warp/tests/assets/test_vec_grid.nvdb +0 -0
  302. warp/tests/assets/torus.nvdb +0 -0
  303. warp/tests/assets/torus.usda +105 -0
  304. warp/tests/aux_test_class_kernel.py +34 -0
  305. warp/tests/aux_test_compile_consts_dummy.py +18 -0
  306. warp/tests/aux_test_conditional_unequal_types_kernels.py +29 -0
  307. warp/tests/aux_test_dependent.py +29 -0
  308. warp/tests/aux_test_grad_customs.py +29 -0
  309. warp/tests/aux_test_instancing_gc.py +26 -0
  310. warp/tests/aux_test_module_aot.py +7 -0
  311. warp/tests/aux_test_module_unload.py +23 -0
  312. warp/tests/aux_test_name_clash1.py +40 -0
  313. warp/tests/aux_test_name_clash2.py +40 -0
  314. warp/tests/aux_test_reference.py +9 -0
  315. warp/tests/aux_test_reference_reference.py +8 -0
  316. warp/tests/aux_test_square.py +16 -0
  317. warp/tests/aux_test_unresolved_func.py +22 -0
  318. warp/tests/aux_test_unresolved_symbol.py +22 -0
  319. warp/tests/cuda/__init__.py +0 -0
  320. warp/tests/cuda/test_async.py +676 -0
  321. warp/tests/cuda/test_conditional_captures.py +1147 -0
  322. warp/tests/cuda/test_ipc.py +124 -0
  323. warp/tests/cuda/test_mempool.py +233 -0
  324. warp/tests/cuda/test_multigpu.py +169 -0
  325. warp/tests/cuda/test_peer.py +139 -0
  326. warp/tests/cuda/test_pinned.py +84 -0
  327. warp/tests/cuda/test_streams.py +691 -0
  328. warp/tests/geometry/__init__.py +0 -0
  329. warp/tests/geometry/test_bvh.py +335 -0
  330. warp/tests/geometry/test_hash_grid.py +259 -0
  331. warp/tests/geometry/test_marching_cubes.py +294 -0
  332. warp/tests/geometry/test_mesh.py +318 -0
  333. warp/tests/geometry/test_mesh_query_aabb.py +392 -0
  334. warp/tests/geometry/test_mesh_query_point.py +935 -0
  335. warp/tests/geometry/test_mesh_query_ray.py +323 -0
  336. warp/tests/geometry/test_volume.py +1103 -0
  337. warp/tests/geometry/test_volume_write.py +346 -0
  338. warp/tests/interop/__init__.py +0 -0
  339. warp/tests/interop/test_dlpack.py +730 -0
  340. warp/tests/interop/test_jax.py +1673 -0
  341. warp/tests/interop/test_paddle.py +800 -0
  342. warp/tests/interop/test_torch.py +1001 -0
  343. warp/tests/run_coverage_serial.py +39 -0
  344. warp/tests/test_adam.py +162 -0
  345. warp/tests/test_arithmetic.py +1096 -0
  346. warp/tests/test_array.py +3756 -0
  347. warp/tests/test_array_reduce.py +156 -0
  348. warp/tests/test_assert.py +303 -0
  349. warp/tests/test_atomic.py +336 -0
  350. warp/tests/test_atomic_bitwise.py +209 -0
  351. warp/tests/test_atomic_cas.py +312 -0
  352. warp/tests/test_bool.py +220 -0
  353. warp/tests/test_builtins_resolution.py +732 -0
  354. warp/tests/test_closest_point_edge_edge.py +327 -0
  355. warp/tests/test_codegen.py +974 -0
  356. warp/tests/test_codegen_instancing.py +1495 -0
  357. warp/tests/test_compile_consts.py +215 -0
  358. warp/tests/test_conditional.py +298 -0
  359. warp/tests/test_context.py +35 -0
  360. warp/tests/test_copy.py +319 -0
  361. warp/tests/test_ctypes.py +618 -0
  362. warp/tests/test_dense.py +73 -0
  363. warp/tests/test_devices.py +127 -0
  364. warp/tests/test_enum.py +136 -0
  365. warp/tests/test_examples.py +424 -0
  366. warp/tests/test_fabricarray.py +998 -0
  367. warp/tests/test_fast_math.py +72 -0
  368. warp/tests/test_fem.py +2204 -0
  369. warp/tests/test_fixedarray.py +229 -0
  370. warp/tests/test_fp16.py +136 -0
  371. warp/tests/test_func.py +501 -0
  372. warp/tests/test_future_annotations.py +100 -0
  373. warp/tests/test_generics.py +656 -0
  374. warp/tests/test_grad.py +893 -0
  375. warp/tests/test_grad_customs.py +339 -0
  376. warp/tests/test_grad_debug.py +341 -0
  377. warp/tests/test_implicit_init.py +411 -0
  378. warp/tests/test_import.py +45 -0
  379. warp/tests/test_indexedarray.py +1140 -0
  380. warp/tests/test_intersect.py +103 -0
  381. warp/tests/test_iter.py +76 -0
  382. warp/tests/test_large.py +177 -0
  383. warp/tests/test_launch.py +411 -0
  384. warp/tests/test_lerp.py +151 -0
  385. warp/tests/test_linear_solvers.py +223 -0
  386. warp/tests/test_lvalue.py +427 -0
  387. warp/tests/test_map.py +526 -0
  388. warp/tests/test_mat.py +3515 -0
  389. warp/tests/test_mat_assign_copy.py +178 -0
  390. warp/tests/test_mat_constructors.py +573 -0
  391. warp/tests/test_mat_lite.py +122 -0
  392. warp/tests/test_mat_scalar_ops.py +2913 -0
  393. warp/tests/test_math.py +212 -0
  394. warp/tests/test_module_aot.py +287 -0
  395. warp/tests/test_module_hashing.py +258 -0
  396. warp/tests/test_modules_lite.py +70 -0
  397. warp/tests/test_noise.py +252 -0
  398. warp/tests/test_operators.py +299 -0
  399. warp/tests/test_options.py +129 -0
  400. warp/tests/test_overwrite.py +551 -0
  401. warp/tests/test_print.py +408 -0
  402. warp/tests/test_quat.py +2653 -0
  403. warp/tests/test_quat_assign_copy.py +145 -0
  404. warp/tests/test_rand.py +339 -0
  405. warp/tests/test_reload.py +303 -0
  406. warp/tests/test_rounding.py +157 -0
  407. warp/tests/test_runlength_encode.py +196 -0
  408. warp/tests/test_scalar_ops.py +133 -0
  409. warp/tests/test_smoothstep.py +108 -0
  410. warp/tests/test_snippet.py +318 -0
  411. warp/tests/test_sparse.py +845 -0
  412. warp/tests/test_spatial.py +2859 -0
  413. warp/tests/test_spatial_assign_copy.py +160 -0
  414. warp/tests/test_special_values.py +361 -0
  415. warp/tests/test_static.py +640 -0
  416. warp/tests/test_struct.py +901 -0
  417. warp/tests/test_tape.py +242 -0
  418. warp/tests/test_transient_module.py +93 -0
  419. warp/tests/test_triangle_closest_point.py +192 -0
  420. warp/tests/test_tuple.py +361 -0
  421. warp/tests/test_types.py +615 -0
  422. warp/tests/test_utils.py +594 -0
  423. warp/tests/test_vec.py +1408 -0
  424. warp/tests/test_vec_assign_copy.py +143 -0
  425. warp/tests/test_vec_constructors.py +325 -0
  426. warp/tests/test_vec_lite.py +80 -0
  427. warp/tests/test_vec_scalar_ops.py +2327 -0
  428. warp/tests/test_verify_fp.py +100 -0
  429. warp/tests/test_version.py +75 -0
  430. warp/tests/tile/__init__.py +0 -0
  431. warp/tests/tile/test_tile.py +1519 -0
  432. warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
  433. warp/tests/tile/test_tile_cholesky.py +608 -0
  434. warp/tests/tile/test_tile_load.py +724 -0
  435. warp/tests/tile/test_tile_mathdx.py +156 -0
  436. warp/tests/tile/test_tile_matmul.py +179 -0
  437. warp/tests/tile/test_tile_mlp.py +400 -0
  438. warp/tests/tile/test_tile_reduce.py +950 -0
  439. warp/tests/tile/test_tile_shared_memory.py +376 -0
  440. warp/tests/tile/test_tile_sort.py +121 -0
  441. warp/tests/tile/test_tile_view.py +173 -0
  442. warp/tests/unittest_serial.py +47 -0
  443. warp/tests/unittest_suites.py +430 -0
  444. warp/tests/unittest_utils.py +469 -0
  445. warp/tests/walkthrough_debug.py +95 -0
  446. warp/torch.py +24 -0
  447. warp/types.py +51 -0
  448. warp/utils.py +31 -0
  449. warp_lang-1.10.0.dist-info/METADATA +459 -0
  450. warp_lang-1.10.0.dist-info/RECORD +468 -0
  451. warp_lang-1.10.0.dist-info/WHEEL +5 -0
  452. warp_lang-1.10.0.dist-info/licenses/LICENSE.md +176 -0
  453. warp_lang-1.10.0.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
  454. warp_lang-1.10.0.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
  455. warp_lang-1.10.0.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
  456. warp_lang-1.10.0.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
  457. warp_lang-1.10.0.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
  458. warp_lang-1.10.0.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
  459. warp_lang-1.10.0.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
  460. warp_lang-1.10.0.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
  461. warp_lang-1.10.0.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
  462. warp_lang-1.10.0.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
  463. warp_lang-1.10.0.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
  464. warp_lang-1.10.0.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
  465. warp_lang-1.10.0.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
  466. warp_lang-1.10.0.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
  467. warp_lang-1.10.0.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
  468. warp_lang-1.10.0.dist-info/top_level.txt +1 -0
warp/native/mesh.h ADDED
@@ -0,0 +1,2097 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include "builtin.h"
21
+ #include "bvh.h"
22
+ #include "intersect.h"
23
+ #include "array.h"
24
+ #include "solid_angle.h"
25
+
26
+ #define BVH_DEBUG 0
27
+
28
+ namespace wp
29
+ {
30
+
31
+ struct Mesh
32
+ {
33
+ array_t<vec3> points;
34
+ array_t<vec3> velocities;
35
+
36
+ array_t<int> indices;
37
+
38
+ vec3* lowers;
39
+ vec3* uppers;
40
+
41
+ SolidAngleProps* solid_angle_props;
42
+
43
+ int num_points;
44
+ int num_tris;
45
+
46
+ BVH bvh;
47
+
48
+ void* context;
49
+ float average_edge_length;
50
+
51
+ inline CUDA_CALLABLE Mesh(int id = 0)
52
+ {
53
+ // for backward a = 0 initialization syntax
54
+ lowers = nullptr;
55
+ uppers = nullptr;
56
+ num_points = 0;
57
+ num_tris = 0;
58
+ context = nullptr;
59
+ solid_angle_props = nullptr;
60
+ average_edge_length = 0.0f;
61
+ bvh = BVH{};
62
+ }
63
+
64
+ inline CUDA_CALLABLE Mesh(
65
+ array_t<vec3> points,
66
+ array_t<vec3> velocities,
67
+ array_t<int> indices,
68
+ int num_points,
69
+ int num_tris,
70
+ void* context = nullptr
71
+ ) : points(points), velocities(velocities), indices(indices), num_points(num_points), num_tris(num_tris), context(context)
72
+ {
73
+ lowers = nullptr;
74
+ uppers = nullptr;
75
+ solid_angle_props = nullptr;
76
+ average_edge_length = 0.0f;
77
+ bvh = BVH{};
78
+ }
79
+ };
80
+
81
+ CUDA_CALLABLE inline Mesh mesh_get(uint64_t id)
82
+ {
83
+ return *(Mesh*)(id);
84
+ }
85
+
86
+
87
+ CUDA_CALLABLE inline Mesh& operator += (Mesh& a, const Mesh& b) {
88
+ // dummy operator needed for adj_select involving meshes
89
+ return a;
90
+ }
91
+
92
+ CUDA_CALLABLE inline float distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
93
+ {
94
+ const float dx = min(upper[0], max(lower[0], p[0])) - p[0];
95
+ const float dy = min(upper[1], max(lower[1], p[1])) - p[1];
96
+ const float dz = min(upper[2], max(lower[2], p[2])) - p[2];
97
+ return dx * dx + dy * dy + dz * dz;
98
+ }
99
+
100
+ CUDA_CALLABLE inline float furthest_distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
101
+ {
102
+ // X-axis
103
+ float dist_lower_x = fabs(p[0] - lower[0]);
104
+ float dist_upper_x = fabs(p[0] - upper[0]);
105
+ float corner_diff_x = (dist_lower_x > dist_upper_x) ? dist_lower_x : dist_upper_x;
106
+
107
+ // Y-axis
108
+ float dist_lower_y = fabs(p[1] - lower[1]);
109
+ float dist_upper_y = fabs(p[1] - upper[1]);
110
+ float corner_diff_y = (dist_lower_y > dist_upper_y) ? dist_lower_y : dist_upper_y;
111
+
112
+ // Z-axis
113
+ float dist_lower_z = fabs(p[2] - lower[2]);
114
+ float dist_upper_z = fabs(p[2] - upper[2]);
115
+ float corner_diff_z = (dist_lower_z > dist_upper_z) ? dist_lower_z : dist_upper_z;
116
+
117
+ // Calculate and return the distance
118
+ return corner_diff_x* corner_diff_x + corner_diff_y * corner_diff_y + corner_diff_z * corner_diff_z;
119
+ }
120
+
121
+ CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p);
122
+
123
+ // returns true if there is a point (strictly) < distance max_dist
124
+ CUDA_CALLABLE inline bool mesh_query_point(uint64_t id, const vec3& point, float max_dist, float& inside, int& face, float& u, float& v)
125
+ {
126
+ Mesh mesh = mesh_get(id);
127
+
128
+ int stack[BVH_QUERY_STACK_SIZE];
129
+ stack[0] = *mesh.bvh.root;
130
+
131
+ int count = 1;
132
+
133
+ float min_dist_sq = max_dist*max_dist;
134
+ int min_face;
135
+ float min_v;
136
+ float min_w;
137
+
138
+ #if BVH_DEBUG
139
+ int tests = 0;
140
+ int secondary_culls = 0;
141
+
142
+ std::vector<int> test_history;
143
+ std::vector<vec3> test_centers;
144
+ std::vector<vec3> test_extents;
145
+ #endif
146
+
147
+ while (count)
148
+ {
149
+ const int nodeIndex = stack[--count];
150
+
151
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
152
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
153
+
154
+ // re-test distance
155
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
156
+ if (node_dist_sq > min_dist_sq)
157
+ {
158
+ #if BVH_DEBUG
159
+ secondary_culls++;
160
+ #endif
161
+ continue;
162
+ }
163
+
164
+ const int left_index = lower.i;
165
+ const int right_index = upper.i;
166
+
167
+ if (lower.b)
168
+ {
169
+ const int start = left_index;
170
+ const int end = right_index;
171
+ // loops through primitives in the leaf
172
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
173
+ {
174
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
175
+ int i = mesh.indices[primitive_index * 3 + 0];
176
+ int j = mesh.indices[primitive_index * 3 + 1];
177
+ int k = mesh.indices[primitive_index * 3 + 2];
178
+
179
+ vec3 p = mesh.points[i];
180
+ vec3 q = mesh.points[j];
181
+ vec3 r = mesh.points[k];
182
+
183
+ vec3 e0 = q - p;
184
+ vec3 e1 = r - p;
185
+ vec3 e2 = r - q;
186
+ vec3 normal = cross(e0, e1);
187
+
188
+ // sliver detection
189
+ if (length(normal) / (dot(e0, e0) + dot(e1, e1) + dot(e2, e2)) < 1.e-6f)
190
+ continue;
191
+
192
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
193
+ float u = barycentric[0];
194
+ float v = barycentric[1];
195
+ float w = 1.f - u - v;
196
+ vec3 c = u * p + v * q + w * r;
197
+
198
+ float dist_sq = length_sq(c - point);
199
+
200
+ if (dist_sq < min_dist_sq)
201
+ {
202
+ min_dist_sq = dist_sq;
203
+ min_v = v;
204
+ min_w = w;
205
+ min_face = primitive_index;
206
+ }
207
+ }
208
+
209
+ #if BVH_DEBUG
210
+
211
+ tests++;
212
+
213
+ bounds3 b;
214
+ b = bounds_union(b, p);
215
+ b = bounds_union(b, q);
216
+ b = bounds_union(b, r);
217
+
218
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
219
+ {
220
+ //if (dist_sq < max_dist*max_dist)
221
+ test_history.push_back(left_index);
222
+ test_centers.push_back(b.center());
223
+ test_extents.push_back(b.edges());
224
+ }
225
+ #endif
226
+
227
+ }
228
+ else
229
+ {
230
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
231
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
232
+
233
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
234
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
235
+
236
+ float left_dist_sq = distance_to_aabb_sq(point, vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z));
237
+ float right_dist_sq = distance_to_aabb_sq(point, vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z));
238
+
239
+ wp::vec2i child_indices;
240
+ wp::vec2 child_dist;
241
+ if (left_dist_sq < right_dist_sq)
242
+ {
243
+ child_indices = wp::vec2i(right_index, left_index);
244
+ child_dist = wp::vec2(right_dist_sq, left_dist_sq);
245
+ }
246
+ else
247
+ {
248
+ child_indices = wp::vec2i(left_index, right_index);
249
+ child_dist = wp::vec2(left_dist_sq, right_dist_sq);
250
+ }
251
+
252
+ if (child_dist[0] < min_dist_sq)
253
+ stack[count++] = child_indices[0];
254
+
255
+ if (child_dist[1] < min_dist_sq)
256
+ stack[count++] = child_indices[1];
257
+ }
258
+ }
259
+
260
+
261
+ #if BVH_DEBUG
262
+ printf("%d\n", tests);
263
+
264
+ static int max_tests = 0;
265
+ static vec3 max_point;
266
+ static float max_point_dist = 0.0f;
267
+ static int max_secondary_culls = 0;
268
+
269
+ if (secondary_culls > max_secondary_culls)
270
+ max_secondary_culls = secondary_culls;
271
+
272
+ if (tests > max_tests)
273
+ {
274
+ max_tests = tests;
275
+ max_point = point;
276
+ max_point_dist = sqrtf(min_dist_sq);
277
+
278
+ printf("max_tests: %d max_point: %f %f %f max_point_dist: %f max_second_culls: %d\n", max_tests, max_point[0], max_point[1], max_point[2], max_point_dist, max_secondary_culls);
279
+
280
+ FILE* f = fopen("test_history.txt", "w");
281
+ for (int i=0; i < test_history.size(); ++i)
282
+ {
283
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
284
+ test_history[i],
285
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
286
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
287
+ }
288
+
289
+ fclose(f);
290
+ }
291
+ #endif
292
+
293
+ // check if we found a point, and write outputs
294
+ if (min_dist_sq < max_dist*max_dist)
295
+ {
296
+ u = 1.0f - min_v - min_w;
297
+ v = min_v;
298
+ face = min_face;
299
+
300
+ // determine inside outside using ray-cast parity check
301
+ inside = mesh_query_inside(id, point);
302
+
303
+ return true;
304
+ }
305
+ else
306
+ {
307
+ return false;
308
+ }
309
+ }
310
+
311
+ // returns true if there is a point (strictly) < distance max_dist
312
+ CUDA_CALLABLE inline bool mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist, int& face, float& u, float& v)
313
+ {
314
+ Mesh mesh = mesh_get(id);
315
+
316
+ int stack[BVH_QUERY_STACK_SIZE];
317
+ stack[0] = *mesh.bvh.root;
318
+
319
+ int count = 1;
320
+
321
+ float min_dist_sq = max_dist*max_dist;
322
+ int min_face;
323
+ float min_v;
324
+ float min_w;
325
+
326
+ #if BVH_DEBUG
327
+ int tests = 0;
328
+ int secondary_culls = 0;
329
+
330
+ std::vector<int> test_history;
331
+ std::vector<vec3> test_centers;
332
+ std::vector<vec3> test_extents;
333
+ #endif
334
+
335
+ while (count)
336
+ {
337
+ const int nodeIndex = stack[--count];
338
+
339
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
340
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
341
+
342
+ // re-test distance
343
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
344
+ if (node_dist_sq > min_dist_sq)
345
+ {
346
+ #if BVH_DEBUG
347
+ secondary_culls++;
348
+ #endif
349
+ continue;
350
+ }
351
+
352
+ const int left_index = lower.i;
353
+ const int right_index = upper.i;
354
+
355
+ if (lower.b)
356
+ {
357
+ const int start = left_index;
358
+ const int end = right_index;
359
+ // loops through primitives in the leaf
360
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
361
+ {
362
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
363
+ int i = mesh.indices[primitive_index * 3 + 0];
364
+ int j = mesh.indices[primitive_index * 3 + 1];
365
+ int k = mesh.indices[primitive_index * 3 + 2];
366
+
367
+ vec3 p = mesh.points[i];
368
+ vec3 q = mesh.points[j];
369
+ vec3 r = mesh.points[k];
370
+ vec3 e0 = q - p;
371
+ vec3 e1 = r - p;
372
+ vec3 e2 = r - q;
373
+ vec3 normal = cross(e0, e1);
374
+
375
+ // sliver detection
376
+ if (length(normal) / (dot(e0, e0) + dot(e1, e1) + dot(e2, e2)) < 1.e-6f)
377
+ continue;
378
+
379
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
380
+ float u = barycentric[0];
381
+ float v = barycentric[1];
382
+ float w = 1.f - u - v;
383
+ vec3 c = u * p + v * q + w * r;
384
+
385
+ float dist_sq = length_sq(c - point);
386
+
387
+ if (dist_sq < min_dist_sq)
388
+ {
389
+ min_dist_sq = dist_sq;
390
+ min_v = v;
391
+ min_w = w;
392
+ min_face = primitive_index;
393
+ }
394
+ }
395
+
396
+ #if BVH_DEBUG
397
+
398
+ tests++;
399
+
400
+ bounds3 b;
401
+ b = bounds_union(b, p);
402
+ b = bounds_union(b, q);
403
+ b = bounds_union(b, r);
404
+
405
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
406
+ {
407
+ //if (dist_sq < max_dist*max_dist)
408
+ test_history.push_back(left_index);
409
+ test_centers.push_back(b.center());
410
+ test_extents.push_back(b.edges());
411
+ }
412
+ #endif
413
+
414
+ }
415
+ else
416
+ {
417
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
418
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
419
+
420
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
421
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
422
+
423
+ float left_dist_sq = distance_to_aabb_sq(point, vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z));
424
+ float right_dist_sq = distance_to_aabb_sq(point, vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z));
425
+
426
+ wp::vec2i child_indices;
427
+ wp::vec2 child_dist;
428
+ if (left_dist_sq < right_dist_sq)
429
+ {
430
+ child_indices = wp::vec2i(right_index, left_index);
431
+ child_dist = wp::vec2(right_dist_sq, left_dist_sq);
432
+ }
433
+ else
434
+ {
435
+ child_indices = wp::vec2i(left_index, right_index);
436
+ child_dist = wp::vec2(left_dist_sq, right_dist_sq);
437
+ }
438
+
439
+ if (child_dist[0] < min_dist_sq)
440
+ stack[count++] = child_indices[0];
441
+
442
+ if (child_dist[1] < min_dist_sq)
443
+ stack[count++] = child_indices[1];
444
+ }
445
+ }
446
+
447
+
448
+ #if BVH_DEBUG
449
+ printf("%d\n", tests);
450
+
451
+ static int max_tests = 0;
452
+ static vec3 max_point;
453
+ static float max_point_dist = 0.0f;
454
+ static int max_secondary_culls = 0;
455
+
456
+ if (secondary_culls > max_secondary_culls)
457
+ max_secondary_culls = secondary_culls;
458
+
459
+ if (tests > max_tests)
460
+ {
461
+ max_tests = tests;
462
+ max_point = point;
463
+ max_point_dist = sqrtf(min_dist_sq);
464
+
465
+ printf("max_tests: %d max_point: %f %f %f max_point_dist: %f max_second_culls: %d\n", max_tests, max_point[0], max_point[1], max_point[2], max_point_dist, max_secondary_culls);
466
+
467
+ FILE* f = fopen("test_history.txt", "w");
468
+ for (int i=0; i < test_history.size(); ++i)
469
+ {
470
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
471
+ test_history[i],
472
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
473
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
474
+ }
475
+
476
+ fclose(f);
477
+ }
478
+ #endif
479
+
480
+ // check if we found a point, and write outputs
481
+ if (min_dist_sq < max_dist*max_dist)
482
+ {
483
+ u = 1.0f - min_v - min_w;
484
+ v = min_v;
485
+ face = min_face;
486
+
487
+ return true;
488
+ }
489
+ else
490
+ {
491
+ return false;
492
+ }
493
+ }
494
+
495
+ // returns true if there is a point (strictly) > distance min_dist
496
+ CUDA_CALLABLE inline bool mesh_query_furthest_point_no_sign(uint64_t id, const vec3& point, float min_dist, int& face, float& u, float& v)
497
+ {
498
+ Mesh mesh = mesh_get(id);
499
+
500
+ int stack[BVH_QUERY_STACK_SIZE];
501
+ stack[0] = *mesh.bvh.root;
502
+
503
+ int count = 1;
504
+
505
+ float min_dist_sq = min_dist*min_dist;
506
+ int max_face;
507
+ float max_v;
508
+ float max_w;
509
+
510
+ #if BVH_DEBUG
511
+ int tests = 0;
512
+ int secondary_culls = 0;
513
+
514
+ std::vector<int> test_history;
515
+ std::vector<vec3> test_centers;
516
+ std::vector<vec3> test_extents;
517
+ #endif
518
+
519
+ while (count)
520
+ {
521
+ const int nodeIndex = stack[--count];
522
+
523
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
524
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
525
+
526
+ // re-test distance
527
+ float node_dist_sq = furthest_distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
528
+
529
+ // if maximum distance to this node is less than our existing furthest max then skip
530
+ if (node_dist_sq < min_dist_sq)
531
+ {
532
+ #if BVH_DEBUG
533
+ secondary_culls++;
534
+ #endif
535
+ continue;
536
+ }
537
+
538
+ const int left_index = lower.i;
539
+ const int right_index = upper.i;
540
+
541
+ if (lower.b)
542
+ {
543
+ const int start = left_index;
544
+ const int end = right_index;
545
+ // loops through primitives in the leaf
546
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
547
+ {
548
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
549
+ int i = mesh.indices[primitive_index * 3 + 0];
550
+ int j = mesh.indices[primitive_index * 3 + 1];
551
+ int k = mesh.indices[primitive_index * 3 + 2];
552
+
553
+ vec3 p = mesh.points[i];
554
+ vec3 q = mesh.points[j];
555
+ vec3 r = mesh.points[k];
556
+
557
+ vec3 e0 = q-p;
558
+ vec3 e1 = r-p;
559
+ vec3 e2 = r-q;
560
+ vec3 normal = cross(e0, e1);
561
+
562
+ // sliver detection
563
+ if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
564
+ continue;
565
+
566
+ vec2 barycentric = furthest_point_to_triangle(p, q, r, point);
567
+ float u = barycentric[0];
568
+ float v = barycentric[1];
569
+ float w = 1.f - u - v;
570
+ vec3 c = u*p + v*q + w*r;
571
+
572
+ float dist_sq = length_sq(c-point);
573
+
574
+ if (dist_sq > min_dist_sq)
575
+ {
576
+ min_dist_sq = dist_sq;
577
+ max_v = v;
578
+ max_w = w;
579
+ max_face = primitive_index;
580
+ }
581
+ }
582
+
583
+ #if BVH_DEBUG
584
+
585
+ tests++;
586
+
587
+ bounds3 b;
588
+ b = bounds_union(b, p);
589
+ b = bounds_union(b, q);
590
+ b = bounds_union(b, r);
591
+
592
+ if (distance_to_aabb_sq(point, b.lower, b.upper) > max_dist*max_dist)
593
+ {
594
+ //if (dist_sq < max_dist*max_dist)
595
+ test_history.push_back(left_index);
596
+ test_centers.push_back(b.center());
597
+ test_extents.push_back(b.edges());
598
+ }
599
+ #endif
600
+
601
+ }
602
+ else
603
+ {
604
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
605
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
606
+
607
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
608
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
609
+
610
+ float left_dist_sq = furthest_distance_to_aabb_sq(point, vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z));
611
+ float right_dist_sq = furthest_distance_to_aabb_sq(point, vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z));
612
+
613
+ wp::vec2i child_indices;
614
+ wp::vec2 child_dist;
615
+ if (left_dist_sq > right_dist_sq)
616
+ {
617
+ child_indices = wp::vec2i(right_index, left_index);
618
+ child_dist = wp::vec2(right_dist_sq, left_dist_sq);
619
+ }
620
+ else
621
+ {
622
+ child_indices = wp::vec2i(left_index, right_index);
623
+ child_dist = wp::vec2(left_dist_sq, right_dist_sq);
624
+ }
625
+
626
+ if (child_dist[0] > min_dist_sq)
627
+ stack[count++] = child_indices[0];
628
+
629
+ if (child_dist[1] > min_dist_sq)
630
+ stack[count++] = child_indices[1];
631
+ }
632
+ }
633
+
634
+
635
+ #if BVH_DEBUG
636
+ printf("%d\n", tests);
637
+
638
+ static int max_tests = 0;
639
+ static vec3 max_point;
640
+ static float max_point_dist = 0.0f;
641
+ static int max_secondary_culls = 0;
642
+
643
+ if (secondary_culls > max_secondary_culls)
644
+ max_secondary_culls = secondary_culls;
645
+
646
+ if (tests > max_tests)
647
+ {
648
+ max_tests = tests;
649
+ max_point = point;
650
+ max_point_dist = sqrtf(min_dist_sq);
651
+
652
+ printf("max_tests: %d max_point: %f %f %f max_point_dist: %f max_second_culls: %d\n", max_tests, max_point[0], max_point[1], max_point[2], max_point_dist, max_secondary_culls);
653
+
654
+ FILE* f = fopen("test_history.txt", "w");
655
+ for (int i=0; i < test_history.size(); ++i)
656
+ {
657
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
658
+ test_history[i],
659
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
660
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
661
+ }
662
+
663
+ fclose(f);
664
+ }
665
+ #endif
666
+
667
+ // check if we found a point, and write outputs
668
+ if (min_dist_sq > min_dist*min_dist)
669
+ {
670
+ u = 1.0f - max_v - max_w;
671
+ v = max_v;
672
+ face = max_face;
673
+
674
+ return true;
675
+ }
676
+ else
677
+ {
678
+ return false;
679
+ }
680
+ }
681
+
682
+ // returns true if there is a point (strictly) < distance max_dist
683
+ CUDA_CALLABLE inline bool mesh_query_point_sign_normal(uint64_t id, const vec3& point, float max_dist, float& inside, int& face, float& u, float& v, const float epsilon = 1e-3f)
684
+ {
685
+ Mesh mesh = mesh_get(id);
686
+
687
+ int stack[BVH_QUERY_STACK_SIZE];
688
+ stack[0] = *mesh.bvh.root;
689
+ int count = 1;
690
+ float min_dist = max_dist;
691
+ int min_face;
692
+ float min_v;
693
+ float min_w;
694
+ vec3 accumulated_angle_weighted_normal;
695
+
696
+ #if BVH_DEBUG
697
+ int tests = 0;
698
+ int secondary_culls = 0;
699
+ std::vector<int> test_history;
700
+ std::vector<vec3> test_centers;
701
+ std::vector<vec3> test_extents;
702
+ #endif
703
+ float epsilon_min_dist = mesh.average_edge_length * epsilon;
704
+ float epsilon_min_dist_sq = epsilon_min_dist*epsilon_min_dist;
705
+
706
+ while (count)
707
+ {
708
+ const int nodeIndex = stack[--count];
709
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
710
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
711
+
712
+ // re-test distance
713
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
714
+ if (node_dist_sq > (min_dist + epsilon_min_dist)*(min_dist + epsilon_min_dist))
715
+ {
716
+ #if BVH_DEBUG
717
+ secondary_culls++;
718
+ #endif
719
+ continue;
720
+ }
721
+
722
+ const int left_index = lower.i;
723
+ const int right_index = upper.i;
724
+
725
+ if (lower.b)
726
+ {
727
+ const int start = left_index;
728
+ const int end = right_index;
729
+ // loops through primitives in the leaf
730
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
731
+ {
732
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
733
+ int i = mesh.indices[primitive_index * 3 + 0];
734
+ int j = mesh.indices[primitive_index * 3 + 1];
735
+ int k = mesh.indices[primitive_index * 3 + 2];
736
+
737
+ vec3 p = mesh.points[i];
738
+ vec3 q = mesh.points[j];
739
+ vec3 r = mesh.points[k];
740
+
741
+ vec3 e0 = q-p;
742
+ vec3 e1 = r-p;
743
+ vec3 e2 = r-q;
744
+ vec3 normal = cross(e0, e1);
745
+
746
+ // sliver detection
747
+ float e0_norm_sq = dot(e0,e0);
748
+ float e1_norm_sq = dot(e1,e1);
749
+ float e2_norm_sq = dot(e2,e2);
750
+ if (length(normal)/(e0_norm_sq + e1_norm_sq + e2_norm_sq) < 1.e-6f)
751
+ continue;
752
+
753
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
754
+ float u = barycentric[0];
755
+ float v = barycentric[1];
756
+ float w = 1.f - u - v;
757
+ vec3 c = u*p + v*q + w*r;
758
+ float dist = sqrtf(length_sq(c-point));
759
+ if (dist < min_dist + epsilon_min_dist)
760
+ {
761
+ float weight = 0.0f;
762
+ vec3 cp = c - p;
763
+ vec3 cq = c - q;
764
+ vec3 cr = c - r;
765
+ float len_cp_sq = length_sq(cp);
766
+ float len_cq_sq = length_sq(cq);
767
+ float len_cr_sq = length_sq(cr);
768
+
769
+ // Check if near vertex
770
+ if (len_cp_sq < epsilon_min_dist_sq)
771
+ {
772
+ // Vertex 0 is the closest feature
773
+ weight = acosf(dot(normalize(e0), normalize(e1)));
774
+ }
775
+ else
776
+ if (len_cq_sq < epsilon_min_dist_sq)
777
+ {
778
+ // Vertex 1 is the closest feature
779
+ weight = acosf(dot(normalize(e2), normalize(-e0)));
780
+ }
781
+ else
782
+ if (len_cr_sq < epsilon_min_dist_sq)
783
+ {
784
+ // Vertex 2 is the closest feature
785
+ weight = acosf(dot(normalize(-e1), normalize(-e2)));
786
+ }
787
+ else
788
+ {
789
+ float e0cp = dot(e0, cp);
790
+ float e2cq = dot(e2, cq);
791
+ float e1cp = dot(e1, cp);
792
+
793
+ if ((len_cp_sq * e0_norm_sq - e0cp * e0cp < epsilon_min_dist_sq * e0_norm_sq) ||
794
+ (len_cq_sq * e2_norm_sq - e2cq * e2cq < epsilon_min_dist_sq * e2_norm_sq) ||
795
+ (len_cp_sq * e1_norm_sq - e1cp * e1cp < epsilon_min_dist_sq * e1_norm_sq)) {
796
+ // One of the edge
797
+ weight = 3.14159265359f; // PI
798
+ }
799
+ else {
800
+ weight = 2.0f * 3.14159265359f; // 2*PI
801
+ }
802
+ }
803
+
804
+ if (dist > min_dist - epsilon_min_dist)
805
+ {
806
+ // Treat as equal
807
+ accumulated_angle_weighted_normal += weight * normalize(normal);
808
+ if (dist < min_dist)
809
+ {
810
+ min_dist = dist;
811
+ min_v = v;
812
+ min_w = w;
813
+ min_face = primitive_index;
814
+ }
815
+ }
816
+ else {
817
+ // Less
818
+ min_dist = dist;
819
+ min_v = v;
820
+ min_w = w;
821
+ min_face = primitive_index;
822
+ accumulated_angle_weighted_normal = weight * normalize(normal);
823
+ }
824
+ }
825
+ }
826
+ #if BVH_DEBUG
827
+ tests++;
828
+ bounds3 b;
829
+ b = bounds_union(b, p);
830
+ b = bounds_union(b, q);
831
+ b = bounds_union(b, r);
832
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < (max_dist+epsilon_min_dist)*(max_dist+epsilon_min_dist))
833
+ {
834
+ //if (dist_sq < max_dist*max_dist)
835
+ test_history.push_back(left_index);
836
+ test_centers.push_back(b.center());
837
+ test_extents.push_back(b.edges());
838
+ }
839
+ #endif
840
+ }
841
+ else
842
+ {
843
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
844
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
845
+
846
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
847
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
848
+
849
+ float left_dist_sq = distance_to_aabb_sq(point, vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z));
850
+ float right_dist_sq = distance_to_aabb_sq(point, vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z));
851
+
852
+ wp::vec2i child_indices;
853
+ wp::vec2 child_dist;
854
+ if (left_dist_sq < right_dist_sq)
855
+ {
856
+ child_indices = wp::vec2i(right_index, left_index);
857
+ child_dist = wp::vec2(right_dist_sq, left_dist_sq);
858
+ }
859
+ else
860
+ {
861
+ child_indices = wp::vec2i(left_index, right_index);
862
+ child_dist = wp::vec2(left_dist_sq, right_dist_sq);
863
+ }
864
+
865
+ if (child_dist[0] < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
866
+ stack[count++] = child_indices[0];
867
+
868
+ if (child_dist[1] < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
869
+ stack[count++] = child_indices[1];
870
+ }
871
+ }
872
+ #if BVH_DEBUG
873
+ printf("%d\n", tests);
874
+ static int max_tests = 0;
875
+ static vec3 max_point;
876
+ static float max_point_dist = 0.0f;
877
+ static int max_secondary_culls = 0;
878
+ if (secondary_culls > max_secondary_culls)
879
+ max_secondary_culls = secondary_culls;
880
+ if (tests > max_tests)
881
+ {
882
+ max_tests = tests;
883
+ max_point = point;
884
+ max_point_dist = min_dist;
885
+ printf("max_tests: %d max_point: %f %f %f max_point_dist: %f max_second_culls: %d\n", max_tests, max_point[0], max_point[1], max_point[2], max_point_dist, max_secondary_culls);
886
+ FILE* f = fopen("test_history.txt", "w");
887
+ for (int i=0; i < test_history.size(); ++i)
888
+ {
889
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
890
+ test_history[i],
891
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
892
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
893
+ }
894
+ fclose(f);
895
+ }
896
+ #endif
897
+ // check if we found a point, and write outputs
898
+ if (min_dist < max_dist)
899
+ {
900
+ u = 1.0f - min_v - min_w;
901
+ v = min_v;
902
+ face = min_face;
903
+ // determine inside outside using ray-cast parity check
904
+ //inside = mesh_query_inside(id, point);
905
+ int i = mesh.indices[min_face*3+0];
906
+ int j = mesh.indices[min_face*3+1];
907
+ int k = mesh.indices[min_face*3+2];
908
+ vec3 p = mesh.points[i];
909
+ vec3 q = mesh.points[j];
910
+ vec3 r = mesh.points[k];
911
+ vec3 closest_point = p*u+q*v+r*min_w;
912
+ if (dot(accumulated_angle_weighted_normal, point-closest_point) > 0.0)
913
+ {
914
+ inside = 1.0f;
915
+ } else
916
+ {
917
+ inside = -1.0f;
918
+ }
919
+ return true;
920
+ }
921
+ else
922
+ {
923
+ return false;
924
+ }
925
+ }
926
+
927
+ CUDA_CALLABLE inline float solid_angle_iterative(uint64_t id, const vec3& p, const float accuracy_sq)
928
+ {
929
+ Mesh mesh = mesh_get(id);
930
+
931
+ int stack[BVH_QUERY_STACK_SIZE];
932
+ int at_child[BVH_QUERY_STACK_SIZE]; // 0 for left, 1 for right, 2 for done
933
+ float angle[BVH_QUERY_STACK_SIZE];
934
+ stack[0] = *mesh.bvh.root;
935
+ at_child[0] = 0;
936
+
937
+ int count = 1;
938
+ angle[0] = 0.0f;
939
+
940
+ while (count)
941
+ {
942
+ const int nodeIndex = stack[count - 1];
943
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
944
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
945
+
946
+ const int left_index = lower.i;
947
+ const int right_index = upper.i;
948
+ if (lower.b)
949
+ {
950
+ // compute closest point on tri
951
+ const int start = left_index;
952
+ const int end = right_index;
953
+ angle[count - 1] = 0.f;
954
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
955
+ {
956
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
957
+ int i = mesh.indices[primitive_index * 3 + 0];
958
+ int j = mesh.indices[primitive_index * 3 + 1];
959
+ int k = mesh.indices[primitive_index * 3 + 2];
960
+ angle[count - 1] += robust_solid_angle(
961
+ mesh.points[i],
962
+ mesh.points[j],
963
+ mesh.points[k], p);
964
+ //printf("Leaf %d, got %f\n", leaf_index, my_data[count - 1]);
965
+ }
966
+ count--;
967
+ }
968
+ else
969
+ {
970
+ // See if I have to descend
971
+ if (at_child[count - 1] == 0)
972
+ {
973
+ // First visit
974
+ bool des = evaluate_node_solid_angle(p, &mesh.solid_angle_props[nodeIndex], angle[count - 1], accuracy_sq);
975
+
976
+ //printf("Non-Leaf %d, got %f\n", nodeIndex, angle[count - 1]);
977
+ if (des)
978
+ {
979
+ // Go left
980
+ stack[count] = left_index;
981
+ at_child[count - 1] = 1;
982
+ angle[count] = 0.0f;
983
+ at_child[count] = 0;
984
+ count++;
985
+ } else
986
+ {
987
+ // Does not descend done
988
+ count--;
989
+ }
990
+ } else
991
+ if (at_child[count - 1] == 1)
992
+ {
993
+ // Add data to parent
994
+ angle[count - 1] += angle[count];
995
+ // Go right
996
+ stack[count] = right_index;
997
+ at_child[count - 1] = 2;
998
+ angle[count] = 0.0f;
999
+ at_child[count] = 0;
1000
+ count++;
1001
+ } else {
1002
+ // Descend both sides already
1003
+ angle[count - 1] += angle[count];
1004
+ count--;
1005
+ }
1006
+ }
1007
+ }
1008
+ return angle[0];
1009
+ }
1010
+
1011
+ CUDA_CALLABLE inline float mesh_query_winding_number(uint64_t id, const vec3& p, const float accuracy)
1012
+ {
1013
+ float angle = solid_angle_iterative(id, p, accuracy*accuracy);
1014
+ return angle * 0.07957747154; // divided by 4 PI
1015
+ }
1016
+
1017
+ // returns true if there is a point (strictly) < distance max_dist
1018
+ CUDA_CALLABLE inline bool mesh_query_point_sign_winding_number(uint64_t id, const vec3& point, float max_dist, float& inside, int& face, float& u, float& v, const float accuracy, const float winding_number_threshold)
1019
+ {
1020
+ Mesh mesh = mesh_get(id);
1021
+
1022
+ int stack[BVH_QUERY_STACK_SIZE];
1023
+ stack[0] = *mesh.bvh.root;
1024
+
1025
+ int count = 1;
1026
+
1027
+ float min_dist_sq = max_dist*max_dist;
1028
+ int min_face;
1029
+ float min_v;
1030
+ float min_w;
1031
+
1032
+ #if BVH_DEBUG
1033
+ int tests = 0;
1034
+ int secondary_culls = 0;
1035
+
1036
+ std::vector<int> test_history;
1037
+ std::vector<vec3> test_centers;
1038
+ std::vector<vec3> test_extents;
1039
+ #endif
1040
+
1041
+ while (count)
1042
+ {
1043
+ const int nodeIndex = stack[--count];
1044
+
1045
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
1046
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
1047
+
1048
+ // re-test distance
1049
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
1050
+ if (node_dist_sq > min_dist_sq)
1051
+ {
1052
+ #if BVH_DEBUG
1053
+ secondary_culls++;
1054
+ #endif
1055
+ continue;
1056
+ }
1057
+
1058
+ const int left_index = lower.i;
1059
+ const int right_index = upper.i;
1060
+
1061
+ if (lower.b)
1062
+ {
1063
+ const int start = left_index;
1064
+ const int end = right_index;
1065
+ // loops through primitives in the leaf
1066
+ for (int primitive_counter = start; primitive_counter < end; primitive_counter++)
1067
+ {
1068
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
1069
+ int i = mesh.indices[primitive_index * 3 + 0];
1070
+ int j = mesh.indices[primitive_index * 3 + 1];
1071
+ int k = mesh.indices[primitive_index * 3 + 2];
1072
+
1073
+ vec3 p = mesh.points[i];
1074
+ vec3 q = mesh.points[j];
1075
+ vec3 r = mesh.points[k];
1076
+
1077
+ vec3 e0 = q - p;
1078
+ vec3 e1 = r - p;
1079
+ vec3 e2 = r - q;
1080
+ vec3 normal = cross(e0, e1);
1081
+
1082
+ // sliver detection
1083
+ if (length(normal) / (dot(e0, e0) + dot(e1, e1) + dot(e2, e2)) < 1.e-6f)
1084
+ continue;
1085
+
1086
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
1087
+ float u = barycentric[0];
1088
+ float v = barycentric[1];
1089
+ float w = 1.f - u - v;
1090
+ vec3 c = u * p + v * q + w * r;
1091
+
1092
+ float dist_sq = length_sq(c - point);
1093
+
1094
+ if (dist_sq < min_dist_sq)
1095
+ {
1096
+ min_dist_sq = dist_sq;
1097
+ min_v = v;
1098
+ min_w = w;
1099
+ min_face = primitive_index;
1100
+ }
1101
+ }
1102
+ #if BVH_DEBUG
1103
+
1104
+ tests++;
1105
+
1106
+ bounds3 b;
1107
+ b = bounds_union(b, p);
1108
+ b = bounds_union(b, q);
1109
+ b = bounds_union(b, r);
1110
+
1111
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
1112
+ {
1113
+ //if (dist_sq < max_dist*max_dist)
1114
+ test_history.push_back(left_index);
1115
+ test_centers.push_back(b.center());
1116
+ test_extents.push_back(b.edges());
1117
+ }
1118
+ #endif
1119
+
1120
+ }
1121
+ else
1122
+ {
1123
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
1124
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
1125
+
1126
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
1127
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
1128
+
1129
+ float left_dist_sq = distance_to_aabb_sq(point, vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z));
1130
+ float right_dist_sq = distance_to_aabb_sq(point, vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z));
1131
+
1132
+ wp::vec2i child_indices;
1133
+ wp::vec2 child_dist;
1134
+ if (left_dist_sq < right_dist_sq)
1135
+ {
1136
+ child_indices = wp::vec2i(right_index, left_index);
1137
+ child_dist = wp::vec2(right_dist_sq, left_dist_sq);
1138
+ }
1139
+ else
1140
+ {
1141
+ child_indices = wp::vec2i(left_index, right_index);
1142
+ child_dist = wp::vec2(left_dist_sq, right_dist_sq);
1143
+ }
1144
+
1145
+ if (child_dist[0] < min_dist_sq)
1146
+ stack[count++] = child_indices[0];
1147
+
1148
+ if (child_dist[1] < min_dist_sq)
1149
+ stack[count++] = child_indices[1];
1150
+ }
1151
+ }
1152
+
1153
+
1154
+ #if BVH_DEBUG
1155
+ printf("%d\n", tests);
1156
+
1157
+ static int max_tests = 0;
1158
+ static vec3 max_point;
1159
+ static float max_point_dist = 0.0f;
1160
+ static int max_secondary_culls = 0;
1161
+
1162
+ if (secondary_culls > max_secondary_culls)
1163
+ max_secondary_culls = secondary_culls;
1164
+
1165
+ if (tests > max_tests)
1166
+ {
1167
+ max_tests = tests;
1168
+ max_point = point;
1169
+ max_point_dist = sqrtf(min_dist_sq);
1170
+
1171
+ printf("max_tests: %d max_point: %f %f %f max_point_dist: %f max_second_culls: %d\n", max_tests, max_point[0], max_point[1], max_point[2], max_point_dist, max_secondary_culls);
1172
+
1173
+ FILE* f = fopen("test_history.txt", "w");
1174
+ for (int i=0; i < test_history.size(); ++i)
1175
+ {
1176
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
1177
+ test_history[i],
1178
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
1179
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
1180
+ }
1181
+
1182
+ fclose(f);
1183
+ }
1184
+ #endif
1185
+
1186
+ // check if we found a point, and write outputs
1187
+ if (min_dist_sq < max_dist*max_dist)
1188
+ {
1189
+ u = 1.0f - min_v - min_w;
1190
+ v = min_v;
1191
+ face = min_face;
1192
+
1193
+ // determine inside outside using ray-cast parity check
1194
+ if (!mesh.solid_angle_props) {
1195
+ inside = mesh_query_inside(id, point);
1196
+ }
1197
+ else {
1198
+ float winding_number = mesh_query_winding_number(id, point, accuracy);
1199
+ inside = (winding_number > winding_number_threshold) ? -1.0f:1.0f;
1200
+ }
1201
+
1202
+ return true;
1203
+ }
1204
+ else
1205
+ {
1206
+ return false;
1207
+ }
1208
+ }
1209
+
1210
+ CUDA_CALLABLE inline void adj_mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist, const int& face, const float& u, const float& v,
1211
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, int& adj_face, float& adj_u, float& adj_v, bool& adj_ret)
1212
+ {
1213
+ Mesh mesh = mesh_get(id);
1214
+
1215
+ // face is determined by BVH in forward pass
1216
+ int i = mesh.indices[face*3+0];
1217
+ int j = mesh.indices[face*3+1];
1218
+ int k = mesh.indices[face*3+2];
1219
+
1220
+ vec3 p = mesh.points[i];
1221
+ vec3 q = mesh.points[j];
1222
+ vec3 r = mesh.points[k];
1223
+
1224
+ vec3 adj_p, adj_q, adj_r;
1225
+
1226
+ vec2 adj_uv(adj_u, adj_v);
1227
+
1228
+ adj_closest_point_to_triangle(p, q, r, point, adj_p, adj_q, adj_r, adj_point, adj_uv);
1229
+ }
1230
+
1231
+ CUDA_CALLABLE inline void adj_mesh_query_furthest_point_no_sign(uint64_t id, const vec3& point, float min_dist, const int& face, const float& u, const float& v,
1232
+ uint64_t adj_id, vec3& adj_point, float& adj_min_dist, int& adj_face, float& adj_u, float& adj_v, bool& adj_ret)
1233
+ {
1234
+ Mesh mesh = mesh_get(id);
1235
+
1236
+ // face is determined by BVH in forward pass
1237
+ int i = mesh.indices[face*3+0];
1238
+ int j = mesh.indices[face*3+1];
1239
+ int k = mesh.indices[face*3+2];
1240
+
1241
+ vec3 p = mesh.points[i];
1242
+ vec3 q = mesh.points[j];
1243
+ vec3 r = mesh.points[k];
1244
+
1245
+ vec3 adj_p, adj_q, adj_r;
1246
+
1247
+ vec2 adj_uv(adj_u, adj_v);
1248
+
1249
+ adj_closest_point_to_triangle(p, q, r, point, adj_p, adj_q, adj_r, adj_point, adj_uv); // Todo for Miles :>
1250
+ }
1251
+
1252
+ CUDA_CALLABLE inline void adj_mesh_query_point(uint64_t id, const vec3& point, float max_dist, const float& inside, const int& face, const float& u, const float& v,
1253
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_inside, int& adj_face, float& adj_u, float& adj_v, bool& adj_ret)
1254
+ {
1255
+ adj_mesh_query_point_no_sign(id, point, max_dist, face, u, v, adj_id, adj_point, adj_max_dist, adj_face, adj_u, adj_v, adj_ret);
1256
+ }
1257
+
1258
+ CUDA_CALLABLE inline void adj_mesh_query_point_sign_normal(uint64_t id, const vec3& point, float max_dist, const float& inside, const int& face, const float& u, const float& v, const float epsilon,
1259
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_inside, int& adj_face, float& adj_u, float& adj_v, float& adj_epsilon, bool& adj_ret)
1260
+ {
1261
+ adj_mesh_query_point_no_sign(id, point, max_dist, face, u, v, adj_id, adj_point, adj_max_dist, adj_face, adj_u, adj_v, adj_ret);
1262
+ }
1263
+
1264
+ CUDA_CALLABLE inline void adj_mesh_query_point_sign_winding_number(uint64_t id, const vec3& point, float max_dist, const float& inside, const int& face, const float& u, const float& v, const float accuracy, const float winding_number_threshold,
1265
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_inside, int& adj_face, float& adj_u, float& adj_v, float& adj_accuracy, float& adj_winding_number_threshold, bool& adj_ret)
1266
+ {
1267
+ adj_mesh_query_point_no_sign(id, point, max_dist, face, u, v, adj_id, adj_point, adj_max_dist, adj_face, adj_u, adj_v, adj_ret);
1268
+ }
1269
+
1270
+
1271
+ // Stores the result of querying the closest point on a mesh.
1272
+ struct mesh_query_point_t
1273
+ {
1274
+ CUDA_CALLABLE mesh_query_point_t()
1275
+ : result(false),
1276
+ sign(0.0f),
1277
+ face(0),
1278
+ u(0.0f),
1279
+ v(0.0f)
1280
+ {}
1281
+
1282
+ // Required for adjoint computations.
1283
+ CUDA_CALLABLE inline mesh_query_point_t& operator+=(const mesh_query_point_t& other)
1284
+ {
1285
+ result += other.result;
1286
+ sign += other.sign;
1287
+ face += other.face;
1288
+ u += other.u;
1289
+ v += other.v;
1290
+ return *this;
1291
+ }
1292
+
1293
+ bool result;
1294
+ float sign;
1295
+ int face;
1296
+ float u;
1297
+ float v;
1298
+ };
1299
+
1300
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point(uint64_t id, const vec3& point, float max_dist)
1301
+ {
1302
+ mesh_query_point_t query;
1303
+ query.result = mesh_query_point(id, point, max_dist, query.sign, query.face, query.u, query.v);
1304
+ return query;
1305
+ }
1306
+
1307
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist)
1308
+ {
1309
+ mesh_query_point_t query;
1310
+ query.sign = 0.0;
1311
+ query.result = mesh_query_point_no_sign(id, point, max_dist, query.face, query.u, query.v);
1312
+ return query;
1313
+ }
1314
+
1315
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_furthest_point_no_sign(uint64_t id, const vec3& point, float min_dist)
1316
+ {
1317
+ mesh_query_point_t query;
1318
+ query.sign = 0.0;
1319
+ query.result = mesh_query_furthest_point_no_sign(id, point, min_dist, query.face, query.u, query.v);
1320
+ return query;
1321
+ }
1322
+
1323
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point_sign_normal(uint64_t id, const vec3& point, float max_dist, const float epsilon = 1e-3f)
1324
+ {
1325
+ mesh_query_point_t query;
1326
+ query.result = mesh_query_point_sign_normal(id, point, max_dist, query.sign, query.face, query.u, query.v, epsilon);
1327
+ return query;
1328
+ }
1329
+
1330
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point_sign_winding_number(uint64_t id, const vec3& point, float max_dist, float accuracy, float winding_number_threshold)
1331
+ {
1332
+ mesh_query_point_t query;
1333
+ query.result = mesh_query_point_sign_winding_number(id, point, max_dist, query.sign, query.face, query.u, query.v, accuracy, winding_number_threshold);
1334
+ return query;
1335
+ }
1336
+
1337
+ CUDA_CALLABLE inline void adj_mesh_query_point(uint64_t id, const vec3& point, float max_dist, const mesh_query_point_t& ret,
1338
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, mesh_query_point_t& adj_ret)
1339
+ {
1340
+ adj_mesh_query_point(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v,
1341
+ adj_id, adj_point, adj_max_dist, adj_ret.sign, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1342
+ }
1343
+
1344
+ CUDA_CALLABLE inline void adj_mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist, const mesh_query_point_t& ret,
1345
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, mesh_query_point_t& adj_ret)
1346
+ {
1347
+ adj_mesh_query_point_no_sign(id, point, max_dist, ret.face, ret.u, ret.v,
1348
+ adj_id, adj_point, adj_max_dist, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1349
+ }
1350
+
1351
+ CUDA_CALLABLE inline void adj_mesh_query_furthest_point_no_sign(uint64_t id, const vec3& point, float min_dist, const mesh_query_point_t& ret,
1352
+ uint64_t adj_id, vec3& adj_point, float& adj_min_dist, mesh_query_point_t& adj_ret)
1353
+ {
1354
+ adj_mesh_query_furthest_point_no_sign(id, point, min_dist, ret.face, ret.u, ret.v,
1355
+ adj_id, adj_point, adj_min_dist, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1356
+ }
1357
+
1358
+ CUDA_CALLABLE inline void adj_mesh_query_point_sign_normal(uint64_t id, const vec3& point, float max_dist, float epsilon, const mesh_query_point_t& ret,
1359
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_epsilon, mesh_query_point_t& adj_ret)
1360
+ {
1361
+ adj_mesh_query_point_sign_normal(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v, epsilon,
1362
+ adj_id, adj_point, adj_max_dist, adj_ret.sign, adj_ret.face, adj_ret.u, adj_ret.v, adj_epsilon, adj_ret.result);
1363
+ }
1364
+
1365
+ CUDA_CALLABLE inline void adj_mesh_query_point_sign_winding_number(uint64_t id, const vec3& point, float max_dist, float accuracy, float winding_number_threshold, const mesh_query_point_t& ret,
1366
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_accuracy, float& adj_winding_number_threshold, mesh_query_point_t& adj_ret)
1367
+ {
1368
+ adj_mesh_query_point_sign_winding_number(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v, accuracy, winding_number_threshold,
1369
+ adj_id, adj_point, adj_max_dist, adj_ret.sign, adj_ret.face, adj_ret.u, adj_ret.v, adj_accuracy, adj_winding_number_threshold, adj_ret.result);
1370
+ }
1371
+
1372
+ CUDA_CALLABLE inline bool mesh_query_ray(uint64_t id, const vec3& start, const vec3& dir, float max_t, float& t, float& u, float& v, float& sign, vec3& normal, int& face)
1373
+ {
1374
+ Mesh mesh = mesh_get(id);
1375
+
1376
+ int stack[BVH_QUERY_STACK_SIZE];
1377
+
1378
+ stack[0] = *mesh.bvh.root;
1379
+ int count = 1;
1380
+
1381
+ vec3 rcp_dir = vec3(1.0f/dir[0], 1.0f/dir[1], 1.0f/dir[2]);
1382
+
1383
+ float min_t = max_t;
1384
+ int min_face;
1385
+ float min_u;
1386
+ float min_v;
1387
+ float min_sign = 1.0f;
1388
+ vec3 min_normal;
1389
+
1390
+ while (count)
1391
+ {
1392
+ const int nodeIndex = stack[--count];
1393
+
1394
+ BVHPackedNodeHalf lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
1395
+ BVHPackedNodeHalf upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
1396
+
1397
+ // todo: switch to robust ray-aabb, or expand bounds in build stage
1398
+ float eps = 1.e-3f;
1399
+ float t = 0.0f;
1400
+ bool hit = intersect_ray_aabb(start, rcp_dir, vec3(lower.x-eps, lower.y-eps, lower.z-eps), vec3(upper.x+eps, upper.y+eps, upper.z+eps), t);
1401
+
1402
+ if (hit && t < min_t)
1403
+ {
1404
+ const int left_index = lower.i;
1405
+ const int right_index = upper.i;
1406
+
1407
+ if (lower.b)
1408
+ {
1409
+ const int start_index = left_index;
1410
+ const int end_index = right_index;
1411
+ // loops through primitives in the leaf
1412
+ for (int primitive_counter = start_index; primitive_counter < end_index ; primitive_counter++)
1413
+ {
1414
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
1415
+ int i = mesh.indices[primitive_index * 3 + 0];
1416
+ int j = mesh.indices[primitive_index * 3 + 1];
1417
+ int k = mesh.indices[primitive_index * 3 + 2];
1418
+
1419
+ vec3 p = mesh.points[i];
1420
+ vec3 q = mesh.points[j];
1421
+ vec3 r = mesh.points[k];
1422
+
1423
+ float t, u, v, sign;
1424
+ vec3 n;
1425
+
1426
+ if (intersect_ray_tri_woop(start, dir, p, q, r, t, u, v, sign, &n))
1427
+ {
1428
+ if (t < min_t && t >= 0.0f)
1429
+ {
1430
+ min_t = t;
1431
+ min_face = primitive_index;
1432
+ min_u = u;
1433
+ min_v = v;
1434
+ min_sign = sign;
1435
+ min_normal = n;
1436
+ }
1437
+ }
1438
+ }
1439
+ }
1440
+ else
1441
+ {
1442
+ stack[count++] = left_index;
1443
+ stack[count++] = right_index;
1444
+ }
1445
+ }
1446
+ }
1447
+
1448
+ if (min_t < max_t)
1449
+ {
1450
+ // write outputs
1451
+ u = min_u;
1452
+ v = min_v;
1453
+ sign = min_sign;
1454
+ t = min_t;
1455
+ normal = normalize(min_normal);
1456
+ face = min_face;
1457
+
1458
+ return true;
1459
+ }
1460
+ else
1461
+ {
1462
+ return false;
1463
+ }
1464
+
1465
+ }
1466
+
1467
+ template <typename T>
1468
+ CUDA_CALLABLE inline void _swap(T& a, T& b)
1469
+ {
1470
+ T t = a; a = b; b = t;
1471
+ }
1472
+
1473
+ CUDA_CALLABLE inline bool mesh_query_ray_ordered(uint64_t id, const vec3& start, const vec3& dir, float max_t, float& t, float& u, float& v, float& sign, vec3& normal, int& face)
1474
+ {
1475
+ Mesh mesh = mesh_get(id);
1476
+
1477
+ int stack[BVH_QUERY_STACK_SIZE];
1478
+ float stack_dist[BVH_QUERY_STACK_SIZE];
1479
+
1480
+ stack[0] = *mesh.bvh.root;
1481
+ stack_dist[0] = -FLT_MAX;
1482
+
1483
+ int count = 1;
1484
+
1485
+ vec3 rcp_dir = vec3(1.0f/dir[0], 1.0f/dir[1], 1.0f/dir[2]);
1486
+
1487
+ float min_t = max_t;
1488
+ int min_face;
1489
+ float min_u;
1490
+ float min_v;
1491
+ float min_sign = 1.0f;
1492
+ vec3 min_normal;
1493
+
1494
+ while (count)
1495
+ {
1496
+ count -= 1;
1497
+
1498
+ const int nodeIndex = stack[count];
1499
+ const float nodeDist = stack_dist[count];
1500
+
1501
+ if (nodeDist < min_t)
1502
+ {
1503
+ int left_index = mesh.bvh.node_lowers[nodeIndex].i;
1504
+ int right_index = mesh.bvh.node_uppers[nodeIndex].i;
1505
+ bool leaf = mesh.bvh.node_lowers[nodeIndex].b;
1506
+
1507
+ if (leaf)
1508
+ {
1509
+ const int start_index = left_index;
1510
+ const int end_index = right_index;
1511
+ // loops through primitives in the leaf
1512
+ for (int primitive_counter = start_index; primitive_counter < end_index ; primitive_counter++)
1513
+ {
1514
+ int primitive_index = mesh.bvh.primitive_indices[primitive_counter];
1515
+ int i = mesh.indices[primitive_index * 3 + 0];
1516
+ int j = mesh.indices[primitive_index * 3 + 1];
1517
+ int k = mesh.indices[primitive_index * 3 + 2];
1518
+
1519
+ vec3 p = mesh.points[i];
1520
+ vec3 q = mesh.points[j];
1521
+ vec3 r = mesh.points[k];
1522
+
1523
+ float t, u, v, w, sign;
1524
+ vec3 n;
1525
+
1526
+ if (intersect_ray_tri_rtcd(start, dir, p, q, r, t, u, v, w, sign, &n))
1527
+ {
1528
+ if (t < min_t && t >= 0.0f)
1529
+ {
1530
+ min_t = t;
1531
+ min_face = primitive_index;
1532
+ min_u = u;
1533
+ min_v = v;
1534
+ min_sign = sign;
1535
+ min_normal = n;
1536
+ }
1537
+ }
1538
+ }
1539
+ }
1540
+ else
1541
+ {
1542
+ const float eps = 1.e-3f;
1543
+
1544
+ BVHPackedNodeHalf left_lower = bvh_load_node(mesh.bvh.node_lowers, left_index);
1545
+ BVHPackedNodeHalf left_upper = bvh_load_node(mesh.bvh.node_uppers, left_index);
1546
+
1547
+ BVHPackedNodeHalf right_lower = bvh_load_node(mesh.bvh.node_lowers, right_index);
1548
+ BVHPackedNodeHalf right_upper = bvh_load_node(mesh.bvh.node_uppers, right_index);
1549
+
1550
+ float left_dist = FLT_MAX;
1551
+ bool left_hit = intersect_ray_aabb(start, rcp_dir, vec3(left_lower.x-eps, left_lower.y-eps, left_lower.z-eps), vec3(left_upper.x+eps, left_upper.y+eps, left_upper.z+eps), left_dist);
1552
+
1553
+ float right_dist = FLT_MAX;
1554
+ bool right_hit = intersect_ray_aabb(start, rcp_dir, vec3(right_lower.x-eps, right_lower.y-eps, right_lower.z-eps), vec3(right_upper.x+eps, right_upper.y+eps, right_upper.z+eps), right_dist);
1555
+
1556
+
1557
+ if (left_dist < right_dist)
1558
+ {
1559
+ _swap(left_index, right_index);
1560
+ _swap(left_dist, right_dist);
1561
+ _swap(left_hit, right_hit);
1562
+ }
1563
+
1564
+ if (left_hit && left_dist < min_t)
1565
+ {
1566
+ stack[count] = left_index;
1567
+ stack_dist[count] = left_dist;
1568
+ count += 1;
1569
+ }
1570
+
1571
+ if (right_hit && right_dist < min_t)
1572
+ {
1573
+ stack[count] = right_index;
1574
+ stack_dist[count] = right_dist;
1575
+ count += 1;
1576
+ }
1577
+ }
1578
+ }
1579
+ }
1580
+
1581
+ if (min_t < max_t)
1582
+ {
1583
+ // write outputs
1584
+ u = min_u;
1585
+ v = min_v;
1586
+ sign = min_sign;
1587
+ t = min_t;
1588
+ normal = normalize(min_normal);
1589
+ face = min_face;
1590
+
1591
+ return true;
1592
+ }
1593
+ else
1594
+ {
1595
+ return false;
1596
+ }
1597
+
1598
+ }
1599
+
1600
+
1601
+ CUDA_CALLABLE inline void adj_mesh_query_ray(
1602
+ uint64_t id, const vec3& start, const vec3& dir, float max_t, float t, float u, float v, float sign, const vec3& n, int face,
1603
+ uint64_t adj_id, vec3& adj_start, vec3& adj_dir, float& adj_max_t, float& adj_t, float& adj_u, float& adj_v, float& adj_sign, vec3& adj_n, int& adj_face, bool& adj_ret)
1604
+ {
1605
+
1606
+ Mesh mesh = mesh_get(id);
1607
+
1608
+ // face is determined by BVH in forward pass
1609
+ int i = mesh.indices[face*3+0];
1610
+ int j = mesh.indices[face*3+1];
1611
+ int k = mesh.indices[face*3+2];
1612
+
1613
+ vec3 a = mesh.points[i];
1614
+ vec3 b = mesh.points[j];
1615
+ vec3 c = mesh.points[k];
1616
+
1617
+ vec3 adj_a, adj_b, adj_c;
1618
+
1619
+ adj_intersect_ray_tri_woop(start, dir, a, b, c, t, u, v, sign, n, adj_start, adj_dir, adj_a, adj_b, adj_c, adj_t, adj_u, adj_v, adj_sign, adj_n, adj_ret);
1620
+
1621
+ }
1622
+
1623
+
1624
+ // Stores the result of querying the closest point on a mesh.
1625
+ struct mesh_query_ray_t
1626
+ {
1627
+ CUDA_CALLABLE mesh_query_ray_t()
1628
+ : result(false),
1629
+ sign(0.0f),
1630
+ face(0),
1631
+ t(0.0f),
1632
+ u(0.0f),
1633
+ v(0.0f),
1634
+ normal()
1635
+ {
1636
+ }
1637
+
1638
+ // Required for adjoint computations.
1639
+ CUDA_CALLABLE inline mesh_query_ray_t& operator+=(const mesh_query_ray_t& other)
1640
+ {
1641
+ result += other.result;
1642
+ sign += other.sign;
1643
+ face += other.face;
1644
+ t += other.t;
1645
+ u += other.u;
1646
+ v += other.v;
1647
+ normal += other.normal;
1648
+ return *this;
1649
+ }
1650
+
1651
+ float sign;
1652
+ int face;
1653
+ float t;
1654
+ float u;
1655
+ float v;
1656
+ vec3 normal;
1657
+ bool result;
1658
+ };
1659
+
1660
+ CUDA_CALLABLE inline mesh_query_ray_t mesh_query_ray(uint64_t id, const vec3& start, const vec3& dir, float max_t)
1661
+ {
1662
+ mesh_query_ray_t query;
1663
+ query.result = mesh_query_ray(id, start, dir, max_t, query.t, query.u, query.v, query.sign, query.normal, query.face);
1664
+ return query;
1665
+ }
1666
+
1667
+ CUDA_CALLABLE inline void
1668
+ adj_mesh_query_ray(
1669
+ uint64_t id, const vec3& start, const vec3& dir, float max_t, const mesh_query_ray_t& ret,
1670
+ uint64_t adj_id, vec3& adj_start, vec3& adj_dir, float& adj_max_t, mesh_query_ray_t& adj_ret
1671
+ )
1672
+ {
1673
+ adj_mesh_query_ray(
1674
+ id, start, dir, max_t, ret.t, ret.u, ret.v, ret.sign, ret.normal, ret.face,
1675
+ adj_id, adj_start, adj_dir, adj_max_t, adj_ret.t, adj_ret.u, adj_ret.v, adj_ret.sign, adj_ret.normal, adj_ret.face, adj_ret.result
1676
+ );
1677
+ }
1678
+
1679
+
1680
+ // determine if a point is inside (ret < 0 ) or outside the mesh (ret > 0)
1681
+ CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p)
1682
+ {
1683
+ float t, u, v, sign;
1684
+ vec3 n;
1685
+ int face;
1686
+
1687
+ int vote = 0;
1688
+
1689
+ for(int i = 0; i <3; ++i)
1690
+ {
1691
+ if (mesh_query_ray(id, p, vec3(float(i==0), float(i==1), float(i==2)), FLT_MAX, t, u, v, sign, n, face) && sign < 0)
1692
+ {
1693
+ vote++;
1694
+ }
1695
+ }
1696
+
1697
+ if (vote >= 2)
1698
+ return -1.0f;
1699
+ else
1700
+ return 1.0f;
1701
+ }
1702
+
1703
+ // stores state required to traverse the BVH nodes that
1704
+ // overlap with a query AABB.
1705
+ struct mesh_query_aabb_t
1706
+ {
1707
+ CUDA_CALLABLE mesh_query_aabb_t()
1708
+ : mesh(),
1709
+ stack(),
1710
+ count(0),
1711
+ input_lower(),
1712
+ input_upper(),
1713
+ face(0),
1714
+ primitive_counter(-1)
1715
+ {}
1716
+
1717
+ // Required for adjoint computations.
1718
+ CUDA_CALLABLE inline mesh_query_aabb_t& operator+=(const mesh_query_aabb_t& other)
1719
+ {
1720
+ return *this;
1721
+ }
1722
+
1723
+ // Mesh Id
1724
+ Mesh mesh;
1725
+ // BVH traversal stack:
1726
+ #if BVH_SHARED_STACK
1727
+ bvh_stack_t stack;
1728
+ #else
1729
+ int stack[BVH_QUERY_STACK_SIZE];
1730
+ #endif
1731
+
1732
+ int count;
1733
+
1734
+ // inputs
1735
+ wp::vec3 input_lower;
1736
+ wp::vec3 input_upper;
1737
+
1738
+ // >= 0 if currently in a packed leaf node
1739
+ int primitive_counter;
1740
+
1741
+ // Face
1742
+ int face;
1743
+ };
1744
+
1745
+
1746
+
1747
+ CUDA_CALLABLE inline mesh_query_aabb_t mesh_query_aabb(
1748
+ uint64_t id, const vec3& lower, const vec3& upper)
1749
+ {
1750
+ // This routine traverses the BVH tree until it finds
1751
+ // the first triangle with an overlapping bvh.
1752
+
1753
+ // initialize empty
1754
+ mesh_query_aabb_t query;
1755
+ query.face = -1;
1756
+
1757
+ Mesh mesh = mesh_get(id);
1758
+ query.mesh = mesh;
1759
+
1760
+ #if BVH_SHARED_STACK
1761
+ __shared__ int stack[BVH_QUERY_STACK_SIZE * WP_TILE_BLOCK_DIM];
1762
+ query.stack.ptr = &stack[threadIdx.x];
1763
+ #endif
1764
+
1765
+ query.stack[0] = *mesh.bvh.root;
1766
+ query.count = 1;
1767
+ query.input_lower = lower;
1768
+ query.input_upper = upper;
1769
+
1770
+ // Navigate through the bvh, find the first overlapping leaf node.
1771
+ while (query.count)
1772
+ {
1773
+ const int nodeIndex = query.stack[--query.count];
1774
+ BVHPackedNodeHalf node_lower = bvh_load_node(mesh.bvh.node_lowers, nodeIndex);
1775
+ BVHPackedNodeHalf node_upper = bvh_load_node(mesh.bvh.node_uppers, nodeIndex);
1776
+
1777
+ if (query.primitive_counter == 0)
1778
+ {
1779
+ if (!intersect_aabb_aabb(query.input_lower, query.input_upper, reinterpret_cast<vec3&>(node_lower), reinterpret_cast<vec3&>(node_upper)))
1780
+ {
1781
+ // Skip this box, it doesn't overlap with our target box.
1782
+ continue;
1783
+ }
1784
+ }
1785
+
1786
+ const int left_index = node_lower.i;
1787
+ const int right_index = node_upper.i;
1788
+
1789
+ // Make bounds from this AABB
1790
+ if (node_lower.b)
1791
+ {
1792
+ // Reached a leaf node, point to its first primitive
1793
+ // Back up one level and return
1794
+ query.primitive_counter = 0;
1795
+ query.stack[query.count++] = nodeIndex;
1796
+ return query;
1797
+ }
1798
+ else
1799
+ {
1800
+ query.stack[query.count++] = left_index;
1801
+ query.stack[query.count++] = right_index;
1802
+ }
1803
+ }
1804
+
1805
+ return query;
1806
+ }
1807
+
1808
+ //Stub
1809
+ CUDA_CALLABLE inline void adj_mesh_query_aabb(uint64_t id, const vec3& lower, const vec3& upper,
1810
+ uint64_t, vec3&, vec3&, mesh_query_aabb_t&)
1811
+ {
1812
+
1813
+ }
1814
+
1815
+ CUDA_CALLABLE inline bool mesh_query_aabb_next(mesh_query_aabb_t& query, int& index)
1816
+ {
1817
+ Mesh mesh = query.mesh;
1818
+
1819
+ // Navigate through the bvh, find the first overlapping leaf node.
1820
+ while (query.count)
1821
+ {
1822
+ const int node_index = query.stack[--query.count];
1823
+ BVHPackedNodeHalf node_lower = bvh_load_node(mesh.bvh.node_lowers, node_index);
1824
+ BVHPackedNodeHalf node_upper = bvh_load_node(mesh.bvh.node_uppers, node_index);
1825
+
1826
+ if (!intersect_aabb_aabb(query.input_lower, query.input_upper, reinterpret_cast<vec3&>(node_lower), reinterpret_cast<vec3&>(node_upper)))
1827
+ {
1828
+ // Skip this box, it doesn't overlap with our target box.
1829
+ continue;
1830
+ }
1831
+
1832
+ const int left_index = node_lower.i;
1833
+ const int right_index = node_upper.i;
1834
+
1835
+ // Make bounds from this AABB
1836
+ if (node_lower.b)
1837
+ {
1838
+ // found leaf, loop through its content primitives
1839
+ const int start = left_index;
1840
+
1841
+ if (mesh.bvh.leaf_size == 1)
1842
+ {
1843
+ int primitive_index = mesh.bvh.primitive_indices[start];
1844
+ index = primitive_index;
1845
+ query.face = primitive_index;
1846
+ return true;
1847
+ }
1848
+ else
1849
+ {
1850
+ const int end = right_index;
1851
+ int primitive_index = mesh.bvh.primitive_indices[start + (query.primitive_counter++)];
1852
+ // if already visited the last primitive in the leaf node
1853
+ // move to the next node and reset the primitive counter to 0
1854
+ if (start + query.primitive_counter == end)
1855
+ {
1856
+ query.primitive_counter = 0;
1857
+ }
1858
+ // otherwise we need to keep this leaf node in stack for a future visit
1859
+ else
1860
+ {
1861
+ query.count++;
1862
+ }
1863
+
1864
+ if (intersect_aabb_aabb(query.input_lower, query.input_upper, mesh.lowers[primitive_index], mesh.uppers[primitive_index]))
1865
+ {
1866
+ index = primitive_index;
1867
+ query.face = primitive_index;
1868
+
1869
+ return true;
1870
+ }
1871
+ }
1872
+ }
1873
+ else
1874
+ {
1875
+ query.primitive_counter = 0;
1876
+ query.stack[query.count++] = left_index;
1877
+ query.stack[query.count++] = right_index;
1878
+ }
1879
+ }
1880
+ return false;
1881
+ }
1882
+
1883
+
1884
+ CUDA_CALLABLE inline int iter_next(mesh_query_aabb_t& query)
1885
+ {
1886
+ return query.face;
1887
+ }
1888
+
1889
+ CUDA_CALLABLE inline bool iter_cmp(mesh_query_aabb_t& query)
1890
+ {
1891
+ bool finished = mesh_query_aabb_next(query, query.face);
1892
+ return finished;
1893
+ }
1894
+
1895
+ CUDA_CALLABLE inline mesh_query_aabb_t iter_reverse(const mesh_query_aabb_t& query)
1896
+ {
1897
+ // can't reverse BVH queries, users should not rely on neighbor ordering
1898
+ return query;
1899
+ }
1900
+
1901
+ CUDA_CALLABLE inline void adj_iter_reverse(const mesh_query_aabb_t& query, mesh_query_aabb_t& adj_query, mesh_query_aabb_t& adj_ret)
1902
+ {
1903
+ }
1904
+
1905
+
1906
+ // stub
1907
+ CUDA_CALLABLE inline void adj_mesh_query_aabb_next(mesh_query_aabb_t& query, int& index, mesh_query_aabb_t&, int&, bool&)
1908
+ {
1909
+
1910
+ }
1911
+
1912
+
1913
+ CUDA_CALLABLE inline vec3 mesh_eval_position(uint64_t id, int tri, float u, float v)
1914
+ {
1915
+ Mesh mesh = mesh_get(id);
1916
+
1917
+ if (!mesh.points)
1918
+ return vec3();
1919
+
1920
+ assert(tri < mesh.num_tris);
1921
+
1922
+ int i = mesh.indices[tri*3+0];
1923
+ int j = mesh.indices[tri*3+1];
1924
+ int k = mesh.indices[tri*3+2];
1925
+
1926
+ vec3 p = mesh.points[i];
1927
+ vec3 q = mesh.points[j];
1928
+ vec3 r = mesh.points[k];
1929
+
1930
+ return p*u + q*v + r*(1.0f-u-v);
1931
+ }
1932
+
1933
+ CUDA_CALLABLE inline vec3 mesh_eval_velocity(uint64_t id, int tri, float u, float v)
1934
+ {
1935
+ Mesh mesh = mesh_get(id);
1936
+
1937
+ if (!mesh.velocities)
1938
+ return vec3();
1939
+
1940
+ assert(tri < mesh.num_tris);
1941
+
1942
+ int i = mesh.indices[tri*3+0];
1943
+ int j = mesh.indices[tri*3+1];
1944
+ int k = mesh.indices[tri*3+2];
1945
+
1946
+ vec3 vp = mesh.velocities[i];
1947
+ vec3 vq = mesh.velocities[j];
1948
+ vec3 vr = mesh.velocities[k];
1949
+
1950
+ return vp*u + vq*v + vr*(1.0f-u-v);
1951
+ }
1952
+
1953
+
1954
+ CUDA_CALLABLE inline void adj_mesh_eval_position(uint64_t id, int tri, float u, float v,
1955
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1956
+ {
1957
+ Mesh mesh = mesh_get(id);
1958
+
1959
+ if (!mesh.points)
1960
+ return;
1961
+
1962
+ assert(tri < mesh.num_tris);
1963
+
1964
+ int i = mesh.indices[tri*3+0];
1965
+ int j = mesh.indices[tri*3+1];
1966
+ int k = mesh.indices[tri*3+2];
1967
+
1968
+ vec3 p = mesh.points[i];
1969
+ vec3 q = mesh.points[j];
1970
+ vec3 r = mesh.points[k];
1971
+
1972
+ adj_u += (p[0] - r[0]) * adj_ret[0] + (p[1] - r[1]) * adj_ret[1] + (p[2] - r[2]) * adj_ret[2];
1973
+ adj_v += (q[0] - r[0]) * adj_ret[0] + (q[1] - r[1]) * adj_ret[1] + (q[2] - r[2]) * adj_ret[2];
1974
+ }
1975
+
1976
+ CUDA_CALLABLE inline void adj_mesh_eval_velocity(uint64_t id, int tri, float u, float v,
1977
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1978
+ {
1979
+ Mesh mesh = mesh_get(id);
1980
+
1981
+ if (!mesh.velocities)
1982
+ return;
1983
+
1984
+ assert(tri < mesh.num_tris);
1985
+
1986
+ int i = mesh.indices[tri*3+0];
1987
+ int j = mesh.indices[tri*3+1];
1988
+ int k = mesh.indices[tri*3+2];
1989
+
1990
+ vec3 vp = mesh.velocities[i];
1991
+ vec3 vq = mesh.velocities[j];
1992
+ vec3 vr = mesh.velocities[k];
1993
+
1994
+ adj_u += (vp[0] - vr[0]) * adj_ret[0] + (vp[1] - vr[1]) * adj_ret[1] + (vp[2] - vr[2]) * adj_ret[2];
1995
+ adj_v += (vq[0] - vr[0]) * adj_ret[0] + (vq[1] - vr[1]) * adj_ret[1] + (vq[2] - vr[2]) * adj_ret[2];
1996
+ }
1997
+
1998
+ CUDA_CALLABLE inline vec3 mesh_eval_face_normal(uint64_t id, int tri)
1999
+ {
2000
+ Mesh mesh = mesh_get(id);
2001
+
2002
+ if (!mesh.points)
2003
+ return vec3();
2004
+
2005
+ assert(tri < mesh.num_tris);
2006
+
2007
+ int i = mesh.indices[tri*3+0];
2008
+ int j = mesh.indices[tri*3+1];
2009
+ int k = mesh.indices[tri*3+2];
2010
+
2011
+ vec3 p = mesh.points[i];
2012
+ vec3 q = mesh.points[j];
2013
+ vec3 r = mesh.points[k];
2014
+
2015
+ return normalize(cross(q - p, r - p));
2016
+ }
2017
+
2018
+ CUDA_CALLABLE inline void adj_mesh_eval_face_normal(uint64_t id, int tri,
2019
+ uint64_t& adj_id, int& adj_tri, const vec3& adj_ret)
2020
+ {
2021
+ // no-op
2022
+ }
2023
+
2024
+ CUDA_CALLABLE inline vec3 mesh_get_point(uint64_t id, int index)
2025
+ {
2026
+ Mesh mesh = mesh_get(id);
2027
+
2028
+ if (!mesh.points)
2029
+ return vec3();
2030
+
2031
+ #if FP_CHECK
2032
+ if (index >= mesh.num_tris * 3)
2033
+ {
2034
+ printf("mesh_get_point (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
2035
+ assert(0);
2036
+ }
2037
+ #endif
2038
+
2039
+ int i = mesh.indices[index];
2040
+ return mesh.points[i];
2041
+ }
2042
+
2043
+ CUDA_CALLABLE inline void adj_mesh_get_point(uint64_t id, int index,
2044
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
2045
+ {
2046
+ // no-op
2047
+ }
2048
+
2049
+ CUDA_CALLABLE inline vec3 mesh_get_velocity(uint64_t id, int index)
2050
+ {
2051
+ Mesh mesh = mesh_get(id);
2052
+
2053
+ if (!mesh.velocities)
2054
+ return vec3();
2055
+
2056
+ #if FP_CHECK
2057
+ if (index >= mesh.num_tris * 3)
2058
+ {
2059
+ printf("mesh_get_velocity (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
2060
+ assert(0);
2061
+ }
2062
+ #endif
2063
+
2064
+ int i = mesh.indices[index];
2065
+ return mesh.velocities[i];
2066
+ }
2067
+
2068
+ CUDA_CALLABLE inline void adj_mesh_get_velocity(uint64_t id, int index,
2069
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
2070
+ {
2071
+ // no-op
2072
+ }
2073
+
2074
+ CUDA_CALLABLE inline int mesh_get_index(uint64_t id, int face_vertex_index)
2075
+ {
2076
+ Mesh mesh = mesh_get(id);
2077
+
2078
+ if (!mesh.indices)
2079
+ return -1;
2080
+
2081
+ assert(face_vertex_index < mesh.num_tris * 3);
2082
+
2083
+ return mesh.indices[face_vertex_index];
2084
+ }
2085
+
2086
+ CUDA_CALLABLE inline void adj_mesh_get_index(uint64_t id, int index,
2087
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
2088
+ {
2089
+ // no-op
2090
+ }
2091
+
2092
+ CUDA_CALLABLE bool mesh_get_descriptor(uint64_t id, Mesh& mesh);
2093
+ CUDA_CALLABLE bool mesh_set_descriptor(uint64_t id, const Mesh& mesh);
2094
+ CUDA_CALLABLE void mesh_add_descriptor(uint64_t id, const Mesh& mesh);
2095
+ CUDA_CALLABLE void mesh_rem_descriptor(uint64_t id);
2096
+
2097
+ } // namespace wp