From 841f91e83054740702b21f79ef1b3fe3a67bde01 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Thu, 13 Dec 2012 22:48:20 +0100 Subject: [PATCH] Fixed bug #15, added missing roll, pitch and yaw functions; Fixed half implicit conversions --- glm/core/func_exponential.inl | 8 +- glm/core/func_trigonometric.inl | 20 ++-- glm/core/type_half.hpp | 5 +- glm/core/type_half.inl | 8 +- glm/gtc/quaternion.hpp | 21 ++++ glm/gtc/quaternion.inl | 41 +++++++- glm/gtx/quaternion.hpp | 32 +----- glm/gtx/quaternion.inl | 39 -------- test/gtc/gtc_constants.cpp | 21 +++- test/gtc/gtc_quaternion.cpp | 168 +++++++++++++++++++------------- test/gtx/gtx_quaternion.cpp | 52 +++++++--- 11 files changed, 244 insertions(+), 171 deletions(-) diff --git a/glm/core/func_exponential.inl b/glm/core/func_exponential.inl index 8bbf87a3..6ae709c6 100644 --- a/glm/core/func_exponential.inl +++ b/glm/core/func_exponential.inl @@ -38,7 +38,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'pow' only accept floating-point input"); - return ::std::pow(x, y); + return genType(::std::pow(x, y)); } VECTORIZE_VEC_VEC(pow) @@ -52,7 +52,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'exp' only accept floating-point input"); - return ::std::exp(x); + return genType(::std::exp(x)); } VECTORIZE_VEC(exp) @@ -66,7 +66,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'log' only accept floating-point input"); - return ::std::log(x); + return genType(::std::log(x)); } VECTORIZE_VEC(log) @@ -80,7 +80,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'exp2' only accept floating-point input"); - return ::std::exp(genType(0.69314718055994530941723212145818) * x); + return genType(::std::exp(genType(0.69314718055994530941723212145818) * x)); } VECTORIZE_VEC(exp2) diff --git a/glm/core/func_trigonometric.inl b/glm/core/func_trigonometric.inl index 0b3e7306..240cdafc 100644 --- a/glm/core/func_trigonometric.inl +++ b/glm/core/func_trigonometric.inl @@ -67,7 +67,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'sin' only accept floating-point input"); - return ::std::sin(angle); + return genType(::std::sin(angle)); } VECTORIZE_VEC(sin) @@ -78,7 +78,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'cos' only accept floating-point input"); - return ::std::cos(angle); + return genType(::std::cos(angle)); } VECTORIZE_VEC(cos) @@ -92,7 +92,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'tan' only accept floating-point input"); - return ::std::tan(angle); + return genType(::std::tan(angle)); } VECTORIZE_VEC(tan) @@ -106,7 +106,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'asin' only accept floating-point input"); - return ::std::asin(x); + return genType(::std::asin(x)); } VECTORIZE_VEC(asin) @@ -120,7 +120,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'acos' only accept floating-point input"); - return ::std::acos(x); + return genType(::std::acos(x)); } VECTORIZE_VEC(acos) @@ -135,7 +135,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'atan' only accept floating-point input"); - return ::std::atan2(y, x); + return genType(::std::atan2(y, x)); } VECTORIZE_VEC_VEC(atan) @@ -148,7 +148,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'atan' only accept floating-point input"); - return ::std::atan(x); + return genType(::std::atan(x)); } VECTORIZE_VEC(atan) @@ -162,7 +162,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'sinh' only accept floating-point input"); - return std::sinh(angle); + return genType(std::sinh(angle)); } VECTORIZE_VEC(sinh) @@ -176,7 +176,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'cosh' only accept floating-point input"); - return std::cosh(angle); + return genType(std::cosh(angle)); } VECTORIZE_VEC(cosh) @@ -190,7 +190,7 @@ namespace glm { GLM_STATIC_ASSERT(detail::type::is_float, "'tanh' only accept floating-point input"); - return std::tanh(angle); + return genType(std::tanh(angle)); } VECTORIZE_VEC(tanh) diff --git a/glm/core/type_half.hpp b/glm/core/type_half.hpp index 60a242b3..015c701a 100644 --- a/glm/core/type_half.hpp +++ b/glm/core/type_half.hpp @@ -50,8 +50,9 @@ namespace detail GLM_FUNC_DECL explicit half(U const & s); // Cast - template - GLM_FUNC_DECL operator U() const; + //template + //GLM_FUNC_DECL operator U() const; + GLM_FUNC_DECL operator float() const; // Unary updatable operators GLM_FUNC_DECL half& operator= (half const & s); diff --git a/glm/core/type_half.inl b/glm/core/type_half.inl index cda7f79a..ad54c566 100644 --- a/glm/core/type_half.inl +++ b/glm/core/type_half.inl @@ -266,12 +266,18 @@ namespace detail GLM_FUNC_QUALIFIER half::half(U const & s) : data(toFloat16(float(s))) {} - +/* template GLM_FUNC_QUALIFIER half::operator U() const { return static_cast(toFloat32(this->data)); } +*/ + + GLM_FUNC_QUALIFIER half::operator float() const + { + return toFloat32(this->data); + } // Unary updatable operators GLM_FUNC_QUALIFIER half& half::operator= (half const & s) diff --git a/glm/gtc/quaternion.hpp b/glm/gtc/quaternion.hpp index c5ee4236..44acbebc 100644 --- a/glm/gtc/quaternion.hpp +++ b/glm/gtc/quaternion.hpp @@ -212,6 +212,27 @@ namespace detail detail::tvec3 eulerAngles( detail::tquat const & x); + /// Returns roll value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. + /// + /// @see gtx_quaternion + template + valType roll( + detail::tquat const & x); + + /// Returns pitch value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. + /// + /// @see gtx_quaternion + template + valType pitch( + detail::tquat const & x); + + /// Returns yaw value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. + /// + /// @see gtx_quaternion + template + valType yaw( + detail::tquat const & x); + /// Converts a quaternion to a 3 * 3 matrix. /// /// @see gtc_quaternion diff --git a/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl index 6298ae3a..100c26f3 100644 --- a/glm/gtc/quaternion.inl +++ b/glm/gtc/quaternion.inl @@ -512,7 +512,46 @@ namespace detail { return detail::tvec3(pitch(x), yaw(x), roll(x)); } - + + template + GLM_FUNC_QUALIFIER valType roll + ( + detail::tquat const & q + ) + { +#ifdef GLM_FORCE_RADIANS + return valType(atan2(valType(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); +#else + return glm::degrees(atan(valType(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); +#endif + } + + template + GLM_FUNC_QUALIFIER valType pitch + ( + detail::tquat const & q + ) + { +#ifdef GLM_FORCE_RADIANS + return valType(atan2(valType(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); +#else + return glm::degrees(atan(valType(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); +#endif + } + + template + GLM_FUNC_QUALIFIER valType yaw + ( + detail::tquat const & q + ) + { +#ifdef GLM_FORCE_RADIANS + return asin(valType(-2) * (q.x * q.z - q.w * q.y)); +#else + return glm::degrees(asin(valType(-2) * (q.x * q.z - q.w * q.y))); +#endif + } + template GLM_FUNC_QUALIFIER detail::tmat3x3 mat3_cast ( diff --git a/glm/gtx/quaternion.hpp b/glm/gtx/quaternion.hpp index d41b580d..98949389 100644 --- a/glm/gtx/quaternion.hpp +++ b/glm/gtx/quaternion.hpp @@ -127,7 +127,7 @@ namespace glm detail::tquat const & q, detail::tvec3 const & v); - /// Rotates a 4 components vector by a quaternion. + /// Rotates a 4 components vector by a quaternion. /// /// @see gtx_quaternion template @@ -142,38 +142,10 @@ namespace glm valType extractRealComponent( detail::tquat const & q); - /// Returns roll value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. - /// - /// @see gtx_quaternion - template - valType roll( - detail::tquat const & x); - - /// Returns pitch value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. - /// - /// @see gtx_quaternion - template - valType pitch( - detail::tquat const & x); - - /// Returns yaw value of euler angles expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. - /// - /// @see gtx_quaternion - template - valType yaw( - detail::tquat const & x); - - /// Returns euler angles, yitch as x, yaw as y, roll as z. - /// - /// @see gtx_quaternion - template - detail::tvec3 eulerAngles( - detail::tquat const & x); - /// Converts a quaternion to a 3 * 3 matrix. /// /// @see gtx_quaternion - template + template detail::tmat3x3 toMat3( detail::tquat const & x){return mat3_cast(x);} diff --git a/glm/gtx/quaternion.inl b/glm/gtx/quaternion.inl index bf95f80f..66b3420a 100644 --- a/glm/gtx/quaternion.inl +++ b/glm/gtx/quaternion.inl @@ -154,45 +154,6 @@ namespace glm return -sqrt(w); } - template - GLM_FUNC_QUALIFIER valType roll - ( - detail::tquat const & q - ) - { -#ifdef GLM_FORCE_RADIANS - return atan2(valType(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z); -#else - return glm::degrees(atan2(valType(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); -#endif - } - - template - GLM_FUNC_QUALIFIER valType pitch - ( - detail::tquat const & q - ) - { -#ifdef GLM_FORCE_RADIANS - return atan2(valType(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z); -#else - return glm::degrees(atan2(valType(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); -#endif - } - - template - GLM_FUNC_QUALIFIER valType yaw - ( - detail::tquat const & q - ) - { -#ifdef GLM_FORCE_RADIANS - return asin(valType(-2) * (q.x * q.z - q.w * q.y)); -#else - return glm::degrees(asin(valType(-2) * (q.x * q.z - q.w * q.y))); -#endif - } - template GLM_FUNC_QUALIFIER detail::tquat shortMix ( diff --git a/test/gtc/gtc_constants.cpp b/test/gtc/gtc_constants.cpp index 37ee8258..53f5e08e 100644 --- a/test/gtc/gtc_constants.cpp +++ b/test/gtc/gtc_constants.cpp @@ -2,7 +2,7 @@ // OpenGL Mathematics Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) /////////////////////////////////////////////////////////////////////////////////////////////////// // Created : 2012-09-19 -// Updated : 2012-09-19 +// Updated : 2012-12-13 // Licence : This source is under MIT licence // File : test/gtc/constants.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -10,6 +10,25 @@ #include #include +int test_epsilon() +{ + int Error(0); + + { + glm::half Test = glm::epsilon(); + } + + { + float Test = glm::epsilon(); + } + + { + double Test = glm::epsilon(); + } + + return Error; +} + int main() { int Error(0); diff --git a/test/gtc/gtc_quaternion.cpp b/test/gtc/gtc_quaternion.cpp index 4202a8b2..1de749b9 100644 --- a/test/gtc/gtc_quaternion.cpp +++ b/test/gtc/gtc_quaternion.cpp @@ -13,34 +13,34 @@ int test_quat_angle() { - int Error = 0; - - { - glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; - float A = glm::angle(N); - Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; - } - { - glm::quat Q = glm::angleAxis(45.0f, glm::normalize(glm::vec3(0, 1, 1))); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; - float A = glm::angle(N); - Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; - } - { - glm::quat Q = glm::angleAxis(45.0f, glm::normalize(glm::vec3(1, 2, 3))); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; - float A = glm::angle(N); - Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; - } - - return Error; + int Error = 0; + + { + glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(45.0f, glm::normalize(glm::vec3(0, 1, 1))); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(45.0f, glm::normalize(glm::vec3(1, 2, 3))); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::epsilonEqual(A, 45.0f, 0.01f) ? 0 : 1; + } + + return Error; } int test_quat_angleAxis() @@ -49,10 +49,10 @@ int test_quat_angleAxis() glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); glm::quat B = glm::angleAxis(90.0f, glm::vec3(0, 0, 1)); - glm::quat C = glm::mix(A, B, 0.5f); - glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + glm::quat C = glm::mix(A, B, 0.5f); + glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; @@ -63,17 +63,17 @@ int test_quat_angleAxis() int test_quat_mix() { int Error = 0; - + glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); glm::quat B = glm::angleAxis(90.0f, glm::vec3(0, 0, 1)); - glm::quat C = glm::mix(A, B, 0.5f); - glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - - Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + glm::quat C = glm::mix(A, B, 0.5f); + glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; - + return Error; } @@ -83,54 +83,86 @@ int test_quat_precision() Error += sizeof(glm::lowp_quat) <= sizeof(glm::mediump_quat) ? 0 : 1; Error += sizeof(glm::mediump_quat) <= sizeof(glm::highp_quat) ? 0 : 1; - - return Error; + + return Error; } int test_quat_normalize() { - int Error = 0; - - { - glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; - } - { - glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 2)); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; - } - { - glm::quat Q = glm::angleAxis(45.0f, glm::vec3(1, 2, 3)); - glm::quat N = glm::normalize(Q); - float L = glm::length(N); - Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; - } + int Error(0); - return Error; + { + glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(45.0f, glm::vec3(0, 0, 2)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(45.0f, glm::vec3(1, 2, 3)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::epsilonEqual(L, 1.0f, 0.000001f) ? 0 : 1; + } + + return Error; +} + +int test_quat_euler() +{ + int Error(0); + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float Roll = glm::roll(q); + float Pitch = glm::pitch(q); + float Yaw = glm::yaw(q); + glm::vec3 Angles = glm::eulerAngles(q); + } + + { + glm::dquat q(1.0f, 0.0f, 0.0f, 1.0f); + double Roll = glm::roll(q); + double Pitch = glm::pitch(q); + double Yaw = glm::yaw(q); + glm::dvec3 Angles = glm::eulerAngles(q); + } + + { + glm::hquat q(glm::half(1.0f), glm::half(0.0f), glm::half(0.0f), glm::half(1.0f)); + glm::half Roll = glm::roll(q); + glm::half Pitch = glm::pitch(q); + glm::half Yaw = glm::yaw(q); + glm::hvec3 Angles = glm::eulerAngles(q); + } + + return Error; } int test_quat_type() { - glm::quat A; - glm::dquat B; - - return 0; + glm::quat A; + glm::dquat B; + + return 0; } int main() { - int Error = 0; - + int Error(0); + Error += test_quat_precision(); - Error += test_quat_type(); - Error += test_quat_angle(); + Error += test_quat_type(); + Error += test_quat_angle(); Error += test_quat_angleAxis(); Error += test_quat_mix(); Error += test_quat_normalize(); + Error += test_quat_euler(); return Error; } diff --git a/test/gtx/gtx_quaternion.cpp b/test/gtx/gtx_quaternion.cpp index f4ae8070..2bb3b65f 100644 --- a/test/gtx/gtx_quaternion.cpp +++ b/test/gtx/gtx_quaternion.cpp @@ -14,43 +14,65 @@ int test_quat_fastMix() { int Error = 0; - + glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); glm::quat B = glm::angleAxis(90.0f, glm::vec3(0, 0, 1)); - glm::quat C = glm::fastMix(A, B, 0.5f); - glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - - Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + glm::quat C = glm::fastMix(A, B, 0.5f); + glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; - + return Error; } int test_quat_shortMix() { - int Error = 0; - + int Error(0); + glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); glm::quat B = glm::angleAxis(90.0f, glm::vec3(0, 0, 1)); - glm::quat C = glm::shortMix(A, B, 0.5f); - glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); - - Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + glm::quat C = glm::shortMix(A, B, 0.5f); + glm::quat D = glm::angleAxis(45.0f, glm::vec3(0, 0, 1)); + + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; - + + return Error; +} + +int test_orientation() +{ + int Error(0); + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::roll(q); + } + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::pitch(q); + } + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::yaw(q); + } + return Error; } int main() { int Error = 0; - + Error += test_quat_fastMix(); - Error += test_quat_shortMix(); + Error += test_quat_shortMix(); return Error; }