Added EXT_scalar_common, EXT_vector_common and EXT_quaternion_exponential extensions

This commit is contained in:
Christophe Riccio 2018-08-15 18:54:04 +02:00
parent f905aecd23
commit c4ed4ed0c7
18 changed files with 987 additions and 173 deletions

View File

@ -0,0 +1,69 @@
/// @ref ext_quaternion_exponential
/// @file glm/ext/quaternion_exponential.hpp
///
/// @see core (dependence)
///
/// @defgroup ext_quaternion_exponential GLM_EXT_quaternion_exponential
/// @ingroup ext
///
/// Include <glm/ext/quaternion_exponential.hpp> to use the features of this extension.
///
/// Defines a templated quaternion type and several quaternion operations.
#pragma once
// Dependency:
#include "../common.hpp"
#include "../trigonometric.hpp"
#include "../geometric.hpp"
#include "../ext/scalar_constants.hpp"
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
# pragma message("GLM: GLM_EXT_quaternion_exponential extension included")
#endif
namespace glm
{
/// @addtogroup ext_quaternion_transform
/// @{
/// Returns a exponential of a quaternion.
///
/// @tparam T A floating-point scalar type
/// @tparam Q A value from qualifier enum
///
/// @see ext_quaternion_exponential
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> exp(qua<T, Q> const& q);
/// Returns a logarithm of a quaternion
///
/// @tparam T A floating-point scalar type
/// @tparam Q A value from qualifier enum
///
/// @see ext_quaternion_exponential
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> log(qua<T, Q> const& q);
/// Returns a quaternion raised to a power.
///
/// @tparam T A floating-point scalar type
/// @tparam Q A value from qualifier enum
///
/// @see ext_quaternion_exponential
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> pow(qua<T, Q> const& q, T y);
/// Returns the square root of a quaternion
///
/// @tparam T A floating-point scalar type
/// @tparam Q A value from qualifier enum
///
/// @see ext_quaternion_exponential
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> sqrt(qua<T, Q> const& q);
/// @}
} //namespace glm
#include "quaternion_exponential.inl"

View File

@ -0,0 +1,72 @@
namespace glm
{
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> exp(qua<T, Q> const& q)
{
vec<3, T, Q> u(q.x, q.y, q.z);
T const Angle = glm::length(u);
if (Angle < epsilon<T>())
return qua<T, Q>();
vec<3, T, Q> const v(u / Angle);
return qua<T, Q>(cos(Angle), sin(Angle) * v);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> log(qua<T, Q> const& q)
{
vec<3, T, Q> u(q.x, q.y, q.z);
T Vec3Len = length(u);
if (Vec3Len < epsilon<T>())
{
if(q.w > static_cast<T>(0))
return qua<T, Q>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
else if(q.w < static_cast<T>(0))
return qua<T, Q>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0));
else
return qua<T, Q>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
}
else
{
T t = atan(Vec3Len, T(q.w)) / Vec3Len;
T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w;
return qua<T, Q>(static_cast<T>(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z);
}
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> pow(qua<T, Q> const& x, T y)
{
//Raising to the power of 0 should yield 1
//Needed to prevent a division by 0 error later on
if(y > -epsilon<T>() && y < epsilon<T>())
return qua<T, Q>(1,0,0,0);
//To deal with non-unit quaternions
T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w);
//Equivalent to raising a real number to a power
//Needed to prevent a division by 0 error later on
if(abs(x.w / magnitude) > static_cast<T>(1) - epsilon<T>() && abs(x.w / magnitude) < static_cast<T>(1) + epsilon<T>())
return qua<T, Q>(pow(x.w, y), 0, 0, 0);
T Angle = acos(x.w / magnitude);
T NewAngle = Angle * y;
T Div = sin(NewAngle) / sin(Angle);
T Mag = pow(magnitude, y - static_cast<T>(1));
return qua<T, Q>(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> sqrt(qua<T, Q> const& x)
{
return pow(x, static_cast<T>(0.5));
}
}//namespace glm
#if GLM_CONFIG_SIMD == GLM_ENABLE
# include "quaternion_exponential_simd.inl"
#endif

View File

@ -47,6 +47,7 @@ namespace glm
/// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ...
///
/// @tparam T Floating-point scalar types.
/// @tparam Q Value from qualifier enum
///
/// @see ext_quaternion_geometric
template<typename T, qualifier Q>

View File

@ -39,6 +39,32 @@ namespace glm
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> rotate(qua<T, Q> const& q, T const& angle, vec<3, T, Q> const& axis);
/// Build a look at quaternion based on the default handedness.
///
/// @param direction Desired forward direction. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAt(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// Build a right-handed look at quaternion.
///
/// @param direction Desired forward direction onto which the -z-axis gets mapped. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAtRH(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// Build a left-handed look at quaternion.
///
/// @param direction Desired forward direction onto which the +z-axis gets mapped. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAtLH(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// @}
} //namespace glm

View File

@ -20,6 +20,40 @@ namespace glm
return q * qua<T, Q>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT
return quatLookAtLH(direction, up);
# else
return quatLookAtRH(direction, up);
# endif
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
mat<3, 3, T, Q> Result;
Result[2] = -direction;
Result[0] = normalize(cross(up, Result[2]));
Result[1] = cross(Result[2], Result[0]);
return quat_cast(Result);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
mat<3, 3, T, Q> Result;
Result[2] = direction;
Result[0] = normalize(cross(up, Result[2]));
Result[1] = cross(Result[2], Result[0]);
return quat_cast(Result);
}
}//namespace glm
#if GLM_CONFIG_SIMD == GLM_ENABLE

110
glm/ext/scalar_common.hpp Normal file
View File

@ -0,0 +1,110 @@
/// @ref ext_scalar_common
/// @file glm/ext/scalar_common.hpp
///
/// @see core (dependence)
///
/// @defgroup ext_scalar_common GLM_EXT_scalar_common
/// @ingroup ext
///
/// Include <glm/ext/scalar_common.hpp> to use the features of this extension.
///
/// Min and max functions for 3 to 4 parameters.
#pragma once
// Dependency:
#include "../common.hpp"
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
# pragma message("GLM: GLM_EXT_scalar_common extension included")
#endif
namespace glm
{
/// @addtogroup ext_scalar_common
/// @{
/// Returns the minimum component-wise values of 3 inputs
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
template<typename T>
GLM_FUNC_DECL T min(T a, T b, T c);
/// Returns the minimum component-wise values of 4 inputs
/// @see ext_scalar_common
template<typename T>
GLM_FUNC_DECL T min(T a, T b, T c, T d);
/// Returns the maximum component-wise values of 3 inputs
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
template<typename T>
GLM_FUNC_DECL T max(T a, T b, T c);
/// Returns the maximum component-wise values of 4 inputs
/// @see ext_scalar_common
template<typename T>
GLM_FUNC_DECL T max(T a, T b, T c, T d);
/// Returns the minimum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a>
template<typename T>
GLM_FUNC_DECL T fmin(T a, T b);
/// Returns the minimum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a>
template<typename T>
GLM_FUNC_DECL T fmin(T a, T b, T c);
/// Returns the minimum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a>
template<typename T>
GLM_FUNC_DECL T fmin(T a, T b, T c, T d);
/// Returns the maximum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a>
template<typename T>
GLM_FUNC_DECL T fmax(T a, T b);
/// Returns the maximum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a>
template<typename T>
GLM_FUNC_DECL T fmax(T a, T b, T C);
/// Returns the maximum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam T A floating-point scalar type.
///
/// @see ext_scalar_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a>
template<typename T>
GLM_FUNC_DECL T fmax(T a, T b, T C, T D);
/// @}
}//namespace glm
#include "scalar_common.inl"

115
glm/ext/scalar_common.inl Normal file
View File

@ -0,0 +1,115 @@
namespace glm
{
template<typename T>
GLM_FUNC_QUALIFIER T min(T a, T b, T c)
{
return glm::min(glm::min(a, b), c);
}
template<typename T>
GLM_FUNC_QUALIFIER T min(T a, T b, T c, T d)
{
return glm::min(glm::min(a, b), glm::min(c, d));
}
template<typename T>
GLM_FUNC_QUALIFIER T max(T a, T b, T c)
{
return glm::max(glm::max(a, b), c);
}
template<typename T>
GLM_FUNC_QUALIFIER T max(T a, T b, T c, T d)
{
return glm::max(glm::max(a, b), glm::max(c, d));
}
# if GLM_HAS_CXX11_STL
using std::fmin;
# else
template<typename T>
GLM_FUNC_QUALIFIER T fmin(T a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point input");
if (isnan(a))
return b;
return min(a, b);
}
# endif
template<typename T>
GLM_FUNC_QUALIFIER T fmin(T a, T b, T c)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point input");
if (isnan(a))
return fmin(b, c);
if (isnan(b))
return fmin(a, c);
if (isnan(c))
return min(a, b);
return min(a, b, c);
}
template<typename T>
GLM_FUNC_QUALIFIER T fmin(T a, T b, T c, T d)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point input");
if (isnan(a))
return fmin(b, c, d);
if (isnan(b))
return min(a, fmin(c, d));
if (isnan(c))
return fmin(min(a, b), d);
if (isnan(d))
return min(a, b, c);
return min(a, b, c, d);
}
# if GLM_HAS_CXX11_STL
using std::fmax;
# else
template<typename T>
GLM_FUNC_QUALIFIER T fmax(T a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point input");
if (isnan(a))
return b;
return max(a, b);
}
# endif
template<typename T>
GLM_FUNC_QUALIFIER T fmax(T a, T b, T c)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point input");
if (isnan(a))
return fmax(b, c);
if (isnan(b))
return fmax(a, c);
if (isnan(c))
return max(a, b);
return max(a, b, c);
}
template<typename T>
GLM_FUNC_QUALIFIER T fmax(T a, T b, T c, T d)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point input");
if (isnan(a))
return fmax(b, c, d);
if (isnan(b))
return max(a, fmax(c, d));
if (isnan(c))
return fmax(max(a, b), d);
if (isnan(d))
return max(a, b, c);
return max(a, b, c, d);
}
}//namespace glm

134
glm/ext/vector_common.hpp Normal file
View File

@ -0,0 +1,134 @@
/// @ref ext_vector_common
/// @file glm/ext/vector_common.hpp
///
/// @see core (dependence)
///
/// @defgroup ext_vector_common GLM_EXT_vector_common
/// @ingroup ext
///
/// Include <glm/ext/vector_common.hpp> to use the features of this extension.
///
/// Min and max functions for 3 to 4 parameters.
#pragma once
// Dependency:
#include "../glm.hpp"
#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
# pragma message("GLM: GLM_EXT_vector_common extension included")
#endif
namespace glm
{
/// @addtogroup ext_vector_common
/// @{
/// Return the minimum component-wise values of 3 inputs
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point or integer scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c);
/// Return the minimum component-wise values of 4 inputs
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point or integer scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> const& d);
/// Return the maximum component-wise values of 3 inputs
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point or integer scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z);
/// Return the maximum component-wise values of 4 inputs
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point or integer scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> max( vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> const& w);
/// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a>
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> const& x, T y);
/// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a>
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> const& x, vec<L, T, Q> const& y);
/// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a>
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> const& x, T y);
/// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
/// @see <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a>
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> const& x, vec<L, T, Q> const& y);
/// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fclamp(vec<L, T, Q> const& x, T minVal, T maxVal);
/// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned.
///
/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
/// @tparam T Floating-point scalar types
/// @tparam Q Value from qualifier enum
///
/// @see ext_vector_common
template<length_t L, typename T, qualifier Q>
GLM_FUNC_DECL vec<L, T, Q> fclamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal);
/// @}
}//namespace glm
#include "vector_common.inl"

72
glm/ext/vector_common.inl Normal file
View File

@ -0,0 +1,72 @@
namespace glm
{
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> min(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'min' only accept floating-point or integer inputs");
return glm::min(glm::min(x, y), z);
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> min(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> const& w)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'min' only accept floating-point or integer inputs");
return glm::min(glm::min(x, y), glm::min(z, w));
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'max' only accept floating-point or integer inputs");
return glm::max(glm::max(x, y), z);
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> const& w)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'max' only accept floating-point or integer inputs");
return glm::max(glm::max(x, y), glm::max(z, w));
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs");
return detail::functor2<vec, L, T, Q>::call(fmin, a, vec<L, T, Q>(b));
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs");
return detail::functor2<vec, L, T, Q>::call(fmin, a, b);
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs");
return detail::functor2<vec, L, T, Q>::call(fmax, a, vec<L, T, Q>(b));
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs");
return detail::functor2<vec, L, T, Q>::call(fmax, a, b);
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fclamp(vec<L, T, Q> const& x, T minVal, T maxVal)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fclamp' only accept floating-point inputs");
return fmin(fmax(x, vec<L, T, Q>(minVal)), vec<L, T, Q>(maxVal));
}
template<length_t L, typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<L, T, Q> fclamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fclamp' only accept floating-point inputs");
return fmin(fmax(x, minVal), maxVal);
}
}//namespace glm

View File

@ -24,6 +24,7 @@
#include "../ext/quaternion_double_precision.hpp"
#include "../ext/quaternion_relational.hpp"
#include "../ext/quaternion_geometric.hpp"
#include "../ext/quaternion_transform.hpp"
#include "../detail/type_mat3x3.hpp"
#include "../detail/type_mat4x4.hpp"
#include "../detail/type_vec3.hpp"

View File

@ -17,6 +17,7 @@
#include "../glm.hpp"
#include "../gtc/constants.hpp"
#include "../gtc/quaternion.hpp"
#include "../ext/quaternion_exponential.hpp"
#include "../gtx/norm.hpp"
#ifndef GLM_ENABLE_EXPERIMENTAL
@ -75,28 +76,6 @@ namespace glm
qua<T, Q> const& curr,
qua<T, Q> const& next);
//! Returns a exp of a quaternion.
///
/// @see gtx_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> exp(
qua<T, Q> const& q);
//! Returns a log of a quaternion.
///
/// @see gtx_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> log(
qua<T, Q> const& q);
/// Returns x raised to the y power.
///
/// @see gtx_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> pow(
qua<T, Q> const& x,
T const& y);
//! Returns quarternion square root.
///
/// @see gtx_quaternion
@ -183,33 +162,6 @@ namespace glm
vec<3, T, Q> const& orig,
vec<3, T, Q> const& dest);
/// Build a look at quaternion based on the default handedness.
///
/// @param direction Desired forward direction. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAt(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// Build a right-handed look at quaternion.
///
/// @param direction Desired forward direction onto which the -z-axis gets mapped. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAtRH(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// Build a left-handed look at quaternion.
///
/// @param direction Desired forward direction onto which the +z-axis gets mapped. Needs to be normalized.
/// @param up Up vector, how the camera is oriented. Typically (0, 1, 0).
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> quatLookAtLH(
vec<3, T, Q> const& direction,
vec<3, T, Q> const& up);
/// Returns the squared length of x.
///
/// @see gtx_quaternion

View File

@ -47,65 +47,6 @@ namespace glm
return exp((log(next * invQuat) + log(prev * invQuat)) / static_cast<T>(-4)) * curr;
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> exp(qua<T, Q> const& q)
{
vec<3, T, Q> u(q.x, q.y, q.z);
T const Angle = glm::length(u);
if (Angle < epsilon<T>())
return qua<T, Q>();
vec<3, T, Q> const v(u / Angle);
return qua<T, Q>(cos(Angle), sin(Angle) * v);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> log(qua<T, Q> const& q)
{
vec<3, T, Q> u(q.x, q.y, q.z);
T Vec3Len = length(u);
if (Vec3Len < epsilon<T>())
{
if(q.w > static_cast<T>(0))
return qua<T, Q>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
else if(q.w < static_cast<T>(0))
return qua<T, Q>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0));
else
return qua<T, Q>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
}
else
{
T t = atan(Vec3Len, T(q.w)) / Vec3Len;
T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w;
return qua<T, Q>(static_cast<T>(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z);
}
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> pow(qua<T, Q> const& x, T const& y)
{
//Raising to the power of 0 should yield 1
//Needed to prevent a division by 0 error later on
if(y > -epsilon<T>() && y < epsilon<T>())
return qua<T, Q>(1,0,0,0);
//To deal with non-unit quaternions
T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w);
//Equivalent to raising a real number to a power
//Needed to prevent a division by 0 error later on
if(abs(x.w / magnitude) > static_cast<T>(1) - epsilon<T>() && abs(x.w / magnitude) < static_cast<T>(1) + epsilon<T>())
return qua<T, Q>(pow(x.w, y),0,0,0);
T Angle = acos(x.w / magnitude);
T NewAngle = Angle * y;
T Div = sin(NewAngle) / sin(Angle);
T Mag = pow(magnitude, y - static_cast<T>(1));
return qua<T, Q>(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER vec<3, T, Q> rotate(qua<T, Q> const& q, vec<3, T, Q> const& v)
{
@ -215,39 +156,4 @@ namespace glm
rotationAxis.y * invs,
rotationAxis.z * invs);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT
return quatLookAtLH(direction, up);
# else
return quatLookAtRH(direction, up);
# endif
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
mat<3, 3, T, Q> Result;
Result[2] = -direction;
Result[0] = normalize(cross(up, Result[2]));
Result[1] = cross(Result[2], Result[0]);
return quat_cast(Result);
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
{
mat<3, 3, T, Q> Result;
Result[2] = direction;
Result[0] = normalize(cross(up, Result[2]));
Result[1] = cross(Result[2], Result[0]);
return quat_cast(Result);
}
}//namespace glm

View File

@ -1,11 +1,13 @@
glmCreateTestGTC(ext_matrix_relational)
glmCreateTestGTC(ext_matrix_transform)
glmCreateTestGTC(ext_quaternion_common)
glmCreateTestGTC(ext_quaternion_exponential)
glmCreateTestGTC(ext_quaternion_geometric)
glmCreateTestGTC(ext_quaternion_relational)
glmCreateTestGTC(ext_quaternion_transform)
glmCreateTestGTC(ext_quaternion_trigonometric)
glmCreateTestGTC(ext_quaternion_type)
glmCreateTestGTC(ext_scalar_common)
glmCreateTestGTC(ext_scalar_constants)
glmCreateTestGTC(ext_scalar_float_sized)
glmCreateTestGTC(ext_scalar_int_sized)
@ -13,6 +15,7 @@ glmCreateTestGTC(ext_scalar_uint_sized)
glmCreateTestGTC(ext_scalar_relational)
glmCreateTestGTC(ext_vec1)
glmCreateTestGTC(ext_vector_bool1)
glmCreateTestGTC(ext_vector_common)
glmCreateTestGTC(ext_vector_iec559)
glmCreateTestGTC(ext_vector_integer)
glmCreateTestGTC(ext_vector_relational)

View File

@ -0,0 +1,87 @@
#include <glm/ext/quaternion_exponential.hpp>
#include <glm/ext/quaternion_float.hpp>
#include <glm/ext/quaternion_float_precision.hpp>
#include <glm/ext/quaternion_double.hpp>
#include <glm/ext/quaternion_double_precision.hpp>
#include <glm/ext/quaternion_relational.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/ext/vector_float3_precision.hpp>
#include <glm/ext/vector_double3.hpp>
#include <glm/ext/vector_double3_precision.hpp>
#include <glm/ext/scalar_constants.hpp>
template <typename quaType, typename vecType>
int test_log()
{
typedef typename quaType::value_type T;
T const Epsilon = static_cast<T>(0.001f);
int Error = 0;
quaType const Q(vecType(1, 0, 0), vecType(0, 1, 0));
quaType const P = glm::log(Q);
Error += glm::any(glm::notEqual(Q, P, Epsilon)) ? 0 : 1;
quaType const R = glm::exp(P);
Error += glm::all(glm::equal(Q, R, Epsilon)) ? 0 : 1;
return Error;
}
template <typename quaType, typename vecType>
int test_pow()
{
typedef typename quaType::value_type T;
T const Epsilon = static_cast<T>(0.001f);
int Error = 0;
quaType const Q(vecType(1, 0, 0), vecType(0, 1, 0));
{
T const One = static_cast<T>(1.0f);
quaType const P = glm::pow(Q, One);
Error += glm::all(glm::equal(Q, P, Epsilon)) ? 0 : 1;
}
{
T const Two = static_cast<T>(2.0f);
quaType const P = glm::pow(Q, Two);
quaType const R = Q * Q;
Error += glm::all(glm::equal(P, R, Epsilon)) ? 0 : 1;
quaType const U = glm::sqrt(P);
Error += glm::all(glm::equal(Q, U, Epsilon)) ? 0 : 1;
}
return Error;
}
int main()
{
int Error = 0;
Error += test_log<glm::quat, glm::vec3>();
Error += test_log<glm::lowp_quat, glm::lowp_vec3>();
Error += test_log<glm::mediump_quat, glm::mediump_vec3>();
Error += test_log<glm::highp_quat, glm::highp_vec3>();
Error += test_log<glm::dquat, glm::dvec3>();
Error += test_log<glm::lowp_dquat, glm::lowp_dvec3>();
Error += test_log<glm::mediump_dquat, glm::mediump_dvec3>();
Error += test_log<glm::highp_dquat, glm::highp_dvec3>();
Error += test_pow<glm::quat, glm::vec3>();
Error += test_pow<glm::lowp_quat, glm::lowp_vec3>();
Error += test_pow<glm::mediump_quat, glm::mediump_vec3>();
Error += test_pow<glm::highp_quat, glm::highp_vec3>();
Error += test_pow<glm::dquat, glm::dvec3>();
Error += test_pow<glm::lowp_dquat, glm::lowp_dvec3>();
Error += test_pow<glm::mediump_dquat, glm::mediump_dvec3>();
Error += test_pow<glm::highp_dquat, glm::highp_dvec3>();
return Error;
}

View File

@ -3,9 +3,43 @@
#include <glm/ext/vector_relational.hpp>
#include <glm/ext/scalar_constants.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp>
static int test_lookAt()
{
int Error(0);
glm::vec3 eye(0.0f);
glm::vec3 center(1.1f, -2.0f, 3.1416f);
glm::vec3 up(-0.17f, 7.23f, -1.744f);
glm::quat test_quat = glm::quatLookAt(glm::normalize(center - eye), up);
glm::quat test_mat = glm::conjugate(glm::quat_cast(glm::lookAt(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quat) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quat + (-test_mat)), glm::length(test_quat + test_mat)) > glm::epsilon<float>());
// Test left-handed implementation
glm::quat test_quatLH = glm::quatLookAtLH(glm::normalize(center - eye), up);
glm::quat test_matLH = glm::conjugate(glm::quat_cast(glm::lookAtLH(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quatLH) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quatLH - test_matLH), glm::length(test_quatLH + test_matLH)) > glm::epsilon<float>());
// Test right-handed implementation
glm::quat test_quatRH = glm::quatLookAtRH(glm::normalize(center - eye), up);
glm::quat test_matRH = glm::conjugate(glm::quat_cast(glm::lookAtRH(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quatRH) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quatRH - test_matRH), glm::length(test_quatRH + test_matRH)) > glm::epsilon<float>());
return Error;
}
int main()
{
int Error = 0;
Error += test_lookAt();
return Error;
}

View File

@ -0,0 +1,204 @@
#include <glm/ext/scalar_common.hpp>
#include <glm/ext/scalar_constants.hpp>
#include <glm/ext/scalar_relational.hpp>
#include <glm/common.hpp>
#include <algorithm>
template <typename T>
static int test_min()
{
int Error = 0;
T const N = static_cast<T>(0);
T const B = static_cast<T>(1);
Error += glm::equal(glm::min(N, B), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(B, N), N, glm::epsilon<T>()) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::equal(glm::min(N, B, C), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(B, N, C), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(C, N, B), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(C, B, N), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(B, C, N), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(N, C, B), N, glm::epsilon<T>()) ? 0 : 1;
T const D = static_cast<T>(3);
Error += glm::equal(glm::min(D, N, B, C), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(B, D, N, C), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(C, N, D, B), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(C, B, D, N), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(B, C, N, D), N, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::min(N, C, B, D), N, glm::epsilon<T>()) ? 0 : 1;
return Error;
}
template <typename T>
static int test_min_nan()
{
int Error = 0;
T const A = static_cast<T>(0);
T const B = static_cast<T>(1);
T const N = A / A;
Error += glm::isnan(glm::min(N, B)) ? 0 : 1;
Error += !glm::isnan(glm::min(B, N)) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::isnan(glm::min(N, B, C)) ? 0 : 1;
Error += !glm::isnan(glm::min(B, N, C)) ? 0 : 1;
Error += !glm::isnan(glm::min(C, N, B)) ? 0 : 1;
Error += !glm::isnan(glm::min(C, B, N)) ? 0 : 1;
Error += !glm::isnan(glm::min(B, C, N)) ? 0 : 1;
Error += glm::isnan(glm::min(N, C, B)) ? 0 : 1;
T const D = static_cast<T>(3);
Error += !glm::isnan(glm::min(D, N, B, C)) ? 0 : 1;
Error += !glm::isnan(glm::min(B, D, N, C)) ? 0 : 1;
Error += !glm::isnan(glm::min(C, N, D, B)) ? 0 : 1;
Error += !glm::isnan(glm::min(C, B, D, N)) ? 0 : 1;
Error += !glm::isnan(glm::min(B, C, N, D)) ? 0 : 1;
Error += glm::isnan(glm::min(N, C, B, D)) ? 0 : 1;
return Error;
}
template <typename T>
static int test_max()
{
int Error = 0;
T const N = static_cast<T>(0);
T const B = static_cast<T>(1);
Error += glm::equal(glm::max(N, B), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(B, N), B, glm::epsilon<T>()) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::equal(glm::max(N, B, C), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(B, N, C), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(C, N, B), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(C, B, N), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(B, C, N), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(N, C, B), C, glm::epsilon<T>()) ? 0 : 1;
T const D = static_cast<T>(3);
Error += glm::equal(glm::max(D, N, B, C), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(B, D, N, C), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(C, N, D, B), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(C, B, D, N), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(B, C, N, D), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::max(N, C, B, D), D, glm::epsilon<T>()) ? 0 : 1;
return Error;
}
template <typename T>
static int test_max_nan()
{
int Error = 0;
T const A = static_cast<T>(0);
T const B = static_cast<T>(1);
T const N = A / A;
Error += glm::isnan(glm::max(N, B)) ? 0 : 1;
Error += !glm::isnan(glm::max(B, N)) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::isnan(glm::max(N, B, C)) ? 0 : 1;
Error += !glm::isnan(glm::max(B, N, C)) ? 0 : 1;
Error += !glm::isnan(glm::max(C, N, B)) ? 0 : 1;
Error += !glm::isnan(glm::max(C, B, N)) ? 0 : 1;
Error += !glm::isnan(glm::max(B, C, N)) ? 0 : 1;
Error += glm::isnan(glm::max(N, C, B)) ? 0 : 1;
T const D = static_cast<T>(3);
Error += !glm::isnan(glm::max(D, N, B, C)) ? 0 : 1;
Error += !glm::isnan(glm::max(B, D, N, C)) ? 0 : 1;
Error += !glm::isnan(glm::max(C, N, D, B)) ? 0 : 1;
Error += !glm::isnan(glm::max(C, B, D, N)) ? 0 : 1;
Error += !glm::isnan(glm::max(B, C, N, D)) ? 0 : 1;
Error += glm::isnan(glm::max(N, C, B, D)) ? 0 : 1;
return Error;
}
template <typename T>
static int test_fmin()
{
int Error = 0;
T const A = static_cast<T>(0);
T const B = static_cast<T>(1);
Error += glm::equal(glm::fmin(A / A, B), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(B, A / A), B, glm::epsilon<T>()) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::equal(glm::fmin(A / A, B, C), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(B, A / A, C), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(C, A / A, B), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(C, B, A / A), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(B, C, A / A), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(A / A, C, B), B, glm::epsilon<T>()) ? 0 : 1;
T const D = static_cast<T>(3);
Error += glm::equal(glm::fmin(D, A / A, B, C), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(B, D, A / A, C), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(C, A / A, D, B), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(C, B, D, A / A), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(B, C, A / A, D), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmin(A / A, C, B, D), B, glm::epsilon<T>()) ? 0 : 1;
return Error;
}
template <typename T>
static int test_fmax()
{
int Error = 0;
T const A = static_cast<T>(0);
T const B = static_cast<T>(1);
Error += glm::equal(glm::fmax(A / A, B), B, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(B, A / A), B, glm::epsilon<T>()) ? 0 : 1;
T const C = static_cast<T>(2);
Error += glm::equal(glm::fmax(A / A, B, C), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(B, A / A, C), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(C, A / A, B), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(C, B, A / A), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(B, C, A / A), C, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(A / A, C, B), C, glm::epsilon<T>()) ? 0 : 1;
T const D = static_cast<T>(3);
Error += glm::equal(glm::fmax(D, A / A, B, C), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(B, D, A / A, C), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(C, A / A, D, B), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(C, B, D, A / A), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(B, C, A / A, D), D, glm::epsilon<T>()) ? 0 : 1;
Error += glm::equal(glm::fmax(A / A, C, B, D), D, glm::epsilon<T>()) ? 0 : 1;
return Error;
}
int main()
{
int Error = 0;
Error += test_min<float>();
Error += test_min<double>();
Error += test_min_nan<float>();
Error += test_min_nan<double>();
Error += test_max<float>();
Error += test_max<double>();
Error += test_max_nan<float>();
Error += test_max_nan<double>();
Error += test_fmin<float>();
Error += test_fmin<double>();
Error += test_fmax<float>();
Error += test_fmax<double>();
return Error;
}

View File

@ -0,0 +1,24 @@
#include <glm/ext/vector_common.hpp>
#include <glm/ext/vector_float1.hpp>
#include <glm/ext/vector_float1_precision.hpp>
#include <glm/ext/vector_float2.hpp>
#include <glm/ext/vector_float2_precision.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/ext/vector_float3_precision.hpp>
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/vector_float4_precision.hpp>
#include <glm/ext/vector_double1.hpp>
#include <glm/ext/vector_double1_precision.hpp>
#include <glm/ext/vector_double2.hpp>
#include <glm/ext/vector_double2_precision.hpp>
#include <glm/ext/vector_double3.hpp>
#include <glm/ext/vector_double3_precision.hpp>
#include <glm/ext/vector_double4.hpp>
#include <glm/ext/vector_double4_precision.hpp>
int main()
{
int Error = 0;
return Error;
}

View File

@ -93,35 +93,6 @@ int test_log()
return Error;
}
int test_quat_lookAt()
{
int Error(0);
glm::vec3 eye(0.0f);
glm::vec3 center(1.1f, -2.0f, 3.1416f);
glm::vec3 up(-0.17f, 7.23f, -1.744f);
glm::quat test_quat = glm::quatLookAt(glm::normalize(center - eye), up);
glm::quat test_mat = glm::conjugate(glm::quat_cast(glm::lookAt(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quat) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quat + (-test_mat)), glm::length(test_quat + test_mat)) > glm::epsilon<float>());
// Test left-handed implementation
glm::quat test_quatLH = glm::quatLookAtLH(glm::normalize(center - eye), up);
glm::quat test_matLH = glm::conjugate(glm::quat_cast(glm::lookAtLH(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quatLH) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quatLH - test_matLH), glm::length(test_quatLH + test_matLH)) > glm::epsilon<float>());
// Test right-handed implementation
glm::quat test_quatRH = glm::quatLookAtRH(glm::normalize(center - eye), up);
glm::quat test_matRH = glm::conjugate(glm::quat_cast(glm::lookAtRH(eye, center, up)));
Error += static_cast<int>(glm::abs(glm::length(test_quatRH) - 1.0f) > glm::epsilon<float>());
Error += static_cast<int>(glm::min(glm::length(test_quatRH - test_matRH), glm::length(test_quatRH + test_matRH)) > glm::epsilon<float>());
return Error;
}
int main()
{
int Error = 0;
@ -131,7 +102,6 @@ int main()
Error += test_orientation();
Error += test_quat_fastMix();
Error += test_quat_shortMix();
Error += test_quat_lookAt();
return Error;
}