Math: Add AngleBetween and RotateTowards for Vector3 and Quaternion

This commit is contained in:
SirLynix
2023-12-07 16:50:22 +01:00
parent 3fd696385d
commit f5fefc7b86
4 changed files with 45 additions and 20 deletions

View File

@@ -123,7 +123,7 @@ namespace Nz
*
* \param vec The other vector to measure the angle with
*
* \remark The vectors do not need to be normalised
* \remark The vectors need to be normalised
* \remark Produce a NazaraError if one of the vec components is null with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of the vec components is null
*
@@ -132,20 +132,7 @@ namespace Nz
template<typename T>
RadianAngle<T> Vector3<T>::AngleBetween(const Vector3& vec) const
{
// sqrt(a) * sqrt(b) = sqrt(a*b)
T divisor = std::sqrt(GetSquaredLength() * vec.GetSquaredLength());
#if NAZARA_MATH_SAFE
if (NumberEquals(divisor, T(0.0)))
{
std::string error("Division by zero");
NazaraError(error);
throw std::domain_error(std::move(error));
}
#endif
T alpha = DotProduct(vec) / divisor;
T alpha = DotProduct(vec);
return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0)));
}
@@ -835,6 +822,20 @@ namespace Nz
return min;
}
template<typename T>
Vector3<T> Vector3<T>::RotateTowards(const Vector3& from, const Vector3& to, RadianAngle<T> maxAngle)
{
// https://gamedev.stackexchange.com/a/203036
RadianAngle<T> angleBetween = from.AngleBetween(to);
if (angleBetween < maxAngle)
return to;
Vector3 axis = CrossProduct(from, to);
Quaternion<T> rotationIncrement = Quaternion(maxAngle, axis);
return rotationIncrement * from;
}
/*!
* \brief Gives the normalized vector
* \return A normalized vector from the vec