warp-lang 1.0.2__py3-none-manylinux2014_x86_64.whl → 1.2.0__py3-none-manylinux2014_x86_64.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 (356) hide show
  1. warp/__init__.py +108 -97
  2. warp/__init__.pyi +1 -1
  3. warp/bin/warp-clang.so +0 -0
  4. warp/bin/warp.so +0 -0
  5. warp/build.py +88 -113
  6. warp/build_dll.py +383 -375
  7. warp/builtins.py +3693 -3354
  8. warp/codegen.py +2925 -2792
  9. warp/config.py +40 -36
  10. warp/constants.py +49 -45
  11. warp/context.py +5409 -5102
  12. warp/dlpack.py +442 -442
  13. warp/examples/__init__.py +16 -16
  14. warp/examples/assets/bear.usd +0 -0
  15. warp/examples/assets/bunny.usd +0 -0
  16. warp/examples/assets/cartpole.urdf +110 -110
  17. warp/examples/assets/crazyflie.usd +0 -0
  18. warp/examples/assets/cube.usd +0 -0
  19. warp/examples/assets/nv_ant.xml +92 -92
  20. warp/examples/assets/nv_humanoid.xml +183 -183
  21. warp/examples/assets/quadruped.urdf +267 -267
  22. warp/examples/assets/rocks.nvdb +0 -0
  23. warp/examples/assets/rocks.usd +0 -0
  24. warp/examples/assets/sphere.usd +0 -0
  25. warp/examples/benchmarks/benchmark_api.py +381 -383
  26. warp/examples/benchmarks/benchmark_cloth.py +278 -277
  27. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
  28. warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
  29. warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
  30. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
  31. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
  32. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
  33. warp/examples/benchmarks/benchmark_cloth_warp.py +145 -146
  34. warp/examples/benchmarks/benchmark_launches.py +293 -295
  35. warp/examples/browse.py +29 -29
  36. warp/examples/core/example_dem.py +232 -219
  37. warp/examples/core/example_fluid.py +291 -267
  38. warp/examples/core/example_graph_capture.py +142 -126
  39. warp/examples/core/example_marching_cubes.py +186 -174
  40. warp/examples/core/example_mesh.py +172 -155
  41. warp/examples/core/example_mesh_intersect.py +203 -193
  42. warp/examples/core/example_nvdb.py +174 -170
  43. warp/examples/core/example_raycast.py +103 -90
  44. warp/examples/core/example_raymarch.py +197 -178
  45. warp/examples/core/example_render_opengl.py +183 -141
  46. warp/examples/core/example_sph.py +403 -387
  47. warp/examples/core/example_torch.py +219 -181
  48. warp/examples/core/example_wave.py +261 -248
  49. warp/examples/fem/bsr_utils.py +378 -380
  50. warp/examples/fem/example_apic_fluid.py +432 -389
  51. warp/examples/fem/example_burgers.py +262 -0
  52. warp/examples/fem/example_convection_diffusion.py +180 -168
  53. warp/examples/fem/example_convection_diffusion_dg.py +217 -209
  54. warp/examples/fem/example_deformed_geometry.py +175 -159
  55. warp/examples/fem/example_diffusion.py +199 -173
  56. warp/examples/fem/example_diffusion_3d.py +178 -152
  57. warp/examples/fem/example_diffusion_mgpu.py +219 -214
  58. warp/examples/fem/example_mixed_elasticity.py +242 -222
  59. warp/examples/fem/example_navier_stokes.py +257 -243
  60. warp/examples/fem/example_stokes.py +218 -192
  61. warp/examples/fem/example_stokes_transfer.py +263 -249
  62. warp/examples/fem/mesh_utils.py +133 -109
  63. warp/examples/fem/plot_utils.py +292 -287
  64. warp/examples/optim/example_bounce.py +258 -246
  65. warp/examples/optim/example_cloth_throw.py +220 -209
  66. warp/examples/optim/example_diffray.py +564 -536
  67. warp/examples/optim/example_drone.py +862 -835
  68. warp/examples/optim/example_inverse_kinematics.py +174 -168
  69. warp/examples/optim/example_inverse_kinematics_torch.py +183 -169
  70. warp/examples/optim/example_spring_cage.py +237 -231
  71. warp/examples/optim/example_trajectory.py +221 -199
  72. warp/examples/optim/example_walker.py +304 -293
  73. warp/examples/sim/example_cartpole.py +137 -129
  74. warp/examples/sim/example_cloth.py +194 -186
  75. warp/examples/sim/example_granular.py +122 -111
  76. warp/examples/sim/example_granular_collision_sdf.py +195 -186
  77. warp/examples/sim/example_jacobian_ik.py +234 -214
  78. warp/examples/sim/example_particle_chain.py +116 -105
  79. warp/examples/sim/example_quadruped.py +191 -180
  80. warp/examples/sim/example_rigid_chain.py +195 -187
  81. warp/examples/sim/example_rigid_contact.py +187 -177
  82. warp/examples/sim/example_rigid_force.py +125 -125
  83. warp/examples/sim/example_rigid_gyroscopic.py +107 -95
  84. warp/examples/sim/example_rigid_soft_contact.py +132 -122
  85. warp/examples/sim/example_soft_body.py +188 -177
  86. warp/fabric.py +337 -335
  87. warp/fem/__init__.py +61 -27
  88. warp/fem/cache.py +403 -388
  89. warp/fem/dirichlet.py +178 -179
  90. warp/fem/domain.py +262 -263
  91. warp/fem/field/__init__.py +100 -101
  92. warp/fem/field/field.py +148 -149
  93. warp/fem/field/nodal_field.py +298 -299
  94. warp/fem/field/restriction.py +22 -21
  95. warp/fem/field/test.py +180 -181
  96. warp/fem/field/trial.py +183 -183
  97. warp/fem/geometry/__init__.py +16 -19
  98. warp/fem/geometry/closest_point.py +69 -70
  99. warp/fem/geometry/deformed_geometry.py +270 -271
  100. warp/fem/geometry/element.py +748 -744
  101. warp/fem/geometry/geometry.py +184 -186
  102. warp/fem/geometry/grid_2d.py +380 -373
  103. warp/fem/geometry/grid_3d.py +437 -435
  104. warp/fem/geometry/hexmesh.py +953 -953
  105. warp/fem/geometry/nanogrid.py +455 -0
  106. warp/fem/geometry/partition.py +374 -376
  107. warp/fem/geometry/quadmesh_2d.py +532 -532
  108. warp/fem/geometry/tetmesh.py +840 -840
  109. warp/fem/geometry/trimesh_2d.py +577 -577
  110. warp/fem/integrate.py +1684 -1615
  111. warp/fem/operator.py +190 -191
  112. warp/fem/polynomial.py +214 -213
  113. warp/fem/quadrature/__init__.py +2 -2
  114. warp/fem/quadrature/pic_quadrature.py +243 -245
  115. warp/fem/quadrature/quadrature.py +295 -294
  116. warp/fem/space/__init__.py +179 -292
  117. warp/fem/space/basis_space.py +522 -489
  118. warp/fem/space/collocated_function_space.py +100 -105
  119. warp/fem/space/dof_mapper.py +236 -236
  120. warp/fem/space/function_space.py +148 -145
  121. warp/fem/space/grid_2d_function_space.py +148 -267
  122. warp/fem/space/grid_3d_function_space.py +167 -306
  123. warp/fem/space/hexmesh_function_space.py +253 -352
  124. warp/fem/space/nanogrid_function_space.py +202 -0
  125. warp/fem/space/partition.py +350 -350
  126. warp/fem/space/quadmesh_2d_function_space.py +261 -369
  127. warp/fem/space/restriction.py +161 -160
  128. warp/fem/space/shape/__init__.py +90 -15
  129. warp/fem/space/shape/cube_shape_function.py +728 -738
  130. warp/fem/space/shape/shape_function.py +102 -103
  131. warp/fem/space/shape/square_shape_function.py +611 -611
  132. warp/fem/space/shape/tet_shape_function.py +565 -567
  133. warp/fem/space/shape/triangle_shape_function.py +429 -429
  134. warp/fem/space/tetmesh_function_space.py +224 -292
  135. warp/fem/space/topology.py +297 -295
  136. warp/fem/space/trimesh_2d_function_space.py +153 -221
  137. warp/fem/types.py +77 -77
  138. warp/fem/utils.py +495 -495
  139. warp/jax.py +166 -141
  140. warp/jax_experimental.py +341 -339
  141. warp/native/array.h +1081 -1025
  142. warp/native/builtin.h +1603 -1560
  143. warp/native/bvh.cpp +402 -398
  144. warp/native/bvh.cu +533 -525
  145. warp/native/bvh.h +430 -429
  146. warp/native/clang/clang.cpp +496 -464
  147. warp/native/crt.cpp +42 -32
  148. warp/native/crt.h +352 -335
  149. warp/native/cuda_crt.h +1049 -1049
  150. warp/native/cuda_util.cpp +549 -540
  151. warp/native/cuda_util.h +288 -203
  152. warp/native/cutlass_gemm.cpp +34 -34
  153. warp/native/cutlass_gemm.cu +372 -372
  154. warp/native/error.cpp +66 -66
  155. warp/native/error.h +27 -27
  156. warp/native/exports.h +187 -0
  157. warp/native/fabric.h +228 -228
  158. warp/native/hashgrid.cpp +301 -278
  159. warp/native/hashgrid.cu +78 -77
  160. warp/native/hashgrid.h +227 -227
  161. warp/native/initializer_array.h +32 -32
  162. warp/native/intersect.h +1204 -1204
  163. warp/native/intersect_adj.h +365 -365
  164. warp/native/intersect_tri.h +322 -322
  165. warp/native/marching.cpp +2 -2
  166. warp/native/marching.cu +497 -497
  167. warp/native/marching.h +2 -2
  168. warp/native/mat.h +1545 -1498
  169. warp/native/matnn.h +333 -333
  170. warp/native/mesh.cpp +203 -203
  171. warp/native/mesh.cu +292 -293
  172. warp/native/mesh.h +1887 -1887
  173. warp/native/nanovdb/GridHandle.h +366 -0
  174. warp/native/nanovdb/HostBuffer.h +590 -0
  175. warp/native/nanovdb/NanoVDB.h +6624 -4782
  176. warp/native/nanovdb/PNanoVDB.h +3390 -2553
  177. warp/native/noise.h +850 -850
  178. warp/native/quat.h +1112 -1085
  179. warp/native/rand.h +303 -299
  180. warp/native/range.h +108 -108
  181. warp/native/reduce.cpp +156 -156
  182. warp/native/reduce.cu +348 -348
  183. warp/native/runlength_encode.cpp +61 -61
  184. warp/native/runlength_encode.cu +46 -46
  185. warp/native/scan.cpp +30 -30
  186. warp/native/scan.cu +36 -36
  187. warp/native/scan.h +7 -7
  188. warp/native/solid_angle.h +442 -442
  189. warp/native/sort.cpp +94 -94
  190. warp/native/sort.cu +97 -97
  191. warp/native/sort.h +14 -14
  192. warp/native/sparse.cpp +337 -337
  193. warp/native/sparse.cu +544 -544
  194. warp/native/spatial.h +630 -630
  195. warp/native/svd.h +562 -562
  196. warp/native/temp_buffer.h +30 -30
  197. warp/native/vec.h +1177 -1133
  198. warp/native/volume.cpp +529 -297
  199. warp/native/volume.cu +58 -32
  200. warp/native/volume.h +960 -538
  201. warp/native/volume_builder.cu +446 -425
  202. warp/native/volume_builder.h +34 -19
  203. warp/native/volume_impl.h +61 -0
  204. warp/native/warp.cpp +1057 -1052
  205. warp/native/warp.cu +2949 -2828
  206. warp/native/warp.h +321 -305
  207. warp/optim/__init__.py +9 -9
  208. warp/optim/adam.py +120 -120
  209. warp/optim/linear.py +1104 -939
  210. warp/optim/sgd.py +104 -92
  211. warp/render/__init__.py +10 -10
  212. warp/render/render_opengl.py +3356 -3204
  213. warp/render/render_usd.py +768 -749
  214. warp/render/utils.py +152 -150
  215. warp/sim/__init__.py +52 -59
  216. warp/sim/articulation.py +685 -685
  217. warp/sim/collide.py +1594 -1590
  218. warp/sim/import_mjcf.py +489 -481
  219. warp/sim/import_snu.py +220 -221
  220. warp/sim/import_urdf.py +536 -516
  221. warp/sim/import_usd.py +887 -881
  222. warp/sim/inertia.py +316 -317
  223. warp/sim/integrator.py +234 -233
  224. warp/sim/integrator_euler.py +1956 -1956
  225. warp/sim/integrator_featherstone.py +1917 -1991
  226. warp/sim/integrator_xpbd.py +3288 -3312
  227. warp/sim/model.py +4473 -4314
  228. warp/sim/particles.py +113 -112
  229. warp/sim/render.py +417 -403
  230. warp/sim/utils.py +413 -410
  231. warp/sparse.py +1289 -1227
  232. warp/stubs.py +2192 -2469
  233. warp/tape.py +1162 -225
  234. warp/tests/__init__.py +1 -1
  235. warp/tests/__main__.py +4 -4
  236. warp/tests/assets/test_index_grid.nvdb +0 -0
  237. warp/tests/assets/torus.usda +105 -105
  238. warp/tests/aux_test_class_kernel.py +26 -26
  239. warp/tests/aux_test_compile_consts_dummy.py +10 -10
  240. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
  241. warp/tests/aux_test_dependent.py +20 -22
  242. warp/tests/aux_test_grad_customs.py +21 -23
  243. warp/tests/aux_test_reference.py +9 -11
  244. warp/tests/aux_test_reference_reference.py +8 -10
  245. warp/tests/aux_test_square.py +15 -17
  246. warp/tests/aux_test_unresolved_func.py +14 -14
  247. warp/tests/aux_test_unresolved_symbol.py +14 -14
  248. warp/tests/disabled_kinematics.py +237 -239
  249. warp/tests/run_coverage_serial.py +31 -31
  250. warp/tests/test_adam.py +155 -157
  251. warp/tests/test_arithmetic.py +1088 -1124
  252. warp/tests/test_array.py +2415 -2326
  253. warp/tests/test_array_reduce.py +148 -150
  254. warp/tests/test_async.py +666 -656
  255. warp/tests/test_atomic.py +139 -141
  256. warp/tests/test_bool.py +212 -149
  257. warp/tests/test_builtins_resolution.py +1290 -1292
  258. warp/tests/test_bvh.py +162 -171
  259. warp/tests/test_closest_point_edge_edge.py +227 -228
  260. warp/tests/test_codegen.py +562 -553
  261. warp/tests/test_compile_consts.py +217 -101
  262. warp/tests/test_conditional.py +244 -246
  263. warp/tests/test_copy.py +230 -215
  264. warp/tests/test_ctypes.py +630 -632
  265. warp/tests/test_dense.py +65 -67
  266. warp/tests/test_devices.py +89 -98
  267. warp/tests/test_dlpack.py +528 -529
  268. warp/tests/test_examples.py +403 -378
  269. warp/tests/test_fabricarray.py +952 -955
  270. warp/tests/test_fast_math.py +60 -54
  271. warp/tests/test_fem.py +1298 -1278
  272. warp/tests/test_fp16.py +128 -130
  273. warp/tests/test_func.py +336 -337
  274. warp/tests/test_generics.py +596 -571
  275. warp/tests/test_grad.py +885 -640
  276. warp/tests/test_grad_customs.py +331 -336
  277. warp/tests/test_hash_grid.py +208 -164
  278. warp/tests/test_import.py +37 -39
  279. warp/tests/test_indexedarray.py +1132 -1134
  280. warp/tests/test_intersect.py +65 -67
  281. warp/tests/test_jax.py +305 -307
  282. warp/tests/test_large.py +169 -164
  283. warp/tests/test_launch.py +352 -354
  284. warp/tests/test_lerp.py +217 -261
  285. warp/tests/test_linear_solvers.py +189 -171
  286. warp/tests/test_lvalue.py +419 -493
  287. warp/tests/test_marching_cubes.py +63 -65
  288. warp/tests/test_mat.py +1799 -1827
  289. warp/tests/test_mat_lite.py +113 -115
  290. warp/tests/test_mat_scalar_ops.py +2905 -2889
  291. warp/tests/test_math.py +124 -193
  292. warp/tests/test_matmul.py +498 -499
  293. warp/tests/test_matmul_lite.py +408 -410
  294. warp/tests/test_mempool.py +186 -190
  295. warp/tests/test_mesh.py +281 -324
  296. warp/tests/test_mesh_query_aabb.py +226 -241
  297. warp/tests/test_mesh_query_point.py +690 -702
  298. warp/tests/test_mesh_query_ray.py +290 -303
  299. warp/tests/test_mlp.py +274 -276
  300. warp/tests/test_model.py +108 -110
  301. warp/tests/test_module_hashing.py +111 -0
  302. warp/tests/test_modules_lite.py +36 -39
  303. warp/tests/test_multigpu.py +161 -163
  304. warp/tests/test_noise.py +244 -248
  305. warp/tests/test_operators.py +248 -250
  306. warp/tests/test_options.py +121 -125
  307. warp/tests/test_peer.py +131 -137
  308. warp/tests/test_pinned.py +76 -78
  309. warp/tests/test_print.py +52 -54
  310. warp/tests/test_quat.py +2084 -2086
  311. warp/tests/test_rand.py +324 -288
  312. warp/tests/test_reload.py +207 -217
  313. warp/tests/test_rounding.py +177 -179
  314. warp/tests/test_runlength_encode.py +188 -190
  315. warp/tests/test_sim_grad.py +241 -0
  316. warp/tests/test_sim_kinematics.py +89 -97
  317. warp/tests/test_smoothstep.py +166 -168
  318. warp/tests/test_snippet.py +303 -266
  319. warp/tests/test_sparse.py +466 -460
  320. warp/tests/test_spatial.py +2146 -2148
  321. warp/tests/test_special_values.py +362 -0
  322. warp/tests/test_streams.py +484 -473
  323. warp/tests/test_struct.py +708 -675
  324. warp/tests/test_tape.py +171 -148
  325. warp/tests/test_torch.py +741 -743
  326. warp/tests/test_transient_module.py +85 -87
  327. warp/tests/test_types.py +554 -659
  328. warp/tests/test_utils.py +488 -499
  329. warp/tests/test_vec.py +1262 -1268
  330. warp/tests/test_vec_lite.py +71 -73
  331. warp/tests/test_vec_scalar_ops.py +2097 -2099
  332. warp/tests/test_verify_fp.py +92 -94
  333. warp/tests/test_volume.py +961 -736
  334. warp/tests/test_volume_write.py +338 -265
  335. warp/tests/unittest_serial.py +38 -37
  336. warp/tests/unittest_suites.py +367 -359
  337. warp/tests/unittest_utils.py +434 -578
  338. warp/tests/unused_test_misc.py +69 -71
  339. warp/tests/walkthrough_debug.py +85 -85
  340. warp/thirdparty/appdirs.py +598 -598
  341. warp/thirdparty/dlpack.py +143 -143
  342. warp/thirdparty/unittest_parallel.py +563 -561
  343. warp/torch.py +321 -295
  344. warp/types.py +4941 -4450
  345. warp/utils.py +1008 -821
  346. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +126 -126
  347. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/METADATA +365 -400
  348. warp_lang-1.2.0.dist-info/RECORD +359 -0
  349. warp/examples/assets/cube.usda +0 -42
  350. warp/examples/assets/sphere.usda +0 -56
  351. warp/examples/assets/torus.usda +0 -105
  352. warp/examples/fem/example_convection_diffusion_dg0.py +0 -194
  353. warp/native/nanovdb/PNanoVDBWrite.h +0 -295
  354. warp_lang-1.0.2.dist-info/RECORD +0 -352
  355. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
  356. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
warp/native/mesh.h CHANGED
@@ -1,1887 +1,1887 @@
1
- /** Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
2
- * NVIDIA CORPORATION and its licensors retain all intellectual property
3
- * and proprietary rights in and to this software, related documentation
4
- * and any modifications thereto. Any use, reproduction, disclosure or
5
- * distribution of this software and related documentation without an express
6
- * license agreement from NVIDIA CORPORATION is strictly prohibited.
7
- */
8
-
9
- #pragma once
10
-
11
- #include "builtin.h"
12
- #include "bvh.h"
13
- #include "intersect.h"
14
- #include "array.h"
15
- #include "solid_angle.h"
16
-
17
- #define BVH_DEBUG 0
18
-
19
- namespace wp
20
- {
21
-
22
- struct Mesh
23
- {
24
- array_t<vec3> points;
25
- array_t<vec3> velocities;
26
-
27
- array_t<int> indices;
28
-
29
- vec3* lowers;
30
- vec3* uppers;
31
-
32
- SolidAngleProps* solid_angle_props;
33
-
34
- int num_points;
35
- int num_tris;
36
-
37
- BVH bvh;
38
-
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
- }
68
- };
69
-
70
- CUDA_CALLABLE inline Mesh mesh_get(uint64_t id)
71
- {
72
- return *(Mesh*)(id);
73
- }
74
-
75
-
76
- CUDA_CALLABLE inline Mesh& operator += (Mesh& a, const Mesh& b) {
77
- // dummy operator needed for adj_select involving meshes
78
- return a;
79
- }
80
-
81
- CUDA_CALLABLE inline float distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
82
- {
83
- vec3 cp = closest_point_to_aabb(p, lower, upper);
84
-
85
- return length_sq(p-cp);
86
- }
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
- }
136
-
137
- CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p);
138
-
139
- // returns true if there is a point (strictly) < distance max_dist
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)
141
- {
142
- Mesh mesh = mesh_get(id);
143
-
144
- int stack[32];
145
- stack[0] = *mesh.bvh.root;
146
-
147
- int count = 1;
148
-
149
- float min_dist_sq = max_dist*max_dist;
150
- int min_face;
151
- float min_v;
152
- float min_w;
153
-
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;
182
-
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
- }
218
-
219
- #if BVH_DEBUG
220
-
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
- }
235
- #endif
236
-
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
- {
359
- #if BVH_DEBUG
360
- secondary_culls++;
361
- #endif
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
- }
403
-
404
- #if BVH_DEBUG
405
-
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
-
458
-
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
- }
486
-
487
- fclose(f);
488
- }
489
- #endif
490
-
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;
520
-
521
- #if BVH_DEBUG
522
- int tests = 0;
523
- int secondary_culls = 0;
524
-
525
- std::vector<int> test_history;
526
- std::vector<vec3> test_centers;
527
- std::vector<vec3> test_extents;
528
- #endif
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
- }
548
-
549
- const int left_index = lower.i;
550
- const int right_index = upper.i;
551
-
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
- }
587
-
588
- #if BVH_DEBUG
589
-
590
- tests++;
591
-
592
- bounds3 b;
593
- b = bounds_union(b, p);
594
- b = bounds_union(b, q);
595
- b = bounds_union(b, r);
596
-
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
605
-
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
- }
641
-
642
-
643
- #if BVH_DEBUG
644
- printf("%d\n", tests);
645
-
646
- static int max_tests = 0;
647
- static vec3 max_point;
648
- static float max_point_dist = 0.0f;
649
- static int max_secondary_culls = 0;
650
-
651
- if (secondary_culls > max_secondary_culls)
652
- max_secondary_culls = secondary_culls;
653
-
654
- if (tests > max_tests)
655
- {
656
- max_tests = tests;
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
- }
673
- #endif
674
-
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
- }
688
- }
689
-
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)
692
- {
693
- Mesh mesh = mesh_get(id);
694
-
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);
918
-
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;
924
-
925
- int count = 1;
926
- angle[0] = 0.0f;
927
-
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];
985
- }
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
- }
992
-
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)
1207
- {
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
- }
1296
-
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);
1349
-
1350
- int stack[32];
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
-
1432
- }
1433
-
1434
-
1435
- CUDA_CALLABLE inline void adj_mesh_query_ray(
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)
1438
- {
1439
-
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];
1446
-
1447
- vec3 a = mesh.points[i];
1448
- vec3 b = mesh.points[j];
1449
- vec3 c = mesh.points[k];
1450
-
1451
- vec3 adj_a, adj_b, adj_c;
1452
-
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);
1454
-
1455
- }
1456
-
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
-
1514
- // determine if a point is inside (ret < 0 ) or outside the mesh (ret > 0)
1515
- CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p)
1516
- {
1517
- float t, u, v, sign;
1518
- vec3 n;
1519
- int face;
1520
-
1521
- int vote = 0;
1522
-
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
- }
1530
-
1531
- if (vote == 3)
1532
- return -1.0f;
1533
- else
1534
- return 1.0f;
1535
- }
1536
-
1537
- // stores state required to traverse the BVH nodes that
1538
- // overlap with a query AABB.
1539
- struct mesh_query_aabb_t
1540
- {
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)
1552
- {
1553
- return *this;
1554
- }
1555
-
1556
- // Mesh Id
1557
- Mesh mesh;
1558
- // BVH traversal stack:
1559
- int stack[32];
1560
- int count;
1561
-
1562
- // inputs
1563
- wp::vec3 input_lower;
1564
- wp::vec3 input_upper;
1565
-
1566
- // Face
1567
- int face;
1568
- };
1569
-
1570
-
1571
-
1572
- CUDA_CALLABLE inline mesh_query_aabb_t mesh_query_aabb(
1573
- uint64_t id, const vec3& lower, const vec3& upper)
1574
- {
1575
- // This routine traverses the BVH tree until it finds
1576
- // the first triangle with an overlapping bvh.
1577
-
1578
- // initialize empty
1579
- mesh_query_aabb_t query;
1580
- query.face = -1;
1581
-
1582
- Mesh mesh = mesh_get(id);
1583
- query.mesh = mesh;
1584
-
1585
- query.stack[0] = *mesh.bvh.root;
1586
- query.count = 1;
1587
- query.input_lower = lower;
1588
- query.input_upper = upper;
1589
-
1590
- wp::bounds3 input_bounds(query.input_lower, query.input_upper);
1591
-
1592
- // Navigate through the bvh, find the first overlapping leaf node.
1593
- while (query.count)
1594
- {
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];
1598
-
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);
1601
- wp::bounds3 current_bounds(lower_pos, upper_pos);
1602
- if (!input_bounds.overlaps(current_bounds))
1603
- {
1604
- // Skip this box, it doesn't overlap with our target box.
1605
- continue;
1606
- }
1607
-
1608
- const int left_index = node_lower.i;
1609
- const int right_index = node_upper.i;
1610
-
1611
- // Make bounds from this AABB
1612
- if (node_lower.b)
1613
- {
1614
- // found very first triangle index.
1615
- // Back up one level and return
1616
- query.stack[query.count++] = nodeIndex;
1617
- return query;
1618
- }
1619
- else
1620
- {
1621
- query.stack[query.count++] = left_index;
1622
- query.stack[query.count++] = right_index;
1623
- }
1624
- }
1625
-
1626
- return query;
1627
- }
1628
-
1629
- //Stub
1630
- CUDA_CALLABLE inline void adj_mesh_query_aabb(uint64_t id, const vec3& lower, const vec3& upper,
1631
- uint64_t, vec3&, vec3&, mesh_query_aabb_t&)
1632
- {
1633
-
1634
- }
1635
-
1636
- CUDA_CALLABLE inline bool mesh_query_aabb_next(mesh_query_aabb_t& query, int& index)
1637
- {
1638
- Mesh mesh = query.mesh;
1639
-
1640
- wp::bounds3 input_bounds(query.input_lower, query.input_upper);
1641
- // Navigate through the bvh, find the first overlapping leaf node.
1642
- while (query.count)
1643
- {
1644
- const int nodeIndex = query.stack[--query.count];
1645
- BVHPackedNodeHalf node_lower = mesh.bvh.node_lowers[nodeIndex];
1646
- BVHPackedNodeHalf node_upper = mesh.bvh.node_uppers[nodeIndex];
1647
-
1648
- wp::vec3 lower_pos(node_lower.x, node_lower.y, node_lower.z);
1649
- wp::vec3 upper_pos(node_upper.x, node_upper.y, node_upper.z);
1650
- wp::bounds3 current_bounds(lower_pos, upper_pos);
1651
- if (!input_bounds.overlaps(current_bounds))
1652
- {
1653
- // Skip this box, it doesn't overlap with our target box.
1654
- continue;
1655
- }
1656
-
1657
- const int left_index = node_lower.i;
1658
- const int right_index = node_upper.i;
1659
-
1660
- // Make bounds from this AABB
1661
- if (node_lower.b)
1662
- {
1663
- // found very first triangle index
1664
- query.face = left_index;
1665
- index = left_index;
1666
- return true;
1667
- }
1668
- else
1669
- {
1670
-
1671
- query.stack[query.count++] = left_index;
1672
- query.stack[query.count++] = right_index;
1673
- }
1674
- }
1675
- return false;
1676
- }
1677
-
1678
-
1679
- CUDA_CALLABLE inline int iter_next(mesh_query_aabb_t& query)
1680
- {
1681
- return query.face;
1682
- }
1683
-
1684
- CUDA_CALLABLE inline bool iter_cmp(mesh_query_aabb_t& query)
1685
- {
1686
- bool finished = mesh_query_aabb_next(query, query.face);
1687
- return finished;
1688
- }
1689
-
1690
- CUDA_CALLABLE inline mesh_query_aabb_t iter_reverse(const mesh_query_aabb_t& query)
1691
- {
1692
- // can't reverse BVH queries, users should not rely on neighbor ordering
1693
- return query;
1694
- }
1695
-
1696
-
1697
- // stub
1698
- CUDA_CALLABLE inline void adj_mesh_query_aabb_next(mesh_query_aabb_t& query, int& index, mesh_query_aabb_t&, int&, bool&)
1699
- {
1700
-
1701
- }
1702
-
1703
-
1704
- CUDA_CALLABLE inline vec3 mesh_eval_position(uint64_t id, int tri, float u, float v)
1705
- {
1706
- Mesh mesh = mesh_get(id);
1707
-
1708
- if (!mesh.points)
1709
- return vec3();
1710
-
1711
- assert(tri < mesh.num_tris);
1712
-
1713
- int i = mesh.indices[tri*3+0];
1714
- int j = mesh.indices[tri*3+1];
1715
- int k = mesh.indices[tri*3+2];
1716
-
1717
- vec3 p = mesh.points[i];
1718
- vec3 q = mesh.points[j];
1719
- vec3 r = mesh.points[k];
1720
-
1721
- return p*u + q*v + r*(1.0f-u-v);
1722
- }
1723
-
1724
- CUDA_CALLABLE inline vec3 mesh_eval_velocity(uint64_t id, int tri, float u, float v)
1725
- {
1726
- Mesh mesh = mesh_get(id);
1727
-
1728
- if (!mesh.velocities)
1729
- return vec3();
1730
-
1731
- assert(tri < mesh.num_tris);
1732
-
1733
- int i = mesh.indices[tri*3+0];
1734
- int j = mesh.indices[tri*3+1];
1735
- int k = mesh.indices[tri*3+2];
1736
-
1737
- vec3 vp = mesh.velocities[i];
1738
- vec3 vq = mesh.velocities[j];
1739
- vec3 vr = mesh.velocities[k];
1740
-
1741
- return vp*u + vq*v + vr*(1.0f-u-v);
1742
- }
1743
-
1744
-
1745
- CUDA_CALLABLE inline void adj_mesh_eval_position(uint64_t id, int tri, float u, float v,
1746
- uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1747
- {
1748
- Mesh mesh = mesh_get(id);
1749
-
1750
- if (!mesh.points)
1751
- return;
1752
-
1753
- assert(tri < mesh.num_tris);
1754
-
1755
- int i = mesh.indices[tri*3+0];
1756
- int j = mesh.indices[tri*3+1];
1757
- int k = mesh.indices[tri*3+2];
1758
-
1759
- vec3 p = mesh.points[i];
1760
- vec3 q = mesh.points[j];
1761
- vec3 r = mesh.points[k];
1762
-
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];
1765
- }
1766
-
1767
- CUDA_CALLABLE inline void adj_mesh_eval_velocity(uint64_t id, int tri, float u, float v,
1768
- uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1769
- {
1770
- Mesh mesh = mesh_get(id);
1771
-
1772
- if (!mesh.velocities)
1773
- return;
1774
-
1775
- assert(tri < mesh.num_tris);
1776
-
1777
- int i = mesh.indices[tri*3+0];
1778
- int j = mesh.indices[tri*3+1];
1779
- int k = mesh.indices[tri*3+2];
1780
-
1781
- vec3 vp = mesh.velocities[i];
1782
- vec3 vq = mesh.velocities[j];
1783
- vec3 vr = mesh.velocities[k];
1784
-
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];
1787
- }
1788
-
1789
- CUDA_CALLABLE inline vec3 mesh_eval_face_normal(uint64_t id, int tri)
1790
- {
1791
- Mesh mesh = mesh_get(id);
1792
-
1793
- if (!mesh.points)
1794
- return vec3();
1795
-
1796
- assert(tri < mesh.num_tris);
1797
-
1798
- int i = mesh.indices[tri*3+0];
1799
- int j = mesh.indices[tri*3+1];
1800
- int k = mesh.indices[tri*3+2];
1801
-
1802
- vec3 p = mesh.points[i];
1803
- vec3 q = mesh.points[j];
1804
- vec3 r = mesh.points[k];
1805
-
1806
- return normalize(cross(q - p, r - p));
1807
- }
1808
-
1809
- CUDA_CALLABLE inline void adj_mesh_eval_face_normal(uint64_t id, int tri,
1810
- uint64_t& adj_id, int& adj_tri, const vec3& adj_ret)
1811
- {
1812
- // no-op
1813
- }
1814
-
1815
- CUDA_CALLABLE inline vec3 mesh_get_point(uint64_t id, int index)
1816
- {
1817
- Mesh mesh = mesh_get(id);
1818
-
1819
- if (!mesh.points)
1820
- return vec3();
1821
-
1822
- #if FP_CHECK
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
- }
1828
- #endif
1829
-
1830
- int i = mesh.indices[index];
1831
- return mesh.points[i];
1832
- }
1833
-
1834
- CUDA_CALLABLE inline void adj_mesh_get_point(uint64_t id, int index,
1835
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1836
- {
1837
- // no-op
1838
- }
1839
-
1840
- CUDA_CALLABLE inline vec3 mesh_get_velocity(uint64_t id, int index)
1841
- {
1842
- Mesh mesh = mesh_get(id);
1843
-
1844
- if (!mesh.velocities)
1845
- return vec3();
1846
-
1847
- #if FP_CHECK
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
- }
1853
- #endif
1854
-
1855
- int i = mesh.indices[index];
1856
- return mesh.velocities[i];
1857
- }
1858
-
1859
- CUDA_CALLABLE inline void adj_mesh_get_velocity(uint64_t id, int index,
1860
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1861
- {
1862
- // no-op
1863
- }
1864
-
1865
- CUDA_CALLABLE inline int mesh_get_index(uint64_t id, int face_vertex_index)
1866
- {
1867
- Mesh mesh = mesh_get(id);
1868
-
1869
- if (!mesh.indices)
1870
- return -1;
1871
-
1872
- assert(face_vertex_index < mesh.num_tris * 3);
1873
-
1874
- return mesh.indices[face_vertex_index];
1875
- }
1876
-
1877
- CUDA_CALLABLE inline void adj_mesh_get_index(uint64_t id, int index,
1878
- uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1879
- {
1880
- // no-op
1881
- }
1882
-
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);
1886
-
1887
- } // namespace wp
1
+ /** Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
2
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
3
+ * and proprietary rights in and to this software, related documentation
4
+ * and any modifications thereto. Any use, reproduction, disclosure or
5
+ * distribution of this software and related documentation without an express
6
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include "builtin.h"
12
+ #include "bvh.h"
13
+ #include "intersect.h"
14
+ #include "array.h"
15
+ #include "solid_angle.h"
16
+
17
+ #define BVH_DEBUG 0
18
+
19
+ namespace wp
20
+ {
21
+
22
+ struct Mesh
23
+ {
24
+ array_t<vec3> points;
25
+ array_t<vec3> velocities;
26
+
27
+ array_t<int> indices;
28
+
29
+ vec3* lowers;
30
+ vec3* uppers;
31
+
32
+ SolidAngleProps* solid_angle_props;
33
+
34
+ int num_points;
35
+ int num_tris;
36
+
37
+ BVH bvh;
38
+
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
+ }
68
+ };
69
+
70
+ CUDA_CALLABLE inline Mesh mesh_get(uint64_t id)
71
+ {
72
+ return *(Mesh*)(id);
73
+ }
74
+
75
+
76
+ CUDA_CALLABLE inline Mesh& operator += (Mesh& a, const Mesh& b) {
77
+ // dummy operator needed for adj_select involving meshes
78
+ return a;
79
+ }
80
+
81
+ CUDA_CALLABLE inline float distance_to_aabb_sq(const vec3& p, const vec3& lower, const vec3& upper)
82
+ {
83
+ vec3 cp = closest_point_to_aabb(p, lower, upper);
84
+
85
+ return length_sq(p-cp);
86
+ }
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
+ }
136
+
137
+ CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p);
138
+
139
+ // returns true if there is a point (strictly) < distance max_dist
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)
141
+ {
142
+ Mesh mesh = mesh_get(id);
143
+
144
+ int stack[32];
145
+ stack[0] = *mesh.bvh.root;
146
+
147
+ int count = 1;
148
+
149
+ float min_dist_sq = max_dist*max_dist;
150
+ int min_face;
151
+ float min_v;
152
+ float min_w;
153
+
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;
182
+
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
+ }
218
+
219
+ #if BVH_DEBUG
220
+
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
+ }
235
+ #endif
236
+
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
+ {
359
+ #if BVH_DEBUG
360
+ secondary_culls++;
361
+ #endif
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
+ }
403
+
404
+ #if BVH_DEBUG
405
+
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
+
458
+
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
+ }
486
+
487
+ fclose(f);
488
+ }
489
+ #endif
490
+
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;
520
+
521
+ #if BVH_DEBUG
522
+ int tests = 0;
523
+ int secondary_culls = 0;
524
+
525
+ std::vector<int> test_history;
526
+ std::vector<vec3> test_centers;
527
+ std::vector<vec3> test_extents;
528
+ #endif
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
+ }
548
+
549
+ const int left_index = lower.i;
550
+ const int right_index = upper.i;
551
+
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
+ }
587
+
588
+ #if BVH_DEBUG
589
+
590
+ tests++;
591
+
592
+ bounds3 b;
593
+ b = bounds_union(b, p);
594
+ b = bounds_union(b, q);
595
+ b = bounds_union(b, r);
596
+
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
605
+
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
+ }
641
+
642
+
643
+ #if BVH_DEBUG
644
+ printf("%d\n", tests);
645
+
646
+ static int max_tests = 0;
647
+ static vec3 max_point;
648
+ static float max_point_dist = 0.0f;
649
+ static int max_secondary_culls = 0;
650
+
651
+ if (secondary_culls > max_secondary_culls)
652
+ max_secondary_culls = secondary_culls;
653
+
654
+ if (tests > max_tests)
655
+ {
656
+ max_tests = tests;
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
+ }
673
+ #endif
674
+
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
+ }
688
+ }
689
+
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)
692
+ {
693
+ Mesh mesh = mesh_get(id);
694
+
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);
918
+
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;
924
+
925
+ int count = 1;
926
+ angle[0] = 0.0f;
927
+
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];
985
+ }
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
+ }
992
+
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)
1207
+ {
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
+ }
1296
+
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);
1349
+
1350
+ int stack[32];
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
+
1432
+ }
1433
+
1434
+
1435
+ CUDA_CALLABLE inline void adj_mesh_query_ray(
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)
1438
+ {
1439
+
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];
1446
+
1447
+ vec3 a = mesh.points[i];
1448
+ vec3 b = mesh.points[j];
1449
+ vec3 c = mesh.points[k];
1450
+
1451
+ vec3 adj_a, adj_b, adj_c;
1452
+
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);
1454
+
1455
+ }
1456
+
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
+
1514
+ // determine if a point is inside (ret < 0 ) or outside the mesh (ret > 0)
1515
+ CUDA_CALLABLE inline float mesh_query_inside(uint64_t id, const vec3& p)
1516
+ {
1517
+ float t, u, v, sign;
1518
+ vec3 n;
1519
+ int face;
1520
+
1521
+ int vote = 0;
1522
+
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
+ }
1530
+
1531
+ if (vote == 3)
1532
+ return -1.0f;
1533
+ else
1534
+ return 1.0f;
1535
+ }
1536
+
1537
+ // stores state required to traverse the BVH nodes that
1538
+ // overlap with a query AABB.
1539
+ struct mesh_query_aabb_t
1540
+ {
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)
1552
+ {
1553
+ return *this;
1554
+ }
1555
+
1556
+ // Mesh Id
1557
+ Mesh mesh;
1558
+ // BVH traversal stack:
1559
+ int stack[32];
1560
+ int count;
1561
+
1562
+ // inputs
1563
+ wp::vec3 input_lower;
1564
+ wp::vec3 input_upper;
1565
+
1566
+ // Face
1567
+ int face;
1568
+ };
1569
+
1570
+
1571
+
1572
+ CUDA_CALLABLE inline mesh_query_aabb_t mesh_query_aabb(
1573
+ uint64_t id, const vec3& lower, const vec3& upper)
1574
+ {
1575
+ // This routine traverses the BVH tree until it finds
1576
+ // the first triangle with an overlapping bvh.
1577
+
1578
+ // initialize empty
1579
+ mesh_query_aabb_t query;
1580
+ query.face = -1;
1581
+
1582
+ Mesh mesh = mesh_get(id);
1583
+ query.mesh = mesh;
1584
+
1585
+ query.stack[0] = *mesh.bvh.root;
1586
+ query.count = 1;
1587
+ query.input_lower = lower;
1588
+ query.input_upper = upper;
1589
+
1590
+ wp::bounds3 input_bounds(query.input_lower, query.input_upper);
1591
+
1592
+ // Navigate through the bvh, find the first overlapping leaf node.
1593
+ while (query.count)
1594
+ {
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];
1598
+
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);
1601
+ wp::bounds3 current_bounds(lower_pos, upper_pos);
1602
+ if (!input_bounds.overlaps(current_bounds))
1603
+ {
1604
+ // Skip this box, it doesn't overlap with our target box.
1605
+ continue;
1606
+ }
1607
+
1608
+ const int left_index = node_lower.i;
1609
+ const int right_index = node_upper.i;
1610
+
1611
+ // Make bounds from this AABB
1612
+ if (node_lower.b)
1613
+ {
1614
+ // found very first triangle index.
1615
+ // Back up one level and return
1616
+ query.stack[query.count++] = nodeIndex;
1617
+ return query;
1618
+ }
1619
+ else
1620
+ {
1621
+ query.stack[query.count++] = left_index;
1622
+ query.stack[query.count++] = right_index;
1623
+ }
1624
+ }
1625
+
1626
+ return query;
1627
+ }
1628
+
1629
+ //Stub
1630
+ CUDA_CALLABLE inline void adj_mesh_query_aabb(uint64_t id, const vec3& lower, const vec3& upper,
1631
+ uint64_t, vec3&, vec3&, mesh_query_aabb_t&)
1632
+ {
1633
+
1634
+ }
1635
+
1636
+ CUDA_CALLABLE inline bool mesh_query_aabb_next(mesh_query_aabb_t& query, int& index)
1637
+ {
1638
+ Mesh mesh = query.mesh;
1639
+
1640
+ wp::bounds3 input_bounds(query.input_lower, query.input_upper);
1641
+ // Navigate through the bvh, find the first overlapping leaf node.
1642
+ while (query.count)
1643
+ {
1644
+ const int nodeIndex = query.stack[--query.count];
1645
+ BVHPackedNodeHalf node_lower = mesh.bvh.node_lowers[nodeIndex];
1646
+ BVHPackedNodeHalf node_upper = mesh.bvh.node_uppers[nodeIndex];
1647
+
1648
+ wp::vec3 lower_pos(node_lower.x, node_lower.y, node_lower.z);
1649
+ wp::vec3 upper_pos(node_upper.x, node_upper.y, node_upper.z);
1650
+ wp::bounds3 current_bounds(lower_pos, upper_pos);
1651
+ if (!input_bounds.overlaps(current_bounds))
1652
+ {
1653
+ // Skip this box, it doesn't overlap with our target box.
1654
+ continue;
1655
+ }
1656
+
1657
+ const int left_index = node_lower.i;
1658
+ const int right_index = node_upper.i;
1659
+
1660
+ // Make bounds from this AABB
1661
+ if (node_lower.b)
1662
+ {
1663
+ // found very first triangle index
1664
+ query.face = left_index;
1665
+ index = left_index;
1666
+ return true;
1667
+ }
1668
+ else
1669
+ {
1670
+
1671
+ query.stack[query.count++] = left_index;
1672
+ query.stack[query.count++] = right_index;
1673
+ }
1674
+ }
1675
+ return false;
1676
+ }
1677
+
1678
+
1679
+ CUDA_CALLABLE inline int iter_next(mesh_query_aabb_t& query)
1680
+ {
1681
+ return query.face;
1682
+ }
1683
+
1684
+ CUDA_CALLABLE inline bool iter_cmp(mesh_query_aabb_t& query)
1685
+ {
1686
+ bool finished = mesh_query_aabb_next(query, query.face);
1687
+ return finished;
1688
+ }
1689
+
1690
+ CUDA_CALLABLE inline mesh_query_aabb_t iter_reverse(const mesh_query_aabb_t& query)
1691
+ {
1692
+ // can't reverse BVH queries, users should not rely on neighbor ordering
1693
+ return query;
1694
+ }
1695
+
1696
+
1697
+ // stub
1698
+ CUDA_CALLABLE inline void adj_mesh_query_aabb_next(mesh_query_aabb_t& query, int& index, mesh_query_aabb_t&, int&, bool&)
1699
+ {
1700
+
1701
+ }
1702
+
1703
+
1704
+ CUDA_CALLABLE inline vec3 mesh_eval_position(uint64_t id, int tri, float u, float v)
1705
+ {
1706
+ Mesh mesh = mesh_get(id);
1707
+
1708
+ if (!mesh.points)
1709
+ return vec3();
1710
+
1711
+ assert(tri < mesh.num_tris);
1712
+
1713
+ int i = mesh.indices[tri*3+0];
1714
+ int j = mesh.indices[tri*3+1];
1715
+ int k = mesh.indices[tri*3+2];
1716
+
1717
+ vec3 p = mesh.points[i];
1718
+ vec3 q = mesh.points[j];
1719
+ vec3 r = mesh.points[k];
1720
+
1721
+ return p*u + q*v + r*(1.0f-u-v);
1722
+ }
1723
+
1724
+ CUDA_CALLABLE inline vec3 mesh_eval_velocity(uint64_t id, int tri, float u, float v)
1725
+ {
1726
+ Mesh mesh = mesh_get(id);
1727
+
1728
+ if (!mesh.velocities)
1729
+ return vec3();
1730
+
1731
+ assert(tri < mesh.num_tris);
1732
+
1733
+ int i = mesh.indices[tri*3+0];
1734
+ int j = mesh.indices[tri*3+1];
1735
+ int k = mesh.indices[tri*3+2];
1736
+
1737
+ vec3 vp = mesh.velocities[i];
1738
+ vec3 vq = mesh.velocities[j];
1739
+ vec3 vr = mesh.velocities[k];
1740
+
1741
+ return vp*u + vq*v + vr*(1.0f-u-v);
1742
+ }
1743
+
1744
+
1745
+ CUDA_CALLABLE inline void adj_mesh_eval_position(uint64_t id, int tri, float u, float v,
1746
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1747
+ {
1748
+ Mesh mesh = mesh_get(id);
1749
+
1750
+ if (!mesh.points)
1751
+ return;
1752
+
1753
+ assert(tri < mesh.num_tris);
1754
+
1755
+ int i = mesh.indices[tri*3+0];
1756
+ int j = mesh.indices[tri*3+1];
1757
+ int k = mesh.indices[tri*3+2];
1758
+
1759
+ vec3 p = mesh.points[i];
1760
+ vec3 q = mesh.points[j];
1761
+ vec3 r = mesh.points[k];
1762
+
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];
1765
+ }
1766
+
1767
+ CUDA_CALLABLE inline void adj_mesh_eval_velocity(uint64_t id, int tri, float u, float v,
1768
+ uint64_t& adj_id, int& adj_tri, float& adj_u, float& adj_v, const vec3& adj_ret)
1769
+ {
1770
+ Mesh mesh = mesh_get(id);
1771
+
1772
+ if (!mesh.velocities)
1773
+ return;
1774
+
1775
+ assert(tri < mesh.num_tris);
1776
+
1777
+ int i = mesh.indices[tri*3+0];
1778
+ int j = mesh.indices[tri*3+1];
1779
+ int k = mesh.indices[tri*3+2];
1780
+
1781
+ vec3 vp = mesh.velocities[i];
1782
+ vec3 vq = mesh.velocities[j];
1783
+ vec3 vr = mesh.velocities[k];
1784
+
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];
1787
+ }
1788
+
1789
+ CUDA_CALLABLE inline vec3 mesh_eval_face_normal(uint64_t id, int tri)
1790
+ {
1791
+ Mesh mesh = mesh_get(id);
1792
+
1793
+ if (!mesh.points)
1794
+ return vec3();
1795
+
1796
+ assert(tri < mesh.num_tris);
1797
+
1798
+ int i = mesh.indices[tri*3+0];
1799
+ int j = mesh.indices[tri*3+1];
1800
+ int k = mesh.indices[tri*3+2];
1801
+
1802
+ vec3 p = mesh.points[i];
1803
+ vec3 q = mesh.points[j];
1804
+ vec3 r = mesh.points[k];
1805
+
1806
+ return normalize(cross(q - p, r - p));
1807
+ }
1808
+
1809
+ CUDA_CALLABLE inline void adj_mesh_eval_face_normal(uint64_t id, int tri,
1810
+ uint64_t& adj_id, int& adj_tri, const vec3& adj_ret)
1811
+ {
1812
+ // no-op
1813
+ }
1814
+
1815
+ CUDA_CALLABLE inline vec3 mesh_get_point(uint64_t id, int index)
1816
+ {
1817
+ Mesh mesh = mesh_get(id);
1818
+
1819
+ if (!mesh.points)
1820
+ return vec3();
1821
+
1822
+ #if FP_CHECK
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
+ }
1828
+ #endif
1829
+
1830
+ int i = mesh.indices[index];
1831
+ return mesh.points[i];
1832
+ }
1833
+
1834
+ CUDA_CALLABLE inline void adj_mesh_get_point(uint64_t id, int index,
1835
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1836
+ {
1837
+ // no-op
1838
+ }
1839
+
1840
+ CUDA_CALLABLE inline vec3 mesh_get_velocity(uint64_t id, int index)
1841
+ {
1842
+ Mesh mesh = mesh_get(id);
1843
+
1844
+ if (!mesh.velocities)
1845
+ return vec3();
1846
+
1847
+ #if FP_CHECK
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
+ }
1853
+ #endif
1854
+
1855
+ int i = mesh.indices[index];
1856
+ return mesh.velocities[i];
1857
+ }
1858
+
1859
+ CUDA_CALLABLE inline void adj_mesh_get_velocity(uint64_t id, int index,
1860
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1861
+ {
1862
+ // no-op
1863
+ }
1864
+
1865
+ CUDA_CALLABLE inline int mesh_get_index(uint64_t id, int face_vertex_index)
1866
+ {
1867
+ Mesh mesh = mesh_get(id);
1868
+
1869
+ if (!mesh.indices)
1870
+ return -1;
1871
+
1872
+ assert(face_vertex_index < mesh.num_tris * 3);
1873
+
1874
+ return mesh.indices[face_vertex_index];
1875
+ }
1876
+
1877
+ CUDA_CALLABLE inline void adj_mesh_get_index(uint64_t id, int index,
1878
+ uint64_t& adj_id, int& adj_index, const vec3& adj_ret)
1879
+ {
1880
+ // no-op
1881
+ }
1882
+
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);
1886
+
1887
+ } // namespace wp