Add the ability to convert standard mat4s and mat3s to SIMD quats.

This commit is contained in:
Dave Reid 2013-04-24 09:39:22 +10:00
parent 13837e1079
commit 942bf08fe3
2 changed files with 73 additions and 40 deletions

View File

@ -77,7 +77,7 @@ namespace detail
static size_type value_size(); static size_type value_size();
typedef fquatSIMD type; typedef fquatSIMD type;
typedef tquat<bool, highp> bool_type; typedef tquat<bool, defaultp> bool_type;
#ifdef GLM_SIMD_ENABLE_XYZW_UNION #ifdef GLM_SIMD_ENABLE_XYZW_UNION
union union
@ -172,6 +172,18 @@ namespace detail
detail::fquatSIMD quatSIMD_cast( detail::fquatSIMD quatSIMD_cast(
detail::fmat4x4SIMD const & m); 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 //! Convert a simdQuat to a simdMat4
//! (From GLM_GTX_simd_quat extension) //! (From GLM_GTX_simd_quat extension)
detail::fmat4x4SIMD mat4SIMD_cast( detail::fmat4x4SIMD mat4SIMD_cast(

View File

@ -214,37 +214,23 @@ GLM_FUNC_QUALIFIER quat quat_cast
{ {
GLM_ALIGN(16) quat Result; GLM_ALIGN(16) quat Result;
_mm_store_ps(&Result[0], x.Data); _mm_store_ps(&Result[0], x.Data);
return Result; return Result;
} }
GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast template <typename T>
( GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast_impl(const T m0[], const T m1[], const T m2[])
detail::fmat4x4SIMD const & m
)
{ {
// Scalar implementation for now. T trace = m0[0] + m1[1] + m2[2] + T(1.0);
if (trace > T(0))
GLM_ALIGN(16) float m0[4];
GLM_ALIGN(16) float m1[4];
GLM_ALIGN(16) float m2[4];
GLM_ALIGN(16) float m3[4];
_mm_store_ps(m0, m[0].Data);
_mm_store_ps(m1, m[1].Data);
_mm_store_ps(m2, m[2].Data);
_mm_store_ps(m3, m[3].Data);
float trace = m0[0] + m1[1] + m2[2] + 1.0f;
if (trace > 0)
{ {
float s = 0.5f / sqrt(trace); T s = T(0.5) / sqrt(trace);
return _mm_set_ps( return _mm_set_ps(
0.25f / s, static_cast<float>(T(0.25) / s),
(m0[1] - m1[0]) * s, static_cast<float>((m0[1] - m1[0]) * s),
(m2[0] - m0[2]) * s, static_cast<float>((m2[0] - m0[2]) * s),
(m1[2] - m2[1]) * s); static_cast<float>((m1[2] - m2[1]) * s));
} }
else else
{ {
@ -253,13 +239,13 @@ GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast
if (m0[0] > m2[2]) if (m0[0] > m2[2])
{ {
// X is biggest. // X is biggest.
float s = sqrt(m0[0] - m1[1] - m2[2] + 1.0f) * 0.5f; T s = sqrt(m0[0] - m1[1] - m2[2] + T(1.0)) * T(0.5);
return _mm_set_ps( return _mm_set_ps(
(m1[2] - m2[1]) * s, static_cast<float>((m1[2] - m2[1]) * s),
(m2[0] + m0[2]) * s, static_cast<float>((m2[0] + m0[2]) * s),
(m0[1] + m1[0]) * s, static_cast<float>((m0[1] + m1[0]) * s),
0.5f * s); static_cast<float>(T(0.5) * s));
} }
} }
else else
@ -267,27 +253,62 @@ GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast
if (m1[1] > m2[2]) if (m1[1] > m2[2])
{ {
// Y is biggest. // Y is biggest.
float s = sqrt(m1[1] - m0[0] - m2[2] + 1.0f) * 0.5f; T s = sqrt(m1[1] - m0[0] - m2[2] + T(1.0)) * T(0.5);
return _mm_set_ps( return _mm_set_ps(
(m2[0] - m0[2]) * s, static_cast<float>((m2[0] - m0[2]) * s),
(m1[2] + m2[1]) * s, static_cast<float>((m1[2] + m2[1]) * s),
0.5f * s, static_cast<float>(T(0.5) * s),
(m0[1] + m1[0]) * s); static_cast<float>((m0[1] + m1[0]) * s));
} }
} }
// Z is biggest. // Z is biggest.
float s = sqrt(m2[2] - m0[0] - m1[1] + 1.0f) * 0.5f; T s = sqrt(m2[2] - m0[0] - m1[1] + T(1.0)) * T(0.5);
return _mm_set_ps( return _mm_set_ps(
(m0[1] - m1[0]) * s, static_cast<float>((m0[1] - m1[0]) * s),
0.5f * s, static_cast<float>(T(0.5) * s),
(m1[2] + m2[1]) * s, static_cast<float>((m1[2] + m2[1]) * s),
(m2[0] + m0[2]) * 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 GLM_FUNC_QUALIFIER detail::fmat4x4SIMD mat4SIMD_cast
( (