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/volume.h CHANGED
@@ -1,538 +1,960 @@
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
-
13
- #define PNANOVDB_C
14
- #define PNANOVDB_MEMCPY_CUSTOM
15
- #define pnanovdb_memcpy memcpy
16
- #include "nanovdb/PNanoVDB.h"
17
- #include "nanovdb/PNanoVDBWrite.h"
18
-
19
- namespace wp
20
- {
21
- namespace volume
22
- {
23
-
24
- static constexpr int CLOSEST = 0;
25
- static constexpr int LINEAR = 1;
26
-
27
- // helper functions
28
- CUDA_CALLABLE inline pnanovdb_buf_t id_to_buffer(uint64_t id)
29
- {
30
- pnanovdb_buf_t buf;
31
- buf.data = (uint32_t*)id;
32
- return buf;
33
- }
34
-
35
- CUDA_CALLABLE inline pnanovdb_uint32_t get_grid_type(const pnanovdb_buf_t& buf)
36
- {
37
- const pnanovdb_grid_t *grid_data = (const pnanovdb_grid_t*)buf.data;
38
- return grid_data->grid_type;
39
- }
40
-
41
- CUDA_CALLABLE inline pnanovdb_root_handle_t get_root(const pnanovdb_buf_t& buf,
42
- const pnanovdb_grid_handle_t& grid = { 0u })
43
- {
44
- const auto tree = pnanovdb_grid_get_tree(buf, grid);
45
- return pnanovdb_tree_get_root(buf, tree);
46
- }
47
- } // namespace volume
48
-
49
- CUDA_CALLABLE inline void pnano_read(float& result, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
50
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, root, ijk);
51
- result = pnanovdb_read_float(buf, address);
52
- }
53
- CUDA_CALLABLE inline void pnano_read(int32_t& result, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
54
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_INT32, buf, root, ijk);
55
- result = pnanovdb_read_int32(buf, address);
56
- }
57
- CUDA_CALLABLE inline void pnano_read(vec3& result, pnanovdb_buf_t buf, pnanovdb_root_handle_t root, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
58
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_VEC3F, buf, root, ijk);
59
- const pnanovdb_vec3_t v = pnanovdb_read_vec3f(buf, address);
60
- result = {v.x, v.y, v.z};
61
- }
62
-
63
- CUDA_CALLABLE inline void pnano_read(float& result, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
64
- pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, ijk);
65
- result = pnanovdb_read_float(buf, address);
66
- }
67
- CUDA_CALLABLE inline void pnano_read(int32_t& result, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
68
- pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_INT32, buf, acc, ijk);
69
- result = pnanovdb_read_int32(buf, address);
70
- }
71
- CUDA_CALLABLE inline void pnano_read(vec3& result, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc, PNANOVDB_IN(pnanovdb_coord_t) ijk) {
72
- pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_VEC3F, buf, acc, ijk);
73
- const pnanovdb_vec3_t v = pnanovdb_read_vec3f(buf, address);
74
- result = {v.x, v.y, v.z};
75
- }
76
-
77
- // Sampling the volume at the given index-space coordinates, uvw can be fractional
78
- template<typename T>
79
- CUDA_CALLABLE inline T volume_sample(uint64_t id, vec3 uvw, int sampling_mode)
80
- {
81
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
82
- const pnanovdb_root_handle_t root = volume::get_root(buf);
83
- const pnanovdb_vec3_t uvw_pnano{ uvw[0], uvw[1], uvw[2] };
84
-
85
- if (sampling_mode == volume::CLOSEST)
86
- {
87
- const pnanovdb_coord_t ijk = pnanovdb_vec3_round_to_coord(uvw_pnano);
88
- T val;
89
- pnano_read(val, buf, root, PNANOVDB_REF(ijk));
90
- return val;
91
- }
92
- else if (sampling_mode == volume::LINEAR)
93
- {
94
- // NB. linear sampling is not used on int volumes
95
- constexpr pnanovdb_coord_t OFFSETS[] = {
96
- { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 },
97
- };
98
-
99
- const pnanovdb_vec3_t ijk_base{ floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z) };
100
- const pnanovdb_vec3_t ijk_frac{ uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z };
101
- const pnanovdb_coord_t ijk{ (pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y, (pnanovdb_int32_t)ijk_base.z };
102
-
103
- pnanovdb_readaccessor_t accessor;
104
- pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
105
- T val = 0;
106
- const float wx[2]{ 1 - ijk_frac.x, ijk_frac.x };
107
- const float wy[2]{ 1 - ijk_frac.y, ijk_frac.y };
108
- const float wz[2]{ 1 - ijk_frac.z, ijk_frac.z };
109
- for (int idx = 0; idx < 8; ++idx)
110
- {
111
- const pnanovdb_coord_t& offs = OFFSETS[idx];
112
- const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
113
- T v;
114
- pnano_read(v, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk_shifted));
115
- val = add(val, T(wx[offs.x] * wy[offs.y] * wz[offs.z] * v));
116
- }
117
- return val;
118
- }
119
- return 0;
120
- }
121
-
122
- // Sampling a float volume at the given index-space coordinates, uvw can be fractional
123
- CUDA_CALLABLE inline float volume_sample_f(uint64_t id, vec3 uvw, int sampling_mode)
124
- {
125
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_FLOAT) return 0.f;
126
- return volume_sample<float>(id, uvw, sampling_mode);
127
- }
128
-
129
- // Sampling an int volume at the given index-space coordinates, uvw can be fractional
130
- CUDA_CALLABLE inline int32_t volume_sample_i(uint64_t id, vec3 uvw)
131
- {
132
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_INT32) return 0;
133
- return volume_sample<int32_t>(id, uvw, volume::CLOSEST);
134
- }
135
-
136
- // Sampling a vector volume at the given index-space coordinates, uvw can be fractional
137
- CUDA_CALLABLE inline vec3 volume_sample_v(uint64_t id, vec3 uvw, int sampling_mode)
138
- {
139
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_VEC3F) return vec3(0.f);
140
- return volume_sample<vec3>(id, uvw, sampling_mode);
141
- }
142
-
143
- CUDA_CALLABLE inline void adj_volume_sample_f(
144
- uint64_t id, vec3 uvw, int sampling_mode, uint64_t& adj_id, vec3& adj_uvw, int& adj_sampling_mode, const float& adj_ret)
145
- {
146
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_FLOAT) return;
147
-
148
- if (sampling_mode != volume::LINEAR) {
149
- return; // NOP
150
- }
151
-
152
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
153
- const pnanovdb_root_handle_t root = volume::get_root(buf);
154
- const pnanovdb_vec3_t uvw_pnano{ uvw[0], uvw[1], uvw[2] };
155
-
156
- constexpr pnanovdb_coord_t OFFSETS[] = {
157
- { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 },
158
- };
159
-
160
- const pnanovdb_vec3_t ijk_base{ floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z) };
161
- const pnanovdb_vec3_t ijk_frac{ uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z };
162
- const pnanovdb_coord_t ijk{ (pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y, (pnanovdb_int32_t)ijk_base.z };
163
-
164
- pnanovdb_readaccessor_t accessor;
165
- pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
166
- const float wx[2]{ 1 - ijk_frac.x, ijk_frac.x };
167
- const float wy[2]{ 1 - ijk_frac.y, ijk_frac.y };
168
- const float wz[2]{ 1 - ijk_frac.z, ijk_frac.z };
169
- vec3 dphi(0,0,0);
170
- for (int idx = 0; idx < 8; ++idx)
171
- {
172
- const pnanovdb_coord_t& offs = OFFSETS[idx];
173
- const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
174
- float v;
175
- pnano_read(v, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk_shifted));
176
- const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
177
- const vec3 grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z], signs[2] * wx[offs.x] * wy[offs.y]);
178
- dphi = add(dphi, mul(v, grad_w));
179
- }
180
-
181
- adj_uvw += mul(dphi, adj_ret);
182
- }
183
-
184
- CUDA_CALLABLE inline void adj_volume_sample_v(
185
- uint64_t id, vec3 uvw, int sampling_mode, uint64_t& adj_id, vec3& adj_uvw, int& adj_sampling_mode, const vec3& adj_ret)
186
- {
187
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_VEC3F) return;
188
-
189
- if (sampling_mode != volume::LINEAR) {
190
- return; // NOP
191
- }
192
-
193
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
194
- const pnanovdb_root_handle_t root = volume::get_root(buf);
195
- const pnanovdb_vec3_t uvw_pnano{ uvw[0], uvw[1], uvw[2] };
196
-
197
- constexpr pnanovdb_coord_t OFFSETS[] = {
198
- { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 },
199
- };
200
-
201
- const pnanovdb_vec3_t ijk_base{ floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z) };
202
- const pnanovdb_vec3_t ijk_frac{ uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z };
203
- const pnanovdb_coord_t ijk{ (pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y, (pnanovdb_int32_t)ijk_base.z };
204
-
205
- pnanovdb_readaccessor_t accessor;
206
- pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
207
- const float wx[2]{ 1 - ijk_frac.x, ijk_frac.x };
208
- const float wy[2]{ 1 - ijk_frac.y, ijk_frac.y };
209
- const float wz[2]{ 1 - ijk_frac.z, ijk_frac.z };
210
- vec3 dphi[3] = {{0,0,0}, {0,0,0}, {0,0,0}};
211
- for (int idx = 0; idx < 8; ++idx)
212
- {
213
- const pnanovdb_coord_t& offs = OFFSETS[idx];
214
- const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
215
- vec3 v;
216
- pnano_read(v, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk_shifted));
217
- const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
218
- const vec3 grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z], signs[2] * wx[offs.x] * wy[offs.y]);
219
- dphi[0] = add(dphi[0], mul(v[0], grad_w));
220
- dphi[1] = add(dphi[1], mul(v[1], grad_w));
221
- dphi[2] = add(dphi[2], mul(v[2], grad_w));
222
- }
223
-
224
- for (int k = 0; k < 3; ++k)
225
- {
226
- adj_uvw[k] += dot(dphi[k], adj_ret);
227
- }
228
- }
229
-
230
- CUDA_CALLABLE inline void adj_volume_sample_i(uint64_t id, vec3 uvw, uint64_t& adj_id, vec3& adj_uvw, const int32_t& adj_ret)
231
- {
232
- // NOP
233
- }
234
-
235
- // Sampling the volume at the given index-space coordinates, uvw can be fractional
236
- CUDA_CALLABLE inline float volume_sample_grad_f(uint64_t id, vec3 uvw, int sampling_mode, vec3& grad)
237
- {
238
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
239
- const pnanovdb_root_handle_t root = volume::get_root(buf);
240
- const pnanovdb_vec3_t uvw_pnano{ uvw[0], uvw[1], uvw[2] };
241
-
242
- if (sampling_mode == volume::CLOSEST)
243
- {
244
- const pnanovdb_coord_t ijk = pnanovdb_vec3_round_to_coord(uvw_pnano);
245
- float val;
246
- pnano_read(val, buf, root, PNANOVDB_REF(ijk));
247
- grad = vec3(0.0f, 0.0f, 0.0f);
248
- return val;
249
- }
250
- else if (sampling_mode == volume::LINEAR)
251
- {
252
- // NB. linear sampling is not used on int volumes
253
- constexpr pnanovdb_coord_t OFFSETS[] = {
254
- { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 },
255
- };
256
-
257
- const pnanovdb_vec3_t ijk_base{ floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z) };
258
- const pnanovdb_vec3_t ijk_frac{ uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z };
259
- const pnanovdb_coord_t ijk{ (pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y, (pnanovdb_int32_t)ijk_base.z };
260
-
261
- pnanovdb_readaccessor_t accessor;
262
- pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
263
- float val = 0.0f;
264
- const float wx[2]{ 1 - ijk_frac.x, ijk_frac.x };
265
- const float wy[2]{ 1 - ijk_frac.y, ijk_frac.y };
266
- const float wz[2]{ 1 - ijk_frac.z, ijk_frac.z };
267
-
268
- const float sign_dx[8] = {-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
269
- const float sign_dy[8] = {-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f};
270
- const float sign_dz[8] = {-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f};
271
-
272
- float dfdx = 0.0f;
273
- float dfdy = 0.0f;
274
- float dfdz = 0.0f;
275
- for (int idx = 0; idx < 8; ++idx)
276
- {
277
- const pnanovdb_coord_t& offs = OFFSETS[idx];
278
- const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
279
- float v;
280
- pnano_read(v, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk_shifted));
281
- val = add(val, wx[offs.x] * wy[offs.y] * wz[offs.z] * v);
282
- dfdx = add(dfdx, wy[offs.y] * wz[offs.z] * sign_dx[idx] * v);
283
- dfdy = add(dfdy, wx[offs.x] * wz[offs.z] * sign_dy[idx] * v);
284
- dfdz = add(dfdz, wx[offs.x] * wy[offs.y] * sign_dz[idx] * v);
285
- }
286
- grad = vec3(dfdx, dfdy, dfdz);
287
- return val;
288
- }
289
- return 0.0f;
290
- }
291
-
292
- CUDA_CALLABLE inline void adj_volume_sample_grad_f(
293
- uint64_t id, vec3 uvw, int sampling_mode, vec3& grad, uint64_t& adj_id, vec3& adj_uvw, int& adj_sampling_mode, vec3& adj_grad, const float& adj_ret)
294
- {
295
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_FLOAT) return;
296
-
297
- if (sampling_mode != volume::LINEAR) {
298
- return; // NOP
299
- }
300
-
301
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
302
- const pnanovdb_root_handle_t root = volume::get_root(buf);
303
- const pnanovdb_vec3_t uvw_pnano{ uvw[0], uvw[1], uvw[2] };
304
-
305
- constexpr pnanovdb_coord_t OFFSETS[] = {
306
- { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 },
307
- };
308
-
309
- const pnanovdb_vec3_t ijk_base{ floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z) };
310
- const pnanovdb_vec3_t ijk_frac{ uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z };
311
- const pnanovdb_coord_t ijk{ (pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y, (pnanovdb_int32_t)ijk_base.z };
312
-
313
- pnanovdb_readaccessor_t accessor;
314
- pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
315
- const float wx[2]{ 1 - ijk_frac.x, ijk_frac.x };
316
- const float wy[2]{ 1 - ijk_frac.y, ijk_frac.y };
317
- const float wz[2]{ 1 - ijk_frac.z, ijk_frac.z };
318
- const float sign_dx[8] = {-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
319
- const float sign_dy[8] = {-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f};
320
- const float sign_dz[8] = {-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f};
321
-
322
- float dfdxdy = 0.0f;
323
- float dfdxdz = 0.0f;
324
- float dfdydx = 0.0f;
325
- float dfdydz = 0.0f;
326
- float dfdzdx = 0.0f;
327
- float dfdzdy = 0.0f;
328
- vec3 dphi(0,0,0);
329
- for (int idx = 0; idx < 8; ++idx)
330
- {
331
- const pnanovdb_coord_t& offs = OFFSETS[idx];
332
- const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
333
- float v;
334
- pnano_read(v, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk_shifted));
335
- const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
336
- const vec3 grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z], signs[2] * wx[offs.x] * wy[offs.y]);
337
- dphi = add(dphi, mul(v, grad_w));
338
-
339
- dfdxdy = add(dfdxdy, signs[1] * wz[offs.z] * sign_dx[idx] * v);
340
- dfdxdz = add(dfdxdz, wy[offs.y] * signs[2] * sign_dx[idx] * v);
341
-
342
- dfdydx = add(dfdydx, signs[0] * wz[offs.z] * sign_dy[idx] * v);
343
- dfdydz = add(dfdydz, wx[offs.x] * signs[2] * sign_dy[idx] * v);
344
-
345
- dfdzdx = add(dfdzdx, signs[0] * wy[offs.y] * sign_dz[idx] * v);
346
- dfdzdy = add(dfdzdy, wx[offs.x] * signs[1] * sign_dz[idx] * v);
347
- }
348
-
349
- adj_uvw += mul(dphi, adj_ret);
350
- adj_uvw[0] += adj_grad[1] * dfdydx + adj_grad[2] * dfdzdx;
351
- adj_uvw[1] += adj_grad[0] * dfdxdy + adj_grad[2] * dfdzdy;
352
- adj_uvw[2] += adj_grad[0] * dfdxdz + adj_grad[1] * dfdydz;
353
- }
354
-
355
- CUDA_CALLABLE inline float volume_lookup_f(uint64_t id, int32_t i, int32_t j, int32_t k)
356
- {
357
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_FLOAT) return 0.f;
358
-
359
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
360
- const pnanovdb_root_handle_t root = volume::get_root(buf);
361
-
362
- const pnanovdb_coord_t ijk{ i, j, k };
363
- float val;
364
- pnano_read(val, buf, root, PNANOVDB_REF(ijk));
365
- return val;
366
- }
367
-
368
- CUDA_CALLABLE inline int32_t volume_lookup_i(uint64_t id, int32_t i, int32_t j, int32_t k)
369
- {
370
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_INT32) return 0;
371
-
372
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
373
- const pnanovdb_root_handle_t root = volume::get_root(buf);
374
-
375
- const pnanovdb_coord_t ijk{ i, j, k };
376
- int32_t val;
377
- pnano_read(val, buf, root, PNANOVDB_REF(ijk));
378
- return val;
379
- }
380
-
381
- CUDA_CALLABLE inline vec3 volume_lookup_v(uint64_t id, int32_t i, int32_t j, int32_t k)
382
- {
383
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_VEC3F) return vec3(0.f);
384
-
385
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
386
- const pnanovdb_root_handle_t root = volume::get_root(buf);
387
-
388
- const pnanovdb_coord_t ijk{ i, j, k };
389
- vec3 val;
390
- pnano_read(val, buf, root, PNANOVDB_REF(ijk));
391
- return val;
392
- }
393
-
394
- CUDA_CALLABLE inline void adj_volume_lookup_f(
395
- uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, const float& adj_ret)
396
- {
397
- // NOP
398
- }
399
-
400
- CUDA_CALLABLE inline void adj_volume_lookup_i(
401
- uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, const int32_t& adj_ret)
402
- {
403
- // NOP
404
- }
405
-
406
- CUDA_CALLABLE inline void adj_volume_lookup_v(
407
- uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, const vec3& adj_ret)
408
- {
409
- // NOP
410
- }
411
-
412
- CUDA_CALLABLE inline void volume_store_f(uint64_t id, int32_t i, int32_t j, int32_t k, const float& value)
413
- {
414
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_FLOAT) return;
415
-
416
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
417
- const pnanovdb_root_handle_t root = volume::get_root(buf);
418
-
419
- const pnanovdb_coord_t ijk{ i, j, k };
420
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, root, PNANOVDB_REF(ijk));
421
- pnanovdb_write_float(buf, address, value);
422
- }
423
-
424
- CUDA_CALLABLE inline void adj_volume_store_f(
425
- uint64_t id, int32_t i, int32_t j, int32_t k, const float& value,
426
- uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, float& adj_value)
427
- {
428
- adj_value += volume_lookup_f(id, i, j, k);
429
- }
430
-
431
- CUDA_CALLABLE inline void volume_store_v(uint64_t id, int32_t i, int32_t j, int32_t k, const vec3& value)
432
- {
433
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_VEC3F) return;
434
-
435
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
436
- const pnanovdb_root_handle_t root = volume::get_root(buf);
437
-
438
- const pnanovdb_coord_t ijk{ i, j, k };
439
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_VEC3F, buf, root, PNANOVDB_REF(ijk));
440
- const pnanovdb_vec3_t v{ value[0], value[1], value[2] };
441
- pnanovdb_write_vec3(buf, address, &v);
442
- }
443
-
444
- CUDA_CALLABLE inline void adj_volume_store_v(
445
- uint64_t id, int32_t i, int32_t j, int32_t k, const vec3& value,
446
- uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, vec3& adj_value)
447
- {
448
- adj_value = add(adj_value, volume_lookup_v(id, i, j, k));
449
- }
450
-
451
- CUDA_CALLABLE inline void volume_store_i(uint64_t id, int32_t i, int32_t j, int32_t k, const int32_t& value)
452
- {
453
- if (volume::get_grid_type(volume::id_to_buffer(id)) != PNANOVDB_GRID_TYPE_INT32) return;
454
-
455
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
456
- const pnanovdb_root_handle_t root = volume::get_root(buf);
457
-
458
- const pnanovdb_coord_t ijk{ i, j, k };
459
- const pnanovdb_address_t address = pnanovdb_root_get_value_address(PNANOVDB_GRID_TYPE_INT32, buf, root, PNANOVDB_REF(ijk));
460
- pnanovdb_write_int32(buf, address, value);
461
- }
462
-
463
- CUDA_CALLABLE inline void adj_volume_store_i(
464
- uint64_t id, int32_t i, int32_t j, int32_t k, const int32_t& value,
465
- uint64_t& adj_id, int32_t& adj_i, int32_t& adj_j, int32_t& adj_k, int32_t& adj_value)
466
- {
467
- adj_value = add(adj_value, volume_lookup_i(id, i, j, k));
468
- }
469
-
470
- // Transform position from index space to world space
471
- CUDA_CALLABLE inline vec3 volume_index_to_world(uint64_t id, vec3 uvw)
472
- {
473
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
474
- const pnanovdb_grid_handle_t grid = { 0u };
475
- const pnanovdb_vec3_t pos{ uvw[0], uvw[1], uvw[2] };
476
- const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_worldf(buf, grid, PNANOVDB_REF(pos));
477
- return { xyz.x, xyz.y, xyz.z };
478
- }
479
-
480
- // Transform position from world space to index space
481
- CUDA_CALLABLE inline vec3 volume_world_to_index(uint64_t id, vec3 xyz)
482
- {
483
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
484
- const pnanovdb_grid_handle_t grid = { 0u };
485
- const pnanovdb_vec3_t pos{ xyz[0], xyz[1], xyz[2] };
486
- const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_indexf(buf, grid, PNANOVDB_REF(pos));
487
- return { uvw.x, uvw.y, uvw.z };
488
- }
489
-
490
- CUDA_CALLABLE inline void adj_volume_index_to_world(uint64_t id, vec3 uvw, uint64_t& adj_id, vec3& adj_uvw, const vec3& adj_ret)
491
- {
492
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
493
- const pnanovdb_grid_handle_t grid = { 0u };
494
- const pnanovdb_vec3_t pos{ adj_ret[0], adj_ret[1], adj_ret[2] };
495
- const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_world_dirf(buf, grid, PNANOVDB_REF(pos));
496
- adj_uvw = add(adj_uvw, vec3{ xyz.x, xyz.y, xyz.z });
497
- }
498
-
499
- CUDA_CALLABLE inline void adj_volume_world_to_index(uint64_t id, vec3 xyz, uint64_t& adj_id, vec3& adj_xyz, const vec3& adj_ret)
500
- {
501
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
502
- const pnanovdb_grid_handle_t grid = { 0u };
503
- const pnanovdb_vec3_t pos{ adj_ret[0], adj_ret[1], adj_ret[2] };
504
- const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_index_dirf(buf, grid, PNANOVDB_REF(pos));
505
- adj_xyz = add(adj_xyz, vec3{ uvw.x, uvw.y, uvw.z });
506
- }
507
-
508
- // Transform direction from index space to world space
509
- CUDA_CALLABLE inline vec3 volume_index_to_world_dir(uint64_t id, vec3 uvw)
510
- {
511
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
512
- const pnanovdb_grid_handle_t grid = { 0u };
513
- const pnanovdb_vec3_t pos{ uvw[0], uvw[1], uvw[2] };
514
- const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_world_dirf(buf, grid, PNANOVDB_REF(pos));
515
- return { xyz.x, xyz.y, xyz.z };
516
- }
517
-
518
- // Transform direction from world space to index space
519
- CUDA_CALLABLE inline vec3 volume_world_to_index_dir(uint64_t id, vec3 xyz)
520
- {
521
- const pnanovdb_buf_t buf = volume::id_to_buffer(id);
522
- const pnanovdb_grid_handle_t grid = { 0u };
523
- const pnanovdb_vec3_t pos{ xyz[0], xyz[1], xyz[2] };
524
- const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_index_dirf(buf, grid, PNANOVDB_REF(pos));
525
- return { uvw.x, uvw.y, uvw.z };
526
- }
527
-
528
- CUDA_CALLABLE inline void adj_volume_index_to_world_dir(uint64_t id, vec3 uvw, uint64_t& adj_id, vec3& adj_uvw, const vec3& adj_ret)
529
- {
530
- adj_volume_index_to_world(id, uvw, adj_id, adj_uvw, adj_ret);
531
- }
532
-
533
- CUDA_CALLABLE inline void adj_volume_world_to_index_dir(uint64_t id, vec3 xyz, uint64_t& adj_id, vec3& adj_xyz, const vec3& adj_ret)
534
- {
535
- adj_volume_world_to_index(id, xyz, adj_id, adj_xyz, adj_ret);
536
- }
537
-
538
- } // 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 "array.h"
12
+ #include "builtin.h"
13
+
14
+ #define PNANOVDB_C
15
+ #define PNANOVDB_MEMCPY_CUSTOM
16
+ #define pnanovdb_memcpy memcpy
17
+
18
+ #if defined(WP_NO_CRT) && !defined(__CUDACC__)
19
+ // PNanoVDB will try to include <stdint.h> unless __CUDACC_RTC__ is defined
20
+ #define __CUDACC_RTC__
21
+ #endif
22
+
23
+ #include "nanovdb/PNanoVDB.h"
24
+
25
+ #if defined(WP_NO_CRT) && !defined(__CUDACC__)
26
+ #undef __CUDACC_RTC__
27
+ #endif
28
+
29
+ namespace wp
30
+ {
31
+ namespace volume
32
+ {
33
+
34
+ // Need to kept in sync with constants in python-side Volume class
35
+ static constexpr int CLOSEST = 0;
36
+ static constexpr int LINEAR = 1;
37
+
38
+ // pnanovdb helper function
39
+
40
+ CUDA_CALLABLE inline pnanovdb_buf_t id_to_buffer(uint64_t id)
41
+ {
42
+ pnanovdb_buf_t buf;
43
+ buf.data = (uint32_t *)id;
44
+ return buf;
45
+ }
46
+
47
+ CUDA_CALLABLE inline pnanovdb_grid_handle_t get_grid(pnanovdb_buf_t buf)
48
+ {
49
+ return {0u};
50
+ }
51
+
52
+ CUDA_CALLABLE inline pnanovdb_uint32_t get_grid_type(pnanovdb_buf_t buf)
53
+ {
54
+ return pnanovdb_grid_get_grid_type(buf, get_grid(buf));
55
+ }
56
+
57
+ CUDA_CALLABLE inline pnanovdb_tree_handle_t get_tree(pnanovdb_buf_t buf)
58
+ {
59
+ return pnanovdb_grid_get_tree(buf, get_grid(buf));
60
+ }
61
+
62
+ CUDA_CALLABLE inline pnanovdb_root_handle_t get_root(pnanovdb_buf_t buf)
63
+ {
64
+ return pnanovdb_tree_get_root(buf, get_tree(buf));
65
+ }
66
+
67
+ template <typename T> struct pnano_traits
68
+ {
69
+ };
70
+
71
+ // to add support for more grid types, extend this
72
+ // and update _volume_supported_value_types in builtins.py
73
+
74
+ template <> struct pnano_traits<int32_t>
75
+ {
76
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_INT32;
77
+ };
78
+
79
+ template <> struct pnano_traits<int64_t>
80
+ {
81
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_INT64;
82
+ };
83
+
84
+ template <> struct pnano_traits<uint32_t>
85
+ {
86
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_UINT32;
87
+ };
88
+
89
+ template <> struct pnano_traits<float>
90
+ {
91
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_FLOAT;
92
+ };
93
+
94
+ template <> struct pnano_traits<double>
95
+ {
96
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_DOUBLE;
97
+ };
98
+
99
+ template <> struct pnano_traits<vec3f>
100
+ {
101
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_VEC3F;
102
+ };
103
+
104
+ template <> struct pnano_traits<vec3d>
105
+ {
106
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_VEC3D;
107
+ };
108
+
109
+ template <> struct pnano_traits<vec4f>
110
+ {
111
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_VEC4F;
112
+ };
113
+
114
+ template <> struct pnano_traits<vec4d>
115
+ {
116
+ static constexpr int GRID_TYPE = PNANOVDB_GRID_TYPE_VEC4D;
117
+ };
118
+
119
+ // common accessors over various grid types
120
+ // WARNING: implementation below only for >=32b values, but that's the case for all types above
121
+ // for smaller types add a specialization
122
+
123
+ template <typename T> CUDA_CALLABLE inline void pnano_read(T &result, pnanovdb_buf_t buf, pnanovdb_address_t address)
124
+ {
125
+ result = *reinterpret_cast<const T *>(buf.data + (address.byte_offset >> 2));
126
+ }
127
+
128
+ template <typename T>
129
+ CUDA_CALLABLE inline void pnano_write(const T &value, pnanovdb_buf_t buf, pnanovdb_address_t address)
130
+ {
131
+ *reinterpret_cast<T *>(buf.data + (address.byte_offset >> 2)) = value;
132
+ }
133
+
134
+ template <typename T>
135
+ CUDA_CALLABLE inline void pnano_read(T &result, pnanovdb_buf_t buf, pnanovdb_root_handle_t root,
136
+ PNANOVDB_IN(pnanovdb_coord_t) ijk)
137
+ {
138
+ using traits = pnano_traits<T>;
139
+ const pnanovdb_address_t address = pnanovdb_root_get_value_address(traits::GRID_TYPE, buf, root, ijk);
140
+ pnano_read<T>(result, buf, address);
141
+ }
142
+
143
+ template <typename T>
144
+ CUDA_CALLABLE inline void pnano_read(T &result, pnanovdb_buf_t buf, PNANOVDB_INOUT(pnanovdb_readaccessor_t) acc,
145
+ PNANOVDB_IN(pnanovdb_coord_t) ijk)
146
+ {
147
+ using traits = pnano_traits<T>;
148
+ // pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(traits::GRID_TYPE, buf, acc, ijk);
149
+ pnanovdb_uint32_t level;
150
+ const pnanovdb_address_t address =
151
+ pnanovdb_readaccessor_get_value_address_and_level(traits::GRID_TYPE, buf, acc, ijk, PNANOVDB_REF(level));
152
+ pnano_read<T>(result, buf, address);
153
+ }
154
+
155
+ /// regular grid accessor (values stored in leafs)
156
+
157
+ struct value_accessor_base
158
+ {
159
+ pnanovdb_buf_t buf;
160
+ pnanovdb_root_handle_t root;
161
+ pnanovdb_readaccessor_t accessor;
162
+
163
+ explicit inline CUDA_CALLABLE value_accessor_base(const pnanovdb_buf_t buf) : buf(buf), root(get_root(buf))
164
+ {
165
+ }
166
+
167
+ CUDA_CALLABLE inline void init_cache()
168
+ {
169
+ pnanovdb_readaccessor_init(PNANOVDB_REF(accessor), root);
170
+ }
171
+ };
172
+
173
+ template <typename T> struct leaf_value_accessor : value_accessor_base
174
+ {
175
+ using ValueType = T;
176
+
177
+ explicit inline CUDA_CALLABLE leaf_value_accessor(const pnanovdb_buf_t buf) : value_accessor_base(buf)
178
+ {
179
+ }
180
+
181
+ CUDA_CALLABLE inline bool is_valid() const
182
+ {
183
+ return get_grid_type(buf) == pnano_traits<T>::GRID_TYPE;
184
+ }
185
+
186
+ CUDA_CALLABLE inline T read_single(const pnanovdb_coord_t &ijk) const
187
+ {
188
+ T val;
189
+ pnano_read(val, buf, root, PNANOVDB_REF(ijk));
190
+ return val;
191
+ }
192
+
193
+ CUDA_CALLABLE inline T read_cache(const pnanovdb_coord_t &ijk)
194
+ {
195
+ T val;
196
+ pnano_read(val, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk));
197
+ return val;
198
+ }
199
+
200
+ CUDA_CALLABLE inline void adj_read_single(const pnanovdb_coord_t &ijk, const T &adj_ret)
201
+ {
202
+ // NOP
203
+ }
204
+
205
+ CUDA_CALLABLE inline void adj_read_cache(const pnanovdb_coord_t &ijk, const T &adj_ret)
206
+ {
207
+ // NOP
208
+ }
209
+ };
210
+
211
+ CUDA_CALLABLE inline pnanovdb_uint64_t leaf_regular_get_voxel_index(pnanovdb_buf_t buf,
212
+ pnanovdb_address_t value_address,
213
+ PNANOVDB_IN(pnanovdb_coord_t) ijk)
214
+ {
215
+ // compute leaf index from value address, assuming all leaf voxels are allocated
216
+ const pnanovdb_grid_type_t grid_type = get_grid_type(buf);
217
+ const pnanovdb_uint32_t n = pnanovdb_leaf_coord_to_offset(ijk);
218
+ const pnanovdb_uint32_t byte_offset = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_off_table) +
219
+ ((PNANOVDB_GRID_TYPE_GET(grid_type, value_stride_bits) * n) >> 3u);
220
+ const pnanovdb_address_t leaf_address = pnanovdb_address_offset_neg(value_address, byte_offset);
221
+
222
+ const pnanovdb_uint64_t first_leaf_offset = pnanovdb_tree_get_node_offset_leaf(buf, get_tree(buf));
223
+ const pnanovdb_uint32_t leaf_size = PNANOVDB_GRID_TYPE_GET(grid_type, leaf_size);
224
+ const pnanovdb_uint64_t leaf_index = (leaf_address.byte_offset - first_leaf_offset) / leaf_size;
225
+
226
+ return leaf_index * PNANOVDB_LEAF_TABLE_COUNT + n + 1;
227
+ }
228
+
229
+ CUDA_CALLABLE inline pnanovdb_uint64_t get_grid_voxel_index(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf,
230
+ pnanovdb_address_t value_address,
231
+ const pnanovdb_coord_t &ijk)
232
+ {
233
+ switch (grid_type)
234
+ {
235
+ case PNANOVDB_GRID_TYPE_INDEX:
236
+ return pnanovdb_leaf_index_get_value_index(buf, value_address, PNANOVDB_REF(ijk));
237
+ case PNANOVDB_GRID_TYPE_ONINDEX:
238
+ return pnanovdb_leaf_onindex_get_value_index(buf, value_address, PNANOVDB_REF(ijk));
239
+ case PNANOVDB_GRID_TYPE_INDEXMASK:
240
+ return pnanovdb_leaf_indexmask_get_value_index(buf, value_address, PNANOVDB_REF(ijk));
241
+ case PNANOVDB_GRID_TYPE_ONINDEXMASK:
242
+ return pnanovdb_leaf_onindexmask_get_value_index(buf, value_address, PNANOVDB_REF(ijk));
243
+ default:
244
+ return leaf_regular_get_voxel_index(buf, value_address, PNANOVDB_REF(ijk));
245
+ }
246
+ };
247
+
248
+ /// index grid accessor
249
+ template <typename T> struct index_value_accessor : value_accessor_base
250
+ {
251
+ using ValueType = T;
252
+
253
+ pnanovdb_grid_type_t grid_type;
254
+ array_t<T> data;
255
+ const T &background;
256
+ T *adj_background;
257
+
258
+ explicit inline CUDA_CALLABLE index_value_accessor(const pnanovdb_buf_t buf, const array_t<T> &data,
259
+ const T &background, T *adj_background = nullptr)
260
+ : value_accessor_base(buf), grid_type(get_grid_type(buf)), data(data), background(background),
261
+ adj_background(adj_background)
262
+ {
263
+ }
264
+
265
+ CUDA_CALLABLE inline bool is_valid() const
266
+ {
267
+ // Accessor is valid for all grid types
268
+ return true;
269
+ }
270
+
271
+ CUDA_CALLABLE inline T read_single(const pnanovdb_coord_t &ijk) const
272
+ {
273
+ pnanovdb_uint32_t level;
274
+ const pnanovdb_address_t address =
275
+ pnanovdb_root_get_value_address_and_level(grid_type, buf, root, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
276
+ return read_at(level, address, ijk);
277
+ }
278
+
279
+ CUDA_CALLABLE inline T read_cache(const pnanovdb_coord_t &ijk)
280
+ {
281
+ pnanovdb_uint32_t level;
282
+ const pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address_and_level(
283
+ grid_type, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk), PNANOVDB_REF(level));
284
+ return read_at(level, address, ijk);
285
+ }
286
+
287
+ CUDA_CALLABLE inline T read_at(pnanovdb_uint32_t level, const pnanovdb_address_t address,
288
+ const pnanovdb_coord_t &ijk) const
289
+ {
290
+ if (level == 0)
291
+ {
292
+ pnanovdb_uint64_t voxel_index = get_grid_voxel_index(grid_type, buf, address, ijk);
293
+
294
+ if (voxel_index > 0)
295
+ {
296
+ return *wp::address(data, voxel_index - 1);
297
+ }
298
+ }
299
+
300
+ return background;
301
+ }
302
+
303
+ CUDA_CALLABLE inline void adj_read_single(const pnanovdb_coord_t &ijk, const T &adj_ret)
304
+ {
305
+ pnanovdb_uint32_t level;
306
+ const pnanovdb_address_t address =
307
+ pnanovdb_root_get_value_address_and_level(grid_type, buf, root, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
308
+ adj_read_at(level, address, ijk, adj_ret);
309
+ }
310
+
311
+ CUDA_CALLABLE inline void adj_read_cache(const pnanovdb_coord_t &ijk, const T &adj_ret)
312
+ {
313
+ pnanovdb_uint32_t level;
314
+ const pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address_and_level(
315
+ grid_type, buf, PNANOVDB_REF(accessor), PNANOVDB_REF(ijk), PNANOVDB_REF(level));
316
+ adj_read_at(level, address, ijk, adj_ret);
317
+ }
318
+
319
+ CUDA_CALLABLE inline void adj_read_at(pnanovdb_uint32_t level, const pnanovdb_address_t address,
320
+ const pnanovdb_coord_t &ijk, const T &adj_ret) const
321
+ {
322
+ if (level == 0)
323
+ {
324
+ pnanovdb_uint64_t voxel_index = get_grid_voxel_index(grid_type, buf, address, ijk);
325
+
326
+ if (voxel_index > 0)
327
+ {
328
+ adj_atomic_add(&index_grad(data, voxel_index - 1), adj_ret);
329
+ return;
330
+ }
331
+ }
332
+ *adj_background += adj_ret;
333
+ }
334
+ };
335
+
336
+ CUDA_CALLABLE inline pnanovdb_coord_t vec3_round_to_coord(const pnanovdb_vec3_t a)
337
+ {
338
+ pnanovdb_coord_t v;
339
+ v.x = pnanovdb_float_to_int32(roundf(a.x));
340
+ v.y = pnanovdb_float_to_int32(roundf(a.y));
341
+ v.z = pnanovdb_float_to_int32(roundf(a.z));
342
+ return v;
343
+ }
344
+
345
+ template <typename T> struct val_traits
346
+ {
347
+ using grad_t = vec_t<3, T>;
348
+ using scalar_t = T;
349
+
350
+ // multiplies the gradient on the right
351
+ // needs to be specialized for scalar types as gradient is stored as column rather than row vector
352
+ static CUDA_CALLABLE inline T rmul(const grad_t &grad, const vec_t<3, scalar_t> &rhs)
353
+ {
354
+ return dot(grad, rhs);
355
+ }
356
+ };
357
+
358
+ template <unsigned Length, typename T> struct val_traits<vec_t<Length, T>>
359
+ {
360
+ using grad_t = mat_t<3, Length, T>;
361
+ using scalar_t = T;
362
+
363
+ static CUDA_CALLABLE inline vec_t<Length, T> rmul(const grad_t &grad, const vec_t<3, scalar_t> &rhs)
364
+ {
365
+ return mul(grad, rhs);
366
+ }
367
+ };
368
+
369
+ // Sampling the volume at the given index-space coordinates, uvw can be fractional
370
+ template <typename Accessor>
371
+ CUDA_CALLABLE inline typename Accessor::ValueType volume_sample(Accessor &accessor, vec3 uvw, int sampling_mode)
372
+ {
373
+ using T = typename Accessor::ValueType;
374
+ using w_t = typename val_traits<T>::scalar_t;
375
+
376
+ if (!accessor.is_valid())
377
+ {
378
+ return 0;
379
+ }
380
+
381
+ const pnanovdb_buf_t buf = accessor.buf;
382
+ const pnanovdb_vec3_t uvw_pnano{uvw[0], uvw[1], uvw[2]};
383
+
384
+ if (sampling_mode == CLOSEST)
385
+ {
386
+ const pnanovdb_coord_t ijk = vec3_round_to_coord(uvw_pnano);
387
+ return accessor.read_single(ijk);
388
+ }
389
+ else if (sampling_mode == LINEAR)
390
+ {
391
+ // NB. linear sampling is not used on int volumes
392
+ constexpr pnanovdb_coord_t OFFSETS[] = {
393
+ {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
394
+ };
395
+
396
+ const pnanovdb_vec3_t ijk_base{floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z)};
397
+ const pnanovdb_vec3_t ijk_frac{uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z};
398
+ const pnanovdb_coord_t ijk{(pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y,
399
+ (pnanovdb_int32_t)ijk_base.z};
400
+
401
+ accessor.init_cache();
402
+ T val = 0;
403
+ const float wx[2]{1 - ijk_frac.x, ijk_frac.x};
404
+ const float wy[2]{1 - ijk_frac.y, ijk_frac.y};
405
+ const float wz[2]{1 - ijk_frac.z, ijk_frac.z};
406
+ for (int idx = 0; idx < 8; ++idx)
407
+ {
408
+ const pnanovdb_coord_t &offs = OFFSETS[idx];
409
+ const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
410
+ const T v = accessor.read_cache(ijk_shifted);
411
+
412
+ const w_t w = wx[offs.x] * wy[offs.y] * wz[offs.z];
413
+ val = add(val, w * v);
414
+ }
415
+ return val;
416
+ }
417
+ return 0;
418
+ }
419
+
420
+ template <typename Accessor>
421
+ CUDA_CALLABLE inline void adj_volume_sample(Accessor &accessor, vec3 uvw, int sampling_mode, vec3 &adj_uvw,
422
+ const typename Accessor::ValueType &adj_ret)
423
+ {
424
+ // TODO: accessor data gradients
425
+
426
+ using T = typename Accessor::ValueType;
427
+ using w_t = typename val_traits<T>::scalar_t;
428
+ using w_grad_t = vec_t<3, w_t>;
429
+
430
+ if (!accessor.is_valid())
431
+ {
432
+ return;
433
+ }
434
+
435
+ const pnanovdb_buf_t buf = accessor.buf;
436
+ const pnanovdb_vec3_t uvw_pnano{uvw[0], uvw[1], uvw[2]};
437
+
438
+ if (sampling_mode != LINEAR)
439
+ {
440
+ const pnanovdb_coord_t ijk = vec3_round_to_coord(uvw_pnano);
441
+ accessor.adj_read_single(ijk, adj_ret);
442
+ return;
443
+ }
444
+
445
+ constexpr pnanovdb_coord_t OFFSETS[] = {
446
+ {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
447
+ };
448
+
449
+ const pnanovdb_vec3_t ijk_base{floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z)};
450
+ const pnanovdb_vec3_t ijk_frac{uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z};
451
+ const pnanovdb_coord_t ijk{(pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y,
452
+ (pnanovdb_int32_t)ijk_base.z};
453
+
454
+ accessor.init_cache();
455
+
456
+ const float wx[2]{1 - ijk_frac.x, ijk_frac.x};
457
+ const float wy[2]{1 - ijk_frac.y, ijk_frac.y};
458
+ const float wz[2]{1 - ijk_frac.z, ijk_frac.z};
459
+ for (int idx = 0; idx < 8; ++idx)
460
+ {
461
+ const pnanovdb_coord_t &offs = OFFSETS[idx];
462
+ const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
463
+ const T v = accessor.read_cache(ijk_shifted);
464
+
465
+ const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
466
+
467
+ const w_t w = wx[offs.x] * wy[offs.y] * wz[offs.z];
468
+ const w_grad_t grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z],
469
+ signs[2] * wx[offs.x] * wy[offs.y]);
470
+
471
+ adj_uvw += vec3(mul(w_t(dot(v, adj_ret)), grad_w));
472
+
473
+ const T adj_v = w * adj_ret;
474
+ accessor.adj_read_cache(ijk_shifted, adj_v);
475
+ }
476
+ }
477
+
478
+ // Sampling the volume at the given index-space coordinates, uvw can be fractional
479
+ template <typename Accessor>
480
+ CUDA_CALLABLE inline typename Accessor::ValueType volume_sample_grad(
481
+ Accessor &accessor, vec3 uvw, int sampling_mode, typename val_traits<typename Accessor::ValueType>::grad_t &grad)
482
+ {
483
+ using T = typename Accessor::ValueType;
484
+ using grad_T = typename val_traits<T>::grad_t;
485
+ using w_t = typename val_traits<T>::scalar_t;
486
+ using w_grad_t = vec_t<3, w_t>;
487
+
488
+ grad = grad_T{};
489
+
490
+ if (!accessor.is_valid())
491
+ {
492
+ return 0;
493
+ }
494
+
495
+ const pnanovdb_buf_t buf = accessor.buf;
496
+ const pnanovdb_vec3_t uvw_pnano{uvw[0], uvw[1], uvw[2]};
497
+
498
+ if (sampling_mode == CLOSEST)
499
+ {
500
+ const pnanovdb_coord_t ijk = vec3_round_to_coord(uvw_pnano);
501
+ return accessor.read_single(ijk);
502
+ }
503
+ else if (sampling_mode == LINEAR)
504
+ {
505
+ // NB. linear sampling is not used on int volumes
506
+ constexpr pnanovdb_coord_t OFFSETS[] = {
507
+ {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
508
+ };
509
+
510
+ const pnanovdb_vec3_t ijk_base{floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z)};
511
+ const pnanovdb_vec3_t ijk_frac{uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z};
512
+ const pnanovdb_coord_t ijk{(pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y,
513
+ (pnanovdb_int32_t)ijk_base.z};
514
+
515
+ accessor.init_cache();
516
+ T val = 0;
517
+ const float wx[2]{1 - ijk_frac.x, ijk_frac.x};
518
+ const float wy[2]{1 - ijk_frac.y, ijk_frac.y};
519
+ const float wz[2]{1 - ijk_frac.z, ijk_frac.z};
520
+ for (int idx = 0; idx < 8; ++idx)
521
+ {
522
+ const pnanovdb_coord_t &offs = OFFSETS[idx];
523
+ const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
524
+ const T v = accessor.read_cache(ijk_shifted);
525
+
526
+ const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
527
+
528
+ const w_t w = wx[offs.x] * wy[offs.y] * wz[offs.z];
529
+ const w_grad_t grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z],
530
+ signs[2] * wx[offs.x] * wy[offs.y]);
531
+
532
+ val = add(val, w * v);
533
+ grad += outer(v, grad_w);
534
+ }
535
+ return val;
536
+ }
537
+ return 0;
538
+ }
539
+
540
+ template <typename Accessor>
541
+ CUDA_CALLABLE inline void adj_volume_sample_grad(Accessor &accessor, vec3 uvw, int sampling_mode,
542
+ typename val_traits<typename Accessor::ValueType>::grad_t &grad,
543
+ vec3 &adj_uvw,
544
+ typename val_traits<typename Accessor::ValueType>::grad_t &adj_grad,
545
+ const typename Accessor::ValueType &adj_ret)
546
+ {
547
+ // TODO: accessor data gradients
548
+
549
+ using T = typename Accessor::ValueType;
550
+ using grad_T = typename val_traits<T>::grad_t;
551
+ using w_t = typename val_traits<T>::scalar_t;
552
+ using w_grad_t = vec_t<3, w_t>;
553
+ using w_hess_t = mat_t<3, 3, w_t>;
554
+
555
+ if (!accessor.is_valid())
556
+ {
557
+ return;
558
+ }
559
+
560
+ const pnanovdb_buf_t buf = accessor.buf;
561
+ const pnanovdb_vec3_t uvw_pnano{uvw[0], uvw[1], uvw[2]};
562
+
563
+ if (sampling_mode != LINEAR)
564
+ {
565
+ const pnanovdb_coord_t ijk = vec3_round_to_coord(uvw_pnano);
566
+ accessor.adj_read_single(ijk, adj_ret);
567
+ return;
568
+ }
569
+
570
+ constexpr pnanovdb_coord_t OFFSETS[] = {
571
+ {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
572
+ };
573
+
574
+ const pnanovdb_vec3_t ijk_base{floorf(uvw_pnano.x), floorf(uvw_pnano.y), floorf(uvw_pnano.z)};
575
+ const pnanovdb_vec3_t ijk_frac{uvw_pnano.x - ijk_base.x, uvw_pnano.y - ijk_base.y, uvw_pnano.z - ijk_base.z};
576
+ const pnanovdb_coord_t ijk{(pnanovdb_int32_t)ijk_base.x, (pnanovdb_int32_t)ijk_base.y,
577
+ (pnanovdb_int32_t)ijk_base.z};
578
+
579
+ accessor.init_cache();
580
+
581
+ const float wx[2]{1 - ijk_frac.x, ijk_frac.x};
582
+ const float wy[2]{1 - ijk_frac.y, ijk_frac.y};
583
+ const float wz[2]{1 - ijk_frac.z, ijk_frac.z};
584
+ for (int idx = 0; idx < 8; ++idx)
585
+ {
586
+ const pnanovdb_coord_t &offs = OFFSETS[idx];
587
+ const pnanovdb_coord_t ijk_shifted = pnanovdb_coord_add(ijk, offs);
588
+ const T v = accessor.read_cache(ijk_shifted);
589
+
590
+ const vec3 signs(offs.x * 2 - 1, offs.y * 2 - 1, offs.z * 2 - 1);
591
+
592
+ const w_t w = wx[offs.x] * wy[offs.y] * wz[offs.z];
593
+ const w_grad_t grad_w(signs[0] * wy[offs.y] * wz[offs.z], signs[1] * wx[offs.x] * wz[offs.z],
594
+ signs[2] * wx[offs.x] * wy[offs.y]);
595
+ adj_uvw += vec3(mul(w_t(dot(v, adj_ret)), grad_w));
596
+
597
+ const w_hess_t hess_w(0.0, signs[1] * signs[0] * wz[offs.z], signs[2] * signs[0] * wy[offs.y],
598
+ signs[0] * signs[1] * wz[offs.z], 0.0, signs[2] * signs[1] * wx[offs.x],
599
+ signs[0] * signs[2] * wy[offs.y], signs[1] * signs[2] * wx[offs.x], 0.0);
600
+ adj_uvw += vec3(mul(mul(v, adj_grad), hess_w));
601
+
602
+ const T adj_v = w * adj_ret + val_traits<T>::rmul(adj_grad, grad_w);
603
+ accessor.adj_read_cache(ijk_shifted, adj_v);
604
+ }
605
+ }
606
+
607
+ } // namespace volume
608
+ // namespace volume
609
+
610
+ // exposed kernel builtins
611
+
612
+ // volume_sample
613
+
614
+ template <typename T> CUDA_CALLABLE inline T volume_sample(uint64_t id, vec3 uvw, int sampling_mode)
615
+ {
616
+ volume::leaf_value_accessor<T> accessor(volume::id_to_buffer(id));
617
+ return volume::volume_sample(accessor, uvw, sampling_mode);
618
+ }
619
+
620
+ template <typename T>
621
+ CUDA_CALLABLE inline void adj_volume_sample(uint64_t id, vec3 uvw, int sampling_mode, uint64_t &adj_id, vec3 &adj_uvw,
622
+ int &adj_sampling_mode, const T &adj_ret)
623
+ {
624
+ volume::leaf_value_accessor<T> accessor(volume::id_to_buffer(id));
625
+ volume::adj_volume_sample(accessor, uvw, sampling_mode, adj_uvw, adj_ret);
626
+ }
627
+
628
+ template <typename T>
629
+ CUDA_CALLABLE inline T volume_sample_grad(uint64_t id, vec3 uvw, int sampling_mode,
630
+ typename volume::val_traits<T>::grad_t &grad)
631
+ {
632
+ volume::leaf_value_accessor<T> accessor(volume::id_to_buffer(id));
633
+ return volume::volume_sample_grad(accessor, uvw, sampling_mode, grad);
634
+ }
635
+
636
+ template <typename T>
637
+ CUDA_CALLABLE inline void adj_volume_sample_grad(uint64_t id, vec3 uvw, int sampling_mode,
638
+ typename volume::val_traits<T>::grad_t &grad, uint64_t &adj_id,
639
+ vec3 &adj_uvw, int &adj_sampling_mode,
640
+ typename volume::val_traits<T>::grad_t &adj_grad, const T &adj_ret)
641
+ {
642
+ volume::leaf_value_accessor<T> accessor(volume::id_to_buffer(id));
643
+ volume::adj_volume_sample_grad(accessor, uvw, sampling_mode, grad, adj_uvw, adj_grad, adj_ret);
644
+ }
645
+
646
+ // Sampling a float volume at the given index-space coordinates, uvw can be fractional
647
+ CUDA_CALLABLE inline float volume_sample_f(uint64_t id, vec3 uvw, int sampling_mode)
648
+ {
649
+ return volume_sample<float>(id, uvw, sampling_mode);
650
+ }
651
+
652
+ // Sampling an int volume at the given index-space coordinates, uvw can be fractional
653
+ CUDA_CALLABLE inline int32_t volume_sample_i(uint64_t id, vec3 uvw)
654
+ {
655
+ return volume_sample<int32_t>(id, uvw, volume::CLOSEST);
656
+ }
657
+
658
+ // Sampling a vector volume at the given index-space coordinates, uvw can be fractional
659
+ CUDA_CALLABLE inline vec3 volume_sample_v(uint64_t id, vec3 uvw, int sampling_mode)
660
+ {
661
+ return volume_sample<vec3>(id, uvw, sampling_mode);
662
+ }
663
+
664
+ CUDA_CALLABLE inline void adj_volume_sample_f(uint64_t id, vec3 uvw, int sampling_mode, uint64_t &adj_id, vec3 &adj_uvw,
665
+ int &adj_sampling_mode, const float &adj_ret)
666
+ {
667
+ adj_volume_sample(id, uvw, sampling_mode, adj_id, adj_uvw, adj_sampling_mode, adj_ret);
668
+ }
669
+
670
+ CUDA_CALLABLE inline void adj_volume_sample_v(uint64_t id, vec3 uvw, int sampling_mode, uint64_t &adj_id, vec3 &adj_uvw,
671
+ int &adj_sampling_mode, const vec3 &adj_ret)
672
+ {
673
+ adj_volume_sample(id, uvw, sampling_mode, adj_id, adj_uvw, adj_sampling_mode, adj_ret);
674
+ }
675
+
676
+ CUDA_CALLABLE inline void adj_volume_sample_i(uint64_t id, vec3 uvw, uint64_t &adj_id, vec3 &adj_uvw,
677
+ const int32_t &adj_ret)
678
+ {
679
+ // NOP
680
+ }
681
+
682
+ // Sampling the volume at the given index-space coordinates, uvw can be fractional
683
+ CUDA_CALLABLE inline float volume_sample_grad_f(uint64_t id, vec3 uvw, int sampling_mode, vec3 &grad)
684
+ {
685
+ return volume_sample_grad<float>(id, uvw, sampling_mode, grad);
686
+ }
687
+
688
+ CUDA_CALLABLE inline void adj_volume_sample_grad_f(uint64_t id, vec3 uvw, int sampling_mode, vec3 &grad,
689
+ uint64_t &adj_id, vec3 &adj_uvw, int &adj_sampling_mode,
690
+ vec3 &adj_grad, const float &adj_ret)
691
+ {
692
+ adj_volume_sample_grad<float>(id, uvw, sampling_mode, grad, adj_id, adj_uvw, adj_sampling_mode, adj_grad, adj_ret);
693
+ }
694
+
695
+ // volume_sample_index
696
+
697
+ template <typename T>
698
+ CUDA_CALLABLE inline T volume_sample_index(uint64_t id, vec3 uvw, int sampling_mode, const array_t<T> &voxel_data,
699
+ const T &background)
700
+ {
701
+ volume::index_value_accessor<T> accessor(volume::id_to_buffer(id), voxel_data, background);
702
+ return volume::volume_sample(accessor, uvw, sampling_mode);
703
+ }
704
+
705
+ template <typename T>
706
+ CUDA_CALLABLE inline void adj_volume_sample_index(uint64_t id, vec3 uvw, int sampling_mode,
707
+ const array_t<T> &voxel_data, const T &background, uint64_t &adj_id,
708
+ vec3 &adj_uvw, int &adj_sampling_mode, array_t<T> &adj_voxel_data,
709
+ T &adj_background, const T &adj_ret)
710
+ {
711
+ volume::index_value_accessor<T> accessor(volume::id_to_buffer(id), voxel_data, background, &adj_background);
712
+ volume::adj_volume_sample(accessor, uvw, sampling_mode, adj_uvw, adj_ret);
713
+ }
714
+
715
+ template <typename T>
716
+ CUDA_CALLABLE inline T volume_sample_grad_index(uint64_t id, vec3 uvw, int sampling_mode, const array_t<T> &voxel_data,
717
+ const T &background, typename volume::val_traits<T>::grad_t &grad)
718
+ {
719
+ volume::index_value_accessor<T> accessor(volume::id_to_buffer(id), voxel_data, background);
720
+ return volume::volume_sample_grad(accessor, uvw, sampling_mode, grad);
721
+ }
722
+
723
+ template <typename T>
724
+ CUDA_CALLABLE inline void adj_volume_sample_grad_index(
725
+ uint64_t id, vec3 uvw, int sampling_mode, const array_t<T> &voxel_data, const T &background,
726
+ typename volume::val_traits<T>::grad_t &grad, uint64_t &adj_id, vec3 &adj_uvw, int &adj_sampling_mode,
727
+ array_t<T> &adj_voxel_data, T &adj_background, typename volume::val_traits<T>::grad_t &adj_grad, const T &adj_ret)
728
+ {
729
+ volume::index_value_accessor<T> accessor(volume::id_to_buffer(id), voxel_data, background, &adj_background);
730
+ volume::adj_volume_sample_grad(accessor, uvw, sampling_mode, grad, adj_uvw, adj_grad, adj_ret);
731
+ }
732
+
733
+ // volume_lookup
734
+
735
+ template <typename T> CUDA_CALLABLE inline T volume_lookup(uint64_t id, int32_t i, int32_t j, int32_t k)
736
+ {
737
+ using traits = volume::pnano_traits<T>;
738
+
739
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
740
+ if (volume::get_grid_type(buf) != traits::GRID_TYPE)
741
+ return 0;
742
+
743
+ const pnanovdb_root_handle_t root = volume::get_root(buf);
744
+
745
+ const pnanovdb_coord_t ijk{i, j, k};
746
+ T val;
747
+ volume::pnano_read(val, buf, root, PNANOVDB_REF(ijk));
748
+ return val;
749
+ }
750
+
751
+ template <typename T>
752
+ CUDA_CALLABLE inline void adj_volume_lookup(uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t &adj_id,
753
+ int32_t &adj_i, int32_t &adj_j, int32_t &adj_k, const T &adj_ret)
754
+ {
755
+ // NOP -- adjoint of grid values is not available
756
+ }
757
+
758
+ CUDA_CALLABLE inline float volume_lookup_f(uint64_t id, int32_t i, int32_t j, int32_t k)
759
+ {
760
+ return volume_lookup<float>(id, i, j, k);
761
+ }
762
+
763
+ CUDA_CALLABLE inline int32_t volume_lookup_i(uint64_t id, int32_t i, int32_t j, int32_t k)
764
+ {
765
+ return volume_lookup<int32_t>(id, i, j, k);
766
+ }
767
+
768
+ CUDA_CALLABLE inline vec3 volume_lookup_v(uint64_t id, int32_t i, int32_t j, int32_t k)
769
+ {
770
+ return volume_lookup<vec3>(id, i, j, k);
771
+ }
772
+
773
+ CUDA_CALLABLE inline void adj_volume_lookup_f(uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t &adj_id,
774
+ int32_t &adj_i, int32_t &adj_j, int32_t &adj_k, const float &adj_ret)
775
+ {
776
+ adj_volume_lookup(id, i, j, k, adj_id, adj_i, adj_j, adj_k, adj_ret);
777
+ }
778
+
779
+ CUDA_CALLABLE inline void adj_volume_lookup_i(uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t &adj_id,
780
+ int32_t &adj_i, int32_t &adj_j, int32_t &adj_k, const int32_t &adj_ret)
781
+ {
782
+ adj_volume_lookup(id, i, j, k, adj_id, adj_i, adj_j, adj_k, adj_ret);
783
+ }
784
+
785
+ CUDA_CALLABLE inline void adj_volume_lookup_v(uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t &adj_id,
786
+ int32_t &adj_i, int32_t &adj_j, int32_t &adj_k, const vec3 &adj_ret)
787
+ {
788
+ adj_volume_lookup(id, i, j, k, adj_id, adj_i, adj_j, adj_k, adj_ret);
789
+ }
790
+
791
+ CUDA_CALLABLE inline int32_t volume_lookup_index(uint64_t id, int32_t i, int32_t j, int32_t k)
792
+ {
793
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
794
+ const pnanovdb_root_handle_t root = volume::get_root(buf);
795
+ const pnanovdb_grid_type_t grid_type = volume::get_grid_type(buf);
796
+
797
+ const pnanovdb_coord_t ijk{i, j, k};
798
+
799
+ pnanovdb_uint32_t level;
800
+ const pnanovdb_address_t address =
801
+ pnanovdb_root_get_value_address_and_level(grid_type, buf, root, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
802
+
803
+ if (level == 0)
804
+ {
805
+ pnanovdb_uint64_t voxel_index = volume::get_grid_voxel_index(grid_type, buf, address, ijk);
806
+
807
+ return static_cast<int32_t>(voxel_index) - 1;
808
+ }
809
+ return -1;
810
+ }
811
+
812
+ CUDA_CALLABLE inline void adj_volume_lookup_index(uint64_t id, int32_t i, int32_t j, int32_t k, uint64_t &adj_id,
813
+ int32_t &adj_i, int32_t &adj_j, int32_t &adj_k, const vec3 &adj_ret)
814
+ {
815
+ // NOP
816
+ }
817
+
818
+ // volume_store
819
+
820
+ template <typename T>
821
+ CUDA_CALLABLE inline void volume_store(uint64_t id, int32_t i, int32_t j, int32_t k, const T &value)
822
+ {
823
+ using traits = volume::pnano_traits<T>;
824
+
825
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
826
+ if (volume::get_grid_type(buf) != traits::GRID_TYPE)
827
+ return;
828
+
829
+ const pnanovdb_root_handle_t root = volume::get_root(buf);
830
+ const pnanovdb_coord_t ijk{i, j, k};
831
+
832
+ pnanovdb_uint32_t level;
833
+ const pnanovdb_address_t address =
834
+ pnanovdb_root_get_value_address_and_level(traits::GRID_TYPE, buf, root, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
835
+
836
+ if (level == 0)
837
+ {
838
+ // only write at at leaf level (prevent modifying background value)
839
+ // TODO is this the intended semantics? or should be allow writing to background?
840
+ volume::pnano_write(value, buf, address);
841
+ }
842
+ }
843
+
844
+ template <typename T>
845
+ CUDA_CALLABLE inline void adj_volume_store(uint64_t id, int32_t i, int32_t j, int32_t k, const T &value,
846
+ uint64_t &adj_id, int32_t &adj_i, int32_t &adj_j, int32_t &adj_k,
847
+ T &adj_value)
848
+ {
849
+ // NOP -- adjoint of grid values is not available
850
+ }
851
+
852
+ CUDA_CALLABLE inline void volume_store_f(uint64_t id, int32_t i, int32_t j, int32_t k, const float &value)
853
+ {
854
+ volume_store(id, i, j, k, value);
855
+ }
856
+
857
+ CUDA_CALLABLE inline void adj_volume_store_f(uint64_t id, int32_t i, int32_t j, int32_t k, const float &value,
858
+ uint64_t &adj_id, int32_t &adj_i, int32_t &adj_j, int32_t &adj_k,
859
+ float &adj_value)
860
+ {
861
+ adj_volume_store(id, i, j, k, value, adj_id, adj_i, adj_j, adj_k, adj_value);
862
+ }
863
+
864
+ CUDA_CALLABLE inline void volume_store_v(uint64_t id, int32_t i, int32_t j, int32_t k, const vec3 &value)
865
+ {
866
+ volume_store(id, i, j, k, value);
867
+ }
868
+
869
+ CUDA_CALLABLE inline void adj_volume_store_v(uint64_t id, int32_t i, int32_t j, int32_t k, const vec3 &value,
870
+ uint64_t &adj_id, int32_t &adj_i, int32_t &adj_j, int32_t &adj_k,
871
+ vec3 &adj_value)
872
+ {
873
+ adj_volume_store(id, i, j, k, value, adj_id, adj_i, adj_j, adj_k, adj_value);
874
+ }
875
+
876
+ CUDA_CALLABLE inline void volume_store_i(uint64_t id, int32_t i, int32_t j, int32_t k, const int32_t &value)
877
+ {
878
+ volume_store(id, i, j, k, value);
879
+ }
880
+
881
+ CUDA_CALLABLE inline void adj_volume_store_i(uint64_t id, int32_t i, int32_t j, int32_t k, const int32_t &value,
882
+ uint64_t &adj_id, int32_t &adj_i, int32_t &adj_j, int32_t &adj_k,
883
+ int32_t &adj_value)
884
+ {
885
+ adj_volume_store(id, i, j, k, value, adj_id, adj_i, adj_j, adj_k, adj_value);
886
+ }
887
+
888
+ // Transform position from index space to world space
889
+ CUDA_CALLABLE inline vec3 volume_index_to_world(uint64_t id, vec3 uvw)
890
+ {
891
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
892
+ const pnanovdb_grid_handle_t grid = {0u};
893
+ const pnanovdb_vec3_t pos{uvw[0], uvw[1], uvw[2]};
894
+ const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_worldf(buf, grid, PNANOVDB_REF(pos));
895
+ return {xyz.x, xyz.y, xyz.z};
896
+ }
897
+
898
+ // Transform position from world space to index space
899
+ CUDA_CALLABLE inline vec3 volume_world_to_index(uint64_t id, vec3 xyz)
900
+ {
901
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
902
+ const pnanovdb_grid_handle_t grid = {0u};
903
+ const pnanovdb_vec3_t pos{xyz[0], xyz[1], xyz[2]};
904
+ const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_indexf(buf, grid, PNANOVDB_REF(pos));
905
+ return {uvw.x, uvw.y, uvw.z};
906
+ }
907
+
908
+ CUDA_CALLABLE inline void adj_volume_index_to_world(uint64_t id, vec3 uvw, uint64_t &adj_id, vec3 &adj_uvw,
909
+ const vec3 &adj_ret)
910
+ {
911
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
912
+ const pnanovdb_grid_handle_t grid = {0u};
913
+ const pnanovdb_vec3_t pos{adj_ret[0], adj_ret[1], adj_ret[2]};
914
+ const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_world_dirf(buf, grid, PNANOVDB_REF(pos));
915
+ adj_uvw = add(adj_uvw, vec3{xyz.x, xyz.y, xyz.z});
916
+ }
917
+
918
+ CUDA_CALLABLE inline void adj_volume_world_to_index(uint64_t id, vec3 xyz, uint64_t &adj_id, vec3 &adj_xyz,
919
+ const vec3 &adj_ret)
920
+ {
921
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
922
+ const pnanovdb_grid_handle_t grid = {0u};
923
+ const pnanovdb_vec3_t pos{adj_ret[0], adj_ret[1], adj_ret[2]};
924
+ const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_index_dirf(buf, grid, PNANOVDB_REF(pos));
925
+ adj_xyz = add(adj_xyz, vec3{uvw.x, uvw.y, uvw.z});
926
+ }
927
+
928
+ // Transform direction from index space to world space
929
+ CUDA_CALLABLE inline vec3 volume_index_to_world_dir(uint64_t id, vec3 uvw)
930
+ {
931
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
932
+ const pnanovdb_grid_handle_t grid = {0u};
933
+ const pnanovdb_vec3_t pos{uvw[0], uvw[1], uvw[2]};
934
+ const pnanovdb_vec3_t xyz = pnanovdb_grid_index_to_world_dirf(buf, grid, PNANOVDB_REF(pos));
935
+ return {xyz.x, xyz.y, xyz.z};
936
+ }
937
+
938
+ // Transform direction from world space to index space
939
+ CUDA_CALLABLE inline vec3 volume_world_to_index_dir(uint64_t id, vec3 xyz)
940
+ {
941
+ const pnanovdb_buf_t buf = volume::id_to_buffer(id);
942
+ const pnanovdb_grid_handle_t grid = {0u};
943
+ const pnanovdb_vec3_t pos{xyz[0], xyz[1], xyz[2]};
944
+ const pnanovdb_vec3_t uvw = pnanovdb_grid_world_to_index_dirf(buf, grid, PNANOVDB_REF(pos));
945
+ return {uvw.x, uvw.y, uvw.z};
946
+ }
947
+
948
+ CUDA_CALLABLE inline void adj_volume_index_to_world_dir(uint64_t id, vec3 uvw, uint64_t &adj_id, vec3 &adj_uvw,
949
+ const vec3 &adj_ret)
950
+ {
951
+ adj_volume_index_to_world(id, uvw, adj_id, adj_uvw, adj_ret);
952
+ }
953
+
954
+ CUDA_CALLABLE inline void adj_volume_world_to_index_dir(uint64_t id, vec3 xyz, uint64_t &adj_id, vec3 &adj_xyz,
955
+ const vec3 &adj_ret)
956
+ {
957
+ adj_volume_world_to_index(id, xyz, adj_id, adj_xyz, adj_ret);
958
+ }
959
+
960
+ } // namespace wp