From d5246a3339279b5d0f2538dcf21fdbdf702aeecd Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Mon, 22 Jan 2018 11:50:27 +0100 Subject: [PATCH] Moved raytracing code into its own files --- apps/tutorials/pe/01_ConfinedGas.cpp | 237 +-------------------------- src/pe/raytracing/Raytracer.cpp | 222 +++++++++++++++++++++++++ src/pe/raytracing/Raytracer.h | 142 ++++++++++++++++ 3 files changed, 371 insertions(+), 230 deletions(-) create mode 100644 src/pe/raytracing/Raytracer.cpp create mode 100644 src/pe/raytracing/Raytracer.h diff --git a/apps/tutorials/pe/01_ConfinedGas.cpp b/apps/tutorials/pe/01_ConfinedGas.cpp index 670f6fb42..af7a1a11e 100644 --- a/apps/tutorials/pe/01_ConfinedGas.cpp +++ b/apps/tutorials/pe/01_ConfinedGas.cpp @@ -32,8 +32,7 @@ #include <pe/vtk/SphereVtkOutput.h> #include "vtk/VTKOutput.h" -#include <pe/raytracing/Intersects.h> -#include <pe/raytracing/Ray.h> +#include <pe/raytracing/Raytracer.h> #include <core/mpi/all.h> @@ -47,232 +46,6 @@ using namespace walberla::pe::raytracing; typedef boost::tuple<Sphere, Plane, Box> BodyTypeTuple ; //! [BodyTypeTuple] -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); -} - -void writeTBufferToFile(const std::map<Coordinates, real_t, CoordinatesComparator>& buffer, const std::map<Coordinates, walberla::id_t, CoordinatesComparator> idBuffer, const size_t width, const size_t height, const std::string& fileName) { - real_t t_max = 1; - real_t t_min = INFINITY; - walberla::id_t maxId = 0; - for (size_t x = 0; x < width; x++) { - for (size_t y = 0; y < height; y++) { - Coordinates c = {x, y}; - real_t t = buffer.at(c); - if (t > t_max && !realIsIdentical(t, INFINITY)) { - t_max = t; - } - if (t < t_min) { - t_min = t; - } - if (idBuffer.at(c) > maxId) { - maxId = idBuffer.at(c); - } - } - } - if (realIsIdentical(t_min, INFINITY)) t_min = 0; - - //std::map<walberla::id_t, char> idToColors; - - std::ofstream ofs(fileName, std::ios::out | std::ios::binary); - ofs << "P6\n" << width << " " << height << "\n255\n"; - for (size_t y = height-1; y > 0; y--) { - for (size_t x = 0; x < width; x++) { - Coordinates c = {x, y}; - char r = 0, g = 0, b = 0; - real_t t = buffer.at(c); - //walberla::id_t id = idBuffer[i]; - if (realIsIdentical(t, INFINITY)) { - r = g = b = (char)255; - } else { - //r = g = b = (char)(255 * (t-t_min)/t_max); - //b = (char)(255 * (real_t(id)/real_t(maxId))); - //if (b > (char)250) b = (char)250; - //if (idToColors.count(id) == 0) { - // idToColors.insert(std::make_pair(id, math::intRandom(0, 240))); - //} - r = g = b = (char)(200 * ((t-t_min)/(t_max-t_min))); - //b = (char)(200 * ((t-t_min)/t_max)); - //r = (char)(200 * ((t-t_min)/t_max)); - } - ofs << r << g << b; - } - } - - ofs.close(); -} - -//forest speichert alle blÃķcke meines prozesses - -void rayTrace (shared_ptr<BlockForest> forest, BlockDataID storageID) { - // - settings - size_t pixelsHorizontal = 640; - size_t pixelsVertical = 480; - real_t fov_vertical = 49.13; // in degrees, in vertical direction - // camera settings - Vec3 cameraPosition(-25,10,10); // -5,0,0 for testing, -25,10,10 for simulation - Vec3 lookAtPoint(-5,10,10); // 1,0,0 for testing, -5,10,10 for simulation - Vec3 upVector(0,0,1); - - // - viewing plane construction - // eye cos setup - Vec3 n = (cameraPosition - lookAtPoint).getNormalized(); // normal vector of viewing plane - Vec3 u = (upVector % n).getNormalized(); // u and ... - Vec3 v = n % u; // ... v span the viewing plane - // image plane setup - real_t d = (cameraPosition - lookAtPoint).length(); // distance from camera to viewing plane - real_t aspectRatio = real_t(pixelsHorizontal) / real_t(pixelsVertical); - real_t imagePlaneHeight = tan(deg2rad(fov_vertical)/real_t(2.)) * real_t(2.) * d; - real_t imagePlaneWidth = imagePlaneHeight * aspectRatio; - Vec3 imagePlaneOrigin = lookAtPoint - u*imagePlaneWidth/real_t(2.) - v*imagePlaneHeight/real_t(2.); - real_t pixelWidth = imagePlaneWidth / real_c(pixelsHorizontal); - real_t pixelHeight = imagePlaneHeight / real_c(pixelsVertical); - - // - raytracing - 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 = imagePlaneOrigin + 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 -} - void testRayTracing () { shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); shared_ptr<BlockForest> forest = createBlockForest(AABB(0,-5,-5,10,5,5), Vec3(1,1,1), Vec3(false, false, false)); @@ -286,7 +59,8 @@ void testRayTracing () { createBox(*globalBodyStorage, *forest, storageID, 7, Vec3(5,-4,3), Vec3(2,2,2)); //createSphere(*globalBodyStorage, *forest, storageID, 5, Vec3(1,0,0), real_t(0.1)); - rayTrace(forest, storageID); + //Raytracer raytracer(forest, storageID, uint8_t(640), uint8_t(480), 49.13, Vec3(-5,0,0), Vec3(-1,0,0), Vec3(0,0,1)); + //raytracer.rayTrace<BodyTypeTuple>(0); } int main( int argc, char ** argv ) @@ -356,6 +130,9 @@ int main( int argc, char ** argv ) auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling( globalBodyStorage, storageID ), "CCD"); auto fcdID = forest->addBlockData(fcd::createGenericFCDDataHandling<BodyTypeTuple, fcd::AnalyticCollideFunctor>(), "FCD"); //! [AdditionalBlockData] + + WALBERLA_LOG_INFO_ON_ROOT("*** RAYTRACER ***"); + Raytracer raytracer(forest, storageID, uint8_t(640), uint8_t(480), 49.13, Vec3(-25,10,10), Vec3(-1,10,10), Vec3(0,0,1)); WALBERLA_LOG_INFO_ON_ROOT("*** INTEGRATOR ***"); //! [Integrator] @@ -439,7 +216,7 @@ int main( int argc, char ** argv ) //! [PostProcessing] WALBERLA_LOG_INFO_ON_ROOT("*** RAYTRACING - START ***"); - rayTrace(forest, storageID); + raytracer.rayTrace<BodyTypeTuple>(0); WALBERLA_LOG_INFO_ON_ROOT("*** RAYTRACING - END ***"); // fÞr einzelne sphere vtks: -> SphereVtkOutput.cpp diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp new file mode 100644 index 000000000..4364bbe11 --- /dev/null +++ b/src/pe/raytracing/Raytracer.cpp @@ -0,0 +1,222 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Raytracer.cpp +//! \author Lukas Werner +// +//====================================================================================================================== + +#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); +} + +namespace walberla { +namespace pe { +namespace raytracing { +/*!\brief Instantiation constructor for the Box class. + * + * \param forest BlockForest the raytracer operates on. + * \param storageID Storage ID of the block data storage the raytracer operates on. + * \param pixelsHorizontal Horizontal amount of pixels of the generated image. + * \param pixelsVertical Vertical amount of pixels of the generated image. + * \param fov_vertical Vertical field-of-view of the camera. + * \param cameraPosition Position of the camera in the global world frame. + * \param lookAtPoint Point the camera looks at in the global world frame. + * \param upVector Vector indicating the upwards direction of the camera. + */ +Raytracer::Raytracer(const shared_ptr<BlockStorage>& forest, BlockDataID storageID, + uint8_t pixelsHorizontal, uint8_t pixelsVertical, + real_t fov_vertical, + const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector) + : forest_(forest), storageID_(storageID), + pixelsHorizontal_(pixelsHorizontal), pixelsVertical_(pixelsVertical), + fov_vertical_(fov_vertical), + cameraPosition_(cameraPosition), lookAtPoint_(lookAtPoint), upVector_(upVector) +{ + // eye coordinate system setup + n = (cameraPosition_ - lookAtPoint_).getNormalized(); + u = (upVector_ % n).getNormalized(); + v = n % u; + + // viewing plane setup + d = (cameraPosition_ - lookAtPoint_).length(); + aspectRatio = real_t(pixelsHorizontal_) / real_t(pixelsVertical_); + viewingPlaneHeight = tan(deg2rad(fov_vertical_)/real_t(2.)) * real_t(2.) * d; + viewingPlaneWidth = viewingPlaneHeight * aspectRatio; + 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 +} + +} +} +} diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h new file mode 100644 index 000000000..2ec69e72f --- /dev/null +++ b/src/pe/raytracing/Raytracer.h @@ -0,0 +1,142 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Raytracer.h +//! \author Lukas Werner +// +//====================================================================================================================== + +#pragma once + +#include <pe/basic.h> +#include <pe/Types.h> +#include <core/math/Vector3.h> +#include <core/mpi/all.h> + +namespace walberla { +namespace pe { +namespace raytracing { + +class Raytracer { +public: + /*!\name Constructors */ + //@{ + explicit Raytracer(const shared_ptr<BlockStorage> & forest, BlockDataID storageID, + uint8_t pixelsHorizontal, uint8_t pixelsVertical, + real_t fov_vertical, + const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector); + //@} + +private: + /*!\name Member variables */ + //@{ + const shared_ptr<BlockStorage>& forest_; //!< The BlockForest the raytracer operates on. + BlockDataID storageID_; /*!< The storage ID of the block data storage the raytracer operates + on.*/ + uint8_t pixelsHorizontal_; //!< The horizontal amount of pixels of the generated image. + uint8_t pixelsVertical_; //!< The vertical amount of pixels of the generated image. + real_t fov_vertical_; //!< The vertical field-of-view of the camera. + Vec3 cameraPosition_; //!< The position of the camera in the global world frame. + Vec3 lookAtPoint_; /*!< The point the camera looks at in the global world frame, + marks the center of the view plane.*/ + Vec3 upVector_; //!< The vector indicating the upwards direction of the camera. + //@} + + Vec3 n; // normal vector of viewing plane + Vec3 u; // u and ... + Vec3 v; // ... v span the viewing plane + real_t d; // distance from camera to viewing plane + real_t aspectRatio; // aspect ratio of the generated image and viewing plane + real_t viewingPlaneHeight; // viewing plane height + real_t viewingPlaneWidth; // viewing plane width + Vec3 viewingPlaneOrigin; // origin of the viewing plane + real_t pixelWidth; // width of a pixel of the generated image in the viewing plane + real_t pixelHeight; // height of a pixel of the generated image in the viewing plane + +public: + /*!\name Get functions */ + //@{ + inline uint8_t getPixelsHorizontal() const; + inline uint8_t getPixelsVertical() const; + inline real_t getFOVVertical() const; + inline const Vec3& getCameraPosition() const; + inline const Vec3& getLookAtPoint() const; + inline const Vec3& getUpVector() const; + //@} + + /*!\name Functions */ + //@{ + template <typename BodyTypeTuple> + void rayTrace(const size_t timestep) const; + //@} +}; + +/*!\brief Returns the horizontal amount of pixels of the generated image. + * + * \return The horizontal amount of pixels of the generated image. + */ +inline uint8_t Raytracer::getPixelsHorizontal() const { + return pixelsHorizontal_; +} + +/*!\brief Returns the vertical amount of pixels of the generated image. + * + * \return The vertical amount of pixels of the generated image. + */ +inline uint8_t Raytracer::getPixelsVertical() const { + return pixelsVertical_; +} + +/*!\brief Returns the vertical field-of-view of the camera. + * + * \return The vertical field-of-view of the camera. + */ +inline real_t Raytracer::getFOVVertical() const { + return fov_vertical_; +} + +/*!\brief Returns the position of the camera in the global world frame. + * + * \return The position of the camera. + * + * Returns the position of the camera in the global world frame. + */ +inline const Vec3& Raytracer::getCameraPosition() const { + return cameraPosition_; +} + +/*!\brief Returns the point the camera looks at in the global world frame. + * + * \return The looked at point. + * + * Returns the point the camera looks at in the global world frame, which also marks the center of + * the view plane. + */ +inline const Vec3& Raytracer::getLookAtPoint() const { + return lookAtPoint_; +} + +/*!\brief Returns the vector indicating the upwards direction of the camera. + * + * \return The upwards vector of the camera. + * + * Returns the vector indicating the upwards direction of the camera. + */ +inline const Vec3& Raytracer::getUpVector() const { + return upVector_; +} +} +} +} -- GitLab