commit
0d3883c204
2 changed files with 971 additions and 0 deletions
@ -0,0 +1,343 @@ |
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// OpenGL Mathematics (glm.g-truc.net)
|
||||||
|
///
|
||||||
|
/// Copyright (c) 2005 - 2013 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.
|
||||||
|
///
|
||||||
|
/// 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_simd_quat
|
||||||
|
/// @file glm/gtx/simd_quat.hpp
|
||||||
|
/// @date 2009-05-07 / 2011-06-07
|
||||||
|
/// @author Christophe Riccio
|
||||||
|
///
|
||||||
|
/// @see core (dependence)
|
||||||
|
///
|
||||||
|
/// @defgroup gtx_simd_vec4 GLM_GTX_simd_quat
|
||||||
|
/// @ingroup gtx
|
||||||
|
///
|
||||||
|
/// @brief SIMD implementation of quat type.
|
||||||
|
///
|
||||||
|
/// <glm/gtx/simd_quat.hpp> need to be included to use these functionalities.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef GLM_GTX_simd_quat |
||||||
|
#define GLM_GTX_simd_quat GLM_VERSION |
||||||
|
|
||||||
|
// Dependency:
|
||||||
|
#include "../glm.hpp" |
||||||
|
#include "../gtc/quaternion.hpp" |
||||||
|
#include "../gtx/fast_trigonometry.hpp" |
||||||
|
|
||||||
|
#if(GLM_ARCH != GLM_ARCH_PURE) |
||||||
|
|
||||||
|
#if(GLM_ARCH & GLM_ARCH_SSE2) |
||||||
|
# include "../core/intrinsic_common.hpp" |
||||||
|
# include "../core/intrinsic_geometric.hpp" |
||||||
|
# include "../gtx/simd_mat4.hpp" |
||||||
|
#else |
||||||
|
# error "GLM: GLM_GTX_simd_quat requires compiler support of SSE2 through intrinsics" |
||||||
|
#endif |
||||||
|
|
||||||
|
#if(defined(GLM_MESSAGES) && !defined(glm_ext)) |
||||||
|
# pragma message("GLM: GLM_GTX_simd_quat extension included") |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
// Warning silencer for nameless struct/union.
|
||||||
|
#if (GLM_COMPILER & GLM_COMPILER_VC) |
||||||
|
# pragma warning(push) |
||||||
|
# pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
|
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
namespace glm{ |
||||||
|
namespace detail |
||||||
|
{ |
||||||
|
/// Quaternion implemented using SIMD SEE intrinsics.
|
||||||
|
/// \ingroup gtx_simd_vec4
|
||||||
|
GLM_ALIGNED_STRUCT(16) fquatSIMD |
||||||
|
{ |
||||||
|
enum ctor{null}; |
||||||
|
typedef __m128 value_type; |
||||||
|
typedef std::size_t size_type; |
||||||
|
static size_type value_size(); |
||||||
|
|
||||||
|
typedef fquatSIMD type; |
||||||
|
typedef tquat<bool, defaultp> bool_type; |
||||||
|
|
||||||
|
#ifdef GLM_SIMD_ENABLE_XYZW_UNION |
||||||
|
union
|
||||||
|
{ |
||||||
|
__m128 Data; |
||||||
|
struct {float x, y, z, w;}; |
||||||
|
}; |
||||||
|
#else |
||||||
|
__m128 Data; |
||||||
|
#endif |
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Implicit basic constructors
|
||||||
|
|
||||||
|
fquatSIMD(); |
||||||
|
fquatSIMD(__m128 const & Data); |
||||||
|
fquatSIMD(fquatSIMD const & q); |
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Explicit basic constructors
|
||||||
|
|
||||||
|
explicit fquatSIMD( |
||||||
|
ctor); |
||||||
|
explicit fquatSIMD( |
||||||
|
float const & w,
|
||||||
|
float const & x,
|
||||||
|
float const & y,
|
||||||
|
float const & z); |
||||||
|
explicit fquatSIMD( |
||||||
|
quat const & v); |
||||||
|
explicit fquatSIMD( |
||||||
|
vec3 const & eulerAngles); |
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Unary arithmetic operators
|
||||||
|
|
||||||
|
fquatSIMD& operator =(fquatSIMD const & q); |
||||||
|
fquatSIMD& operator*=(float const & s); |
||||||
|
fquatSIMD& operator/=(float const & s); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Arithmetic operators
|
||||||
|
|
||||||
|
detail::fquatSIMD operator- ( |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
detail::fquatSIMD operator+ (
|
||||||
|
detail::fquatSIMD const & q,
|
||||||
|
detail::fquatSIMD const & p);
|
||||||
|
|
||||||
|
detail::fquatSIMD operator* (
|
||||||
|
detail::fquatSIMD const & q,
|
||||||
|
detail::fquatSIMD const & p);
|
||||||
|
|
||||||
|
detail::fvec4SIMD operator* ( |
||||||
|
detail::fquatSIMD const & q,
|
||||||
|
detail::fvec4SIMD const & v); |
||||||
|
|
||||||
|
detail::fvec4SIMD operator* ( |
||||||
|
detail::fvec4SIMD const & v, |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
detail::fquatSIMD operator* ( |
||||||
|
detail::fquatSIMD const & q,
|
||||||
|
float s); |
||||||
|
|
||||||
|
detail::fquatSIMD operator* ( |
||||||
|
float s, |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
detail::fquatSIMD operator/ ( |
||||||
|
detail::fquatSIMD const & q,
|
||||||
|
float s); |
||||||
|
|
||||||
|
}//namespace detail
|
||||||
|
|
||||||
|
typedef glm::detail::fquatSIMD simdQuat; |
||||||
|
|
||||||
|
/// @addtogroup gtx_simd_quat
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
//! Convert a simdQuat to a quat.
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
quat quat_cast( |
||||||
|
detail::fquatSIMD const & x); |
||||||
|
|
||||||
|
//! Convert a simdMat4 to a simdQuat.
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
detail::fquatSIMD quatSIMD_cast( |
||||||
|
detail::fmat4x4SIMD const & m); |
||||||
|
|
||||||
|
//! Converts a mat4 to a simdQuat.
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
template <typename T, precision P> |
||||||
|
detail::fquatSIMD quatSIMD_cast( |
||||||
|
detail::tmat4x4<T, P> const & m); |
||||||
|
|
||||||
|
//! Converts a mat3 to a simdQuat.
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
template <typename T, precision P> |
||||||
|
detail::fquatSIMD quatSIMD_cast( |
||||||
|
detail::tmat3x3<T, P> const & m); |
||||||
|
|
||||||
|
//! Convert a simdQuat to a simdMat4
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
detail::fmat4x4SIMD mat4SIMD_cast( |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
//! Converts a simdQuat to a standard mat4.
|
||||||
|
//! (From GLM_GTX_simd_quat extension)
|
||||||
|
mat4 mat4_cast( |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
|
||||||
|
/// Returns the length of the quaternion.
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
float length( |
||||||
|
detail::fquatSIMD const & x); |
||||||
|
|
||||||
|
/// Returns the normalized quaternion.
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD normalize( |
||||||
|
detail::fquatSIMD const & x); |
||||||
|
|
||||||
|
/// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ...
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
float dot( |
||||||
|
detail::fquatSIMD const & q1,
|
||||||
|
detail::fquatSIMD const & q2); |
||||||
|
|
||||||
|
/// Spherical linear interpolation of two quaternions.
|
||||||
|
/// The interpolation is oriented and the rotation is performed at constant speed.
|
||||||
|
/// For short path spherical linear interpolation, use the slerp function.
|
||||||
|
///
|
||||||
|
/// @param x A quaternion
|
||||||
|
/// @param y A quaternion
|
||||||
|
/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
|
||||||
|
/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
/// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a)
|
||||||
|
detail::fquatSIMD mix( |
||||||
|
detail::fquatSIMD const & x,
|
||||||
|
detail::fquatSIMD const & y,
|
||||||
|
float const & a); |
||||||
|
|
||||||
|
/// Linear interpolation of two quaternions.
|
||||||
|
/// The interpolation is oriented.
|
||||||
|
///
|
||||||
|
/// @param x A quaternion
|
||||||
|
/// @param y A quaternion
|
||||||
|
/// @param a Interpolation factor. The interpolation is defined in the range [0, 1].
|
||||||
|
/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD lerp( |
||||||
|
detail::fquatSIMD const & x,
|
||||||
|
detail::fquatSIMD const & y,
|
||||||
|
float const & a); |
||||||
|
|
||||||
|
/// Spherical linear interpolation of two quaternions.
|
||||||
|
/// The interpolation always take the short path and the rotation is performed at constant speed.
|
||||||
|
///
|
||||||
|
/// @param x A quaternion
|
||||||
|
/// @param y A quaternion
|
||||||
|
/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
|
||||||
|
/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD slerp( |
||||||
|
detail::fquatSIMD const & x,
|
||||||
|
detail::fquatSIMD const & y,
|
||||||
|
float const & a); |
||||||
|
|
||||||
|
|
||||||
|
/// Faster spherical linear interpolation of two unit length quaternions.
|
||||||
|
///
|
||||||
|
/// This is the same as mix(), except for two rules:
|
||||||
|
/// 1) The two quaternions must be unit length.
|
||||||
|
/// 2) The interpolation factor (a) must be in the range [0, 1].
|
||||||
|
///
|
||||||
|
/// This will use the equivalent to fastAcos() and fastSin().
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
/// @see - mix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a)
|
||||||
|
detail::fquatSIMD fastMix( |
||||||
|
detail::fquatSIMD const & x,
|
||||||
|
detail::fquatSIMD const & y,
|
||||||
|
float const & a); |
||||||
|
|
||||||
|
/// Identical to fastMix() except takes the shortest path.
|
||||||
|
///
|
||||||
|
/// The same rules apply here as those in fastMix(). Both quaternions must be unit length and 'a' must be
|
||||||
|
/// in the range [0, 1].
|
||||||
|
///
|
||||||
|
/// @see - fastMix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a)
|
||||||
|
/// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a)
|
||||||
|
detail::fquatSIMD fastSlerp( |
||||||
|
detail::fquatSIMD const & x,
|
||||||
|
detail::fquatSIMD const & y,
|
||||||
|
float const & a); |
||||||
|
|
||||||
|
|
||||||
|
/// Returns the q conjugate.
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD conjugate( |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
/// Returns the q inverse.
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD inverse( |
||||||
|
detail::fquatSIMD const & q); |
||||||
|
|
||||||
|
/// Build a quaternion from an angle and a normalized axis.
|
||||||
|
///
|
||||||
|
/// @param angle Angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise.
|
||||||
|
/// @param axis Axis of the quaternion, must be normalized.
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD angleAxisSIMD( |
||||||
|
float const & angle,
|
||||||
|
vec3 const & axis); |
||||||
|
|
||||||
|
/// Build a quaternion from an angle and a normalized axis.
|
||||||
|
///
|
||||||
|
/// @param angle Angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise.
|
||||||
|
/// @param x x component of the x-axis, x, y, z must be a normalized axis
|
||||||
|
/// @param y y component of the y-axis, x, y, z must be a normalized axis
|
||||||
|
/// @param z z component of the z-axis, x, y, z must be a normalized axis
|
||||||
|
///
|
||||||
|
/// @see gtc_quaternion
|
||||||
|
detail::fquatSIMD angleAxisSIMD( |
||||||
|
float const & angle,
|
||||||
|
float const & x,
|
||||||
|
float const & y,
|
||||||
|
float const & z); |
||||||
|
|
||||||
|
|
||||||
|
// TODO: Move this to somewhere more appropriate. Used with fastMix() and fastSlerp().
|
||||||
|
/// Performs the equivalent of glm::fastSin() on each component of the given __m128.
|
||||||
|
__m128 fastSin(__m128 x); |
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
}//namespace glm
|
||||||
|
|
||||||
|
#include "simd_quat.inl" |
||||||
|
|
||||||
|
|
||||||
|
#if (GLM_COMPILER & GLM_COMPILER_VC) |
||||||
|
# pragma warning(pop) |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
#endif//(GLM_ARCH != GLM_ARCH_PURE)
|
||||||
|
|
||||||
|
#endif//GLM_GTX_simd_quat
|
@ -0,0 +1,628 @@ |
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
||||||
|
// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) |
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
||||||
|
// Created : 2013-04-22 |
||||||
|
// Updated : 2013-04-22 |
||||||
|
// Licence : This source is under MIT License |
||||||
|
// File : glm/gtx/simd_quat.inl |
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////// |
||||||
|
|
||||||
|
|
||||||
|
namespace glm{ |
||||||
|
namespace detail{ |
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////// |
||||||
|
// Debugging |
||||||
|
#if 0 |
||||||
|
void print(__m128 v) |
||||||
|
{ |
||||||
|
GLM_ALIGN(16) float result[4]; |
||||||
|
_mm_store_ps(result, v); |
||||||
|
|
||||||
|
printf("__m128: %f %f %f %f\n", result[0], result[1], result[2], result[3]); |
||||||
|
} |
||||||
|
|
||||||
|
void print(const fvec4SIMD &v) |
||||||
|
{ |
||||||
|
printf("fvec4SIMD: %f %f %f %f\n", v.x, v.y, v.z, v.w); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////// |
||||||
|
// Implicit basic constructors |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD() |
||||||
|
#ifdef GLM_SIMD_ENABLE_DEFAULT_INIT |
||||||
|
: Data(_mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f)) |
||||||
|
#endif |
||||||
|
{} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(__m128 const & Data) : |
||||||
|
Data(Data) |
||||||
|
{} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(fquatSIMD const & q) : |
||||||
|
Data(q.Data) |
||||||
|
{} |
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////// |
||||||
|
// Explicit basic constructors |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(float const & w, float const & x, float const & y, float const & z) : |
||||||
|
Data(_mm_set_ps(w, z, y, x)) |
||||||
|
{} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(quat const & q) : |
||||||
|
Data(_mm_set_ps(q.w, q.z, q.y, q.x)) |
||||||
|
{} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(vec3 const & eulerAngles) |
||||||
|
{ |
||||||
|
vec3 c = glm::cos(eulerAngles * 0.5f); |
||||||
|
vec3 s = glm::sin(eulerAngles * 0.5f); |
||||||
|
|
||||||
|
Data = _mm_set_ps( |
||||||
|
(c.x * c.y * c.z) + (s.x * s.y * s.z), |
||||||
|
(c.x * c.y * s.z) - (s.x * s.y * c.z), |
||||||
|
(c.x * s.y * c.z) + (s.x * c.y * s.z), |
||||||
|
(s.x * c.y * c.z) - (c.x * s.y * s.z)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////// |
||||||
|
// Unary arithmetic operators |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator=(fquatSIMD const & q) |
||||||
|
{ |
||||||
|
this->Data = q.Data; |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator*=(float const & s) |
||||||
|
{ |
||||||
|
this->Data = _mm_mul_ps(this->Data, _mm_set_ps1(s)); |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator/=(float const & s) |
||||||
|
{ |
||||||
|
this->Data = _mm_div_ps(Data, _mm_set1_ps(s)); |
||||||
|
return *this; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// negate operator |
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator- (fquatSIMD const & q) |
||||||
|
{ |
||||||
|
return fquatSIMD(_mm_mul_ps(q.Data, _mm_set_ps(-1.0f, -1.0f, -1.0f, -1.0f))); |
||||||
|
} |
||||||
|
|
||||||
|
// operator+ |
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator+ (fquatSIMD const & q1, fquatSIMD const & q2) |
||||||
|
{ |
||||||
|
return fquatSIMD(_mm_add_ps(q1.Data, q2.Data)); |
||||||
|
} |
||||||
|
|
||||||
|
//operator* |
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator* (fquatSIMD const & q1, fquatSIMD const & q2) |
||||||
|
{ |
||||||
|
// SSE2 STATS: |
||||||
|
// 11 shuffle |
||||||
|
// 8 mul |
||||||
|
// 8 add |
||||||
|
|
||||||
|
// SSE4 STATS: |
||||||
|
// 3 shuffle |
||||||
|
// 4 mul |
||||||
|
// 4 dpps |
||||||
|
|
||||||
|
__m128 mul0 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(0, 1, 2, 3))); |
||||||
|
__m128 mul1 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(1, 0, 3, 2))); |
||||||
|
__m128 mul2 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(2, 3, 0, 1))); |
||||||
|
__m128 mul3 = _mm_mul_ps(q1.Data, q2.Data); |
||||||
|
|
||||||
|
# if((GLM_ARCH & GLM_ARCH_SSE4)) |
||||||
|
__m128 add0 = _mm_dp_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f), 0xff); |
||||||
|
__m128 add1 = _mm_dp_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f), 0xff); |
||||||
|
__m128 add2 = _mm_dp_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f), 0xff); |
||||||
|
__m128 add3 = _mm_dp_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f), 0xff); |
||||||
|
# else |
||||||
|
mul0 = _mm_mul_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f)); |
||||||
|
__m128 add0 = _mm_add_ps(mul0, _mm_movehl_ps(mul0, mul0)); |
||||||
|
add0 = _mm_add_ss(add0, _mm_shuffle_ps(add0, add0, 1)); |
||||||
|
|
||||||
|
mul1 = _mm_mul_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f)); |
||||||
|
__m128 add1 = _mm_add_ps(mul1, _mm_movehl_ps(mul1, mul1)); |
||||||
|
add1 = _mm_add_ss(add1, _mm_shuffle_ps(add1, add1, 1)); |
||||||
|
|
||||||
|
mul2 = _mm_mul_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f)); |
||||||
|
__m128 add2 = _mm_add_ps(mul2, _mm_movehl_ps(mul2, mul2)); |
||||||
|
add2 = _mm_add_ss(add2, _mm_shuffle_ps(add2, add2, 1)); |
||||||
|
|
||||||
|
mul3 = _mm_mul_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f)); |
||||||
|
__m128 add3 = _mm_add_ps(mul3, _mm_movehl_ps(mul3, mul3)); |
||||||
|
add3 = _mm_add_ss(add3, _mm_shuffle_ps(add3, add3, 1)); |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
// This SIMD code is a politically correct way of doing this, but in every test I've tried it has been slower than |
||||||
|
// the final code below. I'll keep this here for reference - maybe somebody else can do something better... |
||||||
|
// |
||||||
|
//__m128 xxyy = _mm_shuffle_ps(add0, add1, _MM_SHUFFLE(0, 0, 0, 0)); |
||||||
|
//__m128 zzww = _mm_shuffle_ps(add2, add3, _MM_SHUFFLE(0, 0, 0, 0)); |
||||||
|
// |
||||||
|
//return _mm_shuffle_ps(xxyy, zzww, _MM_SHUFFLE(2, 0, 2, 0)); |
||||||
|
|
||||||
|
float x; |
||||||
|
float y; |
||||||
|
float z; |
||||||
|
float w; |
||||||
|
|
||||||
|
_mm_store_ss(&x, add0); |
||||||
|
_mm_store_ss(&y, add1); |
||||||
|
_mm_store_ss(&z, add2); |
||||||
|
_mm_store_ss(&w, add3); |
||||||
|
|
||||||
|
return detail::fquatSIMD(w, x, y, z); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fvec4SIMD operator* (fquatSIMD const & q, fvec4SIMD const & v) |
||||||
|
{ |
||||||
|
static const __m128 two = _mm_set1_ps(2.0f); |
||||||
|
|
||||||
|
__m128 q_wwww = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 3, 3, 3)); |
||||||
|
__m128 q_swp0 = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
__m128 q_swp1 = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 v_swp0 = _mm_shuffle_ps(v.Data, v.Data, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
__m128 v_swp1 = _mm_shuffle_ps(v.Data, v.Data, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
|
||||||
|
__m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); |
||||||
|
__m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
__m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); |
||||||
|
|
||||||
|
|
||||||
|
uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); |
||||||
|
uuv = _mm_mul_ps(uuv, two); |
||||||
|
|
||||||
|
return _mm_add_ps(v.Data, _mm_add_ps(uv, uuv)); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v, fquatSIMD const & q) |
||||||
|
{ |
||||||
|
return inverse(q) * v; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator* (fquatSIMD const & q, float s) |
||||||
|
{ |
||||||
|
return fquatSIMD(_mm_mul_ps(q.Data, _mm_set1_ps(s))); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator* (float s, fquatSIMD const & q) |
||||||
|
{ |
||||||
|
return fquatSIMD(_mm_mul_ps(_mm_set1_ps(s), q.Data)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//operator/ |
||||||
|
GLM_FUNC_QUALIFIER fquatSIMD operator/ (fquatSIMD const & q, float s) |
||||||
|
{ |
||||||
|
return fquatSIMD(_mm_div_ps(q.Data, _mm_set1_ps(s))); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
}//namespace detail |
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER quat quat_cast |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x |
||||||
|
) |
||||||
|
{ |
||||||
|
GLM_ALIGN(16) quat Result; |
||||||
|
_mm_store_ps(&Result[0], x.Data); |
||||||
|
|
||||||
|
return Result; |
||||||
|
} |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast_impl(const T m0[], const T m1[], const T m2[]) |
||||||
|
{ |
||||||
|
T trace = m0[0] + m1[1] + m2[2] + T(1.0); |
||||||
|
if (trace > T(0)) |
||||||
|
{ |
||||||
|
T s = T(0.5) / sqrt(trace); |
||||||
|
|
||||||
|
return _mm_set_ps( |
||||||
|
static_cast<float>(T(0.25) / s), |
||||||
|
static_cast<float>((m0[1] - m1[0]) * s), |
||||||
|
static_cast<float>((m2[0] - m0[2]) * s), |
||||||
|
static_cast<float>((m1[2] - m2[1]) * s)); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
if (m0[0] > m1[1]) |
||||||
|
{ |
||||||
|
if (m0[0] > m2[2]) |
||||||
|
{ |
||||||
|
// X is biggest. |
||||||
|
T s = sqrt(m0[0] - m1[1] - m2[2] + T(1.0)) * T(0.5); |
||||||
|
|
||||||
|
return _mm_set_ps( |
||||||
|
static_cast<float>((m1[2] - m2[1]) * s), |
||||||
|
static_cast<float>((m2[0] + m0[2]) * s), |
||||||
|
static_cast<float>((m0[1] + m1[0]) * s), |
||||||
|
static_cast<float>(T(0.5) * s)); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
if (m1[1] > m2[2]) |
||||||
|
{ |
||||||
|
// Y is biggest. |
||||||
|
T s = sqrt(m1[1] - m0[0] - m2[2] + T(1.0)) * T(0.5); |
||||||
|
|
||||||
|
return _mm_set_ps( |
||||||
|
static_cast<float>((m2[0] - m0[2]) * s), |
||||||
|
static_cast<float>((m1[2] + m2[1]) * s), |
||||||
|
static_cast<float>(T(0.5) * s), |
||||||
|
static_cast<float>((m0[1] + m1[0]) * s)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Z is biggest. |
||||||
|
T s = sqrt(m2[2] - m0[0] - m1[1] + T(1.0)) * T(0.5); |
||||||
|
|
||||||
|
return _mm_set_ps( |
||||||
|
static_cast<float>((m0[1] - m1[0]) * s), |
||||||
|
static_cast<float>(T(0.5) * s), |
||||||
|
static_cast<float>((m1[2] + m2[1]) * s), |
||||||
|
static_cast<float>((m2[0] + m0[2]) * s)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast |
||||||
|
( |
||||||
|
detail::fmat4x4SIMD const & m |
||||||
|
) |
||||||
|
{ |
||||||
|
// Scalar implementation for now. |
||||||
|
GLM_ALIGN(16) float m0[4]; |
||||||
|
GLM_ALIGN(16) float m1[4]; |
||||||
|
GLM_ALIGN(16) float m2[4]; |
||||||
|
|
||||||
|
_mm_store_ps(m0, m[0].Data); |
||||||
|
_mm_store_ps(m1, m[1].Data); |
||||||
|
_mm_store_ps(m2, m[2].Data); |
||||||
|
|
||||||
|
return quatSIMD_cast_impl(m0, m1, m2); |
||||||
|
} |
||||||
|
|
||||||
|
template <typename T, precision P> |
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast |
||||||
|
( |
||||||
|
detail::tmat4x4<T, P> const & m |
||||||
|
) |
||||||
|
{ |
||||||
|
return quatSIMD_cast_impl(&m[0][0], &m[1][0], &m[2][0]); |
||||||
|
} |
||||||
|
|
||||||
|
template <typename T, precision P> |
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast |
||||||
|
( |
||||||
|
detail::tmat3x3<T, P> const & m |
||||||
|
) |
||||||
|
{ |
||||||
|
return quatSIMD_cast_impl(&m[0][0], &m[1][0], &m[2][0]); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fmat4x4SIMD mat4SIMD_cast |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
detail::fmat4x4SIMD result; |
||||||
|
|
||||||
|
__m128 _wwww = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 3, 3, 3)); |
||||||
|
__m128 _xyzw = q.Data; |
||||||
|
__m128 _zxyw = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 _yzxw = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
|
||||||
|
__m128 _xyzw2 = _mm_add_ps(_xyzw, _xyzw); |
||||||
|
__m128 _zxyw2 = _mm_shuffle_ps(_xyzw2, _xyzw2, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 _yzxw2 = _mm_shuffle_ps(_xyzw2, _xyzw2, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
|
||||||
|
__m128 _tmp0 = _mm_sub_ps(_mm_set1_ps(1.0f), _mm_mul_ps(_yzxw2, _yzxw)); |
||||||
|
_tmp0 = _mm_sub_ps(_tmp0, _mm_mul_ps(_zxyw2, _zxyw)); |
||||||
|
|
||||||
|
__m128 _tmp1 = _mm_mul_ps(_yzxw2, _xyzw); |
||||||
|
_tmp1 = _mm_add_ps(_tmp1, _mm_mul_ps(_zxyw2, _wwww)); |
||||||
|
|
||||||
|
__m128 _tmp2 = _mm_mul_ps(_zxyw2, _xyzw); |
||||||
|
_tmp2 = _mm_sub_ps(_tmp2, _mm_mul_ps(_yzxw2, _wwww)); |
||||||
|
|
||||||
|
|
||||||
|
// There's probably a better, more politically correct way of doing this... |
||||||
|
result[0].Data = _mm_set_ps( |
||||||
|
0.0f, |
||||||
|
reinterpret_cast<float*>(&_tmp2)[0], |
||||||
|
reinterpret_cast<float*>(&_tmp1)[0], |
||||||
|
reinterpret_cast<float*>(&_tmp0)[0]); |
||||||
|
|
||||||
|
result[1].Data = _mm_set_ps( |
||||||
|
0.0f, |
||||||
|
reinterpret_cast<float*>(&_tmp1)[1], |
||||||
|
reinterpret_cast<float*>(&_tmp0)[1], |
||||||
|
reinterpret_cast<float*>(&_tmp2)[1]); |
||||||
|
|
||||||
|
result[2].Data = _mm_set_ps( |
||||||
|
0.0f, |
||||||
|
reinterpret_cast<float*>(&_tmp0)[2], |
||||||
|
reinterpret_cast<float*>(&_tmp2)[2], |
||||||
|
reinterpret_cast<float*>(&_tmp1)[2]); |
||||||
|
|
||||||
|
result[3].Data = _mm_set_ps( |
||||||
|
1.0f, |
||||||
|
0.0f, |
||||||
|
0.0f, |
||||||
|
0.0f); |
||||||
|
|
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER mat4 mat4_cast |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
return mat4_cast(mat4SIMD_cast(q)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER float length |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
return glm::sqrt(dot(q, q)); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD normalize |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
return _mm_mul_ps(q.Data, _mm_set1_ps(1.0f / length(q))); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER float dot |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q1, |
||||||
|
detail::fquatSIMD const & q2 |
||||||
|
) |
||||||
|
{ |
||||||
|
float result; |
||||||
|
_mm_store_ss(&result, detail::sse_dot_ps(q1.Data, q2.Data)); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD mix |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x, |
||||||
|
detail::fquatSIMD const & y, |
||||||
|
float const & a |
||||||
|
) |
||||||
|
{ |
||||||
|
float cosTheta = dot(x, y); |
||||||
|
|
||||||
|
if (cosTheta > 1.0f - glm::epsilon<float>()) |
||||||
|
{ |
||||||
|
return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
float angle = glm::acos(cosTheta); |
||||||
|
|
||||||
|
|
||||||
|
float s0 = glm::sin((1.0f - a) * angle); |
||||||
|
float s1 = glm::sin(a * angle); |
||||||
|
float d = 1.0f / glm::sin(angle); |
||||||
|
|
||||||
|
return (s0 * x + s1 * y) * d; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD lerp |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x, |
||||||
|
detail::fquatSIMD const & y, |
||||||
|
float const & a |
||||||
|
) |
||||||
|
{ |
||||||
|
// Lerp is only defined in [0, 1] |
||||||
|
assert(a >= 0.0f); |
||||||
|
assert(a <= 1.0f); |
||||||
|
|
||||||
|
return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD slerp |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x, |
||||||
|
detail::fquatSIMD const & y, |
||||||
|
float const & a |
||||||
|
) |
||||||
|
{ |
||||||
|
detail::fquatSIMD z = y; |
||||||
|
|
||||||
|
float cosTheta = dot(x, y); |
||||||
|
|
||||||
|
// If cosTheta < 0, the interpolation will take the long way around the sphere. |
||||||
|
// To fix this, one quat must be negated. |
||||||
|
if (cosTheta < 0.0f) |
||||||
|
{ |
||||||
|
z = -y; |
||||||
|
cosTheta = -cosTheta; |
||||||
|
} |
||||||
|
|
||||||
|
// Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator |
||||||
|
if(cosTheta > 1.0f - epsilon<float>()) |
||||||
|
{ |
||||||
|
return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
float angle = glm::acos(cosTheta); |
||||||
|
|
||||||
|
|
||||||
|
float s0 = glm::sin((1.0f - a) * angle); |
||||||
|
float s1 = glm::sin(a * angle); |
||||||
|
float d = 1.0f / glm::sin(angle); |
||||||
|
|
||||||
|
return (s0 * x + s1 * y) * d; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD fastMix |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x, |
||||||
|
detail::fquatSIMD const & y, |
||||||
|
float const & a |
||||||
|
) |
||||||
|
{ |
||||||
|
float cosTheta = dot(x, y); |
||||||
|
|
||||||
|
if (cosTheta > 1.0f - glm::epsilon<float>()) |
||||||
|
{ |
||||||
|
return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
float angle = glm::fastAcos(cosTheta); |
||||||
|
|
||||||
|
|
||||||
|
__m128 s = glm::fastSin(_mm_set_ps((1.0f - a) * angle, a * angle, angle, 0.0f)); |
||||||
|
|
||||||
|
__m128 s0 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(3, 3, 3, 3)); |
||||||
|
__m128 s1 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(2, 2, 2, 2)); |
||||||
|
__m128 d = _mm_div_ps(_mm_set1_ps(1.0f), _mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 1, 1))); |
||||||
|
|
||||||
|
return _mm_mul_ps(_mm_add_ps(_mm_mul_ps(s0, x.Data), _mm_mul_ps(s1, y.Data)), d); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD fastSlerp |
||||||
|
( |
||||||
|
detail::fquatSIMD const & x, |
||||||
|
detail::fquatSIMD const & y, |
||||||
|
float const & a |
||||||
|
) |
||||||
|
{ |
||||||
|
detail::fquatSIMD z = y; |
||||||
|
|
||||||
|
float cosTheta = dot(x, y); |
||||||
|
if (cosTheta < 0.0f) |
||||||
|
{ |
||||||
|
z = -y; |
||||||
|
cosTheta = -cosTheta; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if(cosTheta > 1.0f - epsilon<float>()) |
||||||
|
{ |
||||||
|
return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
float angle = glm::fastAcos(cosTheta); |
||||||
|
|
||||||
|
|
||||||
|
__m128 s = glm::fastSin(_mm_set_ps((1.0f - a) * angle, a * angle, angle, 0.0f)); |
||||||
|
|
||||||
|
__m128 s0 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(3, 3, 3, 3)); |
||||||
|
__m128 s1 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(2, 2, 2, 2)); |
||||||
|
__m128 d = _mm_div_ps(_mm_set1_ps(1.0f), _mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 1, 1))); |
||||||
|
|
||||||
|
return _mm_mul_ps(_mm_add_ps(_mm_mul_ps(s0, x.Data), _mm_mul_ps(s1, y.Data)), d); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD conjugate |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
return detail::fquatSIMD(_mm_mul_ps(q.Data, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f))); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD inverse |
||||||
|
( |
||||||
|
detail::fquatSIMD const & q |
||||||
|
) |
||||||
|
{ |
||||||
|
return conjugate(q) / dot(q, q); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD angleAxisSIMD |
||||||
|
( |
||||||
|
float const & angle, |
||||||
|
vec3 const & v |
||||||
|
) |
||||||
|
{ |
||||||
|
#ifdef GLM_FORCE_RADIANS |
||||||
|
float a(angle); |
||||||
|
#else |
||||||
|
float a(glm::radians(angle)); |
||||||
|
#endif |
||||||
|
float s = glm::sin(a * 0.5f); |
||||||
|
|
||||||
|
return _mm_set_ps( |
||||||
|
glm::cos(a * 0.5f), |
||||||
|
v.z * s, |
||||||
|
v.y * s, |
||||||
|
v.x * s); |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER detail::fquatSIMD angleAxisSIMD |
||||||
|
( |
||||||
|
float const & angle, |
||||||
|
float const & x, |
||||||
|
float const & y, |
||||||
|
float const & z |
||||||
|
) |
||||||
|
{ |
||||||
|
return angleAxisSIMD(angle, vec3(x, y, z)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 fastSin(__m128 x) |
||||||
|
{ |
||||||
|
static const __m128 c0 = _mm_set1_ps(0.16666666666666666666666666666667f); |
||||||
|
static const __m128 c1 = _mm_set1_ps(0.00833333333333333333333333333333f); |
||||||
|
static const __m128 c2 = _mm_set1_ps(0.00019841269841269841269841269841f); |
||||||
|
|
||||||
|
__m128 x3 = _mm_mul_ps(x, _mm_mul_ps(x, x)); |
||||||
|
__m128 x5 = _mm_mul_ps(x3, _mm_mul_ps(x, x)); |
||||||
|
__m128 x7 = _mm_mul_ps(x5, _mm_mul_ps(x, x)); |
||||||
|
|
||||||
|
__m128 y0 = _mm_mul_ps(x3, c0); |
||||||
|
__m128 y1 = _mm_mul_ps(x5, c1); |
||||||
|
__m128 y2 = _mm_mul_ps(x7, c2); |
||||||
|
|
||||||
|
return _mm_sub_ps(_mm_add_ps(_mm_sub_ps(x, y0), y1), y2); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
}//namespace glm |
Loading…
Reference in New Issue