diff --git a/glm/gtx/angle.hpp b/glm/gtx/angle.hpp new file mode 100644 index 00000000..021bbaf5 --- /dev/null +++ b/glm/gtx/angle.hpp @@ -0,0 +1,377 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// 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. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// 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. +/// +/// @ref gtx_associated_min_max +/// @file glm/gtx/angle.hpp +/// @date 2015-05-10 +/// @author Miroslav Knejp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_angle GLM_GTX_angle +/// @ingroup gtx +/// +/// @brief Defines a dedicated type and operations for angles taking care of the radians/degrees issue and enforcing semantically sane usage. +/// +/// Applying these types consistently can prevent many problems related to +/// conversions between degrees and radians. Furthermore it only supports +/// operations which preserve the angle's dimension (under the assumption it is +/// not dimensionless) allowing the compiler to detect misuses in equations. By +/// not manually converting between degrees and radians everywhere in your +/// program you can even gain some extra speed efficiency. +/// +/// Where ever you deal with angles (regardless if class members or function +/// arguments) always use fangle/dangle and let it deal with the calculations +/// necessary for radians/degrees conversions. Never again use a plain `float` +/// in interfaces to represent angles or worry about these nuisances. +/// +/// The angle types should be no bigger than the datatype used for +/// representation (if they are complain to your compiler vendor), are +/// as efficient in copy and assignment operations as a native float or double, +/// and can be safely passed by-value without fear of performance problems. +/// +/// needs to be included to use this functionality. +/// +/// This extension also adds convenience overloads accepting angles instead of +/// plain floats to the following extensions for improved semantic checking: +/// - @ref gtc_matrix_transform +/// - @ref gtc_quaternion +/// - @ref gtx_fast_trigonometry +/// - @ref gtx_matrix_interpolation +/// - @ref gtx_matrix_transform_2d +/// - @ref gtx_rotate_normalized_axis +/// - @ref gtx_rotate_vector +/// - @ref gtx_transform +/// - @ref gtx_vector_angle +/// In order to use these overloads the respective extension header must be +/// included before otherwise calling them fails to compile. +/// This avoids making this extension implicitly dependent on those listed above. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_angle included") +#endif + +namespace glm +{ + /// @addtogroup gtx_angle + /// @{ + + template + class tangle; + + ////////////////////////////////////// + // Explicit converting factory functions + + /// Create an angle from radians + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle rad(T radians); + /// Create an angle from degrees + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle deg(T degrees); + + ////////////////////////////////////// + // Explicit converting value access + + /// Extract an angle's magnitude converted to radians + template + GLM_FUNC_DECL GLM_CONSTEXPR T rad(tangle angle); + /// Extract an angle's magnitude converted to degrees + template + GLM_FUNC_DECL GLM_CONSTEXPR T deg(tangle angle); + + ////////////////////////////////////// + // Generic angle class defintion + + template + class tangle + { + public: + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'angle' only accepts floating-point types"); + + typedef tangle type; + typedef T value_type; + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL GLM_CONSTEXPR tangle(); + GLM_FUNC_DECL GLM_CONSTEXPR tangle(tangle const & other); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle(tangle const & other); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL GLM_CONSTEXPR explicit tangle(ctor); + + ////////////////////////////////////// + // Assignment (compound) operators + + GLM_FUNC_DECL tvec4 & operator=(tangle const & rhs); + + template + GLM_FUNC_DECL tangle & operator=(tangle const & rhs); + template + GLM_FUNC_DECL tangle & operator+=(tangle const & rhs); + template + GLM_FUNC_DECL tangle & operator-=(tangle const & rhs); + template + GLM_FUNC_DECL tangle & operator*=(U rhs); + template + GLM_FUNC_DECL tangle & operator/=(U rhs); + + private: + friend GLM_CONSTEXPR tangle rad(T radians); + friend GLM_CONSTEXPR tangle deg(T degrees); + + friend GLM_CONSTEXPR T rad(tangle radians); + friend GLM_CONSTEXPR T deg(tangle degrees); + + GLM_FUNC_DECL GLM_CONSTEXPR tangle(T radians); + + T _radians; + }; + + typedef tangle fangle; // angle is already taken :( + typedef tangle dangle; + + ////////////////////////////////////// + // Unary arithmetic operators + + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator+(tangle angle); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator-(tangle angle); + + ////////////////////////////////////// + // Binary arithmetic operators + + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator+(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator-(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator*(tangle lhs, T rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator*(T lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR tangle operator/(tangle lhs, T rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR T operator/(tangle lhs, tangle rhs); + + ////////////////////////////////////// + // Comparison operators + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator<=(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator>=(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator<(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator>(tangle lhs, tangle rhs); + + ////////////////////////////////////// + // Common functions + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle abs(tangle arg); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle clamp(tangle x, tangle minVal, tangle maxVal); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle max(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle min(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle mix(tangle x, tangle y, U a); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle mix(tangle x, tangle y, bool a); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle mod(tangle lhs, tangle rhs); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T sign(tangle arg); + + ////////////////////////////////////// + // Special angle functions + + /// Normalize an angle's representation so lies within the interval [0; 2pi). + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle normalize(tangle arg); + /// Compute the shortest distance between two *normalized* angles, which is always in the range [-pi; +pi]. + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle distance(tangle from, tangle to); + + ////////////////////////////////////// + // Trigonometric functions + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T cos(tangle arg); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T sin(tangle arg); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T tan(tangle arg); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle atan2(T y, T x); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle atan2(tvec2 const & v); + // TODO: These conflict with existing GLM functions :( +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle acos(T arg); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle asin(T arg); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle atan(T arg); + + ////////////////////////////////////// + // GLM_GTC_matrix_transform + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 infinitePerspective(tangle fovy, T aspect, T near); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 perspective(tangle fovy, T aspect, T near, T far); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 perspectiveFov(tangle fov, T width, T height, T near, T far); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 rotate(tmat4x4 const & m, tangle angle, tvec3 const & axis); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 tweakedInfinitePerspective(tangle fovy, T aspect, T near); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 tweakedInfinitePerspective(tangle fovy, T aspect, T near, T ep); + + ////////////////////////////////////// + // GLM_GTC_quaternion + + template + struct tquat; + + // TODO: Some conflict with existing GTC functions :( +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle angle(tquat const & q); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tquat angleAxis(tangle angle, tvec3 const & axis); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle pitch(tquat const & q); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tquat rotate(tquat< T, P > const & q, tangle angle, tvec3 const & axis); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle roll(tquat const & q); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle yaw(tquat const & q); + + ////////////////////////////////////// + // GLM_GTX_fast_trigonometry + + // TODO: Some conflict with existing GTX functions :( +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle fastAcos(T x); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle fastAsin(T x); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle fastAtan(T y, T x); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle fastAtan(T x); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T fastCos(tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T fastSin(tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ T fastTan(tangle angle); + + ////////////////////////////////////// + // GLM_GTX_matrix_interpolation + + template + GLM_FUNC_DECL void axisAngle(tmat4x4 const & mat, tvec3 & axis, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 axisAngleMatrix(tvec3 const & axis, tangle angle); + + ////////////////////////////////////// + // GLM_GTX_matrix_transform_2d + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat3x3 rotate(tmat3x3 const & m, tangle angle); + + ////////////////////////////////////// + // GLM_GTX_rotate_normalized_axis + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4 rotateNormalizedAxis(tmat4x4 const & m, tangle angle, tvec3 const & axis); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tquat rotateNormalizedAxis(tquat const & q, tangle angle, tvec3 const & axis); + + ////////////////////////////////////// + // GLM_GTX_rotate_vector + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec2 rotate(tvec2 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec3 rotate(tvec3 const & v, tangle angle, tvec3 const & normal); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec4 rotate(tvec4 const & v, tangle angle, tvec3 const & normal); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec3 rotateX(tvec3 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec4 rotateX(tvec4 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec3 rotateY(tvec3 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec4 rotateY(tvec4 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec3 rotateZ(tvec3 const & v, tangle angle); + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tvec4 rotateZ(tvec4 const & v, tangle angle); + + ////////////////////////////////////// + // GLM_GTX_transform + + template + GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tmat4x4< T, P > rotate(tangle angle, tvec3< T, P > const & v); + + ////////////////////////////////////// + // GLM_GTX_vector_angle + + // TODO: These conflict with existing GTX functions :( +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle angle(vecType const & x, vecType const & y); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle orientedAngle(tvec2 const & x, tvec2 const & y); +// template +// GLM_FUNC_DECL /*GLM_CONSTEXPR*/ tangle orientedAngle(tvec3 const & x, tvec3 const & y, tvec3 const &ref); + + /// @} +} // namespace glm + +#include "angle.inl" diff --git a/glm/gtx/angle.inl b/glm/gtx/angle.inl new file mode 100644 index 00000000..51bae601 --- /dev/null +++ b/glm/gtx/angle.inl @@ -0,0 +1,583 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// 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. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// 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. +/// +/// @ref gtx_angle +/// @file glm/gtx/angle.inl +/// @date 2015-05-10 +/// @author Miroslav Knejp +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////// + // Implicit basic constructors + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle::tangle() +# ifndef GLM_FORCE_NO_CTOR_INIT + : _radians(0) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle::tangle(tangle const & other) + : _radians(other._radians) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle::tangle(tangle const & other) + : _radians(other._radians) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle::tangle(ctor) + {} + + ////////////////////////////////////// + // Assignment (compound) operators + + template + GLM_FUNC_QUALIFIER tvec4 & tangle::operator=(tangle const & rhs) + { + this->_radians = rhs._radians; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tangle & tangle::operator=(tangle const & rhs) + { + this->_radians = static_cast(rhs._radians); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tangle & tangle::operator+=(tangle const & rhs) + { + this->_radians += static_cast(rhs._radians); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tangle & tangle::operator-=(tangle const & rhs) + { + this->_radians -= static_cast(rhs._radians); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tangle & tangle::operator*=(U rhs) + { + this->_radians *= static_cast(rhs); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tangle & tangle::operator/=(U rhs) + { + this->_radians /= static_cast(rhs); + return *this; + } + + ////////////////////////////////////// + // Explicit converting factory functions + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle::tangle(T radians) + : _radians(radians) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle rad(T radians) + { + return tangle(radians); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle deg(T degrees) + { + // glm::radians is not constexpr + return tangle(degrees * static_cast(0.01745329251994329576923690768489)); + } + + ////////////////////////////////////// + // Explicit converting value access + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T rad(tangle angle) + { + return angle._radians; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T deg(tangle angle) + { + // glm::degrees is not constexpr + return angle._radians * static_cast(57.295779513082320876798154814105); + } + + ////////////////////////////////////// + // Unary arithmetic operators + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator+(tangle angle) + { + return angle; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator-(tangle angle) + { + return rad(-rad(angle)); + } + + ////////////////////////////////////// + // Binary arithmetic operators + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator+(tangle lhs, tangle rhs) + { + return rad(rad(lhs) + rad(rhs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator-(tangle lhs, tangle rhs) + { + return rad(rad(lhs) - rad(rhs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator*(tangle lhs, T rhs) + { + return rad(rad(lhs) * rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator*(T lhs, tangle rhs) + { + return rad(lhs * rad(rhs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tangle operator/(tangle lhs, T rhs) + { + return rad(rad(lhs) / rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T operator/(tangle lhs, tangle rhs) + { + return rad(lhs) / rad(rhs); + } + + ////////////////////////////////////// + // Comparison operators + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(tangle lhs, tangle rhs) + { + return rad(lhs) == rad(rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(tangle lhs, tangle rhs) + { + return rad(lhs) != rad(rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator<=(tangle lhs, tangle rhs) + { + return rad(lhs) <= rad(rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator>=(tangle lhs, tangle rhs) + { + return rad(lhs) >= rad(rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator<(tangle lhs, tangle rhs) + { + return rad(lhs) < rad(rhs); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator>(tangle lhs, tangle rhs) + { + return rad(lhs) > rad(rhs); + } + + ////////////////////////////////////// + // Common functions + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle abs(tangle arg) + { + return rad(abs(rad(arg))); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle clamp(tangle x, tangle minVal, tangle maxVal) + { + return rad(clamp(rad(x), rad(minVal), rad(maxVal))); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle max(tangle lhs, tangle rhs) + { + return rad(max(rad(lhs), rad(rhs))); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle min(tangle lhs, tangle rhs) + { + return rad(min(rad(lhs), rad(rhs))); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle mix(tangle x, tangle y, U a) + { + return rad(mix(rad(x), rad(y), a)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle mix(tangle x, tangle y, bool a) + { + return a ? y : x; + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle mod(tangle lhs, tangle rhs) + { + return rad(mod(rad(lhs), rad(rhs))); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T sign(tangle arg) + { + return sign(rad(arg)); + } + + ////////////////////////////////////// + // Special angle functions + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle normalize(tangle arg) + { + tangle x = mod(arg, deg(static_cast(360))); + return x < deg(static_cast(0)) ? x + deg(static_cast(360)) : x; + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle distance(tangle from, tangle to) + { + if(abs(to - from) > deg(static_cast(180))) + { + return (from > to ? to + deg(static_cast(360)) : to - deg(static_cast(360))) - from; + } + else + { + return to - from; + } + } + + ////////////////////////////////////// + // Trigonometric functions + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T cos(tangle arg) + { + return std::cos(rad(arg)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T sin(tangle arg) + { + return std::sin(rad(arg)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T tan(tangle arg) + { + return std::tan(rad(arg)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle atan2(T y, T x) + { + return rad(std::atan2(y, x)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle atan2(tvec2 const & v) + { + return rad(std::atan2(v.y, v.x)); + } + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle acos(T arg) +// { +// return rad(std::acos(arg)); +// } +// +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle asin(T arg) +// { +// return rad(std::asin(arg)); +// } +// +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle atan(T arg) +// { +// return rad(std::atan(arg)); +// } + + ////////////////////////////////////// + // GLM_GTC_matrix_transform + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 infinitePerspective(tangle fovy, T aspect, T near) + { + return infinitePerspective(rad(fovy), aspect, near); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 perspective(tangle fovy, T aspect, T near, T far) + { + return perspective(rad(fovy), aspect, near, far); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 perspectiveFov(tangle fov, T width, T height, T near, T far) + { + return prespectiveFov(rad(fov), width, height, near, far); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 rotate(tmat4x4 const & m, tangle angle, tvec3 const & axis) + { + return rotate(m, rad(angle), axis); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 tweakedInfinitePerspective(tangle fovy, T aspect, T near) + { + return tweakedInfinitePerspective(rad(fovy), aspect, near); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 tweakedInfinitePerspective(tangle fovy, T aspect, T near, T ep) + { + return tweakedInfinitePerspective(rad(fovy), aspect, near, ep); + } + + ////////////////////////////////////// + // GLM_GTC_quaternion + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle angle(tquat const & q); + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tquat angleAxis(tangle angle, tvec3 const & axis) + { + return angleAxis(rad(angle), axis); + } + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle pitch(tquat const & q); + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tquat rotate(tquat< T, P > const & q, tangle angle, tvec3 const & axis) + { + return rotate(q, rad(angle), axis); + } + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle roll(tquat const & q); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle yaw(tquat const & q); + + ////////////////////////////////////// + // GLM_GTX_fast_trigonometry + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle fastAcos(T x); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle fastAsin(T x); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle fastAtan(T y, T x); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle fastAtan(T x); + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T fastCos(tangle angle) + { + return fastCos(rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T fastSin(tangle angle) + { + return fastSin(rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ T fastTan(tangle angle) + { + return fastTan(rad(angle)); + } + + ////////////////////////////////////// + // GLM_GTX_matrix_interpolation + + template + GLM_FUNC_QUALIFIER void axisAngle(tmat4x4 const & mat, tvec3 & axis, tangle angle) + { + return axisAngle(mat, axis, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 axisAngleMatrix(tvec3 const & axis, tangle angle) + { + return axisAngleMatrix(axis, rad(angle)); + } + + ////////////////////////////////////// + // GLM_GTX_matrix_transform_2d + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat3x3 rotate(tmat3x3 const & m, tangle angle) + { + return rotate(m, rad(angle)); + } + + ////////////////////////////////////// + // GLM_GTX_rotate_normalized_axis + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4 rotateNormalizedAxis(tmat4x4 const & m, tangle angle, tvec3 const & axis) + { + return rotateNormalizedAxis(m, rad(angle), axis); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tquat rotateNormalizedAxis(tquat const & q, tangle angle, tvec3 const & axis) + { + return rotateNormalizedAxis(q, rad(angle), axis); + } + + ////////////////////////////////////// + // GLM_GTX_rotate_vector + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec2 rotate(tvec2 const & v, tangle angle) + { + return rotate(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec3 rotate(tvec3 const & v, tangle angle, tvec3 const & normal) + { + return rotate(v, rad(angle), normal); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec4 rotate(tvec4 const & v, tangle angle, tvec3 const & normal) + { + return rotate(v, rad(angle), normal); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec3 rotateX(tvec3 const & v, tangle angle) + { + return rotateX(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec4 rotateX(tvec4 const & v, tangle angle) + { + return rotateX(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec3 rotateY(tvec3 const & v, tangle angle) + { + return rotateY(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec4 rotateY(tvec4 const & v, tangle angle) + { + return rotateY(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec3 rotateZ(tvec3 const & v, tangle angle) + { + return rotateZ(v, rad(angle)); + } + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tvec4 rotateZ(tvec4 const & v, tangle angle) + { + return rotateZ(v, rad(angle)); + } + + ////////////////////////////////////// + // GLM_GTX_transform + + template + GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tmat4x4< T, P > rotate(tangle angle, tvec3< T, P > const & v) + { + return rotate(rad(angle), v); + } + + ////////////////////////////////////// + // GLM_GTX_vector_angle + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle angle(vecType const & x, vecType const & y); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle orientedAngle(tvec2 const & x, tvec2 const & y); + +// template +// GLM_FUNC_QUALIFIER /*GLM_CONSTEXPR*/ tangle orientedAngle(tvec3 const & x, tvec3 const & y, tvec3 const &ref); +} diff --git a/test/gtx/CMakeLists.txt b/test/gtx/CMakeLists.txt index 4be4343f..1e53ccd7 100644 --- a/test/gtx/CMakeLists.txt +++ b/test/gtx/CMakeLists.txt @@ -1,3 +1,4 @@ +glmCreateTestGTC(gtx_angle) glmCreateTestGTC(gtx_associated_min_max) glmCreateTestGTC(gtx_closest_point) glmCreateTestGTC(gtx_color_space_YCoCg) diff --git a/test/gtx/gtx_angle.cpp b/test/gtx/gtx_angle.cpp new file mode 100644 index 00000000..602306f5 --- /dev/null +++ b/test/gtx/gtx_angle.cpp @@ -0,0 +1,328 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// 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. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// 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. +/// +/// @file test/gtx/gtx_angle.cpp +/// @date 2015-05-10 +/// @author Miroslav Knejp +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +namespace +{ + const float pi = glm::pi(); + + int test_factory() + { + int Error(0); + + { + glm::fangle a = glm::rad(0.f); + Error += glm::epsilonEqual(rad(a), 0.f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), 0.f, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(0.f); + Error += glm::epsilonEqual(rad(a), 0.f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), 0.f, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(pi); + Error += glm::epsilonEqual(rad(a), pi, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), 180.f, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(180.f); + Error += glm::epsilonEqual(rad(a), pi, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), 180.f, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(-pi / 2); + Error += glm::epsilonEqual(rad(a), -pi / 2, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), -90.f, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(-90.f); + Error += glm::epsilonEqual(rad(a), -pi / 2, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(deg(a), -90.f, 0.01f) ? 0 : 1; + } + return Error; + } + + int test_arithmetic() + { + int Error(0); + float x = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + float y = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(y); + Error += glm::epsilonEqual(x + y, rad(a + b), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(x - y, rad(a - b), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + Error += glm::epsilonEqual(y * x, rad(y * a), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(x * y, rad(a * y), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + Error += glm::epsilonEqual(x / y, rad(a / y), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(y); + Error += glm::epsilonEqual(x / y, a / b, 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + Error += glm::epsilonEqual(+x, rad(+a), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + Error += glm::epsilonEqual(-x, rad(-a), 0.01f) ? 0 : 1; + } + + return Error; + } + + int test_comparison() + { + int Error(0); + float x = -static_cast(std::max(std::rand(), 1)) / RAND_MAX; + float y = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + + Error += glm::rad(x) == glm::rad(x) ? 0 : 1; + Error += glm::rad(x) == glm::rad(y) ? 1 : 0; + Error += glm::rad(x) != glm::rad(x) ? 1 : 0; + Error += glm::rad(x) != glm::rad(y) ? 0 : 1; + + Error += glm::rad(x) < glm::rad(x) ? 1 : 0; + Error += glm::rad(x) < glm::rad(y) ? 0 : 1; + + Error += glm::rad(x) > glm::rad(x) ? 1 : 0; + Error += glm::rad(y) > glm::rad(x) ? 0 : 1; + + Error += glm::rad(x) <= glm::rad(x) ? 0 : 1; + Error += glm::rad(x) <= glm::rad(y) ? 0 : 1; + + Error += glm::rad(x) >= glm::rad(x) ? 0 : 1; + Error += glm::rad(y) >= glm::rad(x) ? 0 : 1; + return Error; + } + + int test_constexpr() + { + int Error(0); + +# if GLM_HAS_CONSTEXPR + static_assert(std::is_literal_type::value, ""); + static_assert(std::is_literal_type::value, ""); + + constexpr auto a = glm::deg(1.f); + constexpr auto b = glm::rad(2.f); + constexpr auto f = 3.f; + + // Force compile-time evaluation + static_assert((rad(a), true), ""); + static_assert((deg(a), true), ""); + + static_assert((+a, true), ""); + static_assert((-a, true), ""); + + static_assert((a + b, true), ""); + static_assert((a - b, true), ""); + static_assert((a * f, true), ""); + static_assert((f * b, true), ""); + static_assert((a / f, true), ""); + static_assert((a / b, true), ""); + + static_assert((a == b) || true, ""); + static_assert((a != b) || true, ""); + static_assert((a <= b) || true, ""); + static_assert((a >= b) || true, ""); + static_assert((a < b) || true, ""); + static_assert((a > b) || true, ""); +# endif + + return Error; + } + + int test_common() + { + int Error(0); + + float x = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + float y = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + float f = static_cast(std::max(std::rand(), 1)) / RAND_MAX; + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(-x); + Error += glm::epsilonEqual(x, rad(abs(b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(rad(a), rad(abs(b)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(100.f); + glm::fangle b = glm::rad(200.f); + glm::fangle c = a - glm::rad(x); + glm::fangle d = b + glm::rad(y); + glm::fangle e = glm::rad(150.f); + Error += clamp(c, a, b) <= b ? 0 : 1; + Error += clamp(c, a, b) >= a ? 0 : 1; + Error += clamp(d, a, b) <= b ? 0 : 1; + Error += clamp(d, a, b) >= a ? 0 : 1; + Error += glm::epsilonEqual(rad(clamp(e, a, b)), rad(e), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(y); + Error += glm::epsilonEqual(std::max(x, y), rad(max(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(std::min(x, y), rad(min(a, b)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(y); + Error += glm::epsilonEqual(glm::mix(x, y, f), rad(mix(a, b, f)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(x, rad(mix(a, b, false)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(y, rad(mix(a, b, true)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(x); + glm::fangle b = glm::rad(y); + Error += glm::epsilonEqual(glm::mod(x, y), rad(mod(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(glm::mod(y, x), rad(mod(b, a)), 0.01f) ? 0 : 1; + } + { + Error += glm::epsilonEqual(1.f, sign(glm::rad(10.f)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(0.f, sign(glm::rad(0.f)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(-1.f, sign(glm::rad(-10.f)), 0.01f) ? 0 : 1; + + Error += glm::epsilonEqual(1.f, sign(glm::deg(10.f)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(0.f, sign(glm::deg(0.f)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(-1.f, sign(glm::deg(-10.f)), 0.01f) ? 0 : 1; + } + return Error; + } + + int test_special() + { + int Error(0); + + { + glm::fangle a = glm::rad(5 * pi); + Error += glm::epsilonEqual(pi, rad(normalize(a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(2 * pi); + Error += glm::epsilonEqual(0.f, rad(normalize(a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(-pi / 2); + Error += glm::epsilonEqual(1.5f * pi, rad(normalize(a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(-pi * 2); + Error += glm::epsilonEqual(0.f, rad(normalize(a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::rad(5 * -pi); + Error += glm::epsilonEqual(pi, rad(normalize(a)), 0.01f) ? 0 : 1; + } + + { + glm::fangle a = glm::deg(0.f); + glm::fangle b = glm::deg(90.f); + Error += glm::epsilonEqual(90.f, deg(distance(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(-90.f, deg(distance(b, a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(0.f); + glm::fangle b = glm::deg(180.f); + Error += glm::epsilonEqual(180.f, deg(distance(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(-180.f, deg(distance(b, a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(0.f); + glm::fangle b = glm::deg(270.f); + Error += glm::epsilonEqual(-90.f, deg(distance(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(90.f, deg(distance(b, a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(0.f); + glm::fangle b = glm::deg(360.f); + Error += glm::epsilonEqual(0.f, deg(distance(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(0.f, deg(distance(b, a)), 0.01f) ? 0 : 1; + } + { + glm::fangle a = glm::deg(10.f); + glm::fangle b = glm::deg(350.f); + Error += glm::epsilonEqual(-20.f, deg(distance(a, b)), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(20.f, deg(distance(b, a)), 0.01f) ? 0 : 1; + } + + return Error; + } + + int test_trigonometric() + { + int Error(0); + + float x = static_cast(std::rand()); + float y = static_cast(std::rand()); + + { + glm::fangle a = glm::rad(x); + Error += glm::epsilonEqual(std::cos(x), cos(a), 0.0001f) ? 0 : 1; + Error += glm::epsilonEqual(std::sin(x), sin(a), 0.0001f) ? 0 : 1; + Error += glm::epsilonEqual(std::tan(x), tan(a), 0.0001f) ? 0 : 1; + } + Error += glm::epsilonEqual(std::atan2(y, x), rad(glm::atan2(y, x)), 0.0001f) ? 0 : 1; + Error += glm::epsilonEqual(std::atan2(y, x), rad(glm::atan2(glm::vec2(x, y))), 0.0001f) ? 0 : 1; + + return Error; + } +} + +int main() +{ + int Error(0); + std::srand(std::time(NULL)); + + Error += test_factory(); + Error += test_comparison(); + Error += test_arithmetic(); + Error += test_constexpr(); + Error += test_common(); + Error += test_special(); + Error += test_trigonometric(); + + return Error; +}