From 9f7ded3b28779ade5c04e1a07279f44b73e5f53f Mon Sep 17 00:00:00 2001
From: Lukas Werner <lks.werner@fau.de>
Date: Sat, 10 Mar 2018 23:46:17 +0100
Subject: [PATCH] Refactor Raytracer to use dynamic algorithm switching

---
 src/pe/raytracing/Raytracer.cpp |   6 +-
 src/pe/raytracing/Raytracer.h   | 287 +++++++++++++++-----------------
 tests/pe/Raytracing.cpp         | 192 +++++++++------------
 3 files changed, 225 insertions(+), 260 deletions(-)

diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp
index ff9d5a775..8112b088b 100644
--- a/src/pe/raytracing/Raytracer.cpp
+++ b/src/pe/raytracing/Raytracer.cpp
@@ -66,7 +66,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
    imageOutputEnabled_(false),
    localImageOutputEnabled_(false),
    filenameTimestepWidth_(5),
-   bodyToShadingParamsFunction_(bodyToShadingParamsFunction) {
+   bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
+   raytracingAlgorithm_(RAYTRACE_HASHGRIDS) {
    
    setupView_();
    setupFilenameRankWidth_();
@@ -92,7 +93,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
                      const Config::BlockHandle& config,
                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction)
    : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), ccdID_(ccdID),
-   bodyToShadingParamsFunction_(bodyToShadingParamsFunction) {
+   bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
+   raytracingAlgorithm_(RAYTRACE_HASHGRIDS) {
    WALBERLA_CHECK(config.isValid(), "No valid config passed to raytracer");
    
    pixelsHorizontal_ = config.getParameter<uint16_t>("image_x");
diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h
index dccf710f5..c7ab2133d 100644
--- a/src/pe/raytracing/Raytracer.h
+++ b/src/pe/raytracing/Raytracer.h
@@ -55,6 +55,8 @@ struct BodyIntersectionInfo {
 
 class Raytracer {
 public:
+   enum Algorithm { RAYTRACE_HASHGRIDS, RAYTRACE_NAIVE, RAYTRACE_COMPARE_BOTH };
+   
    /*!\name Constructors */
    //@{
    explicit Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID storageID,
@@ -108,6 +110,7 @@ private:
    std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction_; /*!< Function which returns a 
                                                                                   * ShadingParameters struct
                                                                                   * given the specified body. */
+   Algorithm raytracingAlgorithm_;    //!< Algorithm to use while intersection testing.
    //@}
    
    /*!\name Member variables for raytracing geometry */
@@ -151,6 +154,7 @@ public:
    inline void setLocalImageOutputEnabled(const bool enabled);
    inline void setImageOutputDirectory(const std::string& path);
    inline void setFilenameTimestepWidth(uint8_t width);
+   inline void setRaytracingAlgorithm(Algorithm algorithm);
    //@}
    
    /*!\name Functions */
@@ -171,6 +175,13 @@ private:
    inline bool isPlaneVisible(const PlaneID plane, const Ray& ray) const;
    inline size_t coordinateToArrayIndex(size_t x, size_t y) const;
    
+   template <typename BodyTypeTuple>
+   inline void traceRayInGlobalBodyStorage(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const;
+   template <typename BodyTypeTuple>
+   inline void traceRayNaively(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const;
+   template <typename BodyTypeTuple>
+   inline void traceRayInHashGrids(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const;
+
    inline Color getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const;
    //@}
 };
@@ -346,6 +357,13 @@ inline void Raytracer::setImageOutputDirectory(const std::string& path) {
 inline void Raytracer::setFilenameTimestepWidth(uint8_t width) {
    filenameTimestepWidth_ = width;
 }
+
+/*!\brief Set the algorithm to use while ray tracing.
+ * \param algorithm One of RAYTRACE_HASHGRIDS, RAYTRACE_NAIVE, RAYTRACE_COMPARE_BOTH.
+ */
+inline void Raytracer::setRaytracingAlgorithm(Algorithm algorithm) {
+   raytracingAlgorithm_ = algorithm;
+}
    
 /*!\brief Checks if a plane should get rendered.
  * \param plane Plane to check for visibility.
@@ -367,6 +385,96 @@ inline size_t Raytracer::coordinateToArrayIndex(size_t x, size_t y) const {
    return y*pixelsHorizontal_ + x;
 }
 
+   
+template <typename BodyTypeTuple>
+inline void Raytracer::traceRayInGlobalBodyStorage(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const {
+   int numProcesses = mpi::MPIManager::instance()->numProcesses();
+   int rank = mpi::MPIManager::instance()->rank();
+   
+   real_t t = std::numeric_limits<real_t>::max();
+   Vec3 n;
+   
+   IntersectsFunctor func(ray, t, n);
+   
+   int i = 0;
+   for(auto bodyIt: *globalBodyStorage_) {
+      ++i;
+      // distribute global objects more or less evenly over all processes
+      if (((i-1)%numProcesses) != rank) {
+         continue;
+      }
+      
+      if (bodyIt->getTypeID() == Plane::getStaticTypeID()) {
+         PlaneID plane = (PlaneID)bodyIt;
+         if (!isPlaneVisible(plane, ray)) {
+            continue;
+         }
+      }
+      
+      bool intersects = SingleCast<BodyTypeTuple, IntersectsFunctor, bool>::execute(bodyIt, func);
+      
+      if (intersects && t < t_closest) {
+         // body was shot by ray and is currently closest to camera
+         t_closest = t;
+         body_closest = bodyIt;
+         n_closest = n;
+      }
+   }
+}
+
+template <typename BodyTypeTuple>
+inline void Raytracer::traceRayNaively(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const {
+   real_t t = std::numeric_limits<real_t>::max();
+   Vec3 n;
+   
+   IntersectsFunctor func(ray, t, n);
+   
+   for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
+      const AABB& blockAabb = blockIt->getAABB();
+      
+#if !defined(DISABLE_BLOCK_AABB_INTERSECTION_PRECHECK)
+      if (!intersects(blockAabb, ray, t, blockAABBIntersectionPadding_)) {
+         continue;
+      }
+#endif
+      
+      for (auto bodyIt = LocalBodyIterator::begin(*blockIt, storageID_); bodyIt != LocalBodyIterator::end(); ++bodyIt) {
+         bool intersects = SingleCast<BodyTypeTuple, IntersectsFunctor, bool>::execute(*bodyIt, func);
+         
+         if (intersects && t < t_closest) {
+            // body was shot by ray and is currently closest to camera
+            t_closest = t;
+            body_closest = *bodyIt;
+            n_closest = n;
+         }
+      }
+   }
+}
+   
+template <typename BodyTypeTuple>
+inline void Raytracer::traceRayInHashGrids(const Ray& ray, BodyID& body_closest, real_t& t_closest, Vec3& n_closest) const {
+   real_t t = std::numeric_limits<real_t>::max();
+   Vec3 n;
+   
+   for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
+      const AABB& blockAabb = blockIt->getAABB();
+      
+#if !defined(DISABLE_BLOCK_AABB_INTERSECTION_PRECHECK)
+      if (!intersects(blockAabb, ray, t, blockAABBIntersectionPadding_)) {
+         continue;
+      }
+#endif
+      
+      ccd::HashGrids* hashgrids = blockIt->uncheckedFastGetData<ccd::HashGrids>(ccdID_);
+      BodyID body = hashgrids->getClosestBodyIntersectingWithRay<BodyTypeTuple>(ray, blockAabb, t, n);
+      if (body != NULL && t < t_closest) {
+         t_closest = t;
+         body_closest = body;
+         n_closest = n;
+      }
+   }
+}
+   
 /*!\brief Does one raytracing step.
  *
  * \param timestep The timestep after which the raytracing starts.
@@ -377,35 +485,20 @@ inline size_t Raytracer::coordinateToArrayIndex(size_t x, size_t y) const {
 template <typename BodyTypeTuple>
 void Raytracer::rayTrace(const size_t timestep, WcTimingTree* tt) {
    if (tt != NULL) tt->start("Raytracing");
-
    real_t inf = std::numeric_limits<real_t>::max();
-
-   int numProcesses = mpi::MPIManager::instance()->numProcesses();
-   int rank = mpi::MPIManager::instance()->rank();
    
    std::vector<real_t> tBuffer(pixelsVertical_ * pixelsHorizontal_, inf);
    std::vector<Color> imageBuffer(pixelsVertical_ * pixelsHorizontal_);
    std::vector<BodyIntersectionInfo> intersections; // contains for each pixel information about an intersection, if existent
    
-   if (tt != NULL) tt->start("HashGrids Update");
-   for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
-      ccd::HashGrids* hashgrids = blockIt->getData<ccd::HashGrids>(ccdID_);
-      hashgrids->update();
+   if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH) {
+      if (tt != NULL) tt->start("HashGrids Update");
+      for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
+         ccd::HashGrids* hashgrids = blockIt->getData<ccd::HashGrids>(ccdID_);
+         hashgrids->update();
+      }
+      if (tt != NULL) tt->stop("HashGrids Update");
    }
-   if (tt != NULL) tt->stop("HashGrids Update");
-   
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   real_t t_naive_closest; BodyID body_naive_closest;
-   real_t t_hashgrids_closest; BodyID body_hashgrids_closest;
-   int errors = 0;
-   std::unordered_set<BodyID> problematicBodies;
-   std::unordered_set<BodyID> problematicHashgridsFoundBodies;
-   ccd::HashGrids::intersectionTestCount = 0;
-#endif
-   
-#if defined(USE_NAIVE_INTERSECTION_FINDING) || defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   uint64_t naiveIntersectionTests = 0;
-#endif
    
    real_t t, t_closest;
    Vec3 n;
@@ -413,6 +506,8 @@ void Raytracer::rayTrace(const size_t timestep, WcTimingTree* tt) {
    BodyID body_closest = NULL;
    Ray ray(cameraPosition_, Vec3(1,0,0));
    IntersectsFunctor func(ray, t, n);
+   bool isErrorneousPixel = false;
+   uint_t pixelErrors = 0;
    
    if (tt != NULL) tt->start("Intersection Testing");
    for (size_t x = 0; x < pixelsHorizontal_; x++) {
@@ -424,113 +519,33 @@ void Raytracer::rayTrace(const size_t timestep, WcTimingTree* tt) {
          n.reset();
          t_closest = inf;
          body_closest = NULL;
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-         t_naive_closest = t_hashgrids_closest = inf;
-         body_naive_closest = body_hashgrids_closest = NULL;
-#endif
-
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) || defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-         for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
-            const AABB& blockAabb = blockIt->getAABB();
-#if !defined(DISABLE_BLOCK_AABB_INTERSECTION_PRECHECK)
-            if (!intersects(blockAabb, ray, t, blockAABBIntersectionPadding_)) {
-               continue;
-            }
-#endif
-            ccd::HashGrids* hashgrids = blockIt->uncheckedFastGetData<ccd::HashGrids>(ccdID_);
-            // ^- nut getData ist ineffizient, braucht insges. 1.66s für 640x480 px. ->uncheckedFastGetData
-            BodyID body = hashgrids->getClosestBodyIntersectingWithRay<BodyTypeTuple>(ray, blockAabb, t, n);
-            
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-            if (body != NULL && t < t_hashgrids_closest)
-#else
-            if (body != NULL && t < t_closest)
-#endif
-            {
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-               t_hashgrids_closest = t;
-               body_hashgrids_closest = body;
-#else
-               t_closest = t;
-               body_closest = body;
-#endif
-               n_closest = n;
-            }
-         }
-#endif
          
-#if defined(USE_NAIVE_INTERSECTION_FINDING) || defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-         for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
-            const AABB& blockAabb = blockIt->getAABB();
-#if !defined(DISABLE_BLOCK_AABB_INTERSECTION_PRECHECK)
-            if (!intersects(blockAabb, ray, t, blockAABBIntersectionPadding_)) {
-               continue;
-            }
-#endif
-            for (auto bodyIt = LocalBodyIterator::begin(*blockIt, storageID_); bodyIt != LocalBodyIterator::end(); ++bodyIt) {
-               bool intersects = SingleCast<BodyTypeTuple, IntersectsFunctor, bool>::execute(*bodyIt, func);
-               naiveIntersectionTests++;
-
-               if (intersects && t < t_closest) {
-                  // body was shot by ray and currently closest to camera
-                  t_closest = t;
-                  body_closest = *bodyIt;
-                  n_closest = n;
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-                  t_naive_closest = t;
-                  body_naive_closest = *bodyIt;
-#endif
-               }
-            }
-         }
-#endif
+         if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS) {
+            traceRayInHashGrids<BodyTypeTuple>(ray, body_closest, t_closest, n_closest);
+         } else if (raytracingAlgorithm_ == RAYTRACE_NAIVE) {
+            traceRayNaively<BodyTypeTuple>(ray, body_closest, t_closest, n_closest);
+         } else {
+            traceRayInHashGrids<BodyTypeTuple>(ray, body_closest, t_closest, n_closest);
+            BodyID hashgrids_body_closest = body_closest;
             
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-         if (body_naive_closest != body_hashgrids_closest && !realIsEqual(t_naive_closest, t_hashgrids_closest)) {
-            problematicBodies.insert(body_naive_closest);
-            problematicHashgridsFoundBodies.insert(body_hashgrids_closest);
-            errors++;
-         }
-#endif
-         
-         int i = 0;
-         for(auto bodyIt: *globalBodyStorage_) {
-            i++;
-            // distribute global objects more or less evenly on all processes
-            if (((i-1)%numProcesses) != rank) {
-               continue;
-            }
+            t_closest = inf;
+            body_closest = NULL;
+            traceRayNaively<BodyTypeTuple>(ray, body_closest, t_closest, n_closest);
             
-            if (bodyIt->getTypeID() == Plane::getStaticTypeID()) {
-               PlaneID plane = (PlaneID)bodyIt;
-               if (!isPlaneVisible(plane, ray)) {
-                  continue;
-               }
-            }
-            
-            bool intersects = SingleCast<BodyTypeTuple, IntersectsFunctor, bool>::execute(bodyIt, func);
-            
-            if (intersects && t < t_closest) {
-               // body was shot by ray and currently closest to camera
-               t_closest = t;
-               body_closest = bodyIt;
-               n_closest = n;
+            if (body_closest != hashgrids_body_closest) {
+               isErrorneousPixel = true;
+               ++pixelErrors;
             }
          }
          
+         traceRayInGlobalBodyStorage<BodyTypeTuple>(ray, body_closest, t_closest, n_closest);
+         
          if (!realIsIdentical(t_closest, inf) && body_closest != NULL) {
             Color color = getColor(body_closest, ray, t_closest, n_closest);
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-            if (body_naive_closest != body_hashgrids_closest && !realIsEqual(t_naive_closest, t_hashgrids_closest)) {
-               if (body_hashgrids_closest == NULL) {
-                  color = Color(0, 1, 0);
-                  //WALBERLA_LOG_INFO("made pixel green");
-               } else {
-                  color = Color(1, 0, 0);
-                  //WALBERLA_LOG_INFO("made pixel red");
-               }
+            if (isErrorneousPixel) {
+               color = Color(1,0,0);
+               isErrorneousPixel = false;
             }
-#endif
             
             imageBuffer[coordinateToArrayIndex(x, y)] = color;
             BodyIntersectionInfo intersectionInfo = {
@@ -548,35 +563,9 @@ void Raytracer::rayTrace(const size_t timestep, WcTimingTree* tt) {
    }
    if (tt != NULL) tt->stop("Intersection Testing");
 
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   std::stringstream ss;
-   for (auto body: problematicBodies) {
-      if (body != NULL) {
-         ss << body->getID() << "(" << body->getHash() << ") ";
-      } else {
-         ss << "NULL" << " ";
-      }
-   };
-   ss << "(";
-   for (auto body: problematicHashgridsFoundBodies) {
-      if (body != NULL) {
-         ss << body->getID() << "(" << body->getHash() << ") ";
-      } else {
-         ss << "NULL" << " ";
-      }
-   };
-   ss << ")";
-   
-   WALBERLA_LOG_INFO(errors << " pixel errors found, problematic bodies: " << ss.str());
-#endif
-
-#if defined(USE_NAIVE_INTERSECTION_FINDING) || defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO("Performed " << naiveIntersectionTests << " naive intersection tests");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO("Performed " << ccd::HashGrids::intersectionTestCount << " intersection tests in hashgrids");
-   WALBERLA_LOG_INFO("Saved " << (int64_t(naiveIntersectionTests)-int64_t(ccd::HashGrids::intersectionTestCount)) << " tests (" << ((real_t(1)-real_c(ccd::HashGrids::intersectionTestCount)/real_c(naiveIntersectionTests))*100) << "%).");
-#endif
+   if (raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH && pixelErrors > 0) {
+      WALBERLA_LOG_WARNING(pixelErrors << " pixel errors found!");
+   }
 
    if (tt != NULL) tt->start("Reduction");
    // intersections synchronisieren
diff --git a/tests/pe/Raytracing.cpp b/tests/pe/Raytracing.cpp
index 4dc638edd..db520fbb0 100644
--- a/tests/pe/Raytracing.cpp
+++ b/tests/pe/Raytracing.cpp
@@ -233,7 +233,7 @@ ShadingParameters customBodyToShadingParams(const BodyID body) {
    }
 }
 
-void RaytracerTest() {
+void RaytracerTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) {
    WALBERLA_LOG_INFO("Raytracer");
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
    shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,10,10,10), Vec3(1,1,1), Vec3(false, false, false));
@@ -291,6 +291,7 @@ void RaytracerTest() {
    raytracer.setImageOutputEnabled(true);
    //raytracer.setLocalImageOutputEnabled(true);
    
+   raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
    raytracer.rayTrace<BodyTuple>(0);
 }
 
@@ -335,7 +336,7 @@ ShadingParameters customSpheresBodyToShadingParams(const BodyID body) {
    }
 }
 
-void RaytracerSpheresTest() {
+void RaytracerSpheresTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) {
    WALBERLA_LOG_INFO("Raytracer Spheres Scene");
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
    shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,10,10,10), Vec3(1,1,1), Vec3(false, false, false));
@@ -375,6 +376,7 @@ void RaytracerSpheresTest() {
    raytracer.setImageOutputDirectory("image");
    raytracer.setImageOutputEnabled(true);
    
+   raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
    raytracer.rayTrace<BodyTuple>(1);
 }
 
@@ -387,19 +389,11 @@ ShadingParameters customHashGridsBodyToShadingParams(const BodyID body) {
 }
 
 
-void HashGridsTest(size_t boxes, size_t capsules, size_t spheres, size_t numberOfViews = 1,
+void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm,
+                   size_t boxes, size_t capsules, size_t spheres, size_t numberOfViews = 1,
                    real_t boxLenMin = 0.1, real_t boxLenMax = 0.2, bool boxRotation = false,
                    real_t capRadiusMin = 0.1, real_t capRadiusMax = 0.2, real_t capLenMin = 0.1, real_t capLenMax = 0.3,
                    real_t sphereRadiusMin = 0.1, real_t sphereRadiusMax = 0.3) {
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   WALBERLA_LOG_INFO("Using naive method for intersection testing");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO("Using hashgrids for intersection testing");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO("Comparing hashgrids and naive method for intersection testing");
-#endif
    WALBERLA_LOG_INFO("Generating " << boxes << " boxes, " << capsules << " capsules and " << spheres << " spheres");
    
    using namespace walberla::pe::ccd;
@@ -437,7 +431,6 @@ void HashGridsTest(size_t boxes, size_t capsules, size_t spheres, size_t numberO
    for (size_t i = 0; i < capsules; i++) {
       real_t len = math::realRandom(capLenMin, capLenMax); // 0.2 0.5
       real_t radius = math::realRandom(capRadiusMin, capRadiusMax);
-      real_t maxlen = len + 2*radius;
       real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax());
       real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax());
       real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax());
@@ -546,18 +539,21 @@ void HashGridsTest(size_t boxes, size_t capsules, size_t spheres, size_t numberO
                            Color(0.2,0.2,0.2),
                            real_t(2),
                            customHashGridsBodyToShadingParams);
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-      raytracer.setImageOutputDirectory("image/naive");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-      raytracer.setImageOutputDirectory("image/hashgrids");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-      raytracer.setImageOutputDirectory("image/comparison");
-#endif
+      switch (raytracingAlgorithm) {
+         case Raytracer::RAYTRACE_NAIVE:
+            raytracer.setImageOutputDirectory("image/naive");
+            break;
+         case Raytracer::RAYTRACE_HASHGRIDS:
+            raytracer.setImageOutputDirectory("image/hashgrids");
+            break;
+         case Raytracer::RAYTRACE_COMPARE_BOTH:
+            raytracer.setImageOutputDirectory("image/comparison");
+            break;
+      }
       raytracer.setImageOutputEnabled(true);
       raytracer.setFilenameTimestepWidth(12);
       WALBERLA_LOG_INFO("output #" << i << " to: " << (boxes*100000000 + capsules*10000 + spheres) << " in " << raytracer.getImageOutputDirectory());
+      raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
       raytracer.rayTrace<BodyTuple>(boxes*100000000 + capsules*10000 + spheres, &tt);
       i++;
    }
@@ -575,7 +571,8 @@ ShadingParameters customArtifactsBodyToShadingParams(const BodyID body) {
    return defaultShadingParams(body);
 }
 
-void raytraceArtifactsForest(const shared_ptr<BlockStorage> forest, const BlockDataID storageID,
+void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm,
+                             const shared_ptr<BlockStorage> forest, const BlockDataID storageID,
                              const shared_ptr<BodyStorage> globalBodyStorage,
                              const BlockDataID ccdID,
                              const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector,
@@ -597,17 +594,20 @@ void raytraceArtifactsForest(const shared_ptr<BlockStorage> forest, const BlockD
                        Color(0.2,0.2,0.2),
                        real_t(2),
                        customArtifactsBodyToShadingParams);
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   raytracer.setImageOutputDirectory("image/artifacts/naive");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   raytracer.setImageOutputDirectory("image/artifacts/hashgrids");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   raytracer.setImageOutputDirectory("image/artifacts/comparison");
-#endif
+   switch (raytracingAlgorithm) {
+      case Raytracer::RAYTRACE_NAIVE:
+         raytracer.setImageOutputDirectory("image/naive");
+         break;
+      case Raytracer::RAYTRACE_HASHGRIDS:
+         raytracer.setImageOutputDirectory("image/hashgrids");
+         break;
+      case Raytracer::RAYTRACE_COMPARE_BOTH:
+         raytracer.setImageOutputDirectory("image/comparison");
+         break;
+   }
    raytracer.setImageOutputEnabled(true);
    raytracer.setFilenameTimestepWidth(timestepWidth);
+   raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
    WALBERLA_LOG_INFO("output to: " << numberOfBoxes << " in " << raytracer.getImageOutputDirectory());
    raytracer.rayTrace<BodyTuple>(numberOfBoxes, &tt);
    
@@ -617,18 +617,9 @@ void raytraceArtifactsForest(const shared_ptr<BlockStorage> forest, const BlockD
    }
 }
 
-void HashGridsArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
+void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
    WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In negative Z direction");
    
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   WALBERLA_LOG_INFO(" Using naive method for intersection testing");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO(" Using hashgrids for intersection testing");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO(" Comparing hashgrids and naive method for intersection testing");
-#endif
    WALBERLA_LOG_INFO(" Generating " << boxes << " boxes");
    
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
@@ -660,23 +651,15 @@ void HashGridsArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, real_t boxLenM
       WALBERLA_CHECK(box_ != NULL);
    }
    
-   raytraceArtifactsForest(forest, storageID, globalBodyStorage, ccdID,
+   raytraceArtifactsForest(raytracingAlgorithm,
+                           forest, storageID, globalBodyStorage, ccdID,
                            Vec3(2, 2, 7), Vec3(2, 2, 4), Vec3(0,1,0),
                            boxes, 3);
 }
 
-void HashGridsFromNegativeArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
+void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
    WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive Z direction");
    
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using naive method for intersection testing");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using hashgrids for intersection testing");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Comparing hashgrids and naive method for intersection testing");
-#endif
    WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes");
    
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
@@ -712,23 +695,14 @@ void HashGridsFromNegativeArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, re
       WALBERLA_CHECK(box_ != NULL);
    }
    
-   raytraceArtifactsForest(forest, storageID, globalBodyStorage, ccdID,
+   raytraceArtifactsForest(raytracingAlgorithm,
+                           forest, storageID, globalBodyStorage, ccdID,
                            Vec3(2, 2, -3), Vec3(2, 2, 0), Vec3(0,1,0),
                            boxes, 4);
 }
 
-void HashGridsFromNegativeXArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
+void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, size_t boxes, real_t boxLenMin = 0.1, real_t boxLenMax = 0.2) {
    WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive X direction");
-
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using naive method for intersection testing");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using hashgrids for intersection testing");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Comparing hashgrids and naive method for intersection testing");
-#endif
    WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes");
    
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
@@ -763,7 +737,8 @@ void HashGridsFromNegativeXArtifactsTest(size_t boxes, real_t boxLenMin = 0.1, r
       WALBERLA_CHECK(box_ != NULL);
    }
    
-   raytraceArtifactsForest(forest, storageID, globalBodyStorage, ccdID,
+   raytraceArtifactsForest(raytracingAlgorithm,
+                           forest, storageID, globalBodyStorage, ccdID,
                            Vec3(-3, 2, 2), Vec3(0, 2, 2), Vec3(0,0,1),
                            boxes, 6);
 }
@@ -773,18 +748,8 @@ Vec3 minCornerToGpos(const Vec3& minCorner, real_t lengths) {
    return minCorner + Vec3(lengths/2, lengths/2, lengths/2);
 }
 
-void HashGridsTestScene() {
-   WALBERLA_LOG_INFO_ON_ROOT("HashGrid Test Scene");
-   
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using naive method for intersection testing");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Using hashgrids for intersection testing");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-   WALBERLA_LOG_INFO_ON_ROOT(" Comparing hashgrids and naive method for intersection testing");
-#endif
+void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) {
+   WALBERLA_LOG_INFO_ON_ROOT("HashGrids Test Scene");
    
    shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>();
    shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,8,8,8), Vec3(1,1,1), Vec3(false, false, false));
@@ -839,24 +804,24 @@ void HashGridsTestScene() {
    
    // in negative x direction -> cubes to the right
    viewVectors.push_back(std::make_tuple(Vec3(15,4,4),
-                                     Vec3(8,4,4),
-                                     Vec3(0,1,0)));
+                                         Vec3(8,4,4),
+                                         Vec3(0,1,0)));
    // in negative x direction and negative z direction, up vector in y direction -> cubes from the right tilted
    viewVectors.push_back(std::make_tuple(Vec3(12,4,8),
-                                     Vec3(6,4,2),
-                                     Vec3(0,1,0)));
+                                         Vec3(6,4,2),
+                                         Vec3(0,1,0)));
    // in negative x direction and negative z direction, up vector in negative y direction
    viewVectors.push_back(std::make_tuple(Vec3(12,4,8),
-                                     Vec3(6,4,2),
-                                     Vec3(0,-1,0)));
+                                         Vec3(6,4,2),
+                                         Vec3(0,-1,0)));
    // in positive x direction
    viewVectors.push_back(std::make_tuple(Vec3(-7,4,4),
-                                     Vec3(0,4,4),
-                                     Vec3(0,1,0)));
+                                         Vec3(0,4,4),
+                                         Vec3(0,1,0)));
    // in negative x direction
    viewVectors.push_back(std::make_tuple(Vec3(4,4,15),
-                                     Vec3(4,4,8),
-                                     Vec3(0,1,0)));
+                                         Vec3(4,4,8),
+                                         Vec3(0,1,0)));
    
    WcTimingTree tt;
    
@@ -877,19 +842,23 @@ void HashGridsTestScene() {
                           Color(0.2,0.2,0.2),
                           real_t(2));
       
-#if defined(USE_NAIVE_INTERSECTION_FINDING)
-      raytracer.setImageOutputDirectory("image/naive");
-#endif
-#if !defined(USE_NAIVE_INTERSECTION_FINDING) && !defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-      raytracer.setImageOutputDirectory("image/hashgrids");
-#endif
-#if defined(COMPARE_NAIVE_AND_HASHGRIDS_RAYTRACING)
-      raytracer.setImageOutputDirectory("image/comparison");
-#endif
+      switch (raytracingAlgorithm) {
+         case Raytracer::RAYTRACE_NAIVE:
+            raytracer.setImageOutputDirectory("image/naive");
+            break;
+         case Raytracer::RAYTRACE_HASHGRIDS:
+            raytracer.setImageOutputDirectory("image/hashgrids");
+            break;
+         case Raytracer::RAYTRACE_COMPARE_BOTH:
+            raytracer.setImageOutputDirectory("image/comparison");
+            break;
+      }
+      
+      raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
       raytracer.setImageOutputEnabled(true);
       raytracer.setFilenameTimestepWidth(1);
       WALBERLA_LOG_INFO("output to: " << i << " in " << raytracer.getImageOutputDirectory());
-      
+      raytracer.setRaytracingAlgorithm(raytracingAlgorithm);
       raytracer.rayTrace<BodyTuple>(size_t(i), &tt);
       
       auto temp = tt.getReduced();
@@ -908,40 +877,45 @@ int main( int argc, char** argv )
    SetBodyTypeIDs<BodyTuple>::execute();
    math::seedRandomGenerator( static_cast<unsigned int>(1337 * mpi::MPIManager::instance()->worldRank()) );
    
+   Raytracer::Algorithm algorithm = Raytracer::RAYTRACE_COMPARE_BOTH;
+   
    //SphereIntersectsTest();
    //PlaneIntersectsTest();
    //BoxIntersectsTest();
    //AABBIntersectsTest();
    //CapsuleIntersectsTest();
-   //RaytracerTest();
-   //RaytracerSpheresTest();
+   //RaytracerTest(algorithm);
+   //RaytracerSpheresTest(algorithm);
    
-   HashGridsTestScene();
+   HashGridsTestScene(algorithm);
 
    std::vector<size_t> boxes = {127, 70, 20, 150};
    std::vector<size_t> capsules = {127, 60, 140, 100};
    std::vector<size_t> spheres = {0, 50, 40, 120};
    
    for (size_t i = 0; i < boxes.size(); ++i) {
-      HashGridsTest(boxes[i], capsules[i], spheres[i], 1);
+      HashGridsTest(algorithm, boxes[i], capsules[i], spheres[i], 1);
    }
    
-   //HashGridsTest(60, 60, 3, 1,
+   //HashGridsTest(algorithm,
+   //              60, 60, 3, 1,
    //              0.1, 0.3, true,
    //              0.1, 0.2, 0.1, 0.2,
    //              0.5, 0.6);
    
-   //HashGridsTest(750, 0, 0, 1,
+   //HashGridsTest(algorithm,
+   //              750, 0, 0, 1,
    //              0.2, 0.3);
    
-   //HashGridsTest(400, 0, 0, 1,
+   //HashGridsTest(algorithm,
+   //              400, 0, 0, 1,
    //              0.1, 0.3);
    
-   //HashGridsArtifactsTest(750, 0.2, 0.3);
-   //HashGridsFromNegativeArtifactsTest(750, 0.2, 0.3);
-   //HashGridsFromNegativeXArtifactsTest(750, 0.2, 0.3);
+   HashGridsArtifactsTest(algorithm, 750, 0.2, 0.3);
+   HashGridsFromNegativeArtifactsTest(algorithm, 750, 0.2, 0.3);
+   HashGridsFromNegativeXArtifactsTest(algorithm, 750, 0.2, 0.3);
    
-   //HashGridsTest(9999, 0, 4000, 1,
+   //HashGridsTest(algorithm, 9999, 0, 4000, 1,
    //              0.1, 0.2);
    
    return EXIT_SUCCESS;
-- 
GitLab