warp-lang 0.9.0__py3-none-win_amd64.whl → 0.11.0__py3-none-win_amd64.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 (315) hide show
  1. warp/__init__.py +15 -7
  2. warp/__init__.pyi +1 -0
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +22 -443
  6. warp/build_dll.py +384 -0
  7. warp/builtins.py +998 -488
  8. warp/codegen.py +1307 -739
  9. warp/config.py +5 -3
  10. warp/constants.py +6 -0
  11. warp/context.py +1291 -548
  12. warp/dlpack.py +31 -31
  13. warp/fabric.py +326 -0
  14. warp/fem/__init__.py +27 -0
  15. warp/fem/cache.py +389 -0
  16. warp/fem/dirichlet.py +181 -0
  17. warp/fem/domain.py +263 -0
  18. warp/fem/field/__init__.py +101 -0
  19. warp/fem/field/field.py +149 -0
  20. warp/fem/field/nodal_field.py +299 -0
  21. warp/fem/field/restriction.py +21 -0
  22. warp/fem/field/test.py +181 -0
  23. warp/fem/field/trial.py +183 -0
  24. warp/fem/geometry/__init__.py +19 -0
  25. warp/fem/geometry/closest_point.py +70 -0
  26. warp/fem/geometry/deformed_geometry.py +271 -0
  27. warp/fem/geometry/element.py +744 -0
  28. warp/fem/geometry/geometry.py +186 -0
  29. warp/fem/geometry/grid_2d.py +373 -0
  30. warp/fem/geometry/grid_3d.py +435 -0
  31. warp/fem/geometry/hexmesh.py +953 -0
  32. warp/fem/geometry/partition.py +376 -0
  33. warp/fem/geometry/quadmesh_2d.py +532 -0
  34. warp/fem/geometry/tetmesh.py +840 -0
  35. warp/fem/geometry/trimesh_2d.py +577 -0
  36. warp/fem/integrate.py +1616 -0
  37. warp/fem/operator.py +191 -0
  38. warp/fem/polynomial.py +213 -0
  39. warp/fem/quadrature/__init__.py +2 -0
  40. warp/fem/quadrature/pic_quadrature.py +245 -0
  41. warp/fem/quadrature/quadrature.py +294 -0
  42. warp/fem/space/__init__.py +292 -0
  43. warp/fem/space/basis_space.py +489 -0
  44. warp/fem/space/collocated_function_space.py +105 -0
  45. warp/fem/space/dof_mapper.py +236 -0
  46. warp/fem/space/function_space.py +145 -0
  47. warp/fem/space/grid_2d_function_space.py +267 -0
  48. warp/fem/space/grid_3d_function_space.py +306 -0
  49. warp/fem/space/hexmesh_function_space.py +352 -0
  50. warp/fem/space/partition.py +350 -0
  51. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  52. warp/fem/space/restriction.py +160 -0
  53. warp/fem/space/shape/__init__.py +15 -0
  54. warp/fem/space/shape/cube_shape_function.py +738 -0
  55. warp/fem/space/shape/shape_function.py +103 -0
  56. warp/fem/space/shape/square_shape_function.py +611 -0
  57. warp/fem/space/shape/tet_shape_function.py +567 -0
  58. warp/fem/space/shape/triangle_shape_function.py +429 -0
  59. warp/fem/space/tetmesh_function_space.py +292 -0
  60. warp/fem/space/topology.py +295 -0
  61. warp/fem/space/trimesh_2d_function_space.py +221 -0
  62. warp/fem/types.py +77 -0
  63. warp/fem/utils.py +495 -0
  64. warp/native/array.h +164 -55
  65. warp/native/builtin.h +150 -174
  66. warp/native/bvh.cpp +75 -328
  67. warp/native/bvh.cu +406 -23
  68. warp/native/bvh.h +37 -45
  69. warp/native/clang/clang.cpp +136 -24
  70. warp/native/crt.cpp +1 -76
  71. warp/native/crt.h +111 -104
  72. warp/native/cuda_crt.h +1049 -0
  73. warp/native/cuda_util.cpp +15 -3
  74. warp/native/cuda_util.h +3 -1
  75. warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
  76. warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
  77. warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
  78. warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
  79. warp/native/cutlass/tools/library/scripts/library.py +799 -0
  80. warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
  81. warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
  82. warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
  83. warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
  84. warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
  85. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
  86. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
  87. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
  88. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
  89. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
  90. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
  91. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
  92. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
  93. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
  94. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
  95. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
  96. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
  97. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
  98. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
  99. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
  100. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
  101. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
  102. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
  103. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
  104. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
  105. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
  106. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
  107. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
  108. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
  109. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
  110. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
  111. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
  112. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
  113. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
  114. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
  115. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
  116. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
  117. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  118. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  119. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
  120. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
  121. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
  122. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  123. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  124. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
  125. warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
  126. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
  127. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
  128. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
  129. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
  130. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
  131. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
  132. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
  133. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
  134. warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
  135. warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
  136. warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
  137. warp/native/cutlass/tools/library/scripts/rt.py +796 -0
  138. warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
  139. warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
  140. warp/native/cutlass_gemm.cu +5 -3
  141. warp/native/exports.h +1240 -949
  142. warp/native/fabric.h +228 -0
  143. warp/native/hashgrid.cpp +4 -4
  144. warp/native/hashgrid.h +22 -2
  145. warp/native/initializer_array.h +2 -2
  146. warp/native/intersect.h +22 -7
  147. warp/native/intersect_adj.h +8 -8
  148. warp/native/intersect_tri.h +13 -16
  149. warp/native/marching.cu +157 -161
  150. warp/native/mat.h +119 -19
  151. warp/native/matnn.h +2 -2
  152. warp/native/mesh.cpp +108 -83
  153. warp/native/mesh.cu +243 -6
  154. warp/native/mesh.h +1547 -458
  155. warp/native/nanovdb/NanoVDB.h +1 -1
  156. warp/native/noise.h +272 -329
  157. warp/native/quat.h +51 -8
  158. warp/native/rand.h +45 -35
  159. warp/native/range.h +6 -2
  160. warp/native/reduce.cpp +157 -0
  161. warp/native/reduce.cu +348 -0
  162. warp/native/runlength_encode.cpp +62 -0
  163. warp/native/runlength_encode.cu +46 -0
  164. warp/native/scan.cu +11 -13
  165. warp/native/scan.h +1 -0
  166. warp/native/solid_angle.h +442 -0
  167. warp/native/sort.cpp +13 -0
  168. warp/native/sort.cu +9 -1
  169. warp/native/sparse.cpp +338 -0
  170. warp/native/sparse.cu +545 -0
  171. warp/native/spatial.h +2 -2
  172. warp/native/temp_buffer.h +30 -0
  173. warp/native/vec.h +126 -24
  174. warp/native/volume.h +120 -0
  175. warp/native/warp.cpp +658 -53
  176. warp/native/warp.cu +660 -68
  177. warp/native/warp.h +112 -12
  178. warp/optim/__init__.py +1 -0
  179. warp/optim/linear.py +922 -0
  180. warp/optim/sgd.py +92 -0
  181. warp/render/render_opengl.py +392 -152
  182. warp/render/render_usd.py +11 -11
  183. warp/sim/__init__.py +2 -2
  184. warp/sim/articulation.py +385 -185
  185. warp/sim/collide.py +21 -8
  186. warp/sim/import_mjcf.py +297 -106
  187. warp/sim/import_urdf.py +389 -210
  188. warp/sim/import_usd.py +198 -97
  189. warp/sim/inertia.py +17 -18
  190. warp/sim/integrator_euler.py +14 -8
  191. warp/sim/integrator_xpbd.py +161 -19
  192. warp/sim/model.py +795 -291
  193. warp/sim/optimizer.py +2 -6
  194. warp/sim/render.py +65 -3
  195. warp/sim/utils.py +3 -0
  196. warp/sparse.py +1227 -0
  197. warp/stubs.py +665 -223
  198. warp/tape.py +66 -15
  199. warp/tests/__main__.py +3 -6
  200. warp/tests/assets/curlnoise_golden.npy +0 -0
  201. warp/tests/assets/pnoise_golden.npy +0 -0
  202. warp/tests/assets/torus.usda +105 -105
  203. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  204. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  205. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  206. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  207. warp/tests/aux_test_unresolved_func.py +14 -0
  208. warp/tests/aux_test_unresolved_symbol.py +14 -0
  209. warp/tests/disabled_kinematics.py +239 -0
  210. warp/tests/run_coverage_serial.py +31 -0
  211. warp/tests/test_adam.py +103 -106
  212. warp/tests/test_arithmetic.py +128 -74
  213. warp/tests/test_array.py +1497 -211
  214. warp/tests/test_array_reduce.py +150 -0
  215. warp/tests/test_atomic.py +64 -28
  216. warp/tests/test_bool.py +99 -0
  217. warp/tests/test_builtins_resolution.py +1292 -0
  218. warp/tests/test_bvh.py +75 -43
  219. warp/tests/test_closest_point_edge_edge.py +54 -57
  220. warp/tests/test_codegen.py +233 -128
  221. warp/tests/test_compile_consts.py +28 -20
  222. warp/tests/test_conditional.py +108 -24
  223. warp/tests/test_copy.py +10 -12
  224. warp/tests/test_ctypes.py +112 -88
  225. warp/tests/test_dense.py +21 -14
  226. warp/tests/test_devices.py +98 -0
  227. warp/tests/test_dlpack.py +136 -108
  228. warp/tests/test_examples.py +277 -0
  229. warp/tests/test_fabricarray.py +955 -0
  230. warp/tests/test_fast_math.py +15 -11
  231. warp/tests/test_fem.py +1271 -0
  232. warp/tests/test_fp16.py +53 -19
  233. warp/tests/test_func.py +187 -74
  234. warp/tests/test_generics.py +194 -49
  235. warp/tests/test_grad.py +180 -116
  236. warp/tests/test_grad_customs.py +176 -0
  237. warp/tests/test_hash_grid.py +52 -37
  238. warp/tests/test_import.py +10 -23
  239. warp/tests/test_indexedarray.py +577 -24
  240. warp/tests/test_intersect.py +18 -9
  241. warp/tests/test_large.py +141 -0
  242. warp/tests/test_launch.py +251 -15
  243. warp/tests/test_lerp.py +64 -65
  244. warp/tests/test_linear_solvers.py +154 -0
  245. warp/tests/test_lvalue.py +493 -0
  246. warp/tests/test_marching_cubes.py +12 -13
  247. warp/tests/test_mat.py +508 -2778
  248. warp/tests/test_mat_lite.py +115 -0
  249. warp/tests/test_mat_scalar_ops.py +2889 -0
  250. warp/tests/test_math.py +103 -9
  251. warp/tests/test_matmul.py +305 -69
  252. warp/tests/test_matmul_lite.py +410 -0
  253. warp/tests/test_mesh.py +71 -14
  254. warp/tests/test_mesh_query_aabb.py +41 -25
  255. warp/tests/test_mesh_query_point.py +325 -34
  256. warp/tests/test_mesh_query_ray.py +39 -22
  257. warp/tests/test_mlp.py +30 -22
  258. warp/tests/test_model.py +92 -89
  259. warp/tests/test_modules_lite.py +39 -0
  260. warp/tests/test_multigpu.py +88 -114
  261. warp/tests/test_noise.py +12 -11
  262. warp/tests/test_operators.py +16 -20
  263. warp/tests/test_options.py +11 -11
  264. warp/tests/test_pinned.py +17 -18
  265. warp/tests/test_print.py +32 -11
  266. warp/tests/test_quat.py +275 -129
  267. warp/tests/test_rand.py +18 -16
  268. warp/tests/test_reload.py +38 -34
  269. warp/tests/test_rounding.py +50 -43
  270. warp/tests/test_runlength_encode.py +190 -0
  271. warp/tests/test_smoothstep.py +9 -11
  272. warp/tests/test_snippet.py +143 -0
  273. warp/tests/test_sparse.py +460 -0
  274. warp/tests/test_spatial.py +276 -243
  275. warp/tests/test_streams.py +110 -85
  276. warp/tests/test_struct.py +331 -85
  277. warp/tests/test_tape.py +39 -21
  278. warp/tests/test_torch.py +118 -89
  279. warp/tests/test_transient_module.py +12 -13
  280. warp/tests/test_types.py +614 -0
  281. warp/tests/test_utils.py +494 -0
  282. warp/tests/test_vec.py +354 -1987
  283. warp/tests/test_vec_lite.py +73 -0
  284. warp/tests/test_vec_scalar_ops.py +2099 -0
  285. warp/tests/test_volume.py +457 -293
  286. warp/tests/test_volume_write.py +124 -134
  287. warp/tests/unittest_serial.py +35 -0
  288. warp/tests/unittest_suites.py +341 -0
  289. warp/tests/unittest_utils.py +568 -0
  290. warp/tests/unused_test_misc.py +71 -0
  291. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  292. warp/thirdparty/appdirs.py +36 -45
  293. warp/thirdparty/unittest_parallel.py +549 -0
  294. warp/torch.py +72 -30
  295. warp/types.py +1744 -713
  296. warp/utils.py +360 -350
  297. warp_lang-0.11.0.dist-info/LICENSE.md +36 -0
  298. warp_lang-0.11.0.dist-info/METADATA +238 -0
  299. warp_lang-0.11.0.dist-info/RECORD +332 -0
  300. {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
  301. warp/bin/warp-clang.exp +0 -0
  302. warp/bin/warp-clang.lib +0 -0
  303. warp/bin/warp.exp +0 -0
  304. warp/bin/warp.lib +0 -0
  305. warp/tests/test_all.py +0 -215
  306. warp/tests/test_array_scan.py +0 -60
  307. warp/tests/test_base.py +0 -208
  308. warp/tests/test_unresolved_func.py +0 -7
  309. warp/tests/test_unresolved_symbol.py +0 -7
  310. warp_lang-0.9.0.dist-info/METADATA +0 -20
  311. warp_lang-0.9.0.dist-info/RECORD +0 -177
  312. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  313. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  314. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  315. {warp_lang-0.9.0.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
warp/native/mesh.h CHANGED
@@ -12,6 +12,7 @@
12
12
  #include "bvh.h"
13
13
  #include "intersect.h"
14
14
  #include "array.h"
15
+ #include "solid_angle.h"
15
16
 
16
17
  #define BVH_DEBUG 0
17
18
 
@@ -21,38 +22,49 @@ namespace wp
21
22
  struct Mesh
22
23
  {
23
24
  array_t<vec3> points;
24
- array_t<vec3> velocities;
25
+ array_t<vec3> velocities;
25
26
 
26
27
  array_t<int> indices;
27
28
 
28
- bounds3* bounds;
29
+ vec3* lowers;
30
+ vec3* uppers;
31
+
32
+ SolidAngleProps* solid_angle_props;
29
33
 
30
34
  int num_points;
31
35
  int num_tris;
32
36
 
33
37
  BVH bvh;
34
38
 
35
- void* context;
36
-
37
- inline CUDA_CALLABLE Mesh(int id = 0) {
38
- // for backward a = 0 initialization syntax
39
- bounds = nullptr;
40
- num_points = 0;
41
- num_tris = 0;
42
- context = nullptr;
43
- }
44
-
45
- inline CUDA_CALLABLE Mesh(
46
- array_t<vec3> points,
47
- array_t<vec3> velocities,
48
- array_t<int> indices,
49
- int num_points,
50
- int num_tris,
51
- void* context = nullptr
52
- ) : points(points), velocities(velocities), indices(indices), num_points(num_points), num_tris(num_tris), context(context)
53
- {
54
- bounds = nullptr;
55
- }
39
+ void* context;
40
+ float average_edge_length;
41
+
42
+ inline CUDA_CALLABLE Mesh(int id = 0)
43
+ {
44
+ // for backward a = 0 initialization syntax
45
+ lowers = nullptr;
46
+ uppers = nullptr;
47
+ num_points = 0;
48
+ num_tris = 0;
49
+ context = nullptr;
50
+ solid_angle_props = nullptr;
51
+ average_edge_length = 0.0f;
52
+ }
53
+
54
+ inline CUDA_CALLABLE Mesh(
55
+ array_t<vec3> points,
56
+ array_t<vec3> velocities,
57
+ array_t<int> indices,
58
+ int num_points,
59
+ int num_tris,
60
+ void* context = nullptr
61
+ ) : points(points), velocities(velocities), indices(indices), num_points(num_points), num_tris(num_tris), context(context)
62
+ {
63
+ lowers = nullptr;
64
+ uppers = nullptr;
65
+ solid_angle_props = nullptr;
66
+ average_edge_length = 0.0f;
67
+ }
56
68
  };
57
69
 
58
70
  CUDA_CALLABLE inline Mesh mesh_get(uint64_t id)
@@ -62,409 +74,1497 @@ CUDA_CALLABLE inline Mesh mesh_get(uint64_t id)
62
74
 
63
75
 
64
76
  CUDA_CALLABLE inline Mesh& operator += (Mesh& a, const Mesh& b) {
65
- // dummy operator needed for adj_select involving meshes
66
- return a;
77
+ // dummy operator needed for adj_select involving meshes
78
+ return a;
67
79
  }
68
80
 
69
81
  CUDA_CALLABLE inline float distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
70
82
  {
71
- vec3 cp = closest_point_to_aabb(p, lower, upper);
83
+ vec3 cp = closest_point_to_aabb(p, lower, upper);
72
84
 
73
- return length_sq(p-cp);
85
+ return length_sq(p-cp);
74
86
  }
75
87
 
88
+ CUDA_CALLABLE inline float furthest_distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
89
+ {
90
+ vec3 c0 = vec3(lower[0], lower[1], lower[2]);
91
+ vec3 c1 = vec3(lower[0], lower[1], upper[2]);
92
+ vec3 c2 = vec3(lower[0], upper[1], lower[2]);
93
+ vec3 c3 = vec3(lower[0], upper[1], upper[2]);
94
+ vec3 c4 = vec3(upper[0], lower[1], lower[2]);
95
+ vec3 c5 = vec3(upper[0], lower[1], upper[2]);
96
+ vec3 c6 = vec3(upper[0], upper[1], lower[2]);
97
+ vec3 c7 = vec3(upper[0], upper[1], upper[2]);
98
+
99
+ float max_dist_sq = 0.0;
100
+ float d;
101
+
102
+ d = length_sq(p-c0);
103
+ if (d > max_dist_sq)
104
+ max_dist_sq = d;
105
+
106
+ d = length_sq(p-c1);
107
+ if (d > max_dist_sq)
108
+ max_dist_sq = d;
109
+
110
+ d = length_sq(p-c2);
111
+ if (d > max_dist_sq)
112
+ max_dist_sq = d;
113
+
114
+ d = length_sq(p-c3);
115
+ if (d > max_dist_sq)
116
+ max_dist_sq = d;
117
+
118
+ d = length_sq(p-c4);
119
+ if (d > max_dist_sq)
120
+ max_dist_sq = d;
121
+
122
+ d = length_sq(p-c5);
123
+ if (d > max_dist_sq)
124
+ max_dist_sq = d;
125
+
126
+ d = length_sq(p-c6);
127
+ if (d > max_dist_sq)
128
+ max_dist_sq = d;
129
+
130
+ d = length_sq(p-c7);
131
+ if (d > max_dist_sq)
132
+ max_dist_sq = d;
133
+
134
+ return max_dist_sq;
135
+ }
76
136
 
77
- // fwd
78
137
  CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p);
79
138
 
80
-
81
139
  // returns true if there is a point (strictly) < distance max_dist
82
140
  CUDA_CALLABLE inline bool mesh_query_point(uint64_t id, const vec3& point, float max_dist, float& inside, int& face, float& u, float& v)
83
141
  {
84
142
  Mesh mesh = mesh_get(id);
85
143
 
86
- if (mesh.bvh.num_nodes == 0)
87
- return false;
144
+ int stack[32];
145
+ stack[0] = *mesh.bvh.root;
146
+
147
+ int count = 1;
88
148
 
89
- int stack[32];
90
- stack[0] = mesh.bvh.root;
149
+ float min_dist_sq = max_dist*max_dist;
150
+ int min_face;
151
+ float min_v;
152
+ float min_w;
91
153
 
92
- int count = 1;
154
+ #if BVH_DEBUG
155
+ int tests = 0;
156
+ int secondary_culls = 0;
157
+
158
+ std::vector<int> test_history;
159
+ std::vector<vec3> test_centers;
160
+ std::vector<vec3> test_extents;
161
+ #endif
162
+
163
+ while (count)
164
+ {
165
+ const int nodeIndex = stack[--count];
166
+
167
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
168
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
169
+
170
+ // re-test distance
171
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
172
+ if (node_dist_sq > min_dist_sq)
173
+ {
174
+ #if BVH_DEBUG
175
+ secondary_culls++;
176
+ #endif
177
+ continue;
178
+ }
179
+
180
+ const int left_index = lower.i;
181
+ const int right_index = upper.i;
93
182
 
94
- float min_dist_sq = max_dist*max_dist;
95
- int min_face;
96
- float min_v;
97
- float min_w;
183
+ if (lower.b)
184
+ {
185
+ // compute closest point on tri
186
+ int i = mesh.indices[left_index*3+0];
187
+ int j = mesh.indices[left_index*3+1];
188
+ int k = mesh.indices[left_index*3+2];
189
+
190
+ vec3 p = mesh.points[i];
191
+ vec3 q = mesh.points[j];
192
+ vec3 r = mesh.points[k];
193
+
194
+ vec3 e0 = q-p;
195
+ vec3 e1 = r-p;
196
+ vec3 e2 = r-q;
197
+ vec3 normal = cross(e0, e1);
198
+
199
+ // sliver detection
200
+ if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
201
+ continue;
202
+
203
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
204
+ float u = barycentric[0];
205
+ float v = barycentric[1];
206
+ float w = 1.f - u - v;
207
+ vec3 c = u*p + v*q + w*r;
208
+
209
+ float dist_sq = length_sq(c-point);
210
+
211
+ if (dist_sq < min_dist_sq)
212
+ {
213
+ min_dist_sq = dist_sq;
214
+ min_v = v;
215
+ min_w = w;
216
+ min_face = left_index;
217
+ }
98
218
 
99
219
  #if BVH_DEBUG
100
- int tests = 0;
101
- int secondary_culls = 0;
102
220
 
103
- std::vector<int> test_history;
104
- std::vector<vec3> test_centers;
105
- std::vector<vec3> test_extents;
221
+ tests++;
222
+
223
+ bounds3 b;
224
+ b = bounds_union(b, p);
225
+ b = bounds_union(b, q);
226
+ b = bounds_union(b, r);
227
+
228
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
229
+ {
230
+ //if (dist_sq < max_dist*max_dist)
231
+ test_history.push_back(left_index);
232
+ test_centers.push_back(b.center());
233
+ test_extents.push_back(b.edges());
234
+ }
106
235
  #endif
107
236
 
108
- while (count)
109
- {
110
- const int nodeIndex = stack[--count];
111
-
112
- BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
113
- BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
114
-
115
- // re-test distance
116
- float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
117
- if (node_dist_sq > min_dist_sq)
118
- {
237
+ }
238
+ else
239
+ {
240
+ BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
241
+ BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
242
+
243
+ BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
244
+ BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
245
+
246
+ 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));
247
+ 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));
248
+
249
+ float left_score = left_dist_sq;
250
+ float right_score = right_dist_sq;
251
+
252
+ if (left_score < right_score)
253
+ {
254
+ // put left on top of the stack
255
+ if (right_dist_sq < min_dist_sq)
256
+ stack[count++] = right_index;
257
+
258
+ if (left_dist_sq < min_dist_sq)
259
+ stack[count++] = left_index;
260
+ }
261
+ else
262
+ {
263
+ // put right on top of the stack
264
+ if (left_dist_sq < min_dist_sq)
265
+ stack[count++] = left_index;
266
+
267
+ if (right_dist_sq < min_dist_sq)
268
+ stack[count++] = right_index;
269
+ }
270
+ }
271
+ }
272
+
273
+
274
+ #if BVH_DEBUG
275
+ printf("%d\n", tests);
276
+
277
+ static int max_tests = 0;
278
+ static vec3 max_point;
279
+ static float max_point_dist = 0.0f;
280
+ static int max_secondary_culls = 0;
281
+
282
+ if (secondary_culls > max_secondary_culls)
283
+ max_secondary_culls = secondary_culls;
284
+
285
+ if (tests > max_tests)
286
+ {
287
+ max_tests = tests;
288
+ max_point = point;
289
+ max_point_dist = sqrtf(min_dist_sq);
290
+
291
+ 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);
292
+
293
+ FILE* f = fopen("test_history.txt", "w");
294
+ for (int i=0; i < test_history.size(); ++i)
295
+ {
296
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
297
+ test_history[i],
298
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
299
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
300
+ }
301
+
302
+ fclose(f);
303
+ }
304
+ #endif
305
+
306
+ // check if we found a point, and write outputs
307
+ if (min_dist_sq < max_dist*max_dist)
308
+ {
309
+ u = 1.0f - min_v - min_w;
310
+ v = min_v;
311
+ face = min_face;
312
+
313
+ // determine inside outside using ray-cast parity check
314
+ inside = mesh_query_inside(id, point);
315
+
316
+ return true;
317
+ }
318
+ else
319
+ {
320
+ return false;
321
+ }
322
+ }
323
+
324
+ // returns true if there is a point (strictly) < distance max_dist
325
+ CUDA_CALLABLE inline bool mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist, int& face, float& u, float& v)
326
+ {
327
+ Mesh mesh = mesh_get(id);
328
+
329
+ int stack[32];
330
+ stack[0] = *mesh.bvh.root;
331
+
332
+ int count = 1;
333
+
334
+ float min_dist_sq = max_dist*max_dist;
335
+ int min_face;
336
+ float min_v;
337
+ float min_w;
338
+
339
+ #if BVH_DEBUG
340
+ int tests = 0;
341
+ int secondary_culls = 0;
342
+
343
+ std::vector<int> test_history;
344
+ std::vector<vec3> test_centers;
345
+ std::vector<vec3> test_extents;
346
+ #endif
347
+
348
+ while (count)
349
+ {
350
+ const int nodeIndex = stack[--count];
351
+
352
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
353
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
354
+
355
+ // re-test distance
356
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
357
+ if (node_dist_sq > min_dist_sq)
358
+ {
119
359
  #if BVH_DEBUG
120
- secondary_culls++;
360
+ secondary_culls++;
121
361
  #endif
122
- continue;
123
- }
124
-
125
- const int left_index = lower.i;
126
- const int right_index = upper.i;
127
-
128
- if (lower.b)
129
- {
130
- // compute closest point on tri
131
- int i = mesh.indices[left_index*3+0];
132
- int j = mesh.indices[left_index*3+1];
133
- int k = mesh.indices[left_index*3+2];
134
-
135
- vec3 p = mesh.points[i];
136
- vec3 q = mesh.points[j];
137
- vec3 r = mesh.points[k];
138
-
139
- vec3 e0 = q-p;
140
- vec3 e1 = r-p;
141
- vec3 e2 = r-q;
142
- vec3 normal = cross(e0, e1);
143
-
144
- // sliver detection
145
- if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
146
- continue;
147
-
148
- vec2 barycentric = closest_point_to_triangle(p, q, r, point);
149
- float u = barycentric[0];
150
- float v = barycentric[1];
151
- float w = 1.f - u - v;
152
- vec3 c = u*p + v*q + w*r;
153
-
154
- float dist_sq = length_sq(c-point);
155
-
156
- if (dist_sq < min_dist_sq)
157
- {
158
- min_dist_sq = dist_sq;
159
- min_v = v;
160
- min_w = w;
161
- min_face = left_index;
162
- }
362
+ continue;
363
+ }
364
+
365
+ const int left_index = lower.i;
366
+ const int right_index = upper.i;
367
+
368
+ if (lower.b)
369
+ {
370
+ // compute closest point on tri
371
+ int i = mesh.indices[left_index*3+0];
372
+ int j = mesh.indices[left_index*3+1];
373
+ int k = mesh.indices[left_index*3+2];
374
+
375
+ vec3 p = mesh.points[i];
376
+ vec3 q = mesh.points[j];
377
+ vec3 r = mesh.points[k];
378
+
379
+ vec3 e0 = q-p;
380
+ vec3 e1 = r-p;
381
+ vec3 e2 = r-q;
382
+ vec3 normal = cross(e0, e1);
383
+
384
+ // sliver detection
385
+ if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
386
+ continue;
387
+
388
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
389
+ float u = barycentric[0];
390
+ float v = barycentric[1];
391
+ float w = 1.f - u - v;
392
+ vec3 c = u*p + v*q + w*r;
393
+
394
+ float dist_sq = length_sq(c-point);
395
+
396
+ if (dist_sq < min_dist_sq)
397
+ {
398
+ min_dist_sq = dist_sq;
399
+ min_v = v;
400
+ min_w = w;
401
+ min_face = left_index;
402
+ }
163
403
 
164
404
  #if BVH_DEBUG
165
405
 
166
- tests++;
406
+ tests++;
407
+
408
+ bounds3 b;
409
+ b = bounds_union(b, p);
410
+ b = bounds_union(b, q);
411
+ b = bounds_union(b, r);
412
+
413
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
414
+ {
415
+ //if (dist_sq < max_dist*max_dist)
416
+ test_history.push_back(left_index);
417
+ test_centers.push_back(b.center());
418
+ test_extents.push_back(b.edges());
419
+ }
420
+ #endif
421
+
422
+ }
423
+ else
424
+ {
425
+ BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
426
+ BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
427
+
428
+ BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
429
+ BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
430
+
431
+ 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));
432
+ 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));
433
+
434
+ float left_score = left_dist_sq;
435
+ float right_score = right_dist_sq;
436
+
437
+ if (left_score < right_score)
438
+ {
439
+ // put left on top of the stack
440
+ if (right_dist_sq < min_dist_sq)
441
+ stack[count++] = right_index;
442
+
443
+ if (left_dist_sq < min_dist_sq)
444
+ stack[count++] = left_index;
445
+ }
446
+ else
447
+ {
448
+ // put right on top of the stack
449
+ if (left_dist_sq < min_dist_sq)
450
+ stack[count++] = left_index;
451
+
452
+ if (right_dist_sq < min_dist_sq)
453
+ stack[count++] = right_index;
454
+ }
455
+ }
456
+ }
457
+
167
458
 
168
- bounds3 b;
169
- b = bounds_union(b, p);
170
- b = bounds_union(b, q);
171
- b = bounds_union(b, r);
459
+ #if BVH_DEBUG
460
+ printf("%d\n", tests);
461
+
462
+ static int max_tests = 0;
463
+ static vec3 max_point;
464
+ static float max_point_dist = 0.0f;
465
+ static int max_secondary_culls = 0;
466
+
467
+ if (secondary_culls > max_secondary_culls)
468
+ max_secondary_culls = secondary_culls;
469
+
470
+ if (tests > max_tests)
471
+ {
472
+ max_tests = tests;
473
+ max_point = point;
474
+ max_point_dist = sqrtf(min_dist_sq);
475
+
476
+ 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);
477
+
478
+ FILE* f = fopen("test_history.txt", "w");
479
+ for (int i=0; i < test_history.size(); ++i)
480
+ {
481
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
482
+ test_history[i],
483
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
484
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
485
+ }
172
486
 
173
- if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
174
- {
175
- //if (dist_sq < max_dist*max_dist)
176
- test_history.push_back(left_index);
177
- test_centers.push_back(b.center());
178
- test_extents.push_back(b.edges());
179
- }
487
+ fclose(f);
488
+ }
180
489
  #endif
181
490
 
182
- }
183
- else
184
- {
185
- BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
186
- BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
491
+ // check if we found a point, and write outputs
492
+ if (min_dist_sq < max_dist*max_dist)
493
+ {
494
+ u = 1.0f - min_v - min_w;
495
+ v = min_v;
496
+ face = min_face;
497
+
498
+ return true;
499
+ }
500
+ else
501
+ {
502
+ return false;
503
+ }
504
+ }
505
+
506
+ // returns true if there is a point (strictly) > distance min_dist
507
+ 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)
508
+ {
509
+ Mesh mesh = mesh_get(id);
510
+
511
+ int stack[32];
512
+ stack[0] = *mesh.bvh.root;
513
+
514
+ int count = 1;
515
+
516
+ float max_dist_sq = min_dist*min_dist;
517
+ int min_face;
518
+ float min_v;
519
+ float min_w;
187
520
 
188
- BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
189
- BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
521
+ #if BVH_DEBUG
522
+ int tests = 0;
523
+ int secondary_culls = 0;
190
524
 
191
- 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));
192
- 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));
525
+ std::vector<int> test_history;
526
+ std::vector<vec3> test_centers;
527
+ std::vector<vec3> test_extents;
528
+ #endif
193
529
 
530
+ while (count)
531
+ {
532
+ const int nodeIndex = stack[--count];
533
+
534
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
535
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
536
+
537
+ // re-test distance
538
+ float node_dist_sq = furthest_distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
539
+
540
+ // if maximum distance to this node is less than our existing furthest max then skip
541
+ if (node_dist_sq < max_dist_sq)
542
+ {
543
+ #if BVH_DEBUG
544
+ secondary_culls++;
545
+ #endif
546
+ continue;
547
+ }
194
548
 
195
- // traverse smaller area first
196
- //float left_score = bounds3(vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z)).area();
197
- //float right_score = bounds3(vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z)).area();
549
+ const int left_index = lower.i;
550
+ const int right_index = upper.i;
198
551
 
199
- float left_score = left_dist_sq;
200
- float right_score = right_dist_sq;
552
+ if (lower.b)
553
+ {
554
+ // compute closest point on tri
555
+ int i = mesh.indices[left_index*3+0];
556
+ int j = mesh.indices[left_index*3+1];
557
+ int k = mesh.indices[left_index*3+2];
558
+
559
+ vec3 p = mesh.points[i];
560
+ vec3 q = mesh.points[j];
561
+ vec3 r = mesh.points[k];
562
+
563
+ vec3 e0 = q-p;
564
+ vec3 e1 = r-p;
565
+ vec3 e2 = r-q;
566
+ vec3 normal = cross(e0, e1);
567
+
568
+ // sliver detection
569
+ if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
570
+ continue;
571
+
572
+ vec2 barycentric = furthest_point_to_triangle(p, q, r, point);
573
+ float u = barycentric[0];
574
+ float v = barycentric[1];
575
+ float w = 1.f - u - v;
576
+ vec3 c = u*p + v*q + w*r;
577
+
578
+ float dist_sq = length_sq(c-point);
579
+
580
+ if (dist_sq > max_dist_sq)
581
+ {
582
+ max_dist_sq = dist_sq;
583
+ min_v = v;
584
+ min_w = w;
585
+ min_face = left_index;
586
+ }
201
587
 
202
- // tie break based on distance to centroid if point inside both bounds
203
- // if (left_score == right_score)
204
- // {
205
- // // use distance from box centroid to order children
206
- // //left_score = -length_sq(point-bounds3(vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z)).center());
207
- // //right_score = -length_sq(point-bounds3(vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z)).center());
208
- // left_score = bounds3(vec3(left_lower.x, left_lower.y, left_lower.z), vec3(left_upper.x, left_upper.y, left_upper.z)).area();
209
- // right_score = bounds3(vec3(right_lower.x, right_lower.y, right_lower.z), vec3(right_upper.x, right_upper.y, right_upper.z)).area();
588
+ #if BVH_DEBUG
210
589
 
211
- // }
590
+ tests++;
212
591
 
213
- //if (left_dist_sq < right_dist_sq)
214
- if (left_score < right_score)
215
- {
216
- // put left on top of the stack
217
- if (right_dist_sq < min_dist_sq)
218
- stack[count++] = right_index;
592
+ bounds3 b;
593
+ b = bounds_union(b, p);
594
+ b = bounds_union(b, q);
595
+ b = bounds_union(b, r);
219
596
 
220
- if (left_dist_sq < min_dist_sq)
221
- stack[count++] = left_index;
222
- }
223
- else
224
- {
225
- // put right on top of the stack
226
- if (left_dist_sq < min_dist_sq)
227
- stack[count++] = left_index;
597
+ if (distance_to_aabb_sq(point, b.lower, b.upper) > max_dist*max_dist)
598
+ {
599
+ //if (dist_sq < max_dist*max_dist)
600
+ test_history.push_back(left_index);
601
+ test_centers.push_back(b.center());
602
+ test_extents.push_back(b.edges());
603
+ }
604
+ #endif
228
605
 
229
- if (right_dist_sq < min_dist_sq)
230
- stack[count++] = right_index;
231
- }
232
- }
233
- }
606
+ }
607
+ else
608
+ {
609
+ BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
610
+ BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
611
+
612
+ BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
613
+ BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
614
+
615
+ 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));
616
+ 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));
617
+
618
+ float left_score = left_dist_sq;
619
+ float right_score = right_dist_sq;
620
+
621
+ if (left_score > right_score)
622
+ {
623
+ // put left on top of the stack
624
+ if (right_dist_sq > max_dist_sq)
625
+ stack[count++] = right_index;
626
+
627
+ if (left_dist_sq > max_dist_sq)
628
+ stack[count++] = left_index;
629
+ }
630
+ else
631
+ {
632
+ // put right on top of the stack
633
+ if (left_dist_sq > max_dist_sq)
634
+ stack[count++] = left_index;
635
+
636
+ if (right_dist_sq > max_dist_sq)
637
+ stack[count++] = right_index;
638
+ }
639
+ }
640
+ }
234
641
 
235
642
 
236
643
  #if BVH_DEBUG
237
- printf("%d\n", tests);
644
+ printf("%d\n", tests);
238
645
 
239
646
  static int max_tests = 0;
240
- static vec3 max_point;
241
- static float max_point_dist = 0.0f;
242
- static int max_secondary_culls = 0;
647
+ static vec3 max_point;
648
+ static float max_point_dist = 0.0f;
649
+ static int max_secondary_culls = 0;
243
650
 
244
- if (secondary_culls > max_secondary_culls)
245
- max_secondary_culls = secondary_culls;
651
+ if (secondary_culls > max_secondary_culls)
652
+ max_secondary_culls = secondary_culls;
246
653
 
247
654
  if (tests > max_tests)
248
- {
655
+ {
249
656
  max_tests = tests;
250
- max_point = point;
251
- max_point_dist = sqrtf(min_dist_sq);
252
-
253
- 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);
254
-
255
- FILE* f = fopen("test_history.txt", "w");
256
- for (int i=0; i < test_history.size(); ++i)
257
- {
258
- fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
259
- test_history[i],
260
- test_centers[i][0], test_centers[i][1], test_centers[i][2],
261
- test_extents[i][0], test_extents[i][1], test_extents[i][2]);
262
- }
263
-
264
- fclose(f);
265
- }
657
+ max_point = point;
658
+ max_point_dist = sqrtf(max_dist_sq);
659
+
660
+ 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);
661
+
662
+ FILE* f = fopen("test_history.txt", "w");
663
+ for (int i=0; i < test_history.size(); ++i)
664
+ {
665
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
666
+ test_history[i],
667
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
668
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
669
+ }
670
+
671
+ fclose(f);
672
+ }
266
673
  #endif
267
674
 
268
- // check if we found a point, and write outputs
269
- if (min_dist_sq < max_dist*max_dist)
270
- {
271
- u = 1.0f - min_v - min_w;
272
- v = min_v;
273
- face = min_face;
274
-
275
- // determine inside outside using ray-cast parity check
276
- inside = mesh_query_inside(id, point);
277
-
278
- return true;
279
- }
280
- else
281
- {
282
- return false;
283
- }
675
+ // check if we found a point, and write outputs
676
+ if (max_dist_sq > min_dist*min_dist)
677
+ {
678
+ u = 1.0f - min_v - min_w;
679
+ v = min_v;
680
+ face = min_face;
681
+
682
+ return true;
683
+ }
684
+ else
685
+ {
686
+ return false;
687
+ }
284
688
  }
285
689
 
286
- CUDA_CALLABLE inline void adj_mesh_query_point(uint64_t id, const vec3& point, float max_dist, float& inside, int& face, float& u, float& v,
287
- 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)
690
+ // returns true if there is a point (strictly) < distance max_dist
691
+ 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)
288
692
  {
289
- Mesh mesh = mesh_get(id);
290
-
291
- // face is determined by BVH in forward pass
292
- int i = mesh.indices[face*3+0];
293
- int j = mesh.indices[face*3+1];
294
- int k = mesh.indices[face*3+2];
693
+ Mesh mesh = mesh_get(id);
295
694
 
296
- vec3 p = mesh.points[i];
297
- vec3 q = mesh.points[j];
298
- vec3 r = mesh.points[k];
695
+ int stack[32];
696
+ stack[0] = *mesh.bvh.root;
697
+ int count = 1;
698
+ float min_dist = max_dist;
699
+ int min_face;
700
+ float min_v;
701
+ float min_w;
702
+ vec3 accumulated_angle_weighted_normal;
703
+ #if BVH_DEBUG
704
+ int tests = 0;
705
+ int secondary_culls = 0;
706
+ std::vector<int> test_history;
707
+ std::vector<vec3> test_centers;
708
+ std::vector<vec3> test_extents;
709
+ #endif
710
+ float epsilon_min_dist = mesh.average_edge_length * epsilon;
711
+ float epsilon_min_dist_sq = epsilon_min_dist*epsilon_min_dist;
712
+ while (count)
713
+ {
714
+ const int nodeIndex = stack[--count];
715
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
716
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
717
+ // re-test distance
718
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
719
+ if (node_dist_sq > (min_dist + epsilon_min_dist)*(min_dist + epsilon_min_dist))
720
+ {
721
+ #if BVH_DEBUG
722
+ secondary_culls++;
723
+ #endif
724
+ continue;
725
+ }
726
+ const int left_index = lower.i;
727
+ const int right_index = upper.i;
728
+ if (lower.b)
729
+ {
730
+ // compute closest point on tri
731
+ int i = mesh.indices[left_index*3+0];
732
+ int j = mesh.indices[left_index*3+1];
733
+ int k = mesh.indices[left_index*3+2];
734
+ vec3 p = mesh.points[i];
735
+ vec3 q = mesh.points[j];
736
+ vec3 r = mesh.points[k];
737
+ vec3 e0 = q-p;
738
+ vec3 e1 = r-p;
739
+ vec3 e2 = r-q;
740
+ vec3 normal = cross(e0, e1);
741
+ // sliver detection
742
+ float e0_norm_sq = dot(e0,e0);
743
+ float e1_norm_sq = dot(e1,e1);
744
+ float e2_norm_sq = dot(e2,e2);
745
+ if (length(normal)/(e0_norm_sq + e1_norm_sq + e2_norm_sq) < 1.e-6f)
746
+ continue;
747
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
748
+ float u = barycentric[0];
749
+ float v = barycentric[1];
750
+ float w = 1.f - u - v;
751
+ vec3 c = u*p + v*q + w*r;
752
+ float dist = sqrtf(length_sq(c-point));
753
+ if (dist < min_dist + epsilon_min_dist)
754
+ {
755
+ float weight = 0.0f;
756
+ vec3 cp = c-p;
757
+ vec3 cq = c-q;
758
+ vec3 cr = c-r;
759
+ float len_cp_sq = length_sq(cp);
760
+ float len_cq_sq = length_sq(cq);
761
+ float len_cr_sq = length_sq(cr);
762
+
763
+ // Check if near vertex
764
+ if (len_cp_sq < epsilon_min_dist_sq)
765
+ {
766
+ // Vertex 0 is the closest feature
767
+ weight = acosf(dot(normalize(e0), normalize(e1)));
768
+ } else
769
+ if (len_cq_sq < epsilon_min_dist_sq)
770
+ {
771
+ // Vertex 1 is the closest feature
772
+ weight = acosf(dot(normalize(e2), normalize(-e0)));
773
+ } else
774
+ if (len_cr_sq < epsilon_min_dist_sq)
775
+ {
776
+ // Vertex 2 is the closest feature
777
+ weight = acosf(dot(normalize(-e1), normalize(-e2)));
778
+ } else
779
+ {
780
+ float e0cp = dot(e0, cp);
781
+ float e2cq = dot(e2, cq);
782
+ float e1cp = dot(e1, cp);
783
+
784
+ if ((len_cp_sq*e0_norm_sq-e0cp*e0cp < epsilon_min_dist_sq*e0_norm_sq) ||
785
+ (len_cq_sq*e2_norm_sq-e2cq*e2cq < epsilon_min_dist_sq*e2_norm_sq) ||
786
+ (len_cp_sq*e1_norm_sq-e1cp*e1cp < epsilon_min_dist_sq*e1_norm_sq)) {
787
+ // One of the edge
788
+ weight = 3.14159265359f; // PI
789
+ } else {
790
+ weight = 2.0f*3.14159265359f; // 2*PI
791
+ }
792
+ }
793
+
794
+ if (dist > min_dist - epsilon_min_dist)
795
+ {
796
+ // Treat as equal
797
+ accumulated_angle_weighted_normal += weight*normalize(normal);
798
+ if (dist < min_dist)
799
+ {
800
+ min_dist = dist;
801
+ min_v = v;
802
+ min_w = w;
803
+ min_face = left_index;
804
+ }
805
+ } else {
806
+ // Less
807
+ min_dist = dist;
808
+ min_v = v;
809
+ min_w = w;
810
+ min_face = left_index;
811
+ accumulated_angle_weighted_normal = weight*normalize(normal);
812
+ }
813
+ }
814
+ #if BVH_DEBUG
815
+ tests++;
816
+ bounds3 b;
817
+ b = bounds_union(b, p);
818
+ b = bounds_union(b, q);
819
+ b = bounds_union(b, r);
820
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < (max_dist+epsilon_min_dist)*(max_dist+epsilon_min_dist))
821
+ {
822
+ //if (dist_sq < max_dist*max_dist)
823
+ test_history.push_back(left_index);
824
+ test_centers.push_back(b.center());
825
+ test_extents.push_back(b.edges());
826
+ }
827
+ #endif
828
+ }
829
+ else
830
+ {
831
+ BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
832
+ BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
833
+ BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
834
+ BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
835
+
836
+ 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));
837
+ 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));
838
+
839
+ float left_score = left_dist_sq;
840
+ float right_score = right_dist_sq;
841
+
842
+ if (left_score < right_score)
843
+ {
844
+ // put left on top of the stack
845
+ if (right_dist_sq < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
846
+ stack[count++] = right_index;
847
+ if (left_dist_sq < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
848
+ stack[count++] = left_index;
849
+ }
850
+ else
851
+ {
852
+ // put right on top of the stack
853
+ if (left_dist_sq < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
854
+ stack[count++] = left_index;
855
+ if (right_dist_sq < (min_dist + epsilon_min_dist) * (min_dist + epsilon_min_dist))
856
+ stack[count++] = right_index;
857
+ }
858
+ }
859
+ }
860
+ #if BVH_DEBUG
861
+ printf("%d\n", tests);
862
+ static int max_tests = 0;
863
+ static vec3 max_point;
864
+ static float max_point_dist = 0.0f;
865
+ static int max_secondary_culls = 0;
866
+ if (secondary_culls > max_secondary_culls)
867
+ max_secondary_culls = secondary_culls;
868
+ if (tests > max_tests)
869
+ {
870
+ max_tests = tests;
871
+ max_point = point;
872
+ max_point_dist = min_dist;
873
+ 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);
874
+ FILE* f = fopen("test_history.txt", "w");
875
+ for (int i=0; i < test_history.size(); ++i)
876
+ {
877
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
878
+ test_history[i],
879
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
880
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
881
+ }
882
+ fclose(f);
883
+ }
884
+ #endif
885
+ // check if we found a point, and write outputs
886
+ if (min_dist < max_dist)
887
+ {
888
+ u = 1.0f - min_v - min_w;
889
+ v = min_v;
890
+ face = min_face;
891
+ // determine inside outside using ray-cast parity check
892
+ //inside = mesh_query_inside(id, point);
893
+ int i = mesh.indices[min_face*3+0];
894
+ int j = mesh.indices[min_face*3+1];
895
+ int k = mesh.indices[min_face*3+2];
896
+ vec3 p = mesh.points[i];
897
+ vec3 q = mesh.points[j];
898
+ vec3 r = mesh.points[k];
899
+ vec3 closest_point = p*u+q*v+r*min_w;
900
+ if (dot(accumulated_angle_weighted_normal, point-closest_point) > 0.0)
901
+ {
902
+ inside = 1.0f;
903
+ } else
904
+ {
905
+ inside = -1.0f;
906
+ }
907
+ return true;
908
+ }
909
+ else
910
+ {
911
+ return false;
912
+ }
913
+ }
914
+
915
+ CUDA_CALLABLE inline float solid_angle_iterative(uint64_t id, const vec3& p, const float accuracy_sq)
916
+ {
917
+ Mesh mesh = mesh_get(id);
299
918
 
300
- vec3 adj_p, adj_q, adj_r;
919
+ int stack[32];
920
+ int at_child[32]; // 0 for left, 1 for right, 2 for done
921
+ float angle[32];
922
+ stack[0] = *mesh.bvh.root;
923
+ at_child[0] = 0;
301
924
 
302
- vec2 adj_uv(adj_u, adj_v);
925
+ int count = 1;
926
+ angle[0] = 0.0f;
303
927
 
304
- adj_closest_point_to_triangle(p, q, r, point, adj_p, adj_q, adj_r, adj_point, adj_uv);
928
+ while (count)
929
+ {
930
+ const int nodeIndex = stack[count - 1];
931
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
932
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
933
+
934
+ const int left_index = lower.i;
935
+ const int right_index = upper.i;
936
+ if (lower.b)
937
+ {
938
+ // compute closest point on tri
939
+ const int leaf_index = left_index;
940
+ angle[count - 1] = robust_solid_angle(mesh.points[mesh.indices[leaf_index*3+0]], mesh.points[mesh.indices[leaf_index*3+1]], mesh.points[mesh.indices[leaf_index*3+2]], p);
941
+ //printf("Leaf %d, got %f\n", leaf_index, my_data[count - 1]);
942
+ count--;
943
+ }
944
+ else
945
+ {
946
+ // See if I have to descend
947
+ if (at_child[count - 1] == 0)
948
+ {
949
+ // First visit
950
+ bool des = evaluate_node_solid_angle(p, &mesh.solid_angle_props[nodeIndex], angle[count - 1], accuracy_sq);
951
+
952
+ //printf("Non-Leaf %d, got %f\n", nodeIndex, angle[count - 1]);
953
+ if (des)
954
+ {
955
+ // Go left
956
+ stack[count] = left_index;
957
+ at_child[count - 1] = 1;
958
+ angle[count] = 0.0f;
959
+ at_child[count] = 0;
960
+ count++;
961
+ } else
962
+ {
963
+ // Does not descend done
964
+ count--;
965
+ }
966
+ } else
967
+ if (at_child[count - 1] == 1)
968
+ {
969
+ // Add data to parent
970
+ angle[count - 1] += angle[count];
971
+ // Go right
972
+ stack[count] = right_index;
973
+ at_child[count - 1] = 2;
974
+ angle[count] = 0.0f;
975
+ at_child[count] = 0;
976
+ count++;
977
+ } else {
978
+ // Descend both sides already
979
+ angle[count - 1] += angle[count];
980
+ count--;
981
+ }
982
+ }
983
+ }
984
+ return angle[0];
305
985
  }
306
986
 
987
+ CUDA_CALLABLE inline float mesh_query_winding_number(uint64_t id, const vec3& p, const float accuracy)
988
+ {
989
+ float angle = solid_angle_iterative(id, p, accuracy*accuracy);
990
+ return angle * 0.07957747154; // divided by 4 PI
991
+ }
307
992
 
308
- 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)
993
+ // returns true if there is a point (strictly) < distance max_dist
994
+ 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)
995
+ {
996
+ Mesh mesh = mesh_get(id);
997
+
998
+ int stack[32];
999
+ stack[0] = *mesh.bvh.root;
1000
+
1001
+ int count = 1;
1002
+
1003
+ float min_dist_sq = max_dist*max_dist;
1004
+ int min_face;
1005
+ float min_v;
1006
+ float min_w;
1007
+
1008
+ #if BVH_DEBUG
1009
+ int tests = 0;
1010
+ int secondary_culls = 0;
1011
+
1012
+ std::vector<int> test_history;
1013
+ std::vector<vec3> test_centers;
1014
+ std::vector<vec3> test_extents;
1015
+ #endif
1016
+
1017
+ while (count)
1018
+ {
1019
+ const int nodeIndex = stack[--count];
1020
+
1021
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
1022
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
1023
+
1024
+ // re-test distance
1025
+ float node_dist_sq = distance_to_aabb_sq(point, vec3(lower.x, lower.y, lower.z), vec3(upper.x, upper.y, upper.z));
1026
+ if (node_dist_sq > min_dist_sq)
1027
+ {
1028
+ #if BVH_DEBUG
1029
+ secondary_culls++;
1030
+ #endif
1031
+ continue;
1032
+ }
1033
+
1034
+ const int left_index = lower.i;
1035
+ const int right_index = upper.i;
1036
+
1037
+ if (lower.b)
1038
+ {
1039
+ // compute closest point on tri
1040
+ int i = mesh.indices[left_index*3+0];
1041
+ int j = mesh.indices[left_index*3+1];
1042
+ int k = mesh.indices[left_index*3+2];
1043
+
1044
+ vec3 p = mesh.points[i];
1045
+ vec3 q = mesh.points[j];
1046
+ vec3 r = mesh.points[k];
1047
+
1048
+ vec3 e0 = q-p;
1049
+ vec3 e1 = r-p;
1050
+ vec3 e2 = r-q;
1051
+ vec3 normal = cross(e0, e1);
1052
+
1053
+ // sliver detection
1054
+ if (length(normal)/(dot(e0,e0) + dot(e1,e1) + dot(e2,e2)) < 1.e-6f)
1055
+ continue;
1056
+
1057
+ vec2 barycentric = closest_point_to_triangle(p, q, r, point);
1058
+ float u = barycentric[0];
1059
+ float v = barycentric[1];
1060
+ float w = 1.f - u - v;
1061
+ vec3 c = u*p + v*q + w*r;
1062
+
1063
+ float dist_sq = length_sq(c-point);
1064
+
1065
+ if (dist_sq < min_dist_sq)
1066
+ {
1067
+ min_dist_sq = dist_sq;
1068
+ min_v = v;
1069
+ min_w = w;
1070
+ min_face = left_index;
1071
+ }
1072
+
1073
+ #if BVH_DEBUG
1074
+
1075
+ tests++;
1076
+
1077
+ bounds3 b;
1078
+ b = bounds_union(b, p);
1079
+ b = bounds_union(b, q);
1080
+ b = bounds_union(b, r);
1081
+
1082
+ if (distance_to_aabb_sq(point, b.lower, b.upper) < max_dist*max_dist)
1083
+ {
1084
+ //if (dist_sq < max_dist*max_dist)
1085
+ test_history.push_back(left_index);
1086
+ test_centers.push_back(b.center());
1087
+ test_extents.push_back(b.edges());
1088
+ }
1089
+ #endif
1090
+
1091
+ }
1092
+ else
1093
+ {
1094
+ BVHPackedNodeHalf left_lower = mesh.bvh.node_lowers[left_index];
1095
+ BVHPackedNodeHalf left_upper = mesh.bvh.node_uppers[left_index];
1096
+
1097
+ BVHPackedNodeHalf right_lower = mesh.bvh.node_lowers[right_index];
1098
+ BVHPackedNodeHalf right_upper = mesh.bvh.node_uppers[right_index];
1099
+
1100
+ 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));
1101
+ 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));
1102
+
1103
+ float left_score = left_dist_sq;
1104
+ float right_score = right_dist_sq;
1105
+
1106
+ if (left_score < right_score)
1107
+ {
1108
+ // put left on top of the stack
1109
+ if (right_dist_sq < min_dist_sq)
1110
+ stack[count++] = right_index;
1111
+
1112
+ if (left_dist_sq < min_dist_sq)
1113
+ stack[count++] = left_index;
1114
+ }
1115
+ else
1116
+ {
1117
+ // put right on top of the stack
1118
+ if (left_dist_sq < min_dist_sq)
1119
+ stack[count++] = left_index;
1120
+
1121
+ if (right_dist_sq < min_dist_sq)
1122
+ stack[count++] = right_index;
1123
+ }
1124
+ }
1125
+ }
1126
+
1127
+
1128
+ #if BVH_DEBUG
1129
+ printf("%d\n", tests);
1130
+
1131
+ static int max_tests = 0;
1132
+ static vec3 max_point;
1133
+ static float max_point_dist = 0.0f;
1134
+ static int max_secondary_culls = 0;
1135
+
1136
+ if (secondary_culls > max_secondary_culls)
1137
+ max_secondary_culls = secondary_culls;
1138
+
1139
+ if (tests > max_tests)
1140
+ {
1141
+ max_tests = tests;
1142
+ max_point = point;
1143
+ max_point_dist = sqrtf(min_dist_sq);
1144
+
1145
+ 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);
1146
+
1147
+ FILE* f = fopen("test_history.txt", "w");
1148
+ for (int i=0; i < test_history.size(); ++i)
1149
+ {
1150
+ fprintf(f, "%d, %f, %f, %f, %f, %f, %f\n",
1151
+ test_history[i],
1152
+ test_centers[i][0], test_centers[i][1], test_centers[i][2],
1153
+ test_extents[i][0], test_extents[i][1], test_extents[i][2]);
1154
+ }
1155
+
1156
+ fclose(f);
1157
+ }
1158
+ #endif
1159
+
1160
+ // check if we found a point, and write outputs
1161
+ if (min_dist_sq < max_dist*max_dist)
1162
+ {
1163
+ u = 1.0f - min_v - min_w;
1164
+ v = min_v;
1165
+ face = min_face;
1166
+
1167
+ // determine inside outside using ray-cast parity check
1168
+ if (!mesh.solid_angle_props) {
1169
+ inside = mesh_query_inside(id, point);
1170
+ }
1171
+ else {
1172
+ float winding_number = mesh_query_winding_number(id, point, accuracy);
1173
+ inside = (winding_number > winding_number_threshold) ? -1.0f:1.0f;
1174
+ }
1175
+
1176
+ return true;
1177
+ }
1178
+ else
1179
+ {
1180
+ return false;
1181
+ }
1182
+ }
1183
+
1184
+ 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,
1185
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, int& adj_face, float& adj_u, float& adj_v, bool& adj_ret)
1186
+ {
1187
+ Mesh mesh = mesh_get(id);
1188
+
1189
+ // face is determined by BVH in forward pass
1190
+ int i = mesh.indices[face*3+0];
1191
+ int j = mesh.indices[face*3+1];
1192
+ int k = mesh.indices[face*3+2];
1193
+
1194
+ vec3 p = mesh.points[i];
1195
+ vec3 q = mesh.points[j];
1196
+ vec3 r = mesh.points[k];
1197
+
1198
+ vec3 adj_p, adj_q, adj_r;
1199
+
1200
+ vec2 adj_uv(adj_u, adj_v);
1201
+
1202
+ adj_closest_point_to_triangle(p, q, r, point, adj_p, adj_q, adj_r, adj_point, adj_uv);
1203
+ }
1204
+
1205
+ 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,
1206
+ uint64_t adj_id, vec3& adj_point, float& adj_min_dist, int& adj_face, float& adj_u, float& adj_v, bool& adj_ret)
309
1207
  {
310
1208
  Mesh mesh = mesh_get(id);
1209
+
1210
+ // face is determined by BVH in forward pass
1211
+ int i = mesh.indices[face*3+0];
1212
+ int j = mesh.indices[face*3+1];
1213
+ int k = mesh.indices[face*3+2];
1214
+
1215
+ vec3 p = mesh.points[i];
1216
+ vec3 q = mesh.points[j];
1217
+ vec3 r = mesh.points[k];
1218
+
1219
+ vec3 adj_p, adj_q, adj_r;
1220
+
1221
+ vec2 adj_uv(adj_u, adj_v);
1222
+
1223
+ adj_closest_point_to_triangle(p, q, r, point, adj_p, adj_q, adj_r, adj_point, adj_uv); // Todo for Miles :>
1224
+ }
1225
+
1226
+ 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,
1227
+ 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)
1228
+ {
1229
+ 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);
1230
+ }
1231
+
1232
+ 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,
1233
+ 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)
1234
+ {
1235
+ 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);
1236
+ }
1237
+
1238
+ 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,
1239
+ 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)
1240
+ {
1241
+ 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);
1242
+ }
1243
+
1244
+
1245
+ // Stores the result of querying the closest point on a mesh.
1246
+ struct mesh_query_point_t
1247
+ {
1248
+ CUDA_CALLABLE mesh_query_point_t()
1249
+ : result(false),
1250
+ sign(0.0f),
1251
+ face(0),
1252
+ u(0.0f),
1253
+ v(0.0f)
1254
+ {}
1255
+
1256
+ // Required for adjoint computations.
1257
+ CUDA_CALLABLE inline mesh_query_point_t& operator+=(const mesh_query_point_t& other)
1258
+ {
1259
+ result += other.result;
1260
+ sign += other.sign;
1261
+ face += other.face;
1262
+ u += other.u;
1263
+ v += other.v;
1264
+ return *this;
1265
+ }
1266
+
1267
+ bool result;
1268
+ float sign;
1269
+ int face;
1270
+ float u;
1271
+ float v;
1272
+ };
1273
+
1274
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point(uint64_t id, const vec3& point, float max_dist)
1275
+ {
1276
+ mesh_query_point_t query;
1277
+ query.result = mesh_query_point(id, point, max_dist, query.sign, query.face, query.u, query.v);
1278
+ return query;
1279
+ }
1280
+
1281
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_point_no_sign(uint64_t id, const vec3& point, float max_dist)
1282
+ {
1283
+ mesh_query_point_t query;
1284
+ query.sign = 0.0;
1285
+ query.result = mesh_query_point_no_sign(id, point, max_dist, query.face, query.u, query.v);
1286
+ return query;
1287
+ }
1288
+
1289
+ CUDA_CALLABLE inline mesh_query_point_t mesh_query_furthest_point_no_sign(uint64_t id, const vec3& point, float min_dist)
1290
+ {
1291
+ mesh_query_point_t query;
1292
+ query.sign = 0.0;
1293
+ query.result = mesh_query_furthest_point_no_sign(id, point, min_dist, query.face, query.u, query.v);
1294
+ return query;
1295
+ }
311
1296
 
312
- if (mesh.bvh.num_nodes == 0)
313
- return false;
1297
+ 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)
1298
+ {
1299
+ mesh_query_point_t query;
1300
+ query.result = mesh_query_point_sign_normal(id, point, max_dist, query.sign, query.face, query.u, query.v, epsilon);
1301
+ return query;
1302
+ }
1303
+
1304
+ 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)
1305
+ {
1306
+ mesh_query_point_t query;
1307
+ query.result = mesh_query_point_sign_winding_number(id, point, max_dist, query.sign, query.face, query.u, query.v, accuracy, winding_number_threshold);
1308
+ return query;
1309
+ }
1310
+
1311
+ CUDA_CALLABLE inline void adj_mesh_query_point(uint64_t id, const vec3& point, float max_dist, const mesh_query_point_t& ret,
1312
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, mesh_query_point_t& adj_ret)
1313
+ {
1314
+ adj_mesh_query_point(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v,
1315
+ adj_id, adj_point, adj_max_dist, adj_ret.sign, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1316
+ }
1317
+
1318
+ 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,
1319
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, mesh_query_point_t& adj_ret)
1320
+ {
1321
+ adj_mesh_query_point_no_sign(id, point, max_dist, ret.face, ret.u, ret.v,
1322
+ adj_id, adj_point, adj_max_dist, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1323
+ }
1324
+
1325
+ 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,
1326
+ uint64_t adj_id, vec3& adj_point, float& adj_min_dist, mesh_query_point_t& adj_ret)
1327
+ {
1328
+ adj_mesh_query_furthest_point_no_sign(id, point, min_dist, ret.face, ret.u, ret.v,
1329
+ adj_id, adj_point, adj_min_dist, adj_ret.face, adj_ret.u, adj_ret.v, adj_ret.result);
1330
+ }
1331
+
1332
+ 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,
1333
+ uint64_t adj_id, vec3& adj_point, float& adj_max_dist, float& adj_epsilon, mesh_query_point_t& adj_ret)
1334
+ {
1335
+ adj_mesh_query_point_sign_normal(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v, epsilon,
1336
+ adj_id, adj_point, adj_max_dist, adj_ret.sign, adj_ret.face, adj_ret.u, adj_ret.v, epsilon, adj_ret.result);
1337
+ }
1338
+
1339
+ 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,
1340
+ 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)
1341
+ {
1342
+ adj_mesh_query_point_sign_winding_number(id, point, max_dist, ret.sign, ret.face, ret.u, ret.v, accuracy, winding_number_threshold,
1343
+ 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);
1344
+ }
1345
+
1346
+ 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)
1347
+ {
1348
+ Mesh mesh = mesh_get(id);
314
1349
 
315
1350
  int stack[32];
316
- stack[0] = mesh.bvh.root;
317
- int count = 1;
318
-
319
- vec3 rcp_dir = vec3(1.0f/dir[0], 1.0f/dir[1], 1.0f/dir[2]);
320
-
321
- float min_t = max_t;
322
- int min_face;
323
- float min_u;
324
- float min_v;
325
- float min_sign = 1.0f;
326
- vec3 min_normal;
327
-
328
- while (count)
329
- {
330
- const int nodeIndex = stack[--count];
331
-
332
- BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
333
- BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
334
-
335
- // todo: switch to robust ray-aabb, or expand bounds in build stage
336
- float eps = 1.e-3f;
337
- float t = 0.0f;
338
- 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);
339
-
340
- if (hit && t < min_t)
341
- {
342
- const int left_index = lower.i;
343
- const int right_index = upper.i;
344
-
345
- if (lower.b)
346
- {
347
- // compute closest point on tri
348
- int i = mesh.indices[left_index*3+0];
349
- int j = mesh.indices[left_index*3+1];
350
- int k = mesh.indices[left_index*3+2];
351
-
352
- vec3 p = mesh.points[i];
353
- vec3 q = mesh.points[j];
354
- vec3 r = mesh.points[k];
355
-
356
- float t, u, v, sign;
357
- vec3 n;
358
-
359
- if (intersect_ray_tri_woop(start, dir, p, q, r, t, u, v, sign, &n))
360
- {
361
- if (t < min_t && t >= 0.0f)
362
- {
363
- min_t = t;
364
- min_face = left_index;
365
- min_u = u;
366
- min_v = v;
367
- min_sign = sign;
368
- min_normal = n;
369
- }
370
- }
371
- }
372
- else
373
- {
374
- stack[count++] = left_index;
375
- stack[count++] = right_index;
376
- }
377
- }
378
- }
379
-
380
- if (min_t < max_t)
381
- {
382
- // write outputs
383
- u = min_u;
384
- v = min_v;
385
- sign = min_sign;
386
- t = min_t;
387
- normal = normalize(min_normal);
388
- face = min_face;
389
-
390
- return true;
391
- }
392
- else
393
- {
394
- return false;
395
- }
396
-
1351
+ stack[0] = *mesh.bvh.root;
1352
+ int count = 1;
1353
+
1354
+ vec3 rcp_dir = vec3(1.0f/dir[0], 1.0f/dir[1], 1.0f/dir[2]);
1355
+
1356
+ float min_t = max_t;
1357
+ int min_face;
1358
+ float min_u;
1359
+ float min_v;
1360
+ float min_sign = 1.0f;
1361
+ vec3 min_normal;
1362
+
1363
+ while (count)
1364
+ {
1365
+ const int nodeIndex = stack[--count];
1366
+
1367
+ BVHPackedNodeHalf lower = mesh.bvh.node_lowers[nodeIndex];
1368
+ BVHPackedNodeHalf upper = mesh.bvh.node_uppers[nodeIndex];
1369
+
1370
+ // todo: switch to robust ray-aabb, or expand bounds in build stage
1371
+ float eps = 1.e-3f;
1372
+ float t = 0.0f;
1373
+ 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);
1374
+
1375
+ if (hit && t < min_t)
1376
+ {
1377
+ const int left_index = lower.i;
1378
+ const int right_index = upper.i;
1379
+
1380
+ if (lower.b)
1381
+ {
1382
+ // compute closest point on tri
1383
+ int i = mesh.indices[left_index*3+0];
1384
+ int j = mesh.indices[left_index*3+1];
1385
+ int k = mesh.indices[left_index*3+2];
1386
+
1387
+ vec3 p = mesh.points[i];
1388
+ vec3 q = mesh.points[j];
1389
+ vec3 r = mesh.points[k];
1390
+
1391
+ float t, u, v, sign;
1392
+ vec3 n;
1393
+
1394
+ if (intersect_ray_tri_woop(start, dir, p, q, r, t, u, v, sign, &n))
1395
+ {
1396
+ if (t < min_t && t >= 0.0f)
1397
+ {
1398
+ min_t = t;
1399
+ min_face = left_index;
1400
+ min_u = u;
1401
+ min_v = v;
1402
+ min_sign = sign;
1403
+ min_normal = n;
1404
+ }
1405
+ }
1406
+ }
1407
+ else
1408
+ {
1409
+ stack[count++] = left_index;
1410
+ stack[count++] = right_index;
1411
+ }
1412
+ }
1413
+ }
1414
+
1415
+ if (min_t < max_t)
1416
+ {
1417
+ // write outputs
1418
+ u = min_u;
1419
+ v = min_v;
1420
+ sign = min_sign;
1421
+ t = min_t;
1422
+ normal = normalize(min_normal);
1423
+ face = min_face;
1424
+
1425
+ return true;
1426
+ }
1427
+ else
1428
+ {
1429
+ return false;
1430
+ }
1431
+
397
1432
  }
398
1433
 
399
1434
 
400
1435
  CUDA_CALLABLE inline void adj_mesh_query_ray(
401
- uint64_t id, const vec3& start, const vec3& dir, float max_t, float& t, float& u, float& v, float& sign, vec3& n, int& face,
402
- 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)
1436
+ 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,
1437
+ 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)
403
1438
  {
404
1439
 
405
- Mesh mesh = mesh_get(id);
406
-
407
- // face is determined by BVH in forward pass
408
- int i = mesh.indices[face*3+0];
409
- int j = mesh.indices[face*3+1];
410
- int k = mesh.indices[face*3+2];
1440
+ Mesh mesh = mesh_get(id);
1441
+
1442
+ // face is determined by BVH in forward pass
1443
+ int i = mesh.indices[face*3+0];
1444
+ int j = mesh.indices[face*3+1];
1445
+ int k = mesh.indices[face*3+2];
411
1446
 
412
- vec3 a = mesh.points[i];
413
- vec3 b = mesh.points[j];
414
- vec3 c = mesh.points[k];
1447
+ vec3 a = mesh.points[i];
1448
+ vec3 b = mesh.points[j];
1449
+ vec3 c = mesh.points[k];
415
1450
 
416
- vec3 adj_a, adj_b, adj_c;
1451
+ vec3 adj_a, adj_b, adj_c;
417
1452
 
418
- 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);
1453
+ 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);
419
1454
 
420
1455
  }
421
1456
 
422
1457
 
1458
+ // Stores the result of querying the closest point on a mesh.
1459
+ struct mesh_query_ray_t
1460
+ {
1461
+ CUDA_CALLABLE mesh_query_ray_t()
1462
+ : result(false),
1463
+ sign(0.0f),
1464
+ face(0),
1465
+ t(0.0f),
1466
+ u(0.0f),
1467
+ v(0.0f),
1468
+ normal()
1469
+ {
1470
+ }
1471
+
1472
+ // Required for adjoint computations.
1473
+ CUDA_CALLABLE inline mesh_query_ray_t& operator+=(const mesh_query_ray_t& other)
1474
+ {
1475
+ result += other.result;
1476
+ sign += other.sign;
1477
+ face += other.face;
1478
+ t += other.t;
1479
+ u += other.u;
1480
+ v += other.v;
1481
+ normal += other.normal;
1482
+ return *this;
1483
+ }
1484
+
1485
+ bool result;
1486
+ float sign;
1487
+ int face;
1488
+ float t;
1489
+ float u;
1490
+ float v;
1491
+ vec3 normal;
1492
+ };
1493
+
1494
+ CUDA_CALLABLE inline mesh_query_ray_t mesh_query_ray(uint64_t id, const vec3& start, const vec3& dir, float max_t)
1495
+ {
1496
+ mesh_query_ray_t query;
1497
+ query.result = mesh_query_ray(id, start, dir, max_t, query.t, query.u, query.v, query.sign, query.normal, query.face);
1498
+ return query;
1499
+ }
1500
+
1501
+ CUDA_CALLABLE inline void
1502
+ adj_mesh_query_ray(
1503
+ uint64_t id, const vec3& start, const vec3& dir, float max_t, const mesh_query_ray_t& ret,
1504
+ uint64_t adj_id, vec3& adj_start, vec3& adj_dir, float& adj_max_t, mesh_query_ray_t& adj_ret
1505
+ )
1506
+ {
1507
+ adj_mesh_query_ray(
1508
+ id, start, dir, max_t, ret.t, ret.u, ret.v, ret.sign, ret.normal, ret.face,
1509
+ 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
1510
+ );
1511
+ }
1512
+
1513
+
423
1514
  // determine if a point is inside (ret < 0 ) or outside the mesh (ret > 0)
424
1515
  CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p)
425
1516
  {
426
1517
  float t, u, v, sign;
427
- vec3 n;
428
- int face;
1518
+ vec3 n;
1519
+ int face;
429
1520
 
430
- int vote = 0;
1521
+ int vote = 0;
431
1522
 
432
- for(int i = 0; i <3; ++i){
433
- 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) {
434
- vote++;
435
- }
436
- }
1523
+ for(int i = 0; i <3; ++i)
1524
+ {
1525
+ 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)
1526
+ {
1527
+ vote++;
1528
+ }
1529
+ }
437
1530
 
438
- if (vote == 3)
439
- return -1.0f;
440
- else
441
- return 1.0f;
1531
+ if (vote == 3)
1532
+ return -1.0f;
1533
+ else
1534
+ return 1.0f;
442
1535
  }
443
1536
 
444
-
445
1537
  // stores state required to traverse the BVH nodes that
446
1538
  // overlap with a query AABB.
447
1539
  struct mesh_query_aabb_t
448
1540
  {
449
1541
  CUDA_CALLABLE mesh_query_aabb_t()
1542
+ : mesh(),
1543
+ stack(),
1544
+ count(0),
1545
+ input_lower(),
1546
+ input_upper(),
1547
+ face(0)
1548
+ {}
1549
+
1550
+ // Required for adjoint computations.
1551
+ CUDA_CALLABLE inline mesh_query_aabb_t& operator+=(const mesh_query_aabb_t& other)
450
1552
  {
1553
+ return *this;
451
1554
  }
452
- CUDA_CALLABLE mesh_query_aabb_t(int)
453
- {
454
- } // for backward pass
455
1555
 
456
1556
  // Mesh Id
457
1557
  Mesh mesh;
458
- // BVH traversal stack:
459
- int stack[32];
460
- int count;
1558
+ // BVH traversal stack:
1559
+ int stack[32];
1560
+ int count;
461
1561
 
462
1562
  // inputs
463
1563
  wp::vec3 input_lower;
464
1564
  wp::vec3 input_upper;
465
1565
 
466
- // Face
467
- int face;
1566
+ // Face
1567
+ int face;
468
1568
  };
469
1569
 
470
1570
 
@@ -473,72 +1573,62 @@ CUDA_CALLABLE inline mesh_query_aabb_t mesh_query_aabb(
473
1573
  uint64_t id, const vec3& lower, const vec3& upper)
474
1574
  {
475
1575
  // This routine traverses the BVH tree until it finds
476
- // the first triangle with an overlapping bvh.
1576
+ // the first triangle with an overlapping bvh.
477
1577
 
478
1578
  // initialize empty
479
- mesh_query_aabb_t query;
480
- query.face = -1;
1579
+ mesh_query_aabb_t query;
1580
+ query.face = -1;
481
1581
 
482
- Mesh mesh = mesh_get(id);
483
-
484
- query.mesh = mesh;
485
-
486
- // if no bvh nodes, return empty query.
487
- if (mesh.bvh.num_nodes == 0)
488
- {
489
- query.count = 0;
490
- return query;
491
- }
492
-
493
- // optimization: make the latest
494
-
495
- query.stack[0] = mesh.bvh.root;
496
- query.count = 1;
1582
+ Mesh mesh = mesh_get(id);
1583
+ query.mesh = mesh;
1584
+
1585
+ query.stack[0] = *mesh.bvh.root;
1586
+ query.count = 1;
497
1587
  query.input_lower = lower;
498
1588
  query.input_upper = upper;
499
1589
 
500
1590
  wp::bounds3 input_bounds(query.input_lower, query.input_upper);
501
-
1591
+
502
1592
  // Navigate through the bvh, find the first overlapping leaf node.
503
1593
  while (query.count)
504
1594
  {
505
- const int nodeIndex = query.stack[--query.count];
506
- BVHPackedNodeHalf node_lower = mesh.bvh.node_lowers[nodeIndex];
507
- BVHPackedNodeHalf node_upper = mesh.bvh.node_uppers[nodeIndex];
1595
+ const int nodeIndex = query.stack[--query.count];
1596
+ BVHPackedNodeHalf node_lower = mesh.bvh.node_lowers[nodeIndex];
1597
+ BVHPackedNodeHalf node_upper = mesh.bvh.node_uppers[nodeIndex];
508
1598
 
509
- wp::vec3 lower_pos(node_lower.x, node_lower.y, node_lower.z);
510
- wp::vec3 upper_pos(node_upper.x, node_upper.y, node_upper.z);
1599
+ wp::vec3 lower_pos(node_lower.x, node_lower.y, node_lower.z);
1600
+ wp::vec3 upper_pos(node_upper.x, node_upper.y, node_upper.z);
511
1601
  wp::bounds3 current_bounds(lower_pos, upper_pos);
512
1602
  if (!input_bounds.overlaps(current_bounds))
513
1603
  {
514
1604
  // Skip this box, it doesn't overlap with our target box.
515
- continue;
516
- }
1605
+ continue;
1606
+ }
517
1607
 
518
- const int left_index = node_lower.i;
519
- const int right_index = node_upper.i;
1608
+ const int left_index = node_lower.i;
1609
+ const int right_index = node_upper.i;
520
1610
 
521
1611
  // Make bounds from this AABB
522
1612
  if (node_lower.b)
523
1613
  {
524
- // found very first triangle index.
525
- // Back up one level and return
526
- query.stack[query.count++] = nodeIndex;
527
- return query;
1614
+ // found very first triangle index.
1615
+ // Back up one level and return
1616
+ query.stack[query.count++] = nodeIndex;
1617
+ return query;
528
1618
  }
529
1619
  else
530
1620
  {
531
- query.stack[query.count++] = left_index;
532
- query.stack[query.count++] = right_index;
533
- }
534
- }
1621
+ query.stack[query.count++] = left_index;
1622
+ query.stack[query.count++] = right_index;
1623
+ }
1624
+ }
535
1625
 
536
- return query;
1626
+ return query;
537
1627
  }
538
1628
 
539
1629
  //Stub
540
1630
  CUDA_CALLABLE inline void adj_mesh_query_aabb(uint64_t id, const vec3& lower, const vec3& upper,
541
- uint64_t, vec3&, vec3&, mesh_query_aabb_t&)
1631
+ uint64_t, vec3&, vec3&, mesh_query_aabb_t&)
542
1632
  {
543
1633
 
544
1634
  }
@@ -546,8 +1636,8 @@ CUDA_CALLABLE inline void adj_mesh_query_aabb(uint64_t id, const vec3& lower, co
546
1636
  CUDA_CALLABLE inline bool mesh_query_aabb_next(mesh_query_aabb_t& query, int& index)
547
1637
  {
548
1638
  Mesh mesh = query.mesh;
549
-
550
- wp::bounds3 input_bounds(query.input_lower, query.input_upper);
1639
+
1640
+ wp::bounds3 input_bounds(query.input_lower, query.input_upper);
551
1641
  // Navigate through the bvh, find the first overlapping leaf node.
552
1642
  while (query.count)
553
1643
  {
@@ -572,7 +1662,7 @@ CUDA_CALLABLE inline bool mesh_query_aabb_next(mesh_query_aabb_t& query, int& in
572
1662
  {
573
1663
  // found very first triangle index
574
1664
  query.face = left_index;
575
- index = left_index;
1665
+ index = left_index;
576
1666
  return true;
577
1667
  }
578
1668
  else
@@ -613,186 +1703,185 @@ CUDA_CALLABLE inline void adj_mesh_query_aabb_next(mesh_query_aabb_t& query, int
613
1703
 
614
1704
  CUDA_CALLABLE inline vec3 mesh_eval_position(uint64_t id, int tri, float u, float v)
615
1705
  {
616
- Mesh mesh = mesh_get(id);
1706
+ Mesh mesh = mesh_get(id);
617
1707
 
618
- if (!mesh.points)
619
- return vec3();
1708
+ if (!mesh.points)
1709
+ return vec3();
620
1710
 
621
- assert(tri < mesh.num_tris);
1711
+ assert(tri < mesh.num_tris);
622
1712
 
623
- int i = mesh.indices[tri*3+0];
624
- int j = mesh.indices[tri*3+1];
625
- int k = mesh.indices[tri*3+2];
1713
+ int i = mesh.indices[tri*3+0];
1714
+ int j = mesh.indices[tri*3+1];
1715
+ int k = mesh.indices[tri*3+2];
626
1716
 
627
- vec3 p = mesh.points[i];
628
- vec3 q = mesh.points[j];
629
- vec3 r = mesh.points[k];
1717
+ vec3 p = mesh.points[i];
1718
+ vec3 q = mesh.points[j];
1719
+ vec3 r = mesh.points[k];
630
1720
 
631
- return p*u + q*v + r*(1.0f-u-v);
1721
+ return p*u + q*v + r*(1.0f-u-v);
632
1722
  }
633
1723
 
634
1724
  CUDA_CALLABLE inline vec3 mesh_eval_velocity(uint64_t id, int tri, float u, float v)
635
1725
  {
636
- Mesh mesh = mesh_get(id);
1726
+ Mesh mesh = mesh_get(id);
637
1727
 
638
- if (!mesh.velocities)
639
- return vec3();
1728
+ if (!mesh.velocities)
1729
+ return vec3();
640
1730
 
641
- assert(tri < mesh.num_tris);
1731
+ assert(tri < mesh.num_tris);
642
1732
 
643
- int i = mesh.indices[tri*3+0];
644
- int j = mesh.indices[tri*3+1];
645
- int k = mesh.indices[tri*3+2];
1733
+ int i = mesh.indices[tri*3+0];
1734
+ int j = mesh.indices[tri*3+1];
1735
+ int k = mesh.indices[tri*3+2];
646
1736
 
647
- vec3 vp = mesh.velocities[i];
648
- vec3 vq = mesh.velocities[j];
649
- vec3 vr = mesh.velocities[k];
1737
+ vec3 vp = mesh.velocities[i];
1738
+ vec3 vq = mesh.velocities[j];
1739
+ vec3 vr = mesh.velocities[k];
650
1740
 
651
- return vp*u + vq*v + vr*(1.0f-u-v);
1741
+ return vp*u + vq*v + vr*(1.0f-u-v);
652
1742
  }
653
1743
 
654
1744
 
655
1745
  CUDA_CALLABLE inline void adj_mesh_eval_position(uint64_t id, int tri, float u, float v,
656
- uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1746
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
657
1747
  {
658
- Mesh mesh = mesh_get(id);
1748
+ Mesh mesh = mesh_get(id);
659
1749
 
660
- if (!mesh.points)
661
- return;
1750
+ if (!mesh.points)
1751
+ return;
662
1752
 
663
- assert(tri < mesh.num_tris);
1753
+ assert(tri < mesh.num_tris);
664
1754
 
665
- int i = mesh.indices[tri*3+0];
666
- int j = mesh.indices[tri*3+1];
667
- int k = mesh.indices[tri*3+2];
1755
+ int i = mesh.indices[tri*3+0];
1756
+ int j = mesh.indices[tri*3+1];
1757
+ int k = mesh.indices[tri*3+2];
668
1758
 
669
- vec3 p = mesh.points[i];
670
- vec3 q = mesh.points[j];
671
- vec3 r = mesh.points[k];
1759
+ vec3 p = mesh.points[i];
1760
+ vec3 q = mesh.points[j];
1761
+ vec3 r = mesh.points[k];
672
1762
 
673
- adj_u += (p[0] - r[0]) * adj_ret[0] + (p[1] - r[1]) * adj_ret[1] + (p[2] - r[2]) * adj_ret[2];
674
- adj_v += (q[0] - r[0]) * adj_ret[0] + (q[1] - r[1]) * adj_ret[1] + (q[2] - r[2]) * adj_ret[2];
1763
+ adj_u += (p[0] - r[0]) * adj_ret[0] + (p[1] - r[1]) * adj_ret[1] + (p[2] - r[2]) * adj_ret[2];
1764
+ adj_v += (q[0] - r[0]) * adj_ret[0] + (q[1] - r[1]) * adj_ret[1] + (q[2] - r[2]) * adj_ret[2];
675
1765
  }
676
1766
 
677
1767
  CUDA_CALLABLE inline void adj_mesh_eval_velocity(uint64_t id, int tri, float u, float v,
678
- uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1768
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
679
1769
  {
680
- Mesh mesh = mesh_get(id);
1770
+ Mesh mesh = mesh_get(id);
681
1771
 
682
- if (!mesh.velocities)
683
- return;
1772
+ if (!mesh.velocities)
1773
+ return;
684
1774
 
685
- assert(tri < mesh.num_tris);
1775
+ assert(tri < mesh.num_tris);
686
1776
 
687
- int i = mesh.indices[tri*3+0];
688
- int j = mesh.indices[tri*3+1];
689
- int k = mesh.indices[tri*3+2];
1777
+ int i = mesh.indices[tri*3+0];
1778
+ int j = mesh.indices[tri*3+1];
1779
+ int k = mesh.indices[tri*3+2];
690
1780
 
691
- vec3 vp = mesh.velocities[i];
692
- vec3 vq = mesh.velocities[j];
693
- vec3 vr = mesh.velocities[k];
1781
+ vec3 vp = mesh.velocities[i];
1782
+ vec3 vq = mesh.velocities[j];
1783
+ vec3 vr = mesh.velocities[k];
694
1784
 
695
- adj_u += (vp[0] - vr[0]) * adj_ret[0] + (vp[1] - vr[1]) * adj_ret[1] + (vp[2] - vr[2]) * adj_ret[2];
696
- adj_v += (vq[0] - vr[0]) * adj_ret[0] + (vq[1] - vr[1]) * adj_ret[1] + (vq[2] - vr[2]) * adj_ret[2];
1785
+ adj_u += (vp[0] - vr[0]) * adj_ret[0] + (vp[1] - vr[1]) * adj_ret[1] + (vp[2] - vr[2]) * adj_ret[2];
1786
+ adj_v += (vq[0] - vr[0]) * adj_ret[0] + (vq[1] - vr[1]) * adj_ret[1] + (vq[2] - vr[2]) * adj_ret[2];
697
1787
  }
698
1788
 
699
1789
  CUDA_CALLABLE inline vec3 mesh_eval_face_normal(uint64_t id, int tri)
700
1790
  {
701
- Mesh mesh = mesh_get(id);
1791
+ Mesh mesh = mesh_get(id);
702
1792
 
703
- if (!mesh.points)
704
- return vec3();
1793
+ if (!mesh.points)
1794
+ return vec3();
705
1795
 
706
- assert(tri < mesh.num_tris);
1796
+ assert(tri < mesh.num_tris);
707
1797
 
708
- int i = mesh.indices[tri*3+0];
709
- int j = mesh.indices[tri*3+1];
710
- int k = mesh.indices[tri*3+2];
1798
+ int i = mesh.indices[tri*3+0];
1799
+ int j = mesh.indices[tri*3+1];
1800
+ int k = mesh.indices[tri*3+2];
711
1801
 
712
- vec3 p = mesh.points[i];
713
- vec3 q = mesh.points[j];
714
- vec3 r = mesh.points[k];
1802
+ vec3 p = mesh.points[i];
1803
+ vec3 q = mesh.points[j];
1804
+ vec3 r = mesh.points[k];
715
1805
 
716
- return normalize(cross(q - p, r - p));
1806
+ return normalize(cross(q - p, r - p));
717
1807
  }
718
1808
 
719
1809
  CUDA_CALLABLE inline void adj_mesh_eval_face_normal(uint64_t id, int tri,
720
- uint64_t& adj_id, int& adj_tri, const vec3& adj_ret)
1810
+ uint64_t& adj_id, int& adj_tri, const vec3& adj_ret)
721
1811
  {
722
- // no-op
1812
+ // no-op
723
1813
  }
724
1814
 
725
1815
  CUDA_CALLABLE inline vec3 mesh_get_point(uint64_t id, int index)
726
1816
  {
727
- Mesh mesh = mesh_get(id);
1817
+ Mesh mesh = mesh_get(id);
728
1818
 
729
- if (!mesh.points)
730
- return vec3();
1819
+ if (!mesh.points)
1820
+ return vec3();
731
1821
 
732
1822
  #if FP_CHECK
733
- if (index >= mesh.num_tris * 3)
734
- {
735
- printf("mesh_get_point (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
736
- assert(0);
737
- }
1823
+ if (index >= mesh.num_tris * 3)
1824
+ {
1825
+ printf("mesh_get_point (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
1826
+ assert(0);
1827
+ }
738
1828
  #endif
739
1829
 
740
- int i = mesh.indices[index];
741
- return mesh.points[i];
1830
+ int i = mesh.indices[index];
1831
+ return mesh.points[i];
742
1832
  }
743
1833
 
744
1834
  CUDA_CALLABLE inline void adj_mesh_get_point(uint64_t id, int index,
745
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1835
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
746
1836
  {
747
- // no-op
1837
+ // no-op
748
1838
  }
749
1839
 
750
1840
  CUDA_CALLABLE inline vec3 mesh_get_velocity(uint64_t id, int index)
751
1841
  {
752
- Mesh mesh = mesh_get(id);
1842
+ Mesh mesh = mesh_get(id);
753
1843
 
754
- if (!mesh.velocities)
755
- return vec3();
1844
+ if (!mesh.velocities)
1845
+ return vec3();
756
1846
 
757
1847
  #if FP_CHECK
758
- if (index >= mesh.num_tris * 3)
759
- {
760
- printf("mesh_get_velocity (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
761
- assert(0);
762
- }
1848
+ if (index >= mesh.num_tris * 3)
1849
+ {
1850
+ printf("mesh_get_velocity (%llu, %d) out of bounds at %s:%d\n", id, index, __FILE__, __LINE__);
1851
+ assert(0);
1852
+ }
763
1853
  #endif
764
1854
 
765
- int i = mesh.indices[index];
766
- return mesh.velocities[i];
1855
+ int i = mesh.indices[index];
1856
+ return mesh.velocities[i];
767
1857
  }
768
1858
 
769
1859
  CUDA_CALLABLE inline void adj_mesh_get_velocity(uint64_t id, int index,
770
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1860
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
771
1861
  {
772
- // no-op
1862
+ // no-op
773
1863
  }
774
1864
 
775
1865
  CUDA_CALLABLE inline int mesh_get_index(uint64_t id, int face_vertex_index)
776
1866
  {
777
- Mesh mesh = mesh_get(id);
1867
+ Mesh mesh = mesh_get(id);
778
1868
 
779
- if (!mesh.indices)
780
- return -1;
1869
+ if (!mesh.indices)
1870
+ return -1;
781
1871
 
782
- assert(face_vertex_index < mesh.num_tris * 3);
1872
+ assert(face_vertex_index < mesh.num_tris * 3);
783
1873
 
784
- return mesh.indices[face_vertex_index];
1874
+ return mesh.indices[face_vertex_index];
785
1875
  }
786
1876
 
787
1877
  CUDA_CALLABLE inline void adj_mesh_get_index(uint64_t id, int index,
788
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1878
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
789
1879
  {
790
- // no-op
1880
+ // no-op
791
1881
  }
792
1882
 
793
- bool mesh_get_descriptor(uint64_t id, Mesh& mesh);
794
- void mesh_add_descriptor(uint64_t id, const Mesh& mesh);
795
- void mesh_rem_descriptor(uint64_t id);
796
-
1883
+ CUDA_CALLABLE bool mesh_get_descriptor(uint64_t id, Mesh& mesh);
1884
+ CUDA_CALLABLE void mesh_add_descriptor(uint64_t id, const Mesh& mesh);
1885
+ CUDA_CALLABLE void mesh_rem_descriptor(uint64_t id);
797
1886
 
798
1887
  } // namespace wp