File indexing completed on 2025-01-18 10:13:52
0001
0002
0003
0004 #ifndef VECGEOM_BASE_BVH_H_
0005 #define VECGEOM_BASE_BVH_H_
0006
0007 #include "VecGeom/base/AABB.h"
0008 #include "VecGeom/base/Config.h"
0009 #include "VecGeom/base/Cuda.h"
0010 #include "VecGeom/navigation/NavStateIndex.h"
0011 #include "VecGeom/navigation/NavigationState.h"
0012 #include "VecGeom/volumes/LogicalVolume.h"
0013 #include "VecGeom/volumes/PlacedVolume.h"
0014
0015 #include <vector>
0016
0017 namespace vecgeom {
0018 VECGEOM_DEVICE_FORWARD_DECLARE(class BVH;);
0019 VECGEOM_DEVICE_DECLARE_CONV(class, BVH);
0020 inline namespace VECGEOM_IMPL_NAMESPACE {
0021
0022 class LogicalVolume;
0023 class VPlacedVolume;
0024
0025
0026
0027
0028
0029
0030 class BVH {
0031 public:
0032
0033 static constexpr int BVH_MAX_DEPTH = 32;
0034
0035
0036
0037
0038
0039
0040
0041
0042 BVH(LogicalVolume const &volume, int depth = 0);
0043
0044
0045 ~BVH();
0046
0047 #ifdef VECGEOM_ENABLE_CUDA
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 VECCORE_ATT_DEVICE
0059 BVH(LogicalVolume const *volume, int depth, int *dPrimId, AABB *dAABBs, int *dOffset, int *NChild, AABB *dNodes);
0060 #endif
0061
0062 #ifdef VECGEOM_CUDA_INTERFACE
0063
0064 DevicePtr<cuda::BVH> CopyToGpu(void *addr) const;
0065 #endif
0066
0067
0068 VECCORE_ATT_HOST_DEVICE
0069 void Print(bool verbose = false) const;
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 VECCORE_ATT_HOST_DEVICE
0096 void CheckDaughterIntersections(Vector3D<Precision> localpoint, Vector3D<Precision> localdir, Precision &step,
0097 VPlacedVolume const *last, VPlacedVolume const *&hitcandidate) const
0098 {
0099 unsigned int stack[BVH_MAX_DEPTH], *ptr = &stack[1];
0100 stack[0] = 0;
0101
0102
0103 Vector3D<Precision> invdir(1.0 / NonZero(localdir[0]), 1.0 / NonZero(localdir[1]), 1.0 / NonZero(localdir[2]));
0104
0105 do {
0106 const unsigned int id = *--ptr;
0107
0108 if (fNChild[id] >= 0) {
0109
0110 for (int i = 0; i < fNChild[id]; ++i) {
0111 const int prim = fPrimId[fOffset[id] + i];
0112
0113 if (fAABBs[prim].IntersectInvDir(localpoint, invdir, step)) {
0114 const auto vol = fLV.GetDaughters()[prim];
0115 const auto dist = vol->DistanceToIn(localpoint, localdir, step);
0116
0117 if (dist < step && !(dist <= 0.0 && vol == last)) step = dist, hitcandidate = vol;
0118 }
0119 }
0120 } else {
0121 const unsigned int childL = 2 * id + 1;
0122 const unsigned int childR = 2 * id + 2;
0123
0124
0125 Precision tminL = kInfLength, tmaxL = -kInfLength, tminR = kInfLength, tmaxR = -kInfLength;
0126
0127 fNodes[childL].ComputeIntersectionInvDir(localpoint, invdir, tminL, tmaxL);
0128 fNodes[childR].ComputeIntersectionInvDir(localpoint, invdir, tminR, tmaxR);
0129
0130 const bool traverseL = tminL <= tmaxL && tmaxL >= 0.0 && tminL < step;
0131 const bool traverseR = tminR <= tmaxR && tmaxR >= 0.0 && tminR < step;
0132
0133
0134
0135
0136
0137 if (tminR < tminL) {
0138 if (traverseR) *ptr++ = childR;
0139 if (traverseL) *ptr++ = childL;
0140 } else {
0141 if (traverseL) *ptr++ = childL;
0142 if (traverseR) *ptr++ = childR;
0143 }
0144 }
0145 } while (ptr > stack);
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 VECCORE_ATT_HOST_DEVICE
0158 void ApproachNextDaughter(Vector3D<Precision> localpoint, Vector3D<Precision> localdir, Precision &step,
0159 VPlacedVolume const *last) const;
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 VECCORE_ATT_HOST_DEVICE
0172 Precision ComputeSafety(Vector3D<Precision> localpoint, Precision safety) const
0173 {
0174 unsigned int stack[BVH_MAX_DEPTH], *ptr = &stack[1];
0175 stack[0] = 0;
0176
0177 do {
0178 const unsigned int id = *--ptr;
0179
0180 if (fNChild[id] >= 0) {
0181 for (int i = 0; i < fNChild[id]; ++i) {
0182 const int prim = fPrimId[fOffset[id] + i];
0183 if (fAABBs[prim].Safety(localpoint) < safety) {
0184 const Precision dist = fLV.GetDaughters()[prim]->SafetyToIn(localpoint);
0185 if (dist < safety) safety = dist;
0186 }
0187 }
0188 } else {
0189 const unsigned int childL = 2 * id + 1;
0190 const unsigned int childR = 2 * id + 2;
0191
0192 const Precision safetyL = fNodes[childL].Safety(localpoint);
0193 const Precision safetyR = fNodes[childR].Safety(localpoint);
0194
0195 const bool traverseL = safetyL < safety;
0196 const bool traverseR = safetyR < safety;
0197
0198 if (safetyR < safetyL) {
0199 if (traverseR) *ptr++ = childR;
0200 if (traverseL) *ptr++ = childL;
0201 } else {
0202 if (traverseL) *ptr++ = childL;
0203 if (traverseR) *ptr++ = childR;
0204 }
0205 }
0206 } while (ptr > stack);
0207
0208 return safety;
0209 }
0210
0211
0212
0213
0214
0215
0216
0217
0218 VECCORE_ATT_HOST_DEVICE
0219 bool LevelLocate(Vector3D<Precision> const &localpoint, VPlacedVolume const *&pvol,
0220 Vector3D<Precision> &daughterlocalpoint) const
0221 {
0222 VPlacedVolume const *exclvol = nullptr;
0223 return LevelLocate(exclvol, localpoint, pvol, daughterlocalpoint);
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233 VECCORE_ATT_HOST_DEVICE
0234 bool LevelLocate(Vector3D<Precision> const &localpoint, NavigationState &state,
0235 Vector3D<Precision> &daughterlocalpoint) const
0236 {
0237 VPlacedVolume const *exclvol = nullptr;
0238 VPlacedVolume const *pvol = nullptr;
0239 bool Result = LevelLocate(exclvol, localpoint, pvol, daughterlocalpoint);
0240 if (Result) {
0241 state.Push(pvol);
0242 }
0243 return Result;
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 VECCORE_ATT_HOST_DEVICE
0255 bool LevelLocate(VPlacedVolume const *exclvol, Vector3D<Precision> const &localpoint, VPlacedVolume const *&pvol,
0256 Vector3D<Precision> &daughterlocalpoint) const
0257 {
0258 unsigned int stack[BVH_MAX_DEPTH], *ptr = &stack[1];
0259 stack[0] = 0;
0260
0261 do {
0262 const unsigned int id = *--ptr;
0263
0264 if (fNChild[id] >= 0) {
0265 for (int i = 0; i < fNChild[id]; ++i) {
0266 const int prim = fPrimId[fOffset[id] + i];
0267 if (fAABBs[prim].Contains(localpoint)) {
0268 const auto vol = fLV.GetDaughters()[prim];
0269 if (vol != exclvol && vol->Contains(localpoint, daughterlocalpoint)) {
0270 pvol = vol;
0271 return true;
0272 }
0273 }
0274 }
0275 } else {
0276 const unsigned int childL = 2 * id + 1;
0277 if (fNodes[childL].Contains(localpoint)) *ptr++ = childL;
0278
0279 const unsigned int childR = 2 * id + 2;
0280 if (fNodes[childR].Contains(localpoint)) *ptr++ = childR;
0281 }
0282 } while (ptr > stack);
0283
0284 return false;
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 VECCORE_ATT_HOST_DEVICE
0297 bool LevelLocate(VPlacedVolume const *exclvol, Vector3D<Precision> const &localpoint,
0298 Vector3D<Precision> const &localdirection, VPlacedVolume const *&pvol,
0299 Vector3D<Precision> &daughterlocalpoint) const
0300 {
0301 unsigned int stack[BVH_MAX_DEPTH], *ptr = &stack[1];
0302 stack[0] = 0;
0303
0304 do {
0305 const unsigned int id = *--ptr;
0306
0307 if (fNChild[id] >= 0) {
0308 for (int i = 0; i < fNChild[id]; ++i) {
0309 const int prim = fPrimId[fOffset[id] + i];
0310 if (fAABBs[prim].Contains(localpoint)) {
0311 const auto v = fLV.GetDaughters()[prim];
0312
0313 if (v == exclvol) continue;
0314
0315 const auto T = v->GetTransformation();
0316 const auto u = v->GetUnplacedVolume();
0317 const auto p = T->Transform(localpoint);
0318
0319 auto Entering = [&]() {
0320 const Vector3D<Precision> dir = T->TransformDirection(localdirection);
0321 Vector3D<Precision> normal;
0322 u->Normal(p, normal);
0323 return Vector3D<Precision>::Dot(normal, dir) < 0.0;
0324 };
0325
0326 const auto inside = u->Inside(p);
0327
0328 if (inside == kInside || (inside == kSurface && Entering())) {
0329 pvol = v, daughterlocalpoint = p;
0330 return true;
0331 }
0332 }
0333 }
0334 } else {
0335 const unsigned int childL = 2 * id + 1;
0336 if (fNodes[childL].Contains(localpoint)) *ptr++ = childL;
0337
0338 const unsigned int childR = 2 * id + 2;
0339 if (fNodes[childR].Contains(localpoint)) *ptr++ = childR;
0340 }
0341 } while (ptr > stack);
0342
0343 return false;
0344 }
0345
0346 private:
0347 enum class ConstructionAlgorithm : unsigned int;
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362 void ComputeNodes(unsigned int id, int *first, int *last, unsigned int nodes, ConstructionAlgorithm);
0363
0364 LogicalVolume const &fLV;
0365 int *fPrimId;
0366 int *fOffset;
0367 int *fNChild;
0368 AABB *fNodes;
0369 AABB *fAABBs;
0370 int fDepth;
0371 };
0372
0373 }
0374 }
0375
0376 #endif