rayd 0.2.2__tar.gz → 0.2.3__tar.gz
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.
- {rayd-0.2.2 → rayd-0.2.3}/PKG-INFO +1 -1
- {rayd-0.2.2 → rayd-0.2.3}/docs/api_reference.md +58 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/multi_bounce_reflection_trace.md +8 -1
- {rayd-0.2.2 → rayd-0.2.3}/docs/reflection_trace_gpu_dedup.md +4 -3
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/edge.h +9 -1
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/intersection.h +14 -2
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/reflection.h +10 -2
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/scene/scene.h +5 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/types.h +20 -0
- {rayd-0.2.2 → rayd-0.2.3}/pyproject.toml +1 -1
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/__init__.py +2 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_native.py +24 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/scene.py +33 -1
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/types.py +65 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/rayd.cpp +36 -7
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/scene.cpp +132 -8
- {rayd-0.2.2 → rayd-0.2.3}/tests/drjit/test_geometry.py +134 -1
- {rayd-0.2.2 → rayd-0.2.3}/tests/torch/test_geometry.py +128 -0
- {rayd-0.2.2 → rayd-0.2.3}/.github/constraints/drjit-build.txt +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/.github/workflows/pypi.yml +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/.gitignore +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/CMakeLists.txt +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/LICENSE +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/README.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/cmake/embed_ptx.cmake +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/build_optimization.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/edge_bvh_bottleneck_analysis.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/edge_bvh_lbvh_treelet_improvement_plan.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/edge_bvh_optimization_log.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/edge_bvh_stage3_preparation.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/performance_benchmark.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/performance_benchmark.png +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/docs/slang_interop.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/README.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/basics/camera_edge_sampling_gradient.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/basics/nearest_edge_query.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/basics/ray_mesh_intersection.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/renderer/README.md +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/renderer/cornell_box.png +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/renderer/cornell_box.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/examples/renderer/rfdt.png +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/camera.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/constants.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/fwd.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/mesh.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/optix.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/ray.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/rayd.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/scene/scene_edge.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/scene/scene_optix.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/slang/interop.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/slang/interop_types.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/slang/rayd.slang +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/transform.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd/utils.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/include/rayd_slang.slang +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/slang/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_convert.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_env.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_interop_patch.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_state.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/_util.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/camera.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/rayd/torch/mesh.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/camera.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/mesh.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_dedup.cu +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_dedup.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_trace.cu +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_trace_host.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_trace_host.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_trace_params.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/multipath/reflection_trace_ptx.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/native_launch_audit.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/native_launch_audit.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/optix.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/edge_bvh.cu +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/edge_bvh.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/edge_bvh_config.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/experimental/edge_bvh_ploc.h +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/experimental/edge_bvh_ploc_build.inc +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/experimental/edge_bvh_ploc_kernels.inc +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/experimental/scene_edge_ploc.inc +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/scene_edge.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/scene/scene_optix.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/src/slang_interop.cpp +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baseline_cases.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baseline_utils.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/camera/perspective_fov.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/camera/perspective_intrinsic.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/camera/sample_primary_ray.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/camera/sample_to_world.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/camera/world_to_sample.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/edges/primary_edge_sampling.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/edges/secondary_edges.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/batched_hits.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/constant_hit.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/degenerate.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/miss.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/multi_mesh.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/geometry/uv.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/gradients/transform_gradients.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/gradients/vertex_gradients.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/manifest.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/stress/repeated_run_summary.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/transforms/composition_left_right.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/transforms/direction_transform_checks.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/transforms/matrix_entry_checks.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/baselines/drjit_v0_4_6/transforms/point_transform_checks.json +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/benchmark_edge_bvh_cutoff_compare.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/benchmark_edge_bvh_pressure.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/benchmark_edge_bvh_stages.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/benchmark_edge_queries.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/benchmark_support.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/drjit/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/drjit/test_baseline.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/profile_kernel_launches.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/load_module_error.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_ad_autograd.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_ad_multi_param.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_ad_optimize.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_ad_struct_return.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_rayd_intersect.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/cases/slang_rayd_nearest_edge.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/shaders/rayd_query.slang +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/shaders/rayd_query_ad.slang +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/test_interop.slang +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/slang/test_slang.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/test_project_metadata.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/test_torch_interop_patch.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/torch/__init__.py +0 -0
- {rayd-0.2.2 → rayd-0.2.3}/tests/torch/test_edge_bvh_pressure.py +0 -0
|
@@ -16,10 +16,14 @@ Public top-level exports:
|
|
|
16
16
|
- `Camera`
|
|
17
17
|
- `Ray`
|
|
18
18
|
- `Intersection`
|
|
19
|
+
- `ReflectionChain`
|
|
19
20
|
- `NearestPointEdge`
|
|
20
21
|
- `NearestRayEdge`
|
|
21
22
|
- `PrimaryEdgeSample`
|
|
22
23
|
- `SecondaryEdgeInfo`
|
|
24
|
+
- `SceneEdgeInfo`
|
|
25
|
+
- `SceneEdgeTopology`
|
|
26
|
+
- `SceneGlobalGeometry`
|
|
23
27
|
|
|
24
28
|
All array-valued inputs and outputs use Dr.Jit CUDA arrays or tensors.
|
|
25
29
|
|
|
@@ -137,8 +141,15 @@ Methods:
|
|
|
137
141
|
- `is_ready() -> bool`
|
|
138
142
|
- `has_pending_updates() -> bool`
|
|
139
143
|
- `intersect(ray, active=True) -> Intersection`
|
|
144
|
+
- `trace_reflections(ray, max_bounces, active=True, *, deduplicate=False, canonical_prim_table=None, image_source_tolerance=1e-5) -> ReflectionChain`
|
|
140
145
|
- `nearest_edge(point, active=True) -> NearestPointEdge`
|
|
141
146
|
- `nearest_edge(ray, active=True) -> NearestRayEdge`
|
|
147
|
+
- `edge_info() -> SceneEdgeInfo`
|
|
148
|
+
- `edge_topology() -> SceneEdgeTopology`
|
|
149
|
+
- `global_geometry() -> SceneGlobalGeometry`
|
|
150
|
+
- `mesh_face_offsets()`
|
|
151
|
+
- `mesh_edge_offsets()`
|
|
152
|
+
- `mesh_vertex_offsets()`
|
|
142
153
|
|
|
143
154
|
Properties:
|
|
144
155
|
|
|
@@ -251,11 +262,58 @@ Fields:
|
|
|
251
262
|
- `barycentric`
|
|
252
263
|
- `shape_id`
|
|
253
264
|
- `prim_id`
|
|
265
|
+
- `local_prim_id`
|
|
266
|
+
- `global_prim_id`
|
|
254
267
|
|
|
255
268
|
Methods:
|
|
256
269
|
|
|
257
270
|
- `is_valid()`
|
|
258
271
|
|
|
272
|
+
Notes:
|
|
273
|
+
|
|
274
|
+
- `prim_id` is kept as the mesh-local triangle id for compatibility.
|
|
275
|
+
- `local_prim_id` is identical to `prim_id`.
|
|
276
|
+
- `global_prim_id` is the scene-global triangle id.
|
|
277
|
+
|
|
278
|
+
### `ReflectionChain`
|
|
279
|
+
|
|
280
|
+
Result of `Scene.trace_reflections(...)`.
|
|
281
|
+
|
|
282
|
+
Fields:
|
|
283
|
+
|
|
284
|
+
- `bounce_count`
|
|
285
|
+
- `discovery_count`
|
|
286
|
+
- `representative_ray_index`
|
|
287
|
+
- `t`
|
|
288
|
+
- `hit_points`
|
|
289
|
+
- `geo_normals`
|
|
290
|
+
- `image_sources`
|
|
291
|
+
- `plane_points`
|
|
292
|
+
- `plane_normals`
|
|
293
|
+
- `shape_ids`
|
|
294
|
+
- `prim_ids`
|
|
295
|
+
- `local_prim_ids`
|
|
296
|
+
- `global_prim_ids`
|
|
297
|
+
|
|
298
|
+
Notes:
|
|
299
|
+
|
|
300
|
+
- `prim_ids` remains mesh-local for compatibility.
|
|
301
|
+
- `local_prim_ids` is identical to `prim_ids`.
|
|
302
|
+
- `global_prim_ids` is the scene-global triangle id chain.
|
|
303
|
+
|
|
304
|
+
### `SceneGlobalGeometry`
|
|
305
|
+
|
|
306
|
+
Canonical scene-global geometry cache exposed by `Scene.global_geometry()`.
|
|
307
|
+
|
|
308
|
+
Fields:
|
|
309
|
+
|
|
310
|
+
- `vertices`
|
|
311
|
+
- `faces`
|
|
312
|
+
- `face_normal`
|
|
313
|
+
- `shape_id`
|
|
314
|
+
- `local_prim_id`
|
|
315
|
+
- `global_prim_id`
|
|
316
|
+
|
|
259
317
|
## Nearest-Edge Types
|
|
260
318
|
|
|
261
319
|
### `NearestPointEdge`
|
|
@@ -46,12 +46,19 @@ ReflectionChain trace_reflections(const RayDetached &ray,
|
|
|
46
46
|
MaskDetached active = true) const;
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
Current API note:
|
|
50
|
+
|
|
51
|
+
- `prim_ids` is mesh-local for compatibility.
|
|
52
|
+
- `local_prim_ids` is identical to `prim_ids`.
|
|
53
|
+
- `global_prim_ids` is the scene-global triangle-id chain.
|
|
54
|
+
|
|
49
55
|
### Python (nanobind)
|
|
50
56
|
|
|
51
57
|
```python
|
|
52
58
|
chain = scene.trace_reflections(ray, max_bounces=3)
|
|
53
59
|
chain.bounce_count # drjit.cuda.Int [N]
|
|
54
60
|
chain.prim_ids # drjit.cuda.Int [N*B]
|
|
61
|
+
chain.global_prim_ids# drjit.cuda.Int [N*B]
|
|
55
62
|
chain.hit_points # drjit.cuda.Array3f [N*B]
|
|
56
63
|
chain.image_sources # drjit.cuda.Array3f [N*B]
|
|
57
64
|
# ...
|
|
@@ -63,6 +70,7 @@ chain.image_sources # drjit.cuda.Array3f [N*B]
|
|
|
63
70
|
chain = scene.trace_reflections(ray, max_bounces=3)
|
|
64
71
|
chain.bounce_count # torch.Tensor int32 [N]
|
|
65
72
|
chain.prim_ids # torch.Tensor int32 [N, B]
|
|
73
|
+
chain.global_prim_ids# torch.Tensor int32 [N, B]
|
|
66
74
|
chain.hit_points # torch.Tensor float32 [N, B, 3]
|
|
67
75
|
chain.image_sources # torch.Tensor float32 [N, B, 3]
|
|
68
76
|
# ...
|
|
@@ -1036,4 +1044,3 @@ file(WRITE "${OUTPUT_FILE}"
|
|
|
1036
1044
|
)
|
|
1037
1045
|
```
|
|
1038
1046
|
|
|
1039
|
-
|
|
@@ -91,7 +91,8 @@ chain = scene.trace_reflections(ray, max_bounces=3,
|
|
|
91
91
|
# PyTorch
|
|
92
92
|
chain = scene.trace_reflections(ray, max_bounces=3, deduplicate=True)
|
|
93
93
|
chain.ray_count # M (unique paths, not input ray count)
|
|
94
|
-
chain.prim_ids # [M, B]
|
|
94
|
+
chain.prim_ids # [M, B] (mesh-local)
|
|
95
|
+
chain.global_prim_ids # [M, B] (scene-global)
|
|
95
96
|
chain.image_sources # [M, B, 3]
|
|
96
97
|
chain.discovery_count # [M]
|
|
97
98
|
```
|
|
@@ -110,8 +111,8 @@ New CUDA kernel: `reflection_dedup_build_keys`
|
|
|
110
111
|
|
|
111
112
|
For each ray `i`:
|
|
112
113
|
1. If `bounce_count[i] == 0` → key = `UINT64_MAX` (dead lane, sorted last)
|
|
113
|
-
2.
|
|
114
|
-
3. Hash the
|
|
114
|
+
2. Build / remap the scene-global prim chain through `canonical_prim_table`
|
|
115
|
+
3. Hash the global prim-id chain into a 64-bit key:
|
|
115
116
|
|
|
116
117
|
```cuda
|
|
117
118
|
__global__ void reflection_dedup_build_keys(
|
|
@@ -173,24 +173,32 @@ struct SceneEdgeInfo {
|
|
|
173
173
|
struct SceneEdgeTopology {
|
|
174
174
|
IntDetached v0;
|
|
175
175
|
IntDetached v1;
|
|
176
|
+
IntDetached v0_global;
|
|
177
|
+
IntDetached v1_global;
|
|
176
178
|
IntDetached face0_local;
|
|
177
179
|
IntDetached face1_local;
|
|
178
180
|
IntDetached face0_global;
|
|
179
181
|
IntDetached face1_global;
|
|
180
182
|
IntDetached opposite_vertex0;
|
|
181
183
|
IntDetached opposite_vertex1;
|
|
184
|
+
IntDetached opposite_vertex0_global;
|
|
185
|
+
IntDetached opposite_vertex1_global;
|
|
182
186
|
|
|
183
187
|
int size() const { return v0.size(); }
|
|
184
188
|
|
|
185
189
|
DRJIT_STRUCT(SceneEdgeTopology,
|
|
186
190
|
v0,
|
|
187
191
|
v1,
|
|
192
|
+
v0_global,
|
|
193
|
+
v1_global,
|
|
188
194
|
face0_local,
|
|
189
195
|
face1_local,
|
|
190
196
|
face0_global,
|
|
191
197
|
face1_global,
|
|
192
198
|
opposite_vertex0,
|
|
193
|
-
opposite_vertex1
|
|
199
|
+
opposite_vertex1,
|
|
200
|
+
opposite_vertex0_global,
|
|
201
|
+
opposite_vertex1_global)
|
|
194
202
|
};
|
|
195
203
|
|
|
196
204
|
} // namespace rayd
|
|
@@ -43,8 +43,20 @@ struct IntersectionData {
|
|
|
43
43
|
Vec3f barycentric = zeros<Vec3f>(1);
|
|
44
44
|
Int_ shape_id = full<Int_>(-1, 1);
|
|
45
45
|
Int_ prim_id = full<Int_>(-1, 1);
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
Int_ local_prim_id = full<Int_>(-1, 1);
|
|
47
|
+
Int_ global_prim_id = full<Int_>(-1, 1);
|
|
48
|
+
|
|
49
|
+
DRJIT_STRUCT(IntersectionData,
|
|
50
|
+
t,
|
|
51
|
+
p,
|
|
52
|
+
n,
|
|
53
|
+
geo_n,
|
|
54
|
+
uv,
|
|
55
|
+
barycentric,
|
|
56
|
+
shape_id,
|
|
57
|
+
prim_id,
|
|
58
|
+
local_prim_id,
|
|
59
|
+
global_prim_id)
|
|
48
60
|
};
|
|
49
61
|
|
|
50
62
|
} // namespace rayd
|
|
@@ -32,6 +32,8 @@ struct ReflectionBounceData {
|
|
|
32
32
|
Vec3f plane_normals = zeros<Vec3f>(1);
|
|
33
33
|
Int_ shape_ids = full<Int_>(-1, 1);
|
|
34
34
|
Int_ prim_ids = full<Int_>(-1, 1);
|
|
35
|
+
Int_ local_prim_ids = full<Int_>(-1, 1);
|
|
36
|
+
Int_ global_prim_ids = full<Int_>(-1, 1);
|
|
35
37
|
|
|
36
38
|
DRJIT_STRUCT(ReflectionBounceData,
|
|
37
39
|
t,
|
|
@@ -41,7 +43,9 @@ struct ReflectionBounceData {
|
|
|
41
43
|
plane_points,
|
|
42
44
|
plane_normals,
|
|
43
45
|
shape_ids,
|
|
44
|
-
prim_ids
|
|
46
|
+
prim_ids,
|
|
47
|
+
local_prim_ids,
|
|
48
|
+
global_prim_ids)
|
|
45
49
|
};
|
|
46
50
|
|
|
47
51
|
template <typename Float_>
|
|
@@ -70,6 +74,8 @@ struct ReflectionChainData {
|
|
|
70
74
|
Vec3f plane_normals = zeros<Vec3f>(1);
|
|
71
75
|
Int_ shape_ids = full<Int_>(-1, 1);
|
|
72
76
|
Int_ prim_ids = full<Int_>(-1, 1);
|
|
77
|
+
Int_ local_prim_ids = full<Int_>(-1, 1);
|
|
78
|
+
Int_ global_prim_ids = full<Int_>(-1, 1);
|
|
73
79
|
|
|
74
80
|
DRJIT_STRUCT(ReflectionChainData,
|
|
75
81
|
bounce_count,
|
|
@@ -82,7 +88,9 @@ struct ReflectionChainData {
|
|
|
82
88
|
plane_points,
|
|
83
89
|
plane_normals,
|
|
84
90
|
shape_ids,
|
|
85
|
-
prim_ids
|
|
91
|
+
prim_ids,
|
|
92
|
+
local_prim_ids,
|
|
93
|
+
global_prim_ids)
|
|
86
94
|
};
|
|
87
95
|
|
|
88
96
|
template <typename Float_>
|
|
@@ -57,6 +57,8 @@ public:
|
|
|
57
57
|
const MaskDetached &edge_mask() const;
|
|
58
58
|
const IntDetached &mesh_face_offsets() const { return face_offsets_; }
|
|
59
59
|
const IntDetached &mesh_edge_offsets() const { return edge_offsets_; }
|
|
60
|
+
const IntDetached &mesh_vertex_offsets() const { return vertex_offsets_; }
|
|
61
|
+
const SceneGlobalGeometry &global_geometry() const;
|
|
60
62
|
uint64_t version() const { return scene_version_; }
|
|
61
63
|
uint64_t edge_version() const { return edge_version_; }
|
|
62
64
|
VectoriT<3, true> triangle_edge_indices(const IntDetached &prim_id, bool global = true) const;
|
|
@@ -107,6 +109,7 @@ private:
|
|
|
107
109
|
bool vertices_dirty = false;
|
|
108
110
|
bool transform_dirty = false;
|
|
109
111
|
mutable bool edge_dirty = false;
|
|
112
|
+
int vertex_offset = 0;
|
|
110
113
|
int face_offset = 0;
|
|
111
114
|
int edge_offset = 0;
|
|
112
115
|
};
|
|
@@ -126,12 +129,14 @@ private:
|
|
|
126
129
|
|
|
127
130
|
IntDetached face_offsets_;
|
|
128
131
|
IntDetached edge_offsets_;
|
|
132
|
+
IntDetached vertex_offsets_;
|
|
129
133
|
TriangleInfo triangle_info_;
|
|
130
134
|
TriangleInfoDetached triangle_info_detached_;
|
|
131
135
|
TriangleUV triangle_uv_;
|
|
132
136
|
TriangleUVDetached triangle_uv_detached_;
|
|
133
137
|
Mask triangle_face_normal_mask_;
|
|
134
138
|
MaskDetached triangle_face_normal_mask_detached_;
|
|
139
|
+
SceneGlobalGeometry global_geometry_;
|
|
135
140
|
SecondaryEdgeInfo edge_info_;
|
|
136
141
|
SceneEdgeTopology edge_topology_;
|
|
137
142
|
IntDetached edge_shape_ids_;
|
|
@@ -130,4 +130,24 @@ using TriangleUVDetached = TriangleUvData<FloatDetached>;
|
|
|
130
130
|
template <bool Detached_>
|
|
131
131
|
using TriangleUVT = std::conditional_t<Detached_, TriangleUVDetached, TriangleUV>;
|
|
132
132
|
|
|
133
|
+
struct SceneGlobalGeometry {
|
|
134
|
+
Vector3f vertices;
|
|
135
|
+
Vector3iDetached faces;
|
|
136
|
+
Vector3f face_normal;
|
|
137
|
+
IntDetached shape_id;
|
|
138
|
+
IntDetached local_prim_id;
|
|
139
|
+
IntDetached global_prim_id;
|
|
140
|
+
|
|
141
|
+
int vertex_count() const { return vertices.x().size(); }
|
|
142
|
+
int face_count() const { return global_prim_id.size(); }
|
|
143
|
+
|
|
144
|
+
DRJIT_STRUCT(SceneGlobalGeometry,
|
|
145
|
+
vertices,
|
|
146
|
+
faces,
|
|
147
|
+
face_normal,
|
|
148
|
+
shape_id,
|
|
149
|
+
local_prim_id,
|
|
150
|
+
global_prim_id)
|
|
151
|
+
};
|
|
152
|
+
|
|
133
153
|
} // namespace rayd
|
|
@@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "rayd"
|
|
8
|
-
version = "0.2.
|
|
8
|
+
version = "0.2.3"
|
|
9
9
|
description = "RayD: minimalist differentiable ray tracing package wrapping Dr.Jit and OptiX."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
authors = [{ name = "Xingyu Chen", email = "xic063@ucsd.edu" }]
|
|
@@ -24,6 +24,7 @@ from .types import (
|
|
|
24
24
|
SceneSyncProfile,
|
|
25
25
|
SceneEdgeInfo,
|
|
26
26
|
SceneEdgeTopology,
|
|
27
|
+
SceneGlobalGeometry,
|
|
27
28
|
SecondaryEdgeInfo,
|
|
28
29
|
)
|
|
29
30
|
from .mesh import Mesh
|
|
@@ -50,6 +51,7 @@ __all__ = [
|
|
|
50
51
|
"SceneSyncProfile",
|
|
51
52
|
"SceneEdgeInfo",
|
|
52
53
|
"SceneEdgeTopology",
|
|
54
|
+
"SceneGlobalGeometry",
|
|
53
55
|
"SecondaryEdgeInfo",
|
|
54
56
|
"set_device",
|
|
55
57
|
]
|
|
@@ -37,6 +37,7 @@ from .types import (
|
|
|
37
37
|
Ray,
|
|
38
38
|
SceneEdgeInfo,
|
|
39
39
|
SceneEdgeTopology,
|
|
40
|
+
SceneGlobalGeometry,
|
|
40
41
|
SecondaryEdgeInfo,
|
|
41
42
|
)
|
|
42
43
|
from ._state import _MeshState, _CameraState
|
|
@@ -319,6 +320,8 @@ def _intersection_from_native(its: Any) -> Intersection:
|
|
|
319
320
|
barycentric=_vec3_to_tensor(its.barycentric),
|
|
320
321
|
shape_id=_scalar_array_to_tensor(its.shape_id),
|
|
321
322
|
prim_id=_scalar_array_to_tensor(its.prim_id),
|
|
323
|
+
local_prim_id=_scalar_array_to_tensor(its.local_prim_id),
|
|
324
|
+
global_prim_id=_scalar_array_to_tensor(its.global_prim_id),
|
|
322
325
|
)
|
|
323
326
|
|
|
324
327
|
|
|
@@ -337,6 +340,8 @@ def _reflection_chain_from_native(chain: Any) -> ReflectionChain:
|
|
|
337
340
|
plane_normals = _vec3_to_tensor(chain.plane_normals)
|
|
338
341
|
shape_ids = _scalar_array_to_tensor(chain.shape_ids)
|
|
339
342
|
prim_ids = _scalar_array_to_tensor(chain.prim_ids)
|
|
343
|
+
local_prim_ids = _scalar_array_to_tensor(chain.local_prim_ids)
|
|
344
|
+
global_prim_ids = _scalar_array_to_tensor(chain.global_prim_ids)
|
|
340
345
|
|
|
341
346
|
if ray_count <= 0 and hasattr(bounce_count, "numel"):
|
|
342
347
|
ray_count = int(bounce_count.numel())
|
|
@@ -358,6 +363,8 @@ def _reflection_chain_from_native(chain: Any) -> ReflectionChain:
|
|
|
358
363
|
plane_normals = dr.reshape(type(plane_normals), plane_normals, shape=(ray_count, max_bounces, 3))
|
|
359
364
|
shape_ids = dr.reshape(type(shape_ids), shape_ids, shape=(ray_count, max_bounces))
|
|
360
365
|
prim_ids = dr.reshape(type(prim_ids), prim_ids, shape=(ray_count, max_bounces))
|
|
366
|
+
local_prim_ids = dr.reshape(type(local_prim_ids), local_prim_ids, shape=(ray_count, max_bounces))
|
|
367
|
+
global_prim_ids = dr.reshape(type(global_prim_ids), global_prim_ids, shape=(ray_count, max_bounces))
|
|
361
368
|
|
|
362
369
|
return ReflectionChain(
|
|
363
370
|
bounce_count=bounce_count,
|
|
@@ -371,6 +378,8 @@ def _reflection_chain_from_native(chain: Any) -> ReflectionChain:
|
|
|
371
378
|
plane_normals=plane_normals,
|
|
372
379
|
shape_ids=shape_ids,
|
|
373
380
|
prim_ids=prim_ids,
|
|
381
|
+
local_prim_ids=local_prim_ids,
|
|
382
|
+
global_prim_ids=global_prim_ids,
|
|
374
383
|
max_bounces=max_bounces,
|
|
375
384
|
ray_count=ray_count,
|
|
376
385
|
)
|
|
@@ -433,12 +442,27 @@ def _scene_edge_topology_from_native(info: Any) -> SceneEdgeTopology:
|
|
|
433
442
|
return SceneEdgeTopology(
|
|
434
443
|
v0=_scalar_array_to_tensor(info.v0),
|
|
435
444
|
v1=_scalar_array_to_tensor(info.v1),
|
|
445
|
+
v0_global=_scalar_array_to_tensor(info.v0_global),
|
|
446
|
+
v1_global=_scalar_array_to_tensor(info.v1_global),
|
|
436
447
|
face0_local=_scalar_array_to_tensor(info.face0_local),
|
|
437
448
|
face1_local=_scalar_array_to_tensor(info.face1_local),
|
|
438
449
|
face0_global=_scalar_array_to_tensor(info.face0_global),
|
|
439
450
|
face1_global=_scalar_array_to_tensor(info.face1_global),
|
|
440
451
|
opposite_vertex0=_scalar_array_to_tensor(info.opposite_vertex0),
|
|
441
452
|
opposite_vertex1=_scalar_array_to_tensor(info.opposite_vertex1),
|
|
453
|
+
opposite_vertex0_global=_scalar_array_to_tensor(info.opposite_vertex0_global),
|
|
454
|
+
opposite_vertex1_global=_scalar_array_to_tensor(info.opposite_vertex1_global),
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def _scene_global_geometry_from_native(geometry: Any) -> SceneGlobalGeometry:
|
|
459
|
+
return SceneGlobalGeometry(
|
|
460
|
+
vertices=_vec3_to_tensor(geometry.vertices),
|
|
461
|
+
faces=_vec3_to_tensor(geometry.faces),
|
|
462
|
+
face_normal=_vec3_to_tensor(geometry.face_normal),
|
|
463
|
+
shape_id=_scalar_array_to_tensor(geometry.shape_id),
|
|
464
|
+
local_prim_id=_scalar_array_to_tensor(geometry.local_prim_id),
|
|
465
|
+
global_prim_id=_scalar_array_to_tensor(geometry.global_prim_id),
|
|
442
466
|
)
|
|
443
467
|
|
|
444
468
|
|
|
@@ -12,11 +12,20 @@ from ._util import (
|
|
|
12
12
|
_normalize_vector_tensor,
|
|
13
13
|
)
|
|
14
14
|
from ._convert import _scalar_array_to_tensor, _tensor_to_mask, _tensor_to_matrix4, _tensor_to_vec3, _to_torch_struct
|
|
15
|
-
from .types import
|
|
15
|
+
from .types import (
|
|
16
|
+
ReflectionChain,
|
|
17
|
+
Intersection,
|
|
18
|
+
Ray,
|
|
19
|
+
SceneSyncProfile,
|
|
20
|
+
SceneEdgeInfo,
|
|
21
|
+
SceneEdgeTopology,
|
|
22
|
+
SceneGlobalGeometry,
|
|
23
|
+
)
|
|
16
24
|
from ._state import _MeshState
|
|
17
25
|
from ._native import (
|
|
18
26
|
_allocate_native_scene_cache_id,
|
|
19
27
|
_build_native_mesh,
|
|
28
|
+
_prepare_native_scene_cache,
|
|
20
29
|
_scene_cache_refresh_policy,
|
|
21
30
|
_mesh_to_world_tensor,
|
|
22
31
|
_ray_batch_size,
|
|
@@ -25,6 +34,7 @@ from ._native import (
|
|
|
25
34
|
_scene_cache_tokens,
|
|
26
35
|
_scene_edge_info_from_native,
|
|
27
36
|
_scene_edge_topology_from_native,
|
|
37
|
+
_scene_global_geometry_from_native,
|
|
28
38
|
_scene_intersect_impl,
|
|
29
39
|
_scene_trace_reflections_impl,
|
|
30
40
|
_scene_nearest_point_impl,
|
|
@@ -250,6 +260,28 @@ class Scene:
|
|
|
250
260
|
raise RuntimeError("Scene.mesh_edge_offsets(): internal detached scene is unavailable.")
|
|
251
261
|
return _scalar_array_to_tensor(self._native_scene.mesh_edge_offsets()).torch()
|
|
252
262
|
|
|
263
|
+
def mesh_vertex_offsets(self) -> _torch.Tensor:
|
|
264
|
+
self._require_ready()
|
|
265
|
+
if self._native_scene is None:
|
|
266
|
+
raise RuntimeError("Scene.mesh_vertex_offsets(): internal detached scene is unavailable.")
|
|
267
|
+
return _scalar_array_to_tensor(self._native_scene.mesh_vertex_offsets()).torch()
|
|
268
|
+
|
|
269
|
+
def global_geometry(self) -> SceneGlobalGeometry:
|
|
270
|
+
self._require_query_ready()
|
|
271
|
+
mesh_states, topology_token, rebuild_token, vertex_tokens, left_tokens, right_tokens, refresh_policy, edge_mask = self._query_cache_inputs()
|
|
272
|
+
scene = _prepare_native_scene_cache(
|
|
273
|
+
self._query_cache_id,
|
|
274
|
+
mesh_states,
|
|
275
|
+
topology_token,
|
|
276
|
+
rebuild_token,
|
|
277
|
+
vertex_tokens,
|
|
278
|
+
left_tokens,
|
|
279
|
+
right_tokens,
|
|
280
|
+
refresh_policy,
|
|
281
|
+
edge_mask,
|
|
282
|
+
)
|
|
283
|
+
return _to_torch_struct(_scene_global_geometry_from_native(scene.global_geometry()))
|
|
284
|
+
|
|
253
285
|
def triangle_edge_indices(self, prim_id: Any, global_: bool = True, **kwargs: Any) -> tuple[_torch.Tensor, _torch.Tensor, _torch.Tensor]:
|
|
254
286
|
self._require_ready()
|
|
255
287
|
if "global" in kwargs:
|
|
@@ -33,6 +33,8 @@ class Intersection(_StructRepr):
|
|
|
33
33
|
"barycentric": object,
|
|
34
34
|
"shape_id": object,
|
|
35
35
|
"prim_id": object,
|
|
36
|
+
"local_prim_id": object,
|
|
37
|
+
"global_prim_id": object,
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
def __init__(
|
|
@@ -45,6 +47,8 @@ class Intersection(_StructRepr):
|
|
|
45
47
|
barycentric: Any = None,
|
|
46
48
|
shape_id: Any = None,
|
|
47
49
|
prim_id: Any = None,
|
|
50
|
+
local_prim_id: Any = None,
|
|
51
|
+
global_prim_id: Any = None,
|
|
48
52
|
):
|
|
49
53
|
self.t = t
|
|
50
54
|
self.p = p
|
|
@@ -54,6 +58,8 @@ class Intersection(_StructRepr):
|
|
|
54
58
|
self.barycentric = barycentric
|
|
55
59
|
self.shape_id = shape_id
|
|
56
60
|
self.prim_id = prim_id
|
|
61
|
+
self.local_prim_id = local_prim_id
|
|
62
|
+
self.global_prim_id = global_prim_id
|
|
57
63
|
|
|
58
64
|
def is_valid(self) -> Any:
|
|
59
65
|
return self.prim_id >= 0
|
|
@@ -72,6 +78,8 @@ class ReflectionChain(_StructRepr):
|
|
|
72
78
|
"plane_normals": object,
|
|
73
79
|
"shape_ids": object,
|
|
74
80
|
"prim_ids": object,
|
|
81
|
+
"local_prim_ids": object,
|
|
82
|
+
"global_prim_ids": object,
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
def __init__(
|
|
@@ -87,6 +95,8 @@ class ReflectionChain(_StructRepr):
|
|
|
87
95
|
plane_normals: Any = None,
|
|
88
96
|
shape_ids: Any = None,
|
|
89
97
|
prim_ids: Any = None,
|
|
98
|
+
local_prim_ids: Any = None,
|
|
99
|
+
global_prim_ids: Any = None,
|
|
90
100
|
max_bounces: int = 0,
|
|
91
101
|
ray_count: int = 0,
|
|
92
102
|
):
|
|
@@ -101,6 +111,8 @@ class ReflectionChain(_StructRepr):
|
|
|
101
111
|
self.plane_normals = plane_normals
|
|
102
112
|
self.shape_ids = shape_ids
|
|
103
113
|
self.prim_ids = prim_ids
|
|
114
|
+
self.local_prim_ids = local_prim_ids
|
|
115
|
+
self.global_prim_ids = global_prim_ids
|
|
104
116
|
self._max_bounces_hint = int(max_bounces)
|
|
105
117
|
self._ray_count_hint = int(ray_count)
|
|
106
118
|
|
|
@@ -311,33 +323,45 @@ class SceneEdgeTopology(_StructRepr):
|
|
|
311
323
|
DRJIT_STRUCT = {
|
|
312
324
|
"v0": object,
|
|
313
325
|
"v1": object,
|
|
326
|
+
"v0_global": object,
|
|
327
|
+
"v1_global": object,
|
|
314
328
|
"face0_local": object,
|
|
315
329
|
"face1_local": object,
|
|
316
330
|
"face0_global": object,
|
|
317
331
|
"face1_global": object,
|
|
318
332
|
"opposite_vertex0": object,
|
|
319
333
|
"opposite_vertex1": object,
|
|
334
|
+
"opposite_vertex0_global": object,
|
|
335
|
+
"opposite_vertex1_global": object,
|
|
320
336
|
}
|
|
321
337
|
|
|
322
338
|
def __init__(
|
|
323
339
|
self,
|
|
324
340
|
v0: Any = None,
|
|
325
341
|
v1: Any = None,
|
|
342
|
+
v0_global: Any = None,
|
|
343
|
+
v1_global: Any = None,
|
|
326
344
|
face0_local: Any = None,
|
|
327
345
|
face1_local: Any = None,
|
|
328
346
|
face0_global: Any = None,
|
|
329
347
|
face1_global: Any = None,
|
|
330
348
|
opposite_vertex0: Any = None,
|
|
331
349
|
opposite_vertex1: Any = None,
|
|
350
|
+
opposite_vertex0_global: Any = None,
|
|
351
|
+
opposite_vertex1_global: Any = None,
|
|
332
352
|
):
|
|
333
353
|
self.v0 = v0
|
|
334
354
|
self.v1 = v1
|
|
355
|
+
self.v0_global = v0_global
|
|
356
|
+
self.v1_global = v1_global
|
|
335
357
|
self.face0_local = face0_local
|
|
336
358
|
self.face1_local = face1_local
|
|
337
359
|
self.face0_global = face0_global
|
|
338
360
|
self.face1_global = face1_global
|
|
339
361
|
self.opposite_vertex0 = opposite_vertex0
|
|
340
362
|
self.opposite_vertex1 = opposite_vertex1
|
|
363
|
+
self.opposite_vertex0_global = opposite_vertex0_global
|
|
364
|
+
self.opposite_vertex1_global = opposite_vertex1_global
|
|
341
365
|
|
|
342
366
|
def size(self) -> int:
|
|
343
367
|
if self.v0 is None:
|
|
@@ -346,6 +370,47 @@ class SceneEdgeTopology(_StructRepr):
|
|
|
346
370
|
return int(_shape_tuple(self.v0)[0])
|
|
347
371
|
|
|
348
372
|
|
|
373
|
+
class SceneGlobalGeometry(_StructRepr):
|
|
374
|
+
DRJIT_STRUCT = {
|
|
375
|
+
"vertices": object,
|
|
376
|
+
"faces": object,
|
|
377
|
+
"face_normal": object,
|
|
378
|
+
"shape_id": object,
|
|
379
|
+
"local_prim_id": object,
|
|
380
|
+
"global_prim_id": object,
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
def __init__(
|
|
384
|
+
self,
|
|
385
|
+
vertices: Any = None,
|
|
386
|
+
faces: Any = None,
|
|
387
|
+
face_normal: Any = None,
|
|
388
|
+
shape_id: Any = None,
|
|
389
|
+
local_prim_id: Any = None,
|
|
390
|
+
global_prim_id: Any = None,
|
|
391
|
+
):
|
|
392
|
+
self.vertices = vertices
|
|
393
|
+
self.faces = faces
|
|
394
|
+
self.face_normal = face_normal
|
|
395
|
+
self.shape_id = shape_id
|
|
396
|
+
self.local_prim_id = local_prim_id
|
|
397
|
+
self.global_prim_id = global_prim_id
|
|
398
|
+
|
|
399
|
+
def vertex_count(self) -> int:
|
|
400
|
+
if self.vertices is None:
|
|
401
|
+
return 0
|
|
402
|
+
from ._util import _shape_tuple
|
|
403
|
+
shape = _shape_tuple(self.vertices)
|
|
404
|
+
return int(shape[0]) if len(shape) >= 1 else 0
|
|
405
|
+
|
|
406
|
+
def face_count(self) -> int:
|
|
407
|
+
if self.global_prim_id is None:
|
|
408
|
+
return 0
|
|
409
|
+
from ._util import _shape_tuple
|
|
410
|
+
shape = _shape_tuple(self.global_prim_id)
|
|
411
|
+
return int(shape[0]) if len(shape) >= 1 else 0
|
|
412
|
+
|
|
413
|
+
|
|
349
414
|
class SceneSyncProfile:
|
|
350
415
|
_FIELDS = (
|
|
351
416
|
"mesh_update_ms",
|