From b77ab0263d7dc32ac389d59b2df6f1ac834197c7 Mon Sep 17 00:00:00 2001
From: Lukas Werner <lks.werner@fau.de>
Date: Wed, 21 Mar 2018 16:07:23 +0100
Subject: [PATCH] Added user definable function for body visibility

---
 src/pe/ccd/HashGrids.h          | 30 ++++++++----
 src/pe/raytracing/Raytracer.cpp | 22 ++++++---
 src/pe/raytracing/Raytracer.h   | 81 +++++++++++++++++++--------------
 3 files changed, 83 insertions(+), 50 deletions(-)

diff --git a/src/pe/ccd/HashGrids.h b/src/pe/ccd/HashGrids.h
index 265ea075d..b6f61458f 100644
--- a/src/pe/ccd/HashGrids.h
+++ b/src/pe/ccd/HashGrids.h
@@ -186,13 +186,15 @@ private:
       void   processBodies( BodyID* bodies, size_t bodyCount, Contacts& contacts ) const;
       
       template<typename BodyTuple>
-      BodyID getRayIntersectingBody(const raytracing::Ray& ray, const AABB& blockAABB, real_t& t, Vec3& n) const;
+      BodyID getRayIntersectingBody(const raytracing::Ray& ray, const AABB& blockAABB, real_t& t, Vec3& n,
+                                    std::function<bool (const BodyID body)> isBodyVisibleFunc) const;
       
       template<typename BodyTuple>
       BodyID getBodyIntersectionForBlockCell(const Vector3<int32_t>& blockCell,
                                              const int8_t cellNormalAxis, const int8_t cellNormalDir,
                                              const raytracing::Ray& ray,
-                                             real_t& t_closest, Vec3& n_closest) const;
+                                             real_t& t_closest, Vec3& n_closest,
+                                             std::function<bool (const BodyID body)> isBodyVisibleFunc) const;
       
       void clear();
       //@}
@@ -304,7 +306,8 @@ public:
    
    template<typename BodyTuple>
    BodyID getClosestBodyIntersectingWithRay(const raytracing::Ray& ray, const AABB& blockAABB,
-                                            real_t& t, Vec3& n);
+                                            real_t& t, Vec3& n,
+                                            std::function<bool (const BodyID body)> isBodyVisibleFunc);
    
 protected:
    //**Utility functions***************************************************************************
@@ -514,7 +517,8 @@ template<typename BodyTuple>
 BodyID HashGrids::HashGrid::getBodyIntersectionForBlockCell(const Vector3<int32_t>& blockCell,
                                                             const int8_t cellNormalAxis, const int8_t cellNormalDir,
                                                             const raytracing::Ray& ray,
-                                                            real_t& t_closest, Vec3& n_closest) const {
+                                                            real_t& t_closest, Vec3& n_closest,
+                                                            std::function<bool (const BodyID body)> isBodyVisibleFunc) const {
    real_t t_local;
    Vec3 n_local;
    BodyID body = NULL;
@@ -575,6 +579,10 @@ BodyID HashGrids::HashGrid::getBodyIntersectionForBlockCell(const Vector3<int32_
       
       if (nbBodies != NULL) {
          for (const BodyID& cellBody: *nbBodies) {
+            if (!isBodyVisibleFunc(cellBody)) {
+               continue;
+            }
+               
             HashGrids::intersectionTestCount++;
             bool intersects = SingleCast<BodyTuple, raytracing::IntersectsFunctor, bool>::execute(cellBody, intersectsFunc);
             if (intersects && t_local < t_closest) {
@@ -603,7 +611,8 @@ BodyID HashGrids::HashGrid::getBodyIntersectionForBlockCell(const Vector3<int32_
  */
 template<typename BodyTuple>
 BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, const AABB& blockAABB,
-                                                   real_t& t_closest, Vec3& n_closest) const {
+                                                   real_t& t_closest, Vec3& n_closest,
+                                                   std::function<bool (const BodyID body)> isBodyVisibleFunc) const {
    const real_t inf = std::numeric_limits<real_t>::max();
    
    BodyID body_local = NULL;
@@ -665,7 +674,8 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c
        currentCell[1] < blockYCellCountMax &&
        currentCell[2] < blockZCellCountMax) {
       body_local = getBodyIntersectionForBlockCell<BodyTuple>(currentCell, BLOCKCELL_NORMAL_INDETERMINATE, 0,
-                                                              ray, t_closest, n_closest);
+                                                              ray, t_closest, n_closest,
+                                                              isBodyVisibleFunc);
       if (body_local != NULL) {
          body_closest = body_local;
       }
@@ -734,7 +744,8 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c
       }
       
       body_local = getBodyIntersectionForBlockCell<BodyTuple>(currentCell, blockCellNormalAxis, blockCellNormalDir,
-                                                              ray, t_closest, n_closest);
+                                                              ray, t_closest, n_closest,
+                                                              isBodyVisibleFunc);
       if (body_local != NULL) {
          body_closest = body_local;
       }
@@ -753,7 +764,8 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c
  */
 template<typename BodyTuple>
 BodyID HashGrids::getClosestBodyIntersectingWithRay(const raytracing::Ray& ray, const AABB& blockAABB,
-                                                    real_t& t, Vec3& n) {
+                                                    real_t& t, Vec3& n,
+                                                    std::function<bool (const BodyID body)> isBodyVisibleFunc) {
    real_t inf = std::numeric_limits<real_t>::max();
 
    BodyID body_closest = NULL;
@@ -775,7 +787,7 @@ BodyID HashGrids::getClosestBodyIntersectingWithRay(const raytracing::Ray& ray,
    }
    
    for(auto grid: gridList_) {
-      body_local = grid->getRayIntersectingBody<BodyTuple>(ray, blockAABB, t_closest, n_closest);
+      body_local = grid->getRayIntersectingBody<BodyTuple>(ray, blockAABB, t_closest, n_closest, isBodyVisibleFunc);
       if (body_local != NULL){
          body_closest = body_local;
       }
diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp
index 4d1f3c86a..9f6bf4b46 100644
--- a/src/pe/raytracing/Raytracer.cpp
+++ b/src/pe/raytracing/Raytracer.cpp
@@ -66,8 +66,10 @@ void BodyIntersectionInfo_Comparator_MPI_OP( BodyIntersectionInfo *in, BodyInter
  * \param blockAABBIntersectionPadding The padding applied in block AABB intersection pretesting.
  *                                     Set it to the value of the farthest distance a object might protrude from
  *                                     its containing block.
- * \param bodyToShadingParamsFunction A function mapping a BodyID to ShadingParameters for this body.
- *                                    This can be used to customize the color and shading of bodies.
+ * \param bodyToShadingParamsFunc A function mapping a BodyID to ShadingParameters for this body.
+ *                                This can be used to customize the color and shading of bodies.
+ * \param isBodyVisibleFunc A function which returns a boolean indicating if a given body should be visible
+ *                          in the final image.
  */
 Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID storageID,
                      const shared_ptr<BodyStorage> globalBodyStorage,
@@ -78,7 +80,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
                      const Lighting& lighting,
                      const Color& backgroundColor,
                      real_t blockAABBIntersectionPadding,
-                     std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction)
+                     std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunc,
+                     std::function<bool (const BodyID)> isBodyVisibleFunc)
    : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), ccdID_(ccdID),
    pixelsHorizontal_(pixelsHorizontal), pixelsVertical_(pixelsVertical),
    fov_vertical_(fov_vertical), antiAliasFactor_(antiAliasFactor),
@@ -92,7 +95,8 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
    localImageOutputEnabled_(false),
    imageOutputDirectory_("."),
    filenameTimestepWidth_(5),
-   bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
+   bodyToShadingParamsFunc_(bodyToShadingParamsFunc),
+   isBodyVisibleFunc_(isBodyVisibleFunc),
    raytracingAlgorithm_(RAYTRACE_HASHGRIDS),
    reductionMethod_(MPI_REDUCE) {
    
@@ -108,6 +112,10 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
  * \param globalBodyStorage Pointer to the global body storage.
  * \param ccdID Block data ID for HashGrids.
  * \param config Config block for the raytracer.
+ * \param bodyToShadingParamsFunc A function mapping a BodyID to ShadingParameters for this body.
+ *                                This can be used to customize the color and shading of bodies.
+ * \param isBodyVisibleFunc A function which returns a boolean indicating if a given body should be visible
+ *                          in the final image.
  *
  * The config block has to contain image_x (int), image_y (int) and fov_vertical (real, in degrees).
  * Additionally a vector of reals for each of cameraPosition, lookAt and the upVector for the view setup are required.
@@ -123,9 +131,11 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st
                      const shared_ptr<BodyStorage> globalBodyStorage,
                      const BlockDataID ccdID,
                      const Config::BlockHandle& config,
-                     std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction)
+                     std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunc,
+                     std::function<bool (const BodyID)> isBodyVisibleFunc)
    : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), ccdID_(ccdID),
-   bodyToShadingParamsFunction_(bodyToShadingParamsFunction),
+   bodyToShadingParamsFunc_(bodyToShadingParamsFunc),
+   isBodyVisibleFunc_(isBodyVisibleFunc),
    raytracingAlgorithm_(RAYTRACE_HASHGRIDS),
    reductionMethod_(MPI_REDUCE) {
    WALBERLA_CHECK(config.isValid(), "No valid config passed to raytracer");
diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h
index 8958fd91b..8d77d63ee 100644
--- a/src/pe/raytracing/Raytracer.h
+++ b/src/pe/raytracing/Raytracer.h
@@ -58,7 +58,12 @@ struct BodyIntersectionInfo {
    double g;                     //!< Green value for the pixel.                             -> MPI_DOUBLE
    double b;                     //!< Blue value for the pixel.                              -> MPI_DOUBLE
 };
-   
+
+inline bool defaultIsBodyVisible(const BodyID body) {
+   WALBERLA_UNUSED(body);
+   return true;
+}
+
 class Raytracer {
 public:
    /*!\brief Which method to use when reducing the process-local image to a global one.
@@ -87,12 +92,15 @@ public:
                       const Lighting& lighting,
                       const Color& backgroundColor = Color(real_t(0.1), real_t(0.1), real_t(0.1)),
                       real_t blockAABBIntersectionPadding = real_t(0.0),
-                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction = defaultBodyTypeDependentShadingParams);
+                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunc = defaultBodyTypeDependentShadingParams,
+                      std::function<bool (const BodyID)> isBodyVisibleFunc = defaultIsBodyVisible);
+
    explicit Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID storageID,
                       const shared_ptr<BodyStorage> globalBodyStorage,
                       const BlockDataID ccdID,
                       const Config::BlockHandle& config,
-                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction = defaultBodyTypeDependentShadingParams);
+                      std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction = defaultBodyTypeDependentShadingParams,
+                      std::function<bool (const BodyID)> isBodyVisibleFunc = defaultIsBodyVisible);
    //@}
 
 private:
@@ -128,9 +136,11 @@ private:
                                    * Use e.g. 5 for ranges from 1 to 99 999: Will result in
                                    * filenames like image_00001.png up to image_99999.png. */
    uint8_t filenameRankWidth_;  //!< Width of the mpi rank part in a filename.
-   std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction_; /*!< Function which returns a 
-                                                                                  * ShadingParameters struct
-                                                                                  * given the specified body. */
+   std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunc_; /*!< Function which returns a
+                                                                              * ShadingParameters struct for the
+                                                                              * specified body. */
+   std::function<bool (const BodyID)> isBodyVisibleFunc_; /*!< Function which returns a boolean indicating if
+                                                           * a given body should be visible in the final image. */
    Algorithm raytracingAlgorithm_;    //!< Algorithm to use while intersection testing.
    ReductionMethod reductionMethod_; //!< Reduction method used for assembling the image from all processes.
    
@@ -441,36 +451,32 @@ inline size_t Raytracer::coordinateToArrayIndex(size_t x, size_t y) const {
  */
 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;
-      }
+   WALBERLA_ROOT_SECTION(){
+      real_t t = std::numeric_limits<real_t>::max();
+      Vec3 n;
+      
+      IntersectsFunctor func(ray, t, n);
       
-      if (bodyIt->getTypeID() == Plane::getStaticTypeID()) {
-         PlaneID plane = (PlaneID)bodyIt;
-         if (!isPlaneVisible(plane, ray)) {
+      for(auto bodyIt: *globalBodyStorage_) {
+         if (!isBodyVisibleFunc_(bodyIt)) {
             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;
+         
+         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;
+         }
       }
    }
 }
@@ -499,6 +505,10 @@ inline void Raytracer::traceRayNaively(const Ray& ray, BodyID& body_closest, rea
 #endif
       
       for (auto bodyIt = LocalBodyIterator::begin(*blockIt, storageID_); bodyIt != LocalBodyIterator::end(); ++bodyIt) {
+         if (!isBodyVisibleFunc_(*bodyIt)) {
+            continue;
+         }
+         
          bool intersects = SingleCast<BodyTypeTuple, IntersectsFunctor, bool>::execute(*bodyIt, func);
          Raytracer::naiveIntersectionTestCount++;
          
@@ -534,7 +544,8 @@ inline void Raytracer::traceRayInHashGrids(const Ray& ray, BodyID& body_closest,
 #endif
       
       ccd::HashGrids* hashgrids = blockIt->uncheckedFastGetData<ccd::HashGrids>(ccdID_);
-      BodyID body = hashgrids->getClosestBodyIntersectingWithRay<BodyTypeTuple>(ray, blockAabb, t, n);
+      BodyID body = hashgrids->getClosestBodyIntersectingWithRay<BodyTypeTuple>(ray, blockAabb, t, n,
+                                                                                isBodyVisibleFunc_);
       if (body != NULL && t < t_closest) {
          t_closest = t;
          body_closest = body;
@@ -722,7 +733,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) {
  * \return Computed color.
  */
 inline Color Raytracer::getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const {
-   const ShadingParameters shadingParams = bodyToShadingParamsFunction_(body);
+   const ShadingParameters shadingParams = bodyToShadingParamsFunc_(body);
    
    const Vec3 intersectionPoint = ray.getOrigin() + ray.getDirection() * t;
    Vec3 lightDirection = lighting_.pointLightOrigin - intersectionPoint;
-- 
GitLab