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