Finished quaternion implementation

This commit is contained in:
Diren D Bharwani 2022-10-23 20:03:18 +08:00
parent bf0c068cc7
commit 57f9898e07
4 changed files with 148 additions and 35 deletions

View File

@ -211,15 +211,6 @@ namespace SHADE
return XMVectorGetX(XMQuaternionDot(*this, rhs)); return XMVectorGetX(XMQuaternionDot(*this, rhs));
} }
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept
{
SHQuaternion result;
// TODO (Diren)
return result;
}
SHVec3 SHQuaternion::ToEuler() const noexcept SHVec3 SHQuaternion::ToEuler() const noexcept
{ {
const float XX = x * x; const float XX = x * x;
@ -317,19 +308,32 @@ namespace SHADE
} }
float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept
{ {
// TODO (Diren) XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2);
return 0.0f; const float RS = XMVectorGetW(R);
R = XMVector3Length(R);
return 2.0f * atan2f(XMVectorGetX(R), RS);
} }
SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept
{ {
SHQuaternion result; SHQuaternion result;
// TODO (Diren) XMVECTOR R = XMVectorZero();
if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R))
{
R = XMVectorLerp(q1, q2, t);
}
else
{
const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t));
const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t));
R = XMVectorSubtract(X0, X1);
}
XMStoreFloat4(&result, XMQuaternionNormalize(R));
return result; return result;
} }
@ -341,13 +345,102 @@ namespace SHADE
return result; return result;
} }
SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
{ {
return Lerp(q1, q2, std::clamp(t, tMin, tMax));
}
SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
{
return Slerp(q1, q2, std::clamp(t, tMin, tMax));
}
SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept
{
// Melax, "The Shortest Arc Quaternion", Game Programming Gems
SHQuaternion result; SHQuaternion result;
// TODO (Diren) const XMVECTOR F = XMVector3Normalize(from);
const XMVECTOR T = XMVector3Normalize(to);
const float dot = XMVectorGetX(XMVector3Dot(F, T));
if (dot >= 1.f)
{
result = Identity;
}
else if (dot <= -1.f)
{
XMVECTOR axis = XMVector3Cross(F, SHVec3::Right);
if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon))
{
axis = XMVector3Cross(F, SHVec3::Up);
}
const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI);
XMStoreFloat4(&result, Q);
}
else
{
const XMVECTOR C = XMVector3Cross(F, T);
XMStoreFloat4(&result, C);
const float s = sqrtf((1.f + dot) * 2.f);
result.x /= s;
result.y /= s;
result.z /= s;
result.w = s * 0.5f;
}
return result; return result;
} }
SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept
{
SHQuaternion result;
const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward);
const XMVECTOR C = XMVector3Cross(forward, up);
if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon))
{
// forward and up are co-linear
return Q1;
}
SHVec3 qU;
XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up));
const SHQuaternion Q2 = FromToRotation(qU, up);
XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1));
return result;
}
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept
{
SHQuaternion result;
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to);
const float RS = XMVectorGetW(R);
const XMVECTOR L = XMVector3Length(R);
const float angle = 2.f * atan2f(XMVectorGetX(L), RS);
if (angle > maxAngleInRad)
{
const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad);
const XMVECTOR Q = XMQuaternionMultiply(delta, from);
XMStoreFloat4(&result, Q);
}
else
{
// Don't overshoot.
result = to;
}
return result;
}
} // namespace SHADE } // namespace SHADE

View File

@ -51,7 +51,6 @@ namespace SHADE
SHQuaternion () noexcept; SHQuaternion () noexcept;
SHQuaternion (const SHVec4& vec4) noexcept; SHQuaternion (const SHVec4& vec4) noexcept;
SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept;
SHQuaternion (float yaw, float pitch, float roll) noexcept;
// Conversion from other math types // Conversion from other math types
@ -103,7 +102,6 @@ namespace SHADE
[[nodiscard]] float Length () const noexcept; [[nodiscard]] float Length () const noexcept;
[[nodiscard]] float LengthSquared () const noexcept; [[nodiscard]] float LengthSquared () const noexcept;
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
[[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept;
[[nodiscard]] SHVec3 ToEuler () const noexcept; [[nodiscard]] SHVec3 ToEuler () const noexcept;
[[nodiscard]] std::string ToString () const noexcept; [[nodiscard]] std::string ToString () const noexcept;
@ -124,8 +122,12 @@ namespace SHADE
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; [[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
[[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
[[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
[[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept; [[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept;
[[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept;
[[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept;
}; };
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept; SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;

View File

@ -0,0 +1,17 @@
/************************************************************************************//*!
\file Quaternion.hxx
\author Diren D Bharwani, diren.dbharwani, 390002520
\par email: diren.dbharwani\@digipen.edu
\date Oct 23, 2022
\brief Contains the definitions of Quaternion struct.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// TODO(Diren)

View File

@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited. of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once #pragma once
// Standard Libraries // Standard Libraries