/*============================================================================= Copyright (c) 2011-2013 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_DARKROOM_OBJECTS_INTERSECT_HPP #define SPROUT_DARKROOM_OBJECTS_INTERSECT_HPP #include #include #include #include #include #include namespace sprout { namespace darkroom { namespace objects { template struct intersection_result; namespace detail { template struct intersection_result; template struct intersection_result : public Object::template intersection {}; template struct intersection_result : public sprout::darkroom::objects::intersection_result::type, Ray> {}; } // namespace detail // // intersection_result // template struct intersection_result : public sprout::darkroom::objects::detail::intersection_result< Object, Ray, sprout::darkroom::access::is_tuple::value > {}; template struct intersection_result : public sprout::darkroom::objects::intersection_result {}; template struct intersection_result : public sprout::darkroom::objects::intersection_result {}; template struct intersection_result : public sprout::darkroom::objects::intersection_result {}; // // intersect // template< typename Object, typename Ray, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type intersect(Object const& obj, Ray const& ray); template< typename Object, typename Ray, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type intersect(Object const& obj, Ray const& ray); namespace detail { template struct intersect_list_impl { private: template SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type comp(A const& a, B const& b) const { return sprout::darkroom::intersects::does_intersect(a) && sprout::darkroom::intersects::does_intersect(b) ? sprout::darkroom::intersects::distance(a) < sprout::darkroom::intersects::distance(b) ? a : b : sprout::darkroom::intersects::does_intersect(a) ? a : b ; } public: template SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type operator()(Objects const& objs, Ray const& ray) const { return comp( sprout::darkroom::objects::intersect(sprout::darkroom::access::get(objs), ray), intersect_list_impl()(objs, ray) ); } }; template<> struct intersect_list_impl<0> { public: template SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type operator()(Objects const& objs, Ray const& ray) const { return sprout::darkroom::objects::intersect(sprout::darkroom::access::get<0>(objs), ray); } }; } // namespace detail // // intersect_list // template inline SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type intersect_list(Objects const& objs, Ray const& ray) { return sprout::darkroom::objects::detail::intersect_list_impl< sprout::darkroom::access::size::value - 1 >()(objs, ray); } // // intersect // template< typename Object, typename Ray, typename sprout::enabler_if::value>::type > inline SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type intersect(Object const& obj, Ray const& ray) { return obj.intersect(ray); } template< typename Object, typename Ray, typename sprout::enabler_if::value>::type > inline SPROUT_CONSTEXPR typename sprout::darkroom::objects::intersection_result::type intersect(Object const& obj, Ray const& ray) { return sprout::darkroom::objects::intersect_list(obj, ray); } } // namespace objects } // namespace darkroom } // namespace sprout #endif // #ifndef SPROUT_DARKROOM_OBJECTS_INTERSECT_HPP