Add more Quaternion methods for SimpleMath (#116)
This commit is contained in:
Родитель
0a267e7afe
Коммит
5013cab0b8
|
@ -713,6 +713,9 @@ namespace DirectX
|
|||
|
||||
float Dot(const Quaternion& Q) const noexcept;
|
||||
|
||||
void RotateTowards(const Quaternion& target, float maxAngle) noexcept;
|
||||
void __cdecl RotateTowards(const Quaternion& target, float maxAngle, Quaternion& result) const noexcept;
|
||||
|
||||
// Computes rotation about y-axis (y), then x-axis (x), then z-axis (z)
|
||||
Vector3 ToEuler() const noexcept;
|
||||
|
||||
|
@ -736,6 +739,14 @@ namespace DirectX
|
|||
static void Concatenate(const Quaternion& q1, const Quaternion& q2, Quaternion& result) noexcept;
|
||||
static Quaternion Concatenate(const Quaternion& q1, const Quaternion& q2) noexcept;
|
||||
|
||||
static void __cdecl FromToRotation(const Vector3& fromDir, const Vector3& toDir, Quaternion& result) noexcept;
|
||||
static Quaternion FromToRotation(const Vector3& fromDir, const Vector3& toDir) noexcept;
|
||||
|
||||
static void __cdecl LookRotation(const Vector3& forward, const Vector3& up, Quaternion& result) noexcept;
|
||||
static Quaternion LookRotation(const Vector3& forward, const Vector3& up) noexcept;
|
||||
|
||||
static float Angle(const Quaternion& q1, const Quaternion& q2) noexcept;
|
||||
|
||||
// Constants
|
||||
static const Quaternion Identity;
|
||||
};
|
||||
|
@ -762,11 +773,11 @@ namespace DirectX
|
|||
Color(const XMFLOAT4& c) noexcept { this->x = c.x; this->y = c.y; this->z = c.z; this->w = c.w; }
|
||||
explicit Color(const XMVECTORF32& F) noexcept { this->x = F.f[0]; this->y = F.f[1]; this->z = F.f[2]; this->w = F.f[3]; }
|
||||
|
||||
explicit Color(const DirectX::PackedVector::XMCOLOR& Packed) noexcept;
|
||||
// BGRA Direct3D 9 D3DCOLOR packed color
|
||||
explicit Color(const DirectX::PackedVector::XMCOLOR& Packed) noexcept;
|
||||
|
||||
explicit Color(const DirectX::PackedVector::XMUBYTEN4& Packed) noexcept;
|
||||
// RGBA XNA Game Studio packed color
|
||||
explicit Color(const DirectX::PackedVector::XMUBYTEN4& Packed) noexcept;
|
||||
|
||||
Color(const Color&) = default;
|
||||
Color& operator=(const Color&) = default;
|
||||
|
|
|
@ -3115,6 +3115,11 @@ inline float Quaternion::Dot(const Quaternion& q) const noexcept
|
|||
return XMVectorGetX(XMQuaternionDot(q1, q2));
|
||||
}
|
||||
|
||||
inline void Quaternion::RotateTowards(const Quaternion& target, float maxAngle) noexcept
|
||||
{
|
||||
RotateTowards(target, maxAngle, *this);
|
||||
}
|
||||
|
||||
inline Vector3 Quaternion::ToEuler() const noexcept
|
||||
{
|
||||
float xx = x * x;
|
||||
|
@ -3273,6 +3278,34 @@ inline Quaternion Quaternion::Concatenate(const Quaternion& q1, const Quaternion
|
|||
return result;
|
||||
}
|
||||
|
||||
inline Quaternion Quaternion::FromToRotation(const Vector3& fromDir, const Vector3& toDir) noexcept
|
||||
{
|
||||
Quaternion result;
|
||||
FromToRotation(fromDir, toDir, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) noexcept
|
||||
{
|
||||
Quaternion result;
|
||||
LookRotation(forward, up, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline float Quaternion::Angle(const Quaternion& q1, const Quaternion& q2) noexcept
|
||||
{
|
||||
using namespace DirectX;
|
||||
XMVECTOR Q0 = XMLoadFloat4(&q1);
|
||||
XMVECTOR Q1 = XMLoadFloat4(&q2);
|
||||
|
||||
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
|
||||
XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(Q0), Q1);
|
||||
|
||||
float rs = XMVectorGetW(R);
|
||||
R = XMVector3Length(R);
|
||||
return 2.f * atan2f(XMVectorGetX(R), rs);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
|
|
|
@ -54,6 +54,95 @@ namespace DirectX
|
|||
}
|
||||
}
|
||||
|
||||
using namespace DirectX;
|
||||
using namespace DirectX::SimpleMath;
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Quaternion
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void Quaternion::RotateTowards(const Quaternion& target, float maxAngle, Quaternion& result) const noexcept
|
||||
{
|
||||
XMVECTOR T = XMLoadFloat4(this);
|
||||
|
||||
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
|
||||
XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(T), target);
|
||||
|
||||
float rs = XMVectorGetW(R);
|
||||
XMVECTOR L = XMVector3Length(R);
|
||||
float angle = 2.f * atan2f(XMVectorGetX(L), rs);
|
||||
if (angle > maxAngle)
|
||||
{
|
||||
XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngle);
|
||||
XMVECTOR Q = XMQuaternionMultiply(delta, T);
|
||||
XMStoreFloat4(&result, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't overshoot.
|
||||
result = target;
|
||||
}
|
||||
}
|
||||
|
||||
void Quaternion::FromToRotation(const Vector3& fromDir, const Vector3& toDir, Quaternion& result) noexcept
|
||||
{
|
||||
// Melax, "The Shortest Arc Quaternion", Game Programming Gems, Charles River Media (2000).
|
||||
|
||||
XMVECTOR F = XMVector3Normalize(fromDir);
|
||||
XMVECTOR T = XMVector3Normalize(toDir);
|
||||
|
||||
float dot = XMVectorGetX(XMVector3Dot(F, T));
|
||||
if (dot >= 1.f)
|
||||
{
|
||||
result = Identity;
|
||||
}
|
||||
else if (dot <= -1.f)
|
||||
{
|
||||
XMVECTOR axis = XMVector3Cross(F, Vector3::Right);
|
||||
if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon))
|
||||
{
|
||||
axis = XMVector3Cross(F, Vector3::Up);
|
||||
}
|
||||
|
||||
XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI);
|
||||
XMStoreFloat4(&result, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
XMVECTOR C = XMVector3Cross(F, T);
|
||||
XMStoreFloat4(&result, C);
|
||||
|
||||
float s = sqrtf((1.f + dot) * 2.f);
|
||||
result.x /= s;
|
||||
result.y /= s;
|
||||
result.z /= s;
|
||||
result.w = s * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
void Quaternion::LookRotation(const Vector3& forward, const Vector3& up, Quaternion& result) noexcept
|
||||
{
|
||||
Quaternion q1;
|
||||
FromToRotation(Vector3::Forward, forward, q1);
|
||||
|
||||
XMVECTOR C = XMVector3Cross(forward, up);
|
||||
if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon))
|
||||
{
|
||||
// forward and up are co-linear
|
||||
result = q1;
|
||||
return;
|
||||
}
|
||||
|
||||
XMVECTOR U = XMQuaternionMultiply(q1, Vector3::Up);
|
||||
|
||||
Quaternion q2;
|
||||
FromToRotation(U, up, q2);
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionMultiply(q2, q1));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
|
@ -82,7 +171,7 @@ static_assert(offsetof(DirectX::SimpleMath::Viewport, maxDepth) == offsetof(D3D1
|
|||
#endif
|
||||
|
||||
#if defined(__dxgi1_2_h__) || defined(__d3d11_x_h__) || defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__)
|
||||
RECT DirectX::SimpleMath::Viewport::ComputeDisplayArea(DXGI_SCALING scaling, UINT backBufferWidth, UINT backBufferHeight, int outputWidth, int outputHeight) noexcept
|
||||
RECT Viewport::ComputeDisplayArea(DXGI_SCALING scaling, UINT backBufferWidth, UINT backBufferHeight, int outputWidth, int outputHeight) noexcept
|
||||
{
|
||||
RECT rct = {};
|
||||
|
||||
|
@ -143,7 +232,7 @@ RECT DirectX::SimpleMath::Viewport::ComputeDisplayArea(DXGI_SCALING scaling, UIN
|
|||
}
|
||||
#endif
|
||||
|
||||
RECT DirectX::SimpleMath::Viewport::ComputeTitleSafeArea(UINT backBufferWidth, UINT backBufferHeight) noexcept
|
||||
RECT Viewport::ComputeTitleSafeArea(UINT backBufferWidth, UINT backBufferHeight) noexcept
|
||||
{
|
||||
float safew = (float(backBufferWidth) + 19.f) / 20.f;
|
||||
float safeh = (float(backBufferHeight) + 19.f) / 20.f;
|
||||
|
|
Загрузка…
Ссылка в новой задаче