nx_bvh.nx
buildroot/runtime/nx_bvh.nx
about
nx_bvh.nx -- axis-aligned bounding volume hierarchy on NxMesh
triangles. Top-down median-split build, flat node array.
Used by the slicer (plane vs triangle pruning), by support tree
generation (ray casts for overhang detection), by mesh repair
(find near-duplicate verts via spatial proximity). Composes
nx_mesh -- does NOT modify it. Per Cardinal 9 (single
responsibility): BVH is a spatial index ON nx_mesh, not part of
the mesh itself.
Storage:
- Flat array of NxBvhNode (64 bytes each)
- Per-tri precomputed centroid + AABB in NxBvhTriInfo
- Permutation array tri_order: leaf nodes point into tri_order;
tri_order[i] is the mesh triangle index
Build complexity: O(n log n) expected with median-of-three partition.
Real-world worst case on degenerate meshes (all tris colinear on
the chosen axis): O(n^2). Acceptable for P0.2b smoke; the
Christus is well-distributed and will see expected complexity.
Node layout invariant: when an internal node is created, its
LEFT child is the very next node in the array (idx + 1) and its
RIGHT child is whatever node is allocated after the left subtree
completes. Depth-first build maintains this.
Per cardinal NISHI_3D_PRINT_ROADMAP ยง2.7: this BVH IS the
incremental-slice substrate. Re-slicing on a config change with
the same mesh reuses the same BVH; only the slice traversal
reruns. That's the slice-time win lever vs OrcaSlicer's per-
param-change full re-slice.
license_tier: ORIGINAL
dependencies 3 imports · 21 importers
diagram shows first 10 each side; +0 more imports, +11 more importers in the complete lists below.
imports: nx_syscalls.nxnx_mesh.nxnx_mesh_print_check.nx
imported by: nx_auto_supports_v2_target_test.nxnx_bvh_test.nxnx_cad_exceed.nxnx_cad_prims2_test.nxnx_cad_test.nxnx_csg_fillet_test.nxnx_csg_scene_gate.nxnx_csg_test.nxnx_csg_torus_test.nxnx_dcc_slice_watertight_gate.nxnx_print_e2e_gate.nxnx_print_e2e_test.nxnx_slice_auto_supports.nxnx_slice_auto_supports_test.nxnx_slice_contour_test.nxnx_slice_layer_probe.nxnx_slice_pipeline.nxnx_slice_pipeline_test.nxnx_slice_plane.nxnx_slice_plane_test.nxnx_underridge_cleaner_gate.nx
structs
| 50 | struct NxBvhNode |
| 63 | struct NxBvhTriInfo |
| 71 | struct NxBvh |
consts
| 39 | const NX_BVH_LEAF_DEFAULT: i64 = 4 |
| 40 | const NX_BVH_NODE_BYTES: i64 = 64 // 8 i64 |
| 41 | const NX_BVH_TRI_BYTES: i64 = 72 // 9 i64 |
| 80 | const NX_BVH_BYTES: i64 = 48 |
functions
| 84 | func nx_bvh_node_at(b: *NxBvh, idx: i64) -> *NxBvhNode |
| 88 | func nx_bvh_tri_at(b: *NxBvh, idx: i64) -> *NxBvhTriInfo |
| 94 | func nx_bvh_min3(a: i64, b: i64, c: i64) -> i64 called by 1: nx_bvh_compute_tri_info |
| 101 | func nx_bvh_max3(a: i64, b: i64, c: i64) -> i64 called by 1: nx_bvh_compute_tri_info |
| 108 | func nx_bvh_compute_tri_info(b: *NxBvh, m: *NxMesh) -> i64 |
| 141 | func nx_bvh_range_aabb(b: *NxBvh, lo: i64, hi: i64, dst: *NxBvhNode) -> i64 |
| 166 | func nx_bvh_longest_axis(n: *NxBvhNode) -> i64 called by 1: nx_bvh_fill_subtree |
| 179 | func nx_bvh_centroid_on_axis(b: *NxBvh, idx: i64, axis: i64) -> i64 |
| 186 | func nx_bvh_swap_tri_order(b: *NxBvh, i: i64, j: i64) -> i64 called by 1: nx_bvh_partition_by_axis |
| 199 | func nx_bvh_partition_by_axis(b: *NxBvh, lo: i64, hi: i64, axis: i64) -> i64 |
| 222 | func nx_bvh_alloc_node(b: *NxBvh) -> i64 |
| 249 | func nx_bvh_fill_subtree(b: *NxBvh, idx: i64, lo: i64, hi: i64, leaf_threshold: i64) -> i64 |
| 275 | func nx_bvh_build_subtree(b: *NxBvh, lo: i64, hi: i64, leaf_threshold: i64) -> i64 |
| 286 | func nx_bvh_build_with_threshold(m: *NxMesh, leaf_threshold: i64) -> *NxBvh |
| 304 | func nx_bvh_build(m: *NxMesh) -> *NxBvh called by 20: mainmainnx_cad_measure_watertightnx_cad_measure_csgnx_cad_measure_filletmain+14 calls 1: nx_bvh_build_with_threshold |
| 312 | func nx_bvh_total_leaf_count(b: *NxBvh) -> i64 |
| 324 | func nx_bvh_leaf_node_count(b: *NxBvh) -> i64 |