Commit 5ac1b38c authored by Lukas Werner's avatar Lukas Werner
Browse files

Added Raytracer with Config loading constructor, fixed linking issue

parent d5246a33
Pipeline #6862 failed with stage
in 72 minutes and 55 seconds
......@@ -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_);
}
}
......
......@@ -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
}
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment