From d75ef41bdb46b58f4f51bc6dc36adb054706c513 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 21 Aug 2017 11:16:46 -0700 Subject: [PATCH 1/5] Checking if either argument is nan in fmin and fmax --- glm/gtx/extended_min_max.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glm/gtx/extended_min_max.inl b/glm/gtx/extended_min_max.inl index 8fc52660..e308c6fe 100644 --- a/glm/gtx/extended_min_max.inl +++ b/glm/gtx/extended_min_max.inl @@ -146,8 +146,8 @@ namespace glm { GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point input"); - if (isnan(y)) - return x; + if (isnan(x)) + return y; if (isnan(y)) return x; @@ -176,8 +176,8 @@ namespace glm { GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point input"); - if (isnan(y)) - return x; + if (isnan(x)) + return y; if (isnan(y)) return x; From 8150e4848bca8a7ca01c747a35106adea626edb3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 21 Aug 2017 11:40:37 -0700 Subject: [PATCH 2/5] Added more testing for fmin/fmax nan cases --- test/gtx/gtx_extended_min_max.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/gtx/gtx_extended_min_max.cpp b/test/gtx/gtx_extended_min_max.cpp index f071b898..b3c67a88 100644 --- a/test/gtx/gtx_extended_min_max.cpp +++ b/test/gtx/gtx_extended_min_max.cpp @@ -1,4 +1,5 @@ #define GLM_ENABLE_EXPERIMENTAL + #include #include #include @@ -18,6 +19,9 @@ namespace fmin_ glm::vec1 A0 = glm::fmin(glm::vec1(1), glm::vec1(Zero_f / 0.0f)); Error += glm::epsilonEqual(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + glm::vec1 A1 = glm::fmin(glm::vec1(Zero_f / 0.0f), glm::vec1(1)); + Error += glm::epsilonEqual(A1.x, 1.0f, glm::epsilon()) ? 0 : 1; + glm::vec2 B0 = glm::fmin(glm::vec2(1), glm::vec2(1)); glm::vec2 B1 = glm::fmin(glm::vec2(1), 1.0f); bool B2 = glm::all(glm::equal(B0, B1)); @@ -47,6 +51,9 @@ namespace fmax_ glm::vec1 A0 = glm::fmax(glm::vec1(1), glm::vec1(Zero_f / 0.0f)); Error += glm::epsilonEqual(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + glm::vec1 A1 = glm::fmax(glm::vec1(Zero_f / 0.0f), glm::vec1(1)); + Error += glm::epsilonEqual(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + glm::vec2 B0 = glm::fmax(glm::vec2(1), glm::vec2(1)); glm::vec2 B1 = glm::fmax(glm::vec2(1), 1.0f); bool B2 = glm::all(glm::equal(B0, B1)); From 6932058f59d8be7efb5e6608ce667416d1c0a5f6 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 22 Aug 2017 22:47:36 +0200 Subject: [PATCH 3/5] Fixed quaternion constructor from two vectors special cases #469 --- glm/gtc/quaternion.inl | 22 ++++++++++++++++++---- readme.md | 1 + test/gtc/gtc_quaternion.cpp | 22 +++++++++++++++++----- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl index eed933fe..edfb6e9a 100644 --- a/glm/gtc/quaternion.inl +++ b/glm/gtc/quaternion.inl @@ -148,11 +148,25 @@ namespace detail template GLM_FUNC_QUALIFIER tquat::tquat(vec<3, T, Q> const& u, vec<3, T, Q> const& v) { - vec<3, T, Q> const LocalW(cross(u, v)); - T Dot = detail::compute_dot, T, detail::is_aligned::value>::call(u, v); - tquat q(T(1) + Dot, LocalW.x, LocalW.y, LocalW.z); + T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); + T real_part = norm_u_norm_v + dot(u, v); + vec<3, T, Q> w; - *this = normalize(q); + if(real_part < static_cast(1.e-6f) * norm_u_norm_v) + { + // If u and v are exactly opposite, rotate 180 degrees + // around an arbitrary orthogonal axis. Axis normalisation + // can happen later, when we normalise the quaternion. + real_part = static_cast(0); + w = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast(0)) : vec<3, T, Q>(static_cast(0), -u.z, u.y); + } + else + { + // Otherwise, build quaternion the standard way. + w = cross(u, v); + } + + *this = normalize(tquat(real_part, w.x, w.y, w.z)); } template diff --git a/readme.md b/readme.md index 76e0ea5b..74043af7 100644 --- a/readme.md +++ b/readme.md @@ -101,6 +101,7 @@ glm::mat4 camera(float Translate, glm::vec2 const& Rotate) - Fixed documentation warnings - Fixed GLM_HAS_OPENMP when OpenMP is not enabled - Fixed Better follow GLSL min and max specification #372 +- Fixed quaternion constructor from two vectors special cases #469 #### Deprecation: - Requires Visual Studio 2013, GCC 4.7, Clang 3.4, Cuda 7, ICC 2013 or a C++11 compiler diff --git a/test/gtc/gtc_quaternion.cpp b/test/gtc/gtc_quaternion.cpp index f94adf5d..b006a12f 100644 --- a/test/gtc/gtc_quaternion.cpp +++ b/test/gtc/gtc_quaternion.cpp @@ -225,16 +225,28 @@ int test_quat_mul() int test_quat_two_axis_ctr() { - int Error(0); + int Error = 0; - glm::quat q1(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); - glm::vec3 v1 = q1 * glm::vec3(1, 0, 0); + glm::quat const q1(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + glm::vec3 const v1 = q1 * glm::vec3(1, 0, 0); Error += glm::all(glm::epsilonEqual(v1, glm::vec3(0, 1, 0), 0.0001f)) ? 0 : 1; - glm::quat q2 = q1 * q1; - glm::vec3 v2 = q2 * glm::vec3(1, 0, 0); + glm::quat const q2 = q1 * q1; + glm::vec3 const v2 = q2 * glm::vec3(1, 0, 0); Error += glm::all(glm::epsilonEqual(v2, glm::vec3(-1, 0, 0), 0.0001f)) ? 0 : 1; + glm::quat const q3(glm::vec3(1, 0, 0), glm::vec3(-1, 0, 0)); + glm::vec3 const v3 = q3 * glm::vec3(1, 0, 0); + Error += glm::all(glm::epsilonEqual(v3, glm::vec3(-1, 0, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q4(glm::vec3(0, 1, 0), glm::vec3(0, -1, 0)); + glm::vec3 const v4 = q4 * glm::vec3(0, 1, 0); + Error += glm::all(glm::epsilonEqual(v4, glm::vec3(0, -1, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q5(glm::vec3(0, 0, 1), glm::vec3(0, 0, -1)); + glm::vec3 const v5 = q5 * glm::vec3(0, 0, 1); + Error += glm::all(glm::epsilonEqual(v5, glm::vec3(0, 0, -1), 0.0001f)) ? 0 : 1; + return Error; } From b5eb654ff043651a7302de3695512d266031bbc1 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 22 Aug 2017 23:58:31 +0200 Subject: [PATCH 4/5] Fixed Visual C++ /W4 warnings --- glm/gtc/quaternion.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl index edfb6e9a..5314d1fa 100644 --- a/glm/gtc/quaternion.inl +++ b/glm/gtc/quaternion.inl @@ -150,7 +150,7 @@ namespace detail { T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); T real_part = norm_u_norm_v + dot(u, v); - vec<3, T, Q> w; + vec<3, T, Q> t; if(real_part < static_cast(1.e-6f) * norm_u_norm_v) { @@ -158,15 +158,15 @@ namespace detail // around an arbitrary orthogonal axis. Axis normalisation // can happen later, when we normalise the quaternion. real_part = static_cast(0); - w = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast(0)) : vec<3, T, Q>(static_cast(0), -u.z, u.y); + t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast(0)) : vec<3, T, Q>(static_cast(0), -u.z, u.y); } else { // Otherwise, build quaternion the standard way. - w = cross(u, v); + t = cross(u, v); } - *this = normalize(tquat(real_part, w.x, w.y, w.z)); + *this = normalize(tquat(real_part, t.x, t.y, t.z)); } template From a6e27e80790e7aa90c6b7884f8fafec2890728bf Mon Sep 17 00:00:00 2001 From: Linqing Feng Date: Fri, 25 Aug 2017 10:50:05 +0900 Subject: [PATCH 5/5] fix mismatched template argument (P to Q) --- glm/gtx/hash.hpp | 80 ++++++++++++++++++++++++------------------------ glm/gtx/hash.inl | 38 +++++++++++------------ 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/glm/gtx/hash.hpp b/glm/gtx/hash.hpp index cfb79baa..fe8a3efd 100644 --- a/glm/gtx/hash.hpp +++ b/glm/gtx/hash.hpp @@ -44,94 +44,94 @@ namespace std { - template - struct hash > + template + struct hash > { GLM_FUNC_DECL size_t operator()(glm::vec<1, T, Q> const& v) const; }; - template - struct hash > + template + struct hash > { GLM_FUNC_DECL size_t operator()(glm::vec<2, T, Q> const& v) const; }; - template - struct hash > + template + struct hash > { GLM_FUNC_DECL size_t operator()(glm::vec<3, T, Q> const& v) const; }; - template - struct hash > + template + struct hash > { GLM_FUNC_DECL size_t operator()(glm::vec<4, T, Q> const& v) const; }; - template - struct hash> + template + struct hash> { GLM_FUNC_DECL size_t operator()(glm::tquat const& q) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::tdualquat const& q) const; + GLM_FUNC_DECL size_t operator()(glm::tdualquat const& q) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,Q> const& m) const; }; - template - struct hash > + template + struct hash > { - GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,P> const& m) const; + GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,Q> const& m) const; }; } // namespace std diff --git a/glm/gtx/hash.inl b/glm/gtx/hash.inl index 5370e5d1..32e7f123 100644 --- a/glm/gtx/hash.inl +++ b/glm/gtx/hash.inl @@ -22,14 +22,14 @@ namespace detail namespace std { - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<1, T, Q> const& v) const { hash hasher; return hasher(v.x); } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<2, T, Q> const& v) const { size_t seed = 0; @@ -39,7 +39,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<3, T, Q> const& v) const { size_t seed = 0; @@ -50,7 +50,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<4, T, Q> const& v) const { size_t seed = 0; @@ -62,8 +62,8 @@ namespace std return seed; } - template - GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::tquat const& q) const + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::tquat const& q) const { size_t seed = 0; hash hasher; @@ -74,7 +74,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::tdualquat const& q) const { size_t seed = 0; @@ -84,7 +84,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 2, T, Q> const& m) const { size_t seed = 0; @@ -94,7 +94,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 3, T, Q> const& m) const { size_t seed = 0; @@ -104,7 +104,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 4, T, Q> const& m) const { size_t seed = 0; @@ -114,7 +114,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 2, T, Q> const& m) const { size_t seed = 0; @@ -125,7 +125,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 3, T, Q> const& m) const { size_t seed = 0; @@ -136,7 +136,7 @@ namespace std return seed; } - template + template GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 4, T, Q> const& m) const { size_t seed = 0; @@ -147,8 +147,8 @@ namespace std return seed; } - template - GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 2, T,P> const& m) const + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 2, T,Q> const& m) const { size_t seed = 0; hash> hasher; @@ -159,8 +159,8 @@ namespace std return seed; } - template - GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 3, T,P> const& m) const + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 3, T,Q> const& m) const { size_t seed = 0; hash> hasher; @@ -171,8 +171,8 @@ namespace std return seed; } - template - GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 4, T, Q> const& m) const + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 4, T, Q> const& m) const { size_t seed = 0; hash> hasher;