From 5ac1b38c188bb12fbdd0ed09726d443cc9f9a76f Mon Sep 17 00:00:00 2001
From: Lukas Werner <lks.werner@fau.de>
Date: Mon, 22 Jan 2018 12:45:47 +0100
Subject: [PATCH] Added Raytracer with Config loading constructor, fixed
 linking issue

---
 src/pe/raytracing/Raytracer.cpp | 197 +++++++-------------------------
 src/pe/raytracing/Raytracer.h   | 158 +++++++++++++++++++++++++
 2 files changed, 201 insertions(+), 154 deletions(-)

diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp
index 4364bbe11..4a88ff183 100644
--- a/src/pe/raytracing/Raytracer.cpp
+++ b/src/pe/raytracing/Raytracer.cpp
@@ -19,30 +19,9 @@
 //======================================================================================================================
 
 #include "Raytracer.h"
-#include "Ray.h"
-#include "Intersects.h"
 
 using namespace walberla;
 
-struct BodyIntersectionInfo {
-   size_t imageX; // viewing plane pixel coordinates to ...
-   size_t imageY; // ... identify ray by pixel it intersected
-   walberla::id_t bodySystemID; // body which was hit
-   real_t t; // distance from camera to intersection point on body
-};
-
-struct Coordinates {
-   size_t x;
-   size_t y;
-};
-
-struct CoordinatesComparator {
-   bool operator() (const Coordinates& lhs, const Coordinates& rhs) const {
-      // standard lexicographical ordering
-      return (lhs.x < rhs.x) || (lhs.x == rhs.x && lhs.y < rhs.y);
-   }
-};
-
 real_t deg2rad(real_t deg) {
    return deg * math::M_PI / real_t(180.0);
 }
@@ -50,7 +29,7 @@ real_t deg2rad(real_t deg) {
 namespace walberla {
 namespace pe {
 namespace raytracing {
-/*!\brief Instantiation constructor for the Box class.
+/*!\brief Instantiation constructor for the Raytracer class.
  *
  * \param forest BlockForest the raytracer operates on.
  * \param storageID Storage ID of the block data storage the raytracer operates on.
@@ -70,6 +49,47 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage>& forest, BlockDataID storage
    fov_vertical_(fov_vertical),
    cameraPosition_(cameraPosition), lookAtPoint_(lookAtPoint), upVector_(upVector)
 {
+   setupView_();
+}
+
+/*!\brief Instantiation constructor for the Raytracer class using a config object for view setup.
+ *
+ * \param forest BlockForest the raytracer operates on.
+ * \param storageID Storage ID of the block data storage the raytracer operates on.
+ * \param config Config block for the raytracer.
+ *
+ * The config block has to contain image_x (int), image_y (int) and fov_vertical (real, in degrees)
+ * parameters, additionally one block with x, y and z values (real) for each of camera,
+ * lookAt and the upVector.
+ */
+Raytracer::Raytracer(const shared_ptr<BlockStorage> & forest, BlockDataID storageID,
+                     const Config::BlockHandle& config) : forest_(forest), storageID_(storageID) {
+   pixelsHorizontal_ = config.getParameter<uint8_t>("image_x");
+   pixelsVertical_ = config.getParameter<uint8_t>("image_y");
+   fov_vertical_ = config.getParameter<real_t>("fov_vertical");
+   
+   WALBERLA_CHECK(config.isDefined("camera"), "No camera block found in config");
+   const Config::BlockHandle cameraConf = config.getBlock("camera");
+   cameraPosition_ = Vec3(cameraConf.getParameter<real_t>("x"),
+                          cameraConf.getParameter<real_t>("y"),
+                          cameraConf.getParameter<real_t>("z"));
+   
+   WALBERLA_CHECK(config.isDefined("lookAt"), "No lookAt block found in config");
+   const Config::BlockHandle lookAtConf = config.getBlock("lookAt");
+   lookAtPoint_ = Vec3(lookAtConf.getParameter<real_t>("x"),
+                       lookAtConf.getParameter<real_t>("y"),
+                       lookAtConf.getParameter<real_t>("z"));
+   
+   WALBERLA_CHECK(config.isDefined("upVector"), "No upVector block found in config");
+   const Config::BlockHandle upVectorConf = config.getBlock("upVector");
+   upVector_ = Vec3(upVectorConf.getParameter<real_t>("x"),
+                    upVectorConf.getParameter<real_t>("y"),
+                    upVectorConf.getParameter<real_t>("z"));
+   
+   setupView_();
+}
+   
+void Raytracer::setupView_() {
    // eye coordinate system setup
    n = (cameraPosition_ - lookAtPoint_).getNormalized();
    u = (upVector_ % n).getNormalized();
@@ -83,138 +103,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage>& forest, BlockDataID storage
    viewingPlaneOrigin = lookAtPoint_ - u*viewingPlaneWidth/real_t(2.) - v*viewingPlaneHeight/real_t(2.);
    
    pixelWidth = viewingPlaneWidth / real_c(pixelsHorizontal_);
-   pixelHeight = viewingPlaneHeight / real_c(pixelsVertical);
-}
-
-/*!\brief Does one raytracing step.
- *
- * \param timestep The timestep after which the raytracing starts.
- */
-template <typename BodyTypeTuple>
-void Raytracer::rayTrace(const size_t timestep) const {
-   std::map<Coordinates, real_t, CoordinatesComparator> tBuffer; // t values for each pixel
-   std::map<Coordinates, walberla::id_t, CoordinatesComparator> idBuffer; // ids of the intersected body for each pixel
-   std::vector<BodyIntersectionInfo> intersections; // contains for each pixel information about an intersection, if existent
-   
-   std::map<Coordinates, BodyIntersectionInfo, CoordinatesComparator> localPixelIntersectionMap;
-   
-   real_t t, t_closest;
-   walberla::id_t id_closest;
-   RigidBody* body_closest = NULL;
-   Ray ray(cameraPosition_, Vec3(1,0,0));
-   IntersectsFunctor func(ray, t);
-   for (size_t x = 0; x < pixelsHorizontal_; x++) {
-      for (size_t y = 0; y < pixelsVertical_; y++) {
-         //WALBERLA_LOG_INFO(x << "/" << y);
-         Vec3 pixelLocation = viewingPlaneOrigin + u*(real_c(x)+real_t(0.5))*pixelWidth + v*(real_c(y)+real_t(0.5))*pixelHeight;
-         Vec3 direction = (pixelLocation - cameraPosition_).getNormalized();
-         ray.setDirection(direction);
-         
-         t_closest = INFINITY;
-         id_closest = 0;
-         body_closest = NULL;
-         for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
-            // blockIt->getAABB();
-            /*const AABB& blockAabb = blockIt->getAABB();
-             if (!intersects(blockAabb, ray, t)) {
-             continue;
-             }*/
-            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 currently closest to camera
-                  t_closest = t;
-                  id_closest = bodyIt->getID();
-                  body_closest = *bodyIt;
-               }
-            }
-         }
-         
-         //std::cout << (t_closest != INFINITY ? size_t(t_closest) : 0) << " ";
-         
-         Coordinates c = {
-            x,
-            y
-         };
-         
-         if (!realIsIdentical(t_closest, INFINITY) && body_closest != NULL) {
-            BodyIntersectionInfo intersectionInfo = {
-               x,
-               y,
-               body_closest->getSystemID(),
-               t_closest
-            };
-            intersections.push_back(intersectionInfo);
-            localPixelIntersectionMap[c] = intersectionInfo;
-         }
-         
-         tBuffer[c] = t_closest;
-         idBuffer[c] = id_closest;
-      }
-      //std::cout << std::endl;
-   }
-   
-   // intersections synchronisieren
-   mpi::SendBuffer sendBuffer;
-   for (auto& info: intersections) {
-      sendBuffer << info.imageX << info.imageY << info.bodySystemID << info.t;
-   }
-   
-   std::vector<BodyIntersectionInfo> gatheredIntersections;
-   
-   std::map<walberla::id_t, bool> visibleBodyIDs;
-   
-   //std::map<Coordinates, BodyIntersectionInfo, CoordinatesComparator> pixelIntersectionMap;
-   
-   mpi::RecvBuffer recvBuffer;
-   mpi::allGathervBuffer(sendBuffer, recvBuffer);
-   while (!recvBuffer.isEmpty()) {
-      BodyIntersectionInfo info;
-      
-      recvBuffer >> info.imageX;
-      recvBuffer >> info.imageY;
-      recvBuffer >> info.bodySystemID;
-      recvBuffer >> info.t;
-      
-      Coordinates c = {
-         info.imageX,
-         info.imageY
-      };
-      
-      /*if (pixelIntersectionMap.find(c) == pixelIntersectionMap.end()) {
-       // map didnt contain coordinates
-       pixelIntersectionMap.insert(std::make_pair(c, info));
-       } else {
-       // map already contains info at coordinates, check if current info is closer
-       BodyIntersectionInfo& existingInfo = pixelIntersectionMap.at(c);
-       if (existingInfo.t < info.t) {
-       pixelIntersectionMap[c] = info;
-       }
-       }*/
-      auto it = localPixelIntersectionMap.find(c);
-      if (it != localPixelIntersectionMap.end()) {
-         // there was a local hit at coordinate c
-         BodyIntersectionInfo& localInfo = localPixelIntersectionMap.at(c);
-         if (localInfo.t < info.t) {
-            localPixelIntersectionMap.erase(it);
-         }
-      }
-      
-      //gatheredIntersections.push_back(info);
-   }
-   
-   for (auto& info: localPixelIntersectionMap) {
-      visibleBodyIDs[info.second.bodySystemID] = true;
-   }
-   
-   WALBERLA_LOG_INFO("#particles visible: " << visibleBodyIDs.size());
-   //WALBERLA_LOG_INFO_ON_ROOT("#gatheredIntersections: " << gatheredIntersections.size());
-   
-#ifdef __APPLE__
-   //mpi::MPIRank rank = mpi::MPIManager::instance()->rank();
-   //writeTBufferToFile(tBuffer, idBuffer, pixelsHorizontal_, pixelsVertical_, "/Users/ng/Desktop/walberla/tbuffer_" + std::to_string(rank) + ".ppm");
-#endif
+   pixelHeight = viewingPlaneHeight / real_c(pixelsVertical_);
 }
 
 }
diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h
index 2ec69e72f..933c5d70b 100644
--- a/src/pe/raytracing/Raytracer.h
+++ b/src/pe/raytracing/Raytracer.h
@@ -24,11 +24,34 @@
 #include <pe/Types.h>
 #include <core/math/Vector3.h>
 #include <core/mpi/all.h>
+#include <core/config/Config.h>
+#include "Ray.h"
+#include "Intersects.h"
 
 namespace walberla {
 namespace pe {
 namespace raytracing {
 
+struct BodyIntersectionInfo {
+   size_t imageX; // viewing plane pixel coordinates to ...
+   size_t imageY; // ... identify ray by pixel it intersected
+   walberla::id_t bodySystemID; // body which was hit
+   real_t t; // distance from camera to intersection point on body
+};
+
+struct Coordinates {
+   size_t x;
+   size_t y;
+};
+
+struct CoordinatesComparator {
+   bool operator() (const Coordinates& lhs, const Coordinates& rhs) const {
+      // standard lexicographical ordering
+      return (lhs.x < rhs.x) || (lhs.x == rhs.x && lhs.y < rhs.y);
+   }
+};
+
+
 class Raytracer {
 public:
    /*!\name Constructors */
@@ -37,6 +60,8 @@ public:
                       uint8_t pixelsHorizontal, uint8_t pixelsVertical,
                       real_t fov_vertical,
                       const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector);
+   explicit Raytracer(const shared_ptr<BlockStorage> & forest, BlockDataID storageID,
+                      const Config::BlockHandle& config);
    //@}
 
 private:
@@ -78,6 +103,7 @@ public:
    
    /*!\name Functions */
    //@{
+   void setupView_();
    template <typename BodyTypeTuple>
    void rayTrace(const size_t timestep)   const;
    //@}
@@ -137,6 +163,138 @@ inline const Vec3& Raytracer::getLookAtPoint() const {
 inline const Vec3& Raytracer::getUpVector() const {
    return upVector_;
 }
+   
+/*!\brief Does one raytracing step.
+ *
+ * \param timestep The timestep after which the raytracing starts.
+ */
+template <typename BodyTypeTuple>
+void Raytracer::rayTrace(const size_t timestep) const {
+   std::map<Coordinates, real_t, CoordinatesComparator> tBuffer; // t values for each pixel
+   std::map<Coordinates, walberla::id_t, CoordinatesComparator> idBuffer; // ids of the intersected body for each pixel
+   std::vector<BodyIntersectionInfo> intersections; // contains for each pixel information about an intersection, if existent
+   
+   std::map<Coordinates, BodyIntersectionInfo, CoordinatesComparator> localPixelIntersectionMap;
+   
+   real_t t, t_closest;
+   walberla::id_t id_closest;
+   RigidBody* body_closest = NULL;
+   Ray ray(cameraPosition_, Vec3(1,0,0));
+   IntersectsFunctor func(ray, t);
+   for (size_t x = 0; x < pixelsHorizontal_; x++) {
+      for (size_t y = 0; y < pixelsVertical_; y++) {
+         //WALBERLA_LOG_INFO(x << "/" << y);
+         Vec3 pixelLocation = viewingPlaneOrigin + u*(real_c(x)+real_t(0.5))*pixelWidth + v*(real_c(y)+real_t(0.5))*pixelHeight;
+         Vec3 direction = (pixelLocation - cameraPosition_).getNormalized();
+         ray.setDirection(direction);
+         
+         t_closest = INFINITY;
+         id_closest = 0;
+         body_closest = NULL;
+         for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) {
+            // blockIt->getAABB();
+            /*const AABB& blockAabb = blockIt->getAABB();
+             if (!intersects(blockAabb, ray, t)) {
+             continue;
+             }*/
+            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 currently closest to camera
+                  t_closest = t;
+                  id_closest = bodyIt->getID();
+                  body_closest = *bodyIt;
+               }
+            }
+         }
+         
+         //std::cout << (t_closest != INFINITY ? size_t(t_closest) : 0) << " ";
+         
+         Coordinates c = {
+            x,
+            y
+         };
+         
+         if (!realIsIdentical(t_closest, INFINITY) && body_closest != NULL) {
+            BodyIntersectionInfo intersectionInfo = {
+               x,
+               y,
+               body_closest->getSystemID(),
+               t_closest
+            };
+            intersections.push_back(intersectionInfo);
+            localPixelIntersectionMap[c] = intersectionInfo;
+         }
+         
+         tBuffer[c] = t_closest;
+         idBuffer[c] = id_closest;
+      }
+      //std::cout << std::endl;
+   }
+   
+   // intersections synchronisieren
+   mpi::SendBuffer sendBuffer;
+   for (auto& info: intersections) {
+      sendBuffer << info.imageX << info.imageY << info.bodySystemID << info.t;
+   }
+   
+   std::vector<BodyIntersectionInfo> gatheredIntersections;
+   
+   std::map<walberla::id_t, bool> visibleBodyIDs;
+   
+   //std::map<Coordinates, BodyIntersectionInfo, CoordinatesComparator> pixelIntersectionMap;
+   
+   mpi::RecvBuffer recvBuffer;
+   mpi::allGathervBuffer(sendBuffer, recvBuffer);
+   while (!recvBuffer.isEmpty()) {
+      BodyIntersectionInfo info;
+      
+      recvBuffer >> info.imageX;
+      recvBuffer >> info.imageY;
+      recvBuffer >> info.bodySystemID;
+      recvBuffer >> info.t;
+      
+      Coordinates c = {
+         info.imageX,
+         info.imageY
+      };
+      
+      /*if (pixelIntersectionMap.find(c) == pixelIntersectionMap.end()) {
+       // map didnt contain coordinates
+       pixelIntersectionMap.insert(std::make_pair(c, info));
+       } else {
+       // map already contains info at coordinates, check if current info is closer
+       BodyIntersectionInfo& existingInfo = pixelIntersectionMap.at(c);
+       if (existingInfo.t < info.t) {
+       pixelIntersectionMap[c] = info;
+       }
+       }*/
+      auto it = localPixelIntersectionMap.find(c);
+      if (it != localPixelIntersectionMap.end()) {
+         // there was a local hit at coordinate c
+         BodyIntersectionInfo& localInfo = localPixelIntersectionMap.at(c);
+         if (localInfo.t < info.t) {
+            localPixelIntersectionMap.erase(it);
+         }
+      }
+      
+      //gatheredIntersections.push_back(info);
+   }
+   
+   for (auto& info: localPixelIntersectionMap) {
+      visibleBodyIDs[info.second.bodySystemID] = true;
+   }
+   
+   WALBERLA_LOG_INFO("#particles visible: " << visibleBodyIDs.size());
+   //WALBERLA_LOG_INFO_ON_ROOT("#gatheredIntersections: " << gatheredIntersections.size());
+   
+#ifdef __APPLE__
+   //mpi::MPIRank rank = mpi::MPIManager::instance()->rank();
+   //writeTBufferToFile(tBuffer, idBuffer, pixelsHorizontal_, pixelsVertical_, "/Users/ng/Desktop/walberla/tbuffer_" + std::to_string(rank) + ".ppm");
+#endif
+}
+
 }
 }
 }
-- 
GitLab