From 0f84f8eda84d2f4a02cbcce32d2754c8b7f34e29 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 13 Jun 2012 17:54:07 +0200 Subject: [PATCH] Added Quaternion spheric interpolation Fixed NzVector(2/3)::Length() and NzQuaternion::Magnitude() returning double instead of template type Added quaternion dot product Added gitignore --- .gitignore | 151 +++++++++++++++++++++++++++++ include/Nazara/Math/Quaternion.hpp | 16 ++- include/Nazara/Math/Quaternion.inl | 108 +++++++++++++++------ include/Nazara/Math/Vector2.hpp | 6 +- include/Nazara/Math/Vector2.inl | 8 +- include/Nazara/Math/Vector3.hpp | 6 +- include/Nazara/Math/Vector3.inl | 8 +- 7 files changed, 254 insertions(+), 49 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..44729e355 --- /dev/null +++ b/.gitignore @@ -0,0 +1,151 @@ +# Codeblocks +*.cbp +*.cscope_file_list +*.depend +*.layout +*.workspace + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so + +# Compiled Static libraries +*.lai +*.la +*.a + +# Object files +*.o + +# Libraries +*.lib + +# Shared objects (inc. Windows DLLs) +*.dll +*.so + +# Executables +*.exe +*.out + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug*/ +[Rr]elease/ + +build/ + + +[Tt]est[Rr]esult +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +*.vssscc +.builds + +*.pidb + +*.log +*.scc +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ + +*.[Rr]e[Ss]harper + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Publish Web Output +*.Publish.xml + +# Others +[Bb]in +[Oo]bj +sql +TestResults +[Tt]est[Rr]esult* +*.Cache +ClientBin +[Ss]tyle[Cc]op.* +~$* +*.dbmdl + +*.[Pp]ublish.xml + +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + +# NuGet +packages/ \ No newline at end of file diff --git a/include/Nazara/Math/Quaternion.hpp b/include/Nazara/Math/Quaternion.hpp index a36a7c4e6..a5e892f2a 100644 --- a/include/Nazara/Math/Quaternion.hpp +++ b/include/Nazara/Math/Quaternion.hpp @@ -26,11 +26,13 @@ template class NzQuaternion NzQuaternion(const NzQuaternion& quat) = default; ~NzQuaternion() = default; + T DotProduct(const NzQuaternion& vec) const; + NzQuaternion GetConjugate() const; NzQuaternion GetNormalized() const; - double Magnitude() const; - double Normalize(); + T Magnitude() const; + T Normalize(); T SquaredMagnitude() const; void Set(T W, T X, T Y, T Z); @@ -47,14 +49,16 @@ template class NzQuaternion //NzMatrix3 ToRotationMatrix() const; NzString ToString() const; + NzQuaternion operator+(const NzQuaternion& quat) const; NzQuaternion operator*(const NzQuaternion& quat) const; NzVector3 operator*(const NzVector3& vec) const; NzQuaternion operator*(T scale) const; NzQuaternion operator/(const NzQuaternion& quat) const; - NzQuaternion operator*=(const NzQuaternion& quat); - NzQuaternion operator*=(T scale); - NzQuaternion operator/=(const NzQuaternion& quat); + NzQuaternion& operator+=(const NzQuaternion& quat); + NzQuaternion& operator*=(const NzQuaternion& quat); + NzQuaternion& operator*=(T scale); + NzQuaternion& operator/=(const NzQuaternion& quat); bool operator==(const NzQuaternion& quat) const; bool operator!=(const NzQuaternion& quat) const; @@ -63,6 +67,8 @@ template class NzQuaternion bool operator>(const NzQuaternion& quat) const; bool operator>=(const NzQuaternion& quat) const; + static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp); + T w, x, y, z; }; diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 1017798df..a49fbde81 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -52,6 +52,12 @@ NzQuaternion::NzQuaternion(const NzQuaternion& quat) Set(quat); } +template +T NzQuaternion::DotProduct(const NzQuaternion& vec) const +{ + return w*vec.w + x*vec.x + y*vec.y + z.vec.z; +} + template NzQuaternion NzQuaternion::GetConjugate() const { @@ -68,19 +74,19 @@ NzQuaternion NzQuaternion::GetNormalized() const } template -double NzQuaternion::Magnitude() const +T NzQuaternion::Magnitude() const { return std::sqrt(SquaredMagnitude()); } template -double NzQuaternion::Normalize() +T NzQuaternion::Normalize() { T squaredLength = SquaredMagnitude(); if (std::fabs(squaredLength) > 0.00001 && std::fabs(squaredLength - 1.0) > 0.00001) { - double length = std::sqrt(squaredLength); + T length = std::sqrt(squaredLength); w /= length; x /= length; @@ -90,7 +96,7 @@ double NzQuaternion::Normalize() return length; } else - return std::sqrt(squaredLength); + return 1.0; // Le quaternion est déjà normalisé } template @@ -106,8 +112,6 @@ void NzQuaternion::Set(T W, T X, T Y, T Z) x = X; y = Y; z = Z; - - Normalize(); } template @@ -117,8 +121,6 @@ void NzQuaternion::Set(T quat[4]) x = quat[1]; y = quat[2]; z = quat[3]; - - Normalize(); } template @@ -175,6 +177,52 @@ void NzQuaternion::SetZero() Set(0.0, 0.0, 0.0, 0.0); } +template +NzQuaternion NzQuaternion::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp) +{ + if (interp <= 0.0) + return quatA; + + if (interp >= 1.0) + return quatB; + + NzQuaternion q; + + T cosOmega = quatA.DotProduct(quatB); + if (cosOmega < 0.0) + { + // On inverse tout + q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z); + cosOmega = -cosOmega; + } + else + q.Set(quatB); + + T k0, k1; + if (cosOmega > 0.9999) + { + // Interpolation linéaire pour éviter une division par zéro + k0 = 1.0 - interp; + k1 = interp; + } + else + { + T sinOmega = std::sqrt(1.0f - (cosOmega * cosOmega)); + T omega = std::atan2(sinOmega, cosOmega); + + // Pour éviter deux divisions + sinOmega = 1/sinOmega; + + k0 = std::sin((1.0 - interp) * omega) * sinOmega; + k1 = std::sin(interp * omega) * sinOmega; + } + + /* interpolate and return new quaternion */ + NzQuaternion result(k0 * quatA.w, k0 * quatA.x, k0 * quatA.y, k0 * quatA.z); + + return result += q; +} + template NzEulerAngles NzQuaternion::ToEulerAngles() const { @@ -203,17 +251,22 @@ NzString NzQuaternion::ToString() const return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')'; } +template +NzQuaternion NzQuaternion::operator+(const NzQuaternion& quat) const +{ + return NzQuaternion(w + quat.w, + x + quat.x, + y + quat.y, + z + quat.z); +} + template NzQuaternion NzQuaternion::operator*(const NzQuaternion& quat) const { - NzQuaternion result(w * quat.w - x * quat.x - y * quat.y - z * quat.z, + return NzQuaternion(w * quat.w - x * quat.x - y * quat.y - z * quat.z, w * quat.x + x * quat.w + y * quat.z - z * quat.y, w * quat.y + y * quat.w + z * quat.x - x * quat.z, w * quat.z + z * quat.w + x * quat.y - y * quat.x); - - result.Normalize(); - - return result; } template @@ -223,9 +276,7 @@ NzVector3 NzQuaternion::operator*(const NzVector3& vec) const normal.Normalise(); NzQuaternion qvec(0.0, normal.x, normal.y, normal.z); - NzQuaternion result; - - result = operator*(qvec * GetConjugate()); + NzQuaternion result = operator*(qvec * GetConjugate()); return NzVector3(result.x, result.y, result.z); @@ -247,30 +298,27 @@ NzQuaternion NzQuaternion::operator/(const NzQuaternion& quat) const } template -NzQuaternion NzQuaternion::operator*=(const NzQuaternion& quat) +NzQuaternion& NzQuaternion::operator+=(const NzQuaternion& quat) { - NzQuaternion q(*this); - - return operator=(q * quat); + return operator=(operator+(quat)); } template -NzQuaternion NzQuaternion::operator*=(T scale) +NzQuaternion& NzQuaternion::operator*=(const NzQuaternion& quat) { - w *= scale; - x *= scale; - y *= scale; - z *= scale; - - return *this; + return operator=(operator*(quat)); } template -NzQuaternion NzQuaternion::operator/=(const NzQuaternion& quat) +NzQuaternion& NzQuaternion::operator*=(T scale) { - NzQuaternion q(*this); + return operator=(operator*(scale)); +} - return operator=(q / quat); +template +NzQuaternion& NzQuaternion::operator/=(const NzQuaternion& quat) +{ + return operator=(operator/(quat)); } template diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index bd2c54017..ec12330c0 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.hpp @@ -21,13 +21,13 @@ template class NzVector2 ~NzVector2() = default; T AbsDotProduct(const NzVector2& vec) const; - double Distance(const NzVector2& vec) const; + T Distance(const NzVector2& vec) const; T DotProduct(const NzVector2& vec) const; NzVector2 GetNormal() const; void MakeCeil(const NzVector2& vec); void MakeFloor(const NzVector2& vec); - double Length() const; - double Normalize(); + T Length() const; + T Normalize(); T SquaredDistance(const NzVector2& vec) const; T SquaredLength() const; diff --git a/include/Nazara/Math/Vector2.inl b/include/Nazara/Math/Vector2.inl index 3026f860b..d8214981c 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -55,7 +55,7 @@ template<> inline int NzVector2::AbsDotProduct(const NzVector2& vec) c } template -double NzVector2::Distance(const NzVector2& vec) const +T NzVector2::Distance(const NzVector2& vec) const { return std::sqrt(SquaredDistance(vec)); } @@ -96,15 +96,15 @@ void NzVector2::MakeFloor(const NzVector2& vec) } template -double NzVector2::Length() const +T NzVector2::Length() const { return std::sqrt(SquaredLength()); } template -double NzVector2::Normalize() +T NzVector2::Normalize() { - double length = Length(); + T length = Length(); if (length != 0.f) { diff --git a/include/Nazara/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index bd0dc9b35..563ec83c8 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -22,13 +22,13 @@ template class NzVector3 T AbsDotProduct(const NzVector3& vec) const; NzVector3 CrossProduct(const NzVector3& vec) const; - double Distance(const NzVector3& vec) const; + T Distance(const NzVector3& vec) const; T DotProduct(const NzVector3& vec) const; NzVector3 GetNormal() const; void MakeCeil(const NzVector3& vec); void MakeFloor(const NzVector3& vec); - double Length() const; - double Normalize(); + T Length() const; + T Normalize(); T SquaredDistance(const NzVector3& vec) const; T SquaredLength() const; diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index 40e1cabb7..30c1e15e4 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -65,7 +65,7 @@ NzVector3 NzVector3::CrossProduct(const NzVector3& vec) const } template -double NzVector3::Distance(const NzVector3& vec) const +T NzVector3::Distance(const NzVector3& vec) const { return std::sqrt(SquaredDistance(vec)); } @@ -112,15 +112,15 @@ void NzVector3::MakeFloor(const NzVector3& vec) } template -double NzVector3::Length() const +T NzVector3::Length() const { return std::sqrt(SquaredLength()); } template -double NzVector3::Normalize() +T NzVector3::Normalize() { - double length = Length(); + T length = Length(); if (length != 0.f) {