warp-lang 1.0.2__py3-none-manylinux2014_aarch64.whl → 1.1.0__py3-none-manylinux2014_aarch64.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.
- warp/__init__.py +108 -97
- warp/__init__.pyi +1 -1
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +115 -113
- warp/build_dll.py +383 -375
- warp/builtins.py +3425 -3354
- warp/codegen.py +2878 -2792
- warp/config.py +40 -36
- warp/constants.py +45 -45
- warp/context.py +5194 -5102
- warp/dlpack.py +442 -442
- warp/examples/__init__.py +16 -16
- warp/examples/assets/bear.usd +0 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -110
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usd +0 -0
- warp/examples/assets/nv_ant.xml +92 -92
- warp/examples/assets/nv_humanoid.xml +183 -183
- warp/examples/assets/quadruped.urdf +267 -267
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usd +0 -0
- warp/examples/benchmarks/benchmark_api.py +383 -383
- warp/examples/benchmarks/benchmark_cloth.py +278 -277
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
- warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
- warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
- warp/examples/benchmarks/benchmark_cloth_warp.py +146 -146
- warp/examples/benchmarks/benchmark_launches.py +295 -295
- warp/examples/browse.py +29 -29
- warp/examples/core/example_dem.py +234 -219
- warp/examples/core/example_fluid.py +293 -267
- warp/examples/core/example_graph_capture.py +144 -126
- warp/examples/core/example_marching_cubes.py +188 -174
- warp/examples/core/example_mesh.py +174 -155
- warp/examples/core/example_mesh_intersect.py +205 -193
- warp/examples/core/example_nvdb.py +176 -170
- warp/examples/core/example_raycast.py +105 -90
- warp/examples/core/example_raymarch.py +199 -178
- warp/examples/core/example_render_opengl.py +185 -141
- warp/examples/core/example_sph.py +405 -387
- warp/examples/core/example_torch.py +222 -181
- warp/examples/core/example_wave.py +263 -248
- warp/examples/fem/bsr_utils.py +378 -380
- warp/examples/fem/example_apic_fluid.py +407 -389
- warp/examples/fem/example_convection_diffusion.py +182 -168
- warp/examples/fem/example_convection_diffusion_dg.py +219 -209
- warp/examples/fem/example_convection_diffusion_dg0.py +204 -194
- warp/examples/fem/example_deformed_geometry.py +177 -159
- warp/examples/fem/example_diffusion.py +201 -173
- warp/examples/fem/example_diffusion_3d.py +177 -152
- warp/examples/fem/example_diffusion_mgpu.py +221 -214
- warp/examples/fem/example_mixed_elasticity.py +244 -222
- warp/examples/fem/example_navier_stokes.py +259 -243
- warp/examples/fem/example_stokes.py +220 -192
- warp/examples/fem/example_stokes_transfer.py +265 -249
- warp/examples/fem/mesh_utils.py +133 -109
- warp/examples/fem/plot_utils.py +292 -287
- warp/examples/optim/example_bounce.py +260 -246
- warp/examples/optim/example_cloth_throw.py +222 -209
- warp/examples/optim/example_diffray.py +566 -536
- warp/examples/optim/example_drone.py +864 -835
- warp/examples/optim/example_inverse_kinematics.py +176 -168
- warp/examples/optim/example_inverse_kinematics_torch.py +185 -169
- warp/examples/optim/example_spring_cage.py +239 -231
- warp/examples/optim/example_trajectory.py +223 -199
- warp/examples/optim/example_walker.py +306 -293
- warp/examples/sim/example_cartpole.py +139 -129
- warp/examples/sim/example_cloth.py +196 -186
- warp/examples/sim/example_granular.py +124 -111
- warp/examples/sim/example_granular_collision_sdf.py +197 -186
- warp/examples/sim/example_jacobian_ik.py +236 -214
- warp/examples/sim/example_particle_chain.py +118 -105
- warp/examples/sim/example_quadruped.py +193 -180
- warp/examples/sim/example_rigid_chain.py +197 -187
- warp/examples/sim/example_rigid_contact.py +189 -177
- warp/examples/sim/example_rigid_force.py +127 -125
- warp/examples/sim/example_rigid_gyroscopic.py +109 -95
- warp/examples/sim/example_rigid_soft_contact.py +134 -122
- warp/examples/sim/example_soft_body.py +190 -177
- warp/fabric.py +337 -335
- warp/fem/__init__.py +60 -27
- warp/fem/cache.py +401 -388
- warp/fem/dirichlet.py +178 -179
- warp/fem/domain.py +262 -263
- warp/fem/field/__init__.py +100 -101
- warp/fem/field/field.py +148 -149
- warp/fem/field/nodal_field.py +298 -299
- warp/fem/field/restriction.py +22 -21
- warp/fem/field/test.py +180 -181
- warp/fem/field/trial.py +183 -183
- warp/fem/geometry/__init__.py +15 -19
- warp/fem/geometry/closest_point.py +69 -70
- warp/fem/geometry/deformed_geometry.py +270 -271
- warp/fem/geometry/element.py +744 -744
- warp/fem/geometry/geometry.py +184 -186
- warp/fem/geometry/grid_2d.py +380 -373
- warp/fem/geometry/grid_3d.py +441 -435
- warp/fem/geometry/hexmesh.py +953 -953
- warp/fem/geometry/partition.py +374 -376
- warp/fem/geometry/quadmesh_2d.py +532 -532
- warp/fem/geometry/tetmesh.py +840 -840
- warp/fem/geometry/trimesh_2d.py +577 -577
- warp/fem/integrate.py +1630 -1615
- warp/fem/operator.py +190 -191
- warp/fem/polynomial.py +214 -213
- warp/fem/quadrature/__init__.py +2 -2
- warp/fem/quadrature/pic_quadrature.py +243 -245
- warp/fem/quadrature/quadrature.py +295 -294
- warp/fem/space/__init__.py +294 -292
- warp/fem/space/basis_space.py +488 -489
- warp/fem/space/collocated_function_space.py +100 -105
- warp/fem/space/dof_mapper.py +236 -236
- warp/fem/space/function_space.py +148 -145
- warp/fem/space/grid_2d_function_space.py +267 -267
- warp/fem/space/grid_3d_function_space.py +305 -306
- warp/fem/space/hexmesh_function_space.py +350 -352
- warp/fem/space/partition.py +350 -350
- warp/fem/space/quadmesh_2d_function_space.py +368 -369
- warp/fem/space/restriction.py +158 -160
- warp/fem/space/shape/__init__.py +13 -15
- warp/fem/space/shape/cube_shape_function.py +738 -738
- warp/fem/space/shape/shape_function.py +102 -103
- warp/fem/space/shape/square_shape_function.py +611 -611
- warp/fem/space/shape/tet_shape_function.py +565 -567
- warp/fem/space/shape/triangle_shape_function.py +429 -429
- warp/fem/space/tetmesh_function_space.py +294 -292
- warp/fem/space/topology.py +297 -295
- warp/fem/space/trimesh_2d_function_space.py +223 -221
- warp/fem/types.py +77 -77
- warp/fem/utils.py +495 -495
- warp/jax.py +166 -141
- warp/jax_experimental.py +341 -339
- warp/native/array.h +1072 -1025
- warp/native/builtin.h +1560 -1560
- warp/native/bvh.cpp +398 -398
- warp/native/bvh.cu +525 -525
- warp/native/bvh.h +429 -429
- warp/native/clang/clang.cpp +495 -464
- warp/native/crt.cpp +31 -31
- warp/native/crt.h +334 -334
- warp/native/cuda_crt.h +1049 -1049
- warp/native/cuda_util.cpp +549 -540
- warp/native/cuda_util.h +288 -203
- warp/native/cutlass_gemm.cpp +34 -34
- warp/native/cutlass_gemm.cu +372 -372
- warp/native/error.cpp +66 -66
- warp/native/error.h +27 -27
- warp/native/fabric.h +228 -228
- warp/native/hashgrid.cpp +301 -278
- warp/native/hashgrid.cu +78 -77
- warp/native/hashgrid.h +227 -227
- warp/native/initializer_array.h +32 -32
- warp/native/intersect.h +1204 -1204
- warp/native/intersect_adj.h +365 -365
- warp/native/intersect_tri.h +322 -322
- warp/native/marching.cpp +2 -2
- warp/native/marching.cu +497 -497
- warp/native/marching.h +2 -2
- warp/native/mat.h +1498 -1498
- warp/native/matnn.h +333 -333
- warp/native/mesh.cpp +203 -203
- warp/native/mesh.cu +293 -293
- warp/native/mesh.h +1887 -1887
- warp/native/nanovdb/NanoVDB.h +4782 -4782
- warp/native/nanovdb/PNanoVDB.h +2553 -2553
- warp/native/nanovdb/PNanoVDBWrite.h +294 -294
- warp/native/noise.h +850 -850
- warp/native/quat.h +1084 -1084
- warp/native/rand.h +299 -299
- warp/native/range.h +108 -108
- warp/native/reduce.cpp +156 -156
- warp/native/reduce.cu +348 -348
- warp/native/runlength_encode.cpp +61 -61
- warp/native/runlength_encode.cu +46 -46
- warp/native/scan.cpp +30 -30
- warp/native/scan.cu +36 -36
- warp/native/scan.h +7 -7
- warp/native/solid_angle.h +442 -442
- warp/native/sort.cpp +94 -94
- warp/native/sort.cu +97 -97
- warp/native/sort.h +14 -14
- warp/native/sparse.cpp +337 -337
- warp/native/sparse.cu +544 -544
- warp/native/spatial.h +630 -630
- warp/native/svd.h +562 -562
- warp/native/temp_buffer.h +30 -30
- warp/native/vec.h +1132 -1132
- warp/native/volume.cpp +297 -297
- warp/native/volume.cu +32 -32
- warp/native/volume.h +538 -538
- warp/native/volume_builder.cu +425 -425
- warp/native/volume_builder.h +19 -19
- warp/native/warp.cpp +1057 -1052
- warp/native/warp.cu +2943 -2828
- warp/native/warp.h +313 -305
- warp/optim/__init__.py +9 -9
- warp/optim/adam.py +120 -120
- warp/optim/linear.py +1104 -939
- warp/optim/sgd.py +104 -92
- warp/render/__init__.py +10 -10
- warp/render/render_opengl.py +3217 -3204
- warp/render/render_usd.py +768 -749
- warp/render/utils.py +152 -150
- warp/sim/__init__.py +52 -59
- warp/sim/articulation.py +685 -685
- warp/sim/collide.py +1594 -1590
- warp/sim/import_mjcf.py +489 -481
- warp/sim/import_snu.py +220 -221
- warp/sim/import_urdf.py +536 -516
- warp/sim/import_usd.py +887 -881
- warp/sim/inertia.py +316 -317
- warp/sim/integrator.py +234 -233
- warp/sim/integrator_euler.py +1956 -1956
- warp/sim/integrator_featherstone.py +1910 -1991
- warp/sim/integrator_xpbd.py +3294 -3312
- warp/sim/model.py +4473 -4314
- warp/sim/particles.py +113 -112
- warp/sim/render.py +417 -403
- warp/sim/utils.py +413 -410
- warp/sparse.py +1227 -1227
- warp/stubs.py +2109 -2469
- warp/tape.py +1162 -225
- warp/tests/__init__.py +1 -1
- warp/tests/__main__.py +4 -4
- warp/tests/assets/torus.usda +105 -105
- warp/tests/aux_test_class_kernel.py +26 -26
- warp/tests/aux_test_compile_consts_dummy.py +10 -10
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
- warp/tests/aux_test_dependent.py +22 -22
- warp/tests/aux_test_grad_customs.py +23 -23
- warp/tests/aux_test_reference.py +11 -11
- warp/tests/aux_test_reference_reference.py +10 -10
- warp/tests/aux_test_square.py +17 -17
- warp/tests/aux_test_unresolved_func.py +14 -14
- warp/tests/aux_test_unresolved_symbol.py +14 -14
- warp/tests/disabled_kinematics.py +239 -239
- warp/tests/run_coverage_serial.py +31 -31
- warp/tests/test_adam.py +157 -157
- warp/tests/test_arithmetic.py +1124 -1124
- warp/tests/test_array.py +2417 -2326
- warp/tests/test_array_reduce.py +150 -150
- warp/tests/test_async.py +668 -656
- warp/tests/test_atomic.py +141 -141
- warp/tests/test_bool.py +204 -149
- warp/tests/test_builtins_resolution.py +1292 -1292
- warp/tests/test_bvh.py +164 -171
- warp/tests/test_closest_point_edge_edge.py +228 -228
- warp/tests/test_codegen.py +566 -553
- warp/tests/test_compile_consts.py +97 -101
- warp/tests/test_conditional.py +246 -246
- warp/tests/test_copy.py +232 -215
- warp/tests/test_ctypes.py +632 -632
- warp/tests/test_dense.py +67 -67
- warp/tests/test_devices.py +91 -98
- warp/tests/test_dlpack.py +530 -529
- warp/tests/test_examples.py +400 -378
- warp/tests/test_fabricarray.py +955 -955
- warp/tests/test_fast_math.py +62 -54
- warp/tests/test_fem.py +1277 -1278
- warp/tests/test_fp16.py +130 -130
- warp/tests/test_func.py +338 -337
- warp/tests/test_generics.py +571 -571
- warp/tests/test_grad.py +746 -640
- warp/tests/test_grad_customs.py +333 -336
- warp/tests/test_hash_grid.py +210 -164
- warp/tests/test_import.py +39 -39
- warp/tests/test_indexedarray.py +1134 -1134
- warp/tests/test_intersect.py +67 -67
- warp/tests/test_jax.py +307 -307
- warp/tests/test_large.py +167 -164
- warp/tests/test_launch.py +354 -354
- warp/tests/test_lerp.py +261 -261
- warp/tests/test_linear_solvers.py +191 -171
- warp/tests/test_lvalue.py +421 -493
- warp/tests/test_marching_cubes.py +65 -65
- warp/tests/test_mat.py +1801 -1827
- warp/tests/test_mat_lite.py +115 -115
- warp/tests/test_mat_scalar_ops.py +2907 -2889
- warp/tests/test_math.py +126 -193
- warp/tests/test_matmul.py +500 -499
- warp/tests/test_matmul_lite.py +410 -410
- warp/tests/test_mempool.py +188 -190
- warp/tests/test_mesh.py +284 -324
- warp/tests/test_mesh_query_aabb.py +228 -241
- warp/tests/test_mesh_query_point.py +692 -702
- warp/tests/test_mesh_query_ray.py +292 -303
- warp/tests/test_mlp.py +276 -276
- warp/tests/test_model.py +110 -110
- warp/tests/test_modules_lite.py +39 -39
- warp/tests/test_multigpu.py +163 -163
- warp/tests/test_noise.py +248 -248
- warp/tests/test_operators.py +250 -250
- warp/tests/test_options.py +123 -125
- warp/tests/test_peer.py +133 -137
- warp/tests/test_pinned.py +78 -78
- warp/tests/test_print.py +54 -54
- warp/tests/test_quat.py +2086 -2086
- warp/tests/test_rand.py +288 -288
- warp/tests/test_reload.py +217 -217
- warp/tests/test_rounding.py +179 -179
- warp/tests/test_runlength_encode.py +190 -190
- warp/tests/test_sim_grad.py +243 -0
- warp/tests/test_sim_kinematics.py +91 -97
- warp/tests/test_smoothstep.py +168 -168
- warp/tests/test_snippet.py +305 -266
- warp/tests/test_sparse.py +468 -460
- warp/tests/test_spatial.py +2148 -2148
- warp/tests/test_streams.py +486 -473
- warp/tests/test_struct.py +710 -675
- warp/tests/test_tape.py +173 -148
- warp/tests/test_torch.py +743 -743
- warp/tests/test_transient_module.py +87 -87
- warp/tests/test_types.py +556 -659
- warp/tests/test_utils.py +490 -499
- warp/tests/test_vec.py +1264 -1268
- warp/tests/test_vec_lite.py +73 -73
- warp/tests/test_vec_scalar_ops.py +2099 -2099
- warp/tests/test_verify_fp.py +94 -94
- warp/tests/test_volume.py +737 -736
- warp/tests/test_volume_write.py +255 -265
- warp/tests/unittest_serial.py +37 -37
- warp/tests/unittest_suites.py +363 -359
- warp/tests/unittest_utils.py +603 -578
- warp/tests/unused_test_misc.py +71 -71
- warp/tests/walkthrough_debug.py +85 -85
- warp/thirdparty/appdirs.py +598 -598
- warp/thirdparty/dlpack.py +143 -143
- warp/thirdparty/unittest_parallel.py +566 -561
- warp/torch.py +321 -295
- warp/types.py +4504 -4450
- warp/utils.py +1008 -821
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/LICENSE.md +126 -126
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/METADATA +338 -400
- warp_lang-1.1.0.dist-info/RECORD +352 -0
- warp/examples/assets/cube.usda +0 -42
- warp/examples/assets/sphere.usda +0 -56
- warp/examples/assets/torus.usda +0 -105
- warp_lang-1.0.2.dist-info/RECORD +0 -352
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.0.2.dist-info → warp_lang-1.1.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
|