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