/*============================================================================= Copyright (c) 2011-2014 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_SPHERE_HPP #define SPROUT_DARKROOM_OBJECTS_SPHERE_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace darkroom { namespace objects { // // basic_sphere // template class basic_sphere { public: typedef Material material_type; typedef Position position_type; typedef typename sprout::darkroom::access::unit::type unit_type; typedef unit_type radius_type; public: template struct intersection { typedef sprout::tuples::tuple< bool, unit_type, position_type, position_type, decltype(sprout::darkroom::materials::calculate_material( std::declval(), std::declval(), std::declval() )), bool > type; }; private: typedef sprout::tuples::tuple zwo_type; typedef sprout::tuples::tuple drei_type; struct zw { SPROUT_STATIC_CONSTEXPR std::size_t hit_side = 0; SPROUT_STATIC_CONSTEXPR std::size_t does_intersect = 1; SPROUT_STATIC_CONSTEXPR std::size_t distance = 2; }; struct dr { SPROUT_STATIC_CONSTEXPR std::size_t point_of_intersection = 0; SPROUT_STATIC_CONSTEXPR std::size_t normal = 1; }; private: position_type pos_; radius_type rad_; material_type mat_; private: SPROUT_STATIC_CONSTEXPR zwo_type zweitens_1(unit_type const& i1, unit_type const& i2) { return zwo_type( i2 > 0 ? i1 < 0 ? -1 : 1 : 0 , i2 > 0, i2 > 0 ? i1 < 0 ? i2 : i1 : -1 ); } SPROUT_STATIC_CONSTEXPR zwo_type zweitens(bool neg, unit_type const& b, unit_type const& det) { return neg ? zweitens_1(b - det, b + det) : zwo_type(0, false, -1) ; } template SPROUT_CONSTEXPR drei_type drittens_1(typename sprout::darkroom::access::unit::type point_of_intersection) const { return drei_type( point_of_intersection, sprout::darkroom::coords::normalize( sprout::darkroom::coords::sub(point_of_intersection, pos_) ) ); } template SPROUT_CONSTEXPR drei_type drittens(Ray const& ray, bool neg, unit_type const& distance) const { return neg ? drittens_1(sprout::darkroom::rays::point_of_intersection(ray, distance)) : drei_type( sprout::tuples::make(0, 0, 0), sprout::tuples::make(1, 1, 1) ) ; } template SPROUT_CONSTEXPR typename intersection::type intersect_6(zwo_type const& zwo, drei_type const& drei,bool is_from_inside, Vec const& normal) const { return typename intersection::type( sprout::tuples::get(zwo), sprout::tuples::get(zwo), sprout::tuples::get(drei), is_from_inside ? sprout::darkroom::coords::negate(normal) : normal , sprout::darkroom::materials::calculate_material( // ! Spherical mat_, sprout::atan2( sprout::darkroom::coords::z(normal), sprout::darkroom::coords::x(normal) ) / sprout::math::pi() , sprout::atan2( sprout::darkroom::coords::y(normal), sprout::sqrt( sprout::darkroom::coords::x(normal) * sprout::darkroom::coords::x(normal) + sprout::darkroom::coords::z(normal) * sprout::darkroom::coords::z(normal) ) ) / sprout::math::half_pi() ), is_from_inside ); } template SPROUT_CONSTEXPR typename intersection::type intersect_5(Ray const& ray, zwo_type const& zwo, drei_type const& drei) const { return intersect_6( zwo, drei, sprout::darkroom::coords::dot(sprout::tuples::get(drei), sprout::darkroom::rays::direction(ray)) > 0, sprout::tuples::get(drei) ); } template SPROUT_CONSTEXPR typename intersection::type intersect_4(Ray const& ray, zwo_type const& zwo) const { return intersect_5( ray, zwo, drittens( ray, sprout::tuples::get(zwo), sprout::tuples::get(zwo) ) ); } template SPROUT_CONSTEXPR typename intersection::type intersect_3(Ray const& ray, unit_type const& b, unit_type const& det_sq) const { return intersect_4( ray, zweitens( det_sq > 0, b, det_sq > 0 ? sprout::sqrt(det_sq) : unit_type(0) ) ); } template SPROUT_CONSTEXPR typename intersection::type intersect_2(Ray const& ray, position_type const& v, unit_type const& b) const { return intersect_3( ray, b, b * b - sprout::darkroom::coords::length_sq(v) + rad_ * rad_ ); } template SPROUT_CONSTEXPR typename intersection::type intersect_1(Ray const& ray, position_type const& v) const { return intersect_2( ray, v, -sprout::darkroom::coords::dot(v, sprout::darkroom::rays::direction(ray)) ); } public: SPROUT_CONSTEXPR basic_sphere(position_type const& pos, radius_type rad, material_type const& mat) : pos_(pos) , rad_(rad) , mat_(mat) {} template SPROUT_CONSTEXPR typename intersection::type intersect(Ray const& ray) const { return intersect_1( ray, sprout::darkroom::coords::sub(sprout::darkroom::rays::position(ray), pos_) ); } }; // // make_sphere // template inline SPROUT_CONSTEXPR sprout::darkroom::objects::basic_sphere make_sphere(Position const& pos, Radius const& rad, Material const& mat) { return sprout::darkroom::objects::basic_sphere(pos, rad, mat); } } // namespace objects } // namespace darkroom } // namespace sprout #endif // #ifndef SPROUT_DARKROOM_OBJECTS_SPHERE_HPP