File indexing completed on 2025-01-30 10:26:06
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef VECGEOM_NAVIGATION_EMBREENAVIGATOR_H_
0009 #define VECGEOM_NAVIGATION_EMBREENAVIGATOR_H_
0010
0011 #include "VecGeom/base/Global.h"
0012
0013 #include "VecGeom/volumes/PlacedVolume.h"
0014 #include "VecGeom/base/Vector3D.h"
0015 #include "VecGeom/management/GeoManager.h"
0016 #include "VecGeom/navigation/NavigationState.h"
0017 #include "VecGeom/base/Transformation3D.h"
0018 #include "VecGeom/management/EmbreeManager.h"
0019 #include "VecGeom/navigation/VNavigator.h"
0020 #include "VecGeom/navigation/HybridSafetyEstimator.h"
0021 #include "VecGeom/navigation/SimpleABBoxNavigator.h"
0022
0023 #include <vector>
0024 #include <stack>
0025
0026 namespace vecgeom {
0027 inline namespace VECGEOM_IMPL_NAMESPACE {
0028
0029 extern double g_step;
0030 extern LogicalVolume const *g_lvol;
0031 extern VPlacedVolume const *g_pvol;
0032 extern VPlacedVolume const *g_lastexited;
0033 extern Vector3D<double> const *g_pos;
0034 extern Vector3D<double> const *g_dir;
0035 extern Vector3D<float> const *g_normals;
0036 extern int g_count;
0037 extern std::vector<int> *g_geomIDs;
0038 extern EmbreeManager::BoxIdDistancePair_t *g_hitlist;
0039
0040
0041
0042 template <bool MotherIsConvex = false>
0043 class EmbreeNavigator : public VNavigatorHelper<EmbreeNavigator<MotherIsConvex>, MotherIsConvex> {
0044
0045 private:
0046 EmbreeManager &fAccelerationManager;
0047 EmbreeNavigator()
0048 : VNavigatorHelper<EmbreeNavigator<MotherIsConvex>, MotherIsConvex>(SimpleABBoxSafetyEstimator::Instance()),
0049 fAccelerationManager(EmbreeManager::Instance())
0050 {
0051 }
0052
0053 static VPlacedVolume const *LookupDaughter(LogicalVolume const *lvol, int const daughterIndex)
0054 {
0055 return lvol->GetDaughters()[daughterIndex];
0056 }
0057
0058
0059 template <typename T>
0060 static void insertionsort(T *arr, unsigned int N)
0061 {
0062 for (unsigned short i = 1; i < N; ++i) {
0063 T value = arr[i];
0064 short hole = i;
0065
0066 for (; hole > 0 && value.second < arr[hole - 1].second; --hole)
0067 arr[hole] = arr[hole - 1];
0068
0069 arr[hole] = value;
0070 }
0071 }
0072
0073
0074
0075
0076 size_t GetHitCandidates_v(EmbreeManager::EmbreeAccelerationStructure const &accstructure,
0077 Vector3D<Precision> const &point, Vector3D<Precision> const &dir,
0078 EmbreeManager::BoxIdDistancePair_t *hitlist, float step) const
0079 {
0080 if (accstructure.fNumberObjects == 0) return false;
0081
0082 RTCRayHit ray;
0083 ray.ray.flags = 0;
0084 ray.ray.org_x = point.x();
0085 ray.ray.org_y = point.y();
0086 ray.ray.org_z = point.z();
0087 ray.ray.dir_x = dir.x();
0088 ray.ray.dir_y = dir.y();
0089 ray.ray.dir_z = dir.z();
0090 ray.ray.tnear = 0.f;
0091 ray.ray.tfar = 1E20f;
0092
0093 g_normals = accstructure.fNormals;
0094 g_hitlist = hitlist;
0095 g_count = 0;
0096 g_geomIDs->clear();
0097
0098 RTCIntersectContext context;
0099
0100 auto hitFilter = [](const RTCFilterFunctionNArguments *args) {
0101
0102
0103 const auto hit = (RTCHit *)args->hit;
0104 int *hitvalid = args->valid;
0105 const auto id = hit->geomID;
0106
0107
0108
0109
0110
0111 if (std::find(g_geomIDs->begin(), g_geomIDs->end(), id) != g_geomIDs->end()) {
0112 hitvalid[0] = 0;
0113 return;
0114 }
0115 g_geomIDs->push_back(id);
0116
0117 const auto ray = (RTCRay *)args->ray;
0118 const auto normalID = id * 6 + hit->primID;
0119 const auto normal = g_normals[normalID];
0120 const bool backface = ray->dir_x * normal.x() + ray->dir_y * normal.y() + ray->dir_z * normal.z() > 0;
0121 float dist = backface ? -1.f : ray->tfar;
0122
0123
0124
0125
0126 g_hitlist[g_count++] = HybridManager2::BoxIdDistancePair_t(id, dist);
0127
0128 hitvalid[0] = 0;
0129 };
0130
0131 rtcInitIntersectContext(&context);
0132 context.filter = hitFilter;
0133 rtcIntersect1(accstructure.fScene, &context, &ray);
0134
0135
0136 return g_count;
0137 }
0138
0139 public:
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 template <typename AccStructure, typename Func>
0150 VECGEOM_FORCE_INLINE
0151 void BVHSortedIntersectionsLooper(AccStructure const &accstructure, Vector3D<Precision> const &localpoint,
0152 Vector3D<Precision> const &localdir, float stepmax, Func &&userhook) const
0153 {
0154
0155
0156 using IdDistPair_t = HybridManager2::BoxIdDistancePair_t;
0157 char stackspace[VECGEOM_MAXFACETS * sizeof(IdDistPair_t)];
0158 IdDistPair_t *hitlist = reinterpret_cast<IdDistPair_t *>(&stackspace);
0159
0160 auto ncandidates = GetHitCandidates_v(accstructure, localpoint, localdir, hitlist, stepmax);
0161
0162 insertionsort(hitlist, ncandidates);
0163
0164
0165
0166
0167
0168 for (size_t index = 0; index < ncandidates; ++index) {
0169 auto hitbox = hitlist[index];
0170
0171
0172 auto done = userhook(hitbox);
0173 if (done) break;
0174 }
0175 }
0176
0177 VECGEOM_FORCE_INLINE
0178 virtual bool CheckDaughterIntersections(LogicalVolume const *lvol, Vector3D<Precision> const &localpoint,
0179 Vector3D<Precision> const &localdir, NavigationState const *in_state,
0180 NavigationState * , Precision &step,
0181 VPlacedVolume const *&hitcandidate) const override
0182 {
0183 if (lvol->GetDaughtersp()->size() == 0) return false;
0184 auto &accstructure = *fAccelerationManager.GetAccStructure(lvol);
0185
0186 BVHSortedIntersectionsLooper(
0187 accstructure, localpoint, localdir, step, [&](HybridManager2::BoxIdDistancePair_t hitbox) {
0188
0189 if (!(step < hitbox.second)) {
0190 VPlacedVolume const *candidate = LookupDaughter(lvol, hitbox.first);
0191 Precision ddistance = candidate->DistanceToIn(localpoint, localdir, step);
0192 const auto valid = !IsInf(ddistance) && ddistance < step &&
0193 !((ddistance <= 0.) && in_state && in_state->GetLastExited() == candidate);
0194 hitcandidate = valid ? candidate : hitcandidate;
0195 step = valid ? ddistance : step;
0196 return false;
0197 }
0198 return true;
0199 });
0200 return false;
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299 static VNavigator *Instance()
0300 {
0301 static EmbreeNavigator instance;
0302 return &instance;
0303 }
0304
0305 static constexpr const char *gClassNameString = "EmbreeNavigator";
0306 typedef SimpleABBoxSafetyEstimator SafetyEstimator_t;
0307 };
0308 }
0309 }
0310
0311 #endif