Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-27 09:40:38

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/detail/BvhData.hh
0006 //! \todo move to orange/BvhTreeData
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/EnumArray.hh"
0012 #include "corecel/data/Collection.hh"
0013 #include "geocel/BoundingBox.hh"  // IWYU pragma: keep
0014 
0015 #include "../OrangeTypes.hh"
0016 
0017 namespace celeritas
0018 {
0019 namespace detail
0020 {
0021 //---------------------------------------------------------------------------//!
0022 // The maximum depth of the BVH tree (single leaf node is 1)
0023 inline constexpr size_type max_bvh_depth = 18;
0024 
0025 //---------------------------------------------------------------------------//
0026 /*!
0027  * Data for a single internal node in a Bounding Volume Hierarchy.
0028  *
0029  * As a convention, a node's LEFT edge corresponds to the half space that is
0030  * less than the partition value. In other words, the LEFT bounding plane
0031  * position is the far right boundary of the left side of the tree, and the
0032  * RIGHT bounding plane position is the far left boundary of the right side of
0033  * the tree. Since the halfspaces created by the bounding planes may overlap,
0034  * the LEFT bounding plane position could be either left or right of the RIGHT
0035  * bounding plane position.
0036  */
0037 struct BvhInternalNode
0038 {
0039     struct Edge
0040     {
0041         //! The child node connected to this edge
0042         BvhNodeId child;
0043         //! Bbox created by clipping an inf bbox with the bounding planes
0044         //! between this edge (inclusive) and the root.
0045         FastBBox bbox;
0046     };
0047 
0048     enum class Side
0049     {
0050         left,
0051         right,
0052         size_
0053     };
0054 
0055     Axis axis;  //!< Axis that the partition is performed on
0056     EnumArray<Side, Edge> edges;  //!< Left/right edges
0057 
0058     explicit CELER_FUNCTION operator bool() const
0059     {
0060         return this->edges[Side::left].child && this->edges[Side::right].child;
0061     }
0062 };
0063 
0064 //---------------------------------------------------------------------------//
0065 /*!
0066  * Data for a single leaf node in a Bounding Volume Hierarchy.
0067  */
0068 struct BvhLeafNode
0069 {
0070     ItemRange<LocalVolumeId> vol_ids;
0071 
0072     explicit CELER_FUNCTION operator bool() const { return !vol_ids.empty(); }
0073 };
0074 
0075 //---------------------------------------------------------------------------//
0076 /*!
0077  * Bounding Volume Hierarchy tree.
0078  *
0079  * Infinite bounding boxes are not included in the tree itself. They are stored
0080  * separately and checked after traversing the tree.
0081  */
0082 struct BvhTreeRecord
0083 {
0084     //// TYPES ////
0085     struct Metadata
0086     {
0087         //! The number of finite bounding boxes in the tree
0088         size_type num_finite_bboxes{};
0089         //! The number of infinite bounding boxes, i.e., those not included in
0090         //! the tree itself.
0091         size_type num_infinite_bboxes{};
0092         //! The depth of the most embedded leaf node. This has a value of 1
0093         //! when the root node is a leaf.
0094         size_type depth{};
0095     };
0096 
0097     //// DATA ////
0098 
0099     //! All bounding boxes managed by the BVH
0100     ItemMap<LocalVolumeId, FastBBoxId> bboxes;
0101 
0102     //! Internal (branch) nodes, the first being the root
0103     ItemRange<BvhInternalNode> internal_nodes;
0104 
0105     //! Leaf nodes
0106     ItemRange<BvhLeafNode> leaf_nodes;
0107 
0108     //! Local volumes that have infinite bounding boxes
0109     ItemRange<LocalVolumeId> inf_vol_ids;
0110 
0111     //! The metadata for this tree
0112     Metadata metadata;
0113 
0114     //// METHODS ////
0115 
0116     explicit CELER_FUNCTION operator bool() const
0117     {
0118         if (!internal_nodes.empty())
0119         {
0120             return !bboxes.empty() && !leaf_nodes.empty();
0121         }
0122         else
0123         {
0124             // Degenerate single leaf node case. This occurs when a tree
0125             // contains either:
0126             // a) a single volume
0127             // b) multiple non-partitionable volumes,
0128             // b) only infinite volumes.
0129             return !bboxes.empty() && leaf_nodes.size() == 1;
0130         }
0131     }
0132 };
0133 
0134 //---------------------------------------------------------------------------//
0135 /*!
0136  * Persistent data used by all BVH trees.
0137  */
0138 template<Ownership W, MemSpace M>
0139 struct BvhTreeData
0140 {
0141     template<class T>
0142     using Items = Collection<T, W, M>;
0143 
0144     // Low-level storage
0145     Items<FastBBox> bboxes;
0146     Items<LocalVolumeId> local_volume_ids;
0147     Items<detail::BvhInternalNode> internal_nodes;
0148     Items<detail::BvhLeafNode> leaf_nodes;
0149 
0150     //! True if assigned
0151     explicit CELER_FUNCTION operator bool() const
0152     {
0153         // Note that internal_nodes may be empty for single-node trees
0154         return !bboxes.empty() && !local_volume_ids.empty()
0155                && !leaf_nodes.empty();
0156     }
0157 
0158     //! Assign from another set of data
0159     template<Ownership W2, MemSpace M2>
0160     BvhTreeData& operator=(BvhTreeData<W2, M2> const& other)
0161     {
0162         bboxes = other.bboxes;
0163         local_volume_ids = other.local_volume_ids;
0164         internal_nodes = other.internal_nodes;
0165         leaf_nodes = other.leaf_nodes;
0166 
0167         CELER_ENSURE(static_cast<bool>(*this) == static_cast<bool>(other));
0168         return *this;
0169     }
0170 };
0171 
0172 //---------------------------------------------------------------------------//
0173 }  // namespace detail
0174 }  // namespace celeritas