diff --git a/sprout/darkroom/cameras.hpp b/sprout/darkroom/cameras.hpp index 21a49a25..83f5d274 100644 --- a/sprout/darkroom/cameras.hpp +++ b/sprout/darkroom/cameras.hpp @@ -2,6 +2,7 @@ #define SPROUT_DARKROOM_CAMERAS_HPP #include +#include #include #endif // #ifndef SPROUT_DARKROOM_CAMERAS_HPP diff --git a/sprout/darkroom/cameras/angle_of_view.hpp b/sprout/darkroom/cameras/angle_of_view.hpp new file mode 100644 index 00000000..427668d1 --- /dev/null +++ b/sprout/darkroom/cameras/angle_of_view.hpp @@ -0,0 +1,27 @@ +#ifndef SPROUT_DARKROOM_CAMERAS_ANGLE_OF_VIEW_HPP +#define SPROUT_DARKROOM_CAMERAS_ANGLE_OF_VIEW_HPP + +#include +#include +#include + +namespace sprout { + namespace darkroom { + namespace cameras { + // + // angle_of_view_reference + // + struct angle_of_view_reference { + public: + enum values { + long_side, + short_side, + width, + height + }; + }; + } // namespace cameras + } // namespace darkroom +} // namespace sprout + +#endif // #ifndef SPROUT_DARKROOM_CAMERAS_ANGLE_OF_VIEW_HPP diff --git a/sprout/darkroom/cameras/simple_camera.hpp b/sprout/darkroom/cameras/simple_camera.hpp index afbed2ff..bb3e057d 100644 --- a/sprout/darkroom/cameras/simple_camera.hpp +++ b/sprout/darkroom/cameras/simple_camera.hpp @@ -1,31 +1,134 @@ #ifndef SPROUT_DARKROOM_CAMERAS_SIMPLE_CAMERA_HPP #define SPROUT_DARKROOM_CAMERAS_SIMPLE_CAMERA_HPP +#include #include #include #include +#include namespace sprout { namespace darkroom { namespace cameras { - template + // + // basic_simple_camera + // + template > class basic_simple_camera { public: typedef Unit unit_type; - typedef sprout::tuples::tuple position_type; + typedef Position position_type; typedef sprout::tuples::tuple ray_type; + typedef sprout::darkroom::cameras::angle_of_view_reference angle_of_view_reference; private: unit_type far_plane_; + angle_of_view_reference::values reference_value_; + position_type position_; + position_type fixation_point_; + unit_type rotate_; + private: + SPROUT_CONSTEXPR position_type transform_1( + position_type const& c, + unit_type const& u, + unit_type const& v, + unit_type const& l + ) const + { + return sprout::darkroom::coords::add( + c, + position_type( + sprout::darkroom::coords::z(c) * u / l, + v, + -sprout::darkroom::coords::x(c) * u / l + ) + ); + } + SPROUT_CONSTEXPR position_type transform( + position_type const& c, + unit_type const& u, + unit_type const& v + ) const + { + using std::sqrt; + using std::sin; + using std::cos; + return transform_1( + c, + u * cos(rotate_) - v * sin(rotate_), + u * sin(rotate_) + v * cos(rotate_), + sqrt( + sprout::darkroom::coords::x(c) * sprout::darkroom::coords::x(c) + + sprout::darkroom::coords::z(c) * sprout::darkroom::coords::z(c) + ) + ); + } + template + SPROUT_CONSTEXPR position_type reference_width( + Unit2D const& x, + Unit2D const& y, + Unit2D const& width, + Unit2D const& height, + unit_type const& rate + ) const + { + return transform( + sprout::darkroom::coords::resize( + sprout::darkroom::coords::sub(fixation_point_, position_), + far_plane_ + ), + static_cast(x) / width - 0.5, + -((static_cast(y) / height - 0.5) * rate) + ); + } + template + SPROUT_CONSTEXPR position_type reference_height( + Unit2D const& x, + Unit2D const& y, + Unit2D const& width, + Unit2D const& height, + unit_type const& rate + ) const + { + return transform( + sprout::darkroom::coords::resize( + sprout::darkroom::coords::sub(fixation_point_, position_), + far_plane_ + ), + (static_cast(x) / width - 0.5) * rate, + -(static_cast(y) / height - 0.5) + ); + } public: SPROUT_CONSTEXPR explicit basic_simple_camera( - unit_type const& far_plane + unit_type const& far_plane, + angle_of_view_reference::values reference_value = angle_of_view_reference::long_side, + position_type const& position = position_type(0, 0, -1), + position_type const& fixation_point = position_type(0, 0, 0), + unit_type const& rotate = 0 ) : far_plane_(far_plane) + , reference_value_(reference_value) + , position_(position) + , fixation_point_(fixation_point) + , rotate_(rotate) {} - SPROUT_CONSTEXPR ray_type operator()(unit_type const& u, unit_type const& v) const { + template + SPROUT_CONSTEXPR ray_type operator()( + Unit2D const& x, + Unit2D const& y, + Unit2D const& width, + Unit2D const& height + ) const + { return ray_type( - position_type(0, 0, 0), - sprout::darkroom::coords::normalize(position_type(u, v, far_plane_)) + position_, + sprout::darkroom::coords::normalize( + (reference_value_ == angle_of_view_reference::long_side && width >= height) + || (reference_value_ == angle_of_view_reference::short_side && width < height) + || reference_value_ == angle_of_view_reference::width + ? reference_width(x, y, width, height, static_cast(height) / width) + : reference_height(x, y, width, height, static_cast(width) / height) + ) ); } }; @@ -34,8 +137,27 @@ namespace sprout { // template SPROUT_CONSTEXPR inline sprout::darkroom::cameras::basic_simple_camera - make_simple_camera(Unit const& far_plane) { - return sprout::darkroom::cameras::basic_simple_camera(far_plane); + make_simple_camera( + Unit const& far_plane, + typename sprout::darkroom::cameras::basic_simple_camera::angle_of_view_reference::values reference_value + = sprout::darkroom::cameras::basic_simple_camera::angle_of_view_reference::long_side + , + typename sprout::darkroom::cameras::basic_simple_camera::position_type const& position + = typename sprout::darkroom::cameras::basic_simple_camera::position_type(0, 0, -1) + , + typename sprout::darkroom::cameras::basic_simple_camera::position_type const& fixation_point + = typename sprout::darkroom::cameras::basic_simple_camera::position_type(0, 0, 0) + , + Unit const& rotate = 0 + ) + { + return sprout::darkroom::cameras::basic_simple_camera( + far_plane, + reference_value, + position, + fixation_point, + rotate + ); } } // namespace cameras } // namespace darkroom diff --git a/sprout/darkroom/coords/vector.hpp b/sprout/darkroom/coords/vector.hpp index c01b2484..6f78be28 100644 --- a/sprout/darkroom/coords/vector.hpp +++ b/sprout/darkroom/coords/vector.hpp @@ -114,6 +114,23 @@ namespace sprout { ; } // + // cross + // + template + SPROUT_CONSTEXPR inline Vector1 cross(Vector1 const& lhs, Vector2 const& rhs) { + return sprout::tuples::remake_clone( + lhs, + sprout::darkroom::coords::y(lhs) * sprout::darkroom::coords::z(rhs) + - sprout::darkroom::coords::z(lhs) * sprout::darkroom::coords::y(rhs) + , + sprout::darkroom::coords::y(lhs) * sprout::darkroom::coords::x(rhs) + - sprout::darkroom::coords::x(lhs) * sprout::darkroom::coords::y(rhs) + , + sprout::darkroom::coords::x(lhs) * sprout::darkroom::coords::y(rhs) + - sprout::darkroom::coords::y(lhs) * sprout::darkroom::coords::x(rhs) + ); + } + // // normalize // namespace detail { @@ -139,6 +156,16 @@ namespace sprout { ); } // + // resize + // + template + SPROUT_CONSTEXPR inline Vector resize(Vector const& lhs, Fac const& rhs) { + return sprout::darkroom::coords::detail::normalize_impl( + lhs, + sprout::darkroom::coords::length(lhs) / rhs + ); + } + // // reflect // template diff --git a/sprout/darkroom/tracers/raytracer.hpp b/sprout/darkroom/tracers/raytracer.hpp index 1d2bd21d..7b92036d 100644 --- a/sprout/darkroom/tracers/raytracer.hpp +++ b/sprout/darkroom/tracers/raytracer.hpp @@ -21,17 +21,17 @@ namespace sprout { typename Camera, typename Objects, typename Lights, - typename Unit + typename Unit2D > SPROUT_CONSTEXPR color_type operator()( Renderer const& renderer, Camera const& camera, Objects const& objs, Lights const& lights, - Unit const& x, - Unit const& y, - Unit const& width, - Unit const& height, + Unit2D const& x, + Unit2D const& y, + Unit2D const& width, + Unit2D const& height, std::size_t depth_max = 8 ) const { @@ -39,10 +39,7 @@ namespace sprout { camera, objs, lights, - camera.template operator()( - static_cast(x) / width - 0.5, - -(static_cast(y) / height - 0.5) - ), + camera.template operator()(x, y, width, height), depth_max ); }