// Copyright (c) 2016-2018 Kiwano - Nomango // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include namespace kiwano { namespace math { template struct InterpolateMethod; template <> struct InterpolateMethod { inline float operator()(float frac) const noexcept { return frac; } }; template <> struct InterpolateMethod { float (*method)(float); InterpolateMethod(float (*method)(float)) noexcept : method(method) { } inline float operator()(float frac) const noexcept { if (method) return method(frac); return frac; } }; template <> struct InterpolateMethod> { Function method; InterpolateMethod(const Function& method) noexcept : method(method) { } inline float operator()(float frac) const noexcept { if (method) return method(frac); return frac; } }; template class Interpolator; template class Interpolator { public: template inline _Ty Interpolate(_Ty start, _Ty end, float frac, const InterpolateMethod<_Method>& method = {}) { if (frac >= 1) return end; return start + static_cast<_Ty>(static_cast(end - start) * method(frac)); } }; template class Interpolator> { public: template inline Vec2T<_Ty> Interpolate(const Vec2T<_Ty>& start, const Vec2T<_Ty>& end, float frac, const InterpolateMethod<_Method>& method = {}) { if (frac >= 1) return end; Interpolator<_Ty> fi; return Vec2T<_Ty>{ fi.Interpolate(start.x, end.x, frac, method), fi.Interpolate(start.y, end.y, frac, method) }; } }; template class Interpolator> { public: template inline RectT<_Ty> Interpolate(const RectT<_Ty>& start, const RectT<_Ty>& end, float frac, const InterpolateMethod<_Method>& method = {}) { if (frac >= 1) return end; Interpolator> vi; return RectT<_Ty>{ vi.Interpolate(start.left_top, end.left_top, frac, method), vi.Interpolate(start.right_bottom, end.right_bottom, frac, method) }; } }; template class Interpolator> { public: template inline TransformT<_Ty> Interpolate(const TransformT<_Ty>& start, const TransformT<_Ty>& end, float frac, const InterpolateMethod<_Method>& method = {}) { if (frac >= 1) return end; Interpolator<_Ty> fi; Interpolator> vi; TransformT<_Ty> transform; transform.rotation = fi.Interpolate(start.rotation, end.rotation, frac, method); transform.position = vi.Interpolate(start.position, end.position, frac, method); transform.scale = vi.Interpolate(start.scale, end.scale, frac, method); transform.skew = vi.Interpolate(start.skew, end.skew, frac, method); return transform; } }; } // namespace math } // namespace kiwano