Improve math module (#396)

* Improve math module

- Mark almost everything constexpr
- Equality (a == b) is now exact, down to the bit level. If you want approximate equality use the new ApproxEqual method/static method
- Rename Nz::Extend to Nz::Extent
- Removed Make[] and Set[] methods in favor of their static counterpart and operator=
This commit is contained in:
Jérôme Leclercq
2023-06-02 22:30:51 +02:00
committed by GitHub
parent de88873c35
commit 1a55b550fb
64 changed files with 2200 additions and 3758 deletions

View File

@@ -26,9 +26,8 @@ namespace Nz
*
* \remark Position will be (0, 0, 0)
*/
template<typename T>
Box<T>::Box(T Width, T Height, T Depth) :
constexpr Box<T>::Box(T Width, T Height, T Depth) :
x(0),
y(0),
z(0),
@@ -49,7 +48,7 @@ namespace Nz
* \param Depth Depth of the box (following Z)
*/
template<typename T>
Box<T>::Box(T X, T Y, T Z, T Width, T Height, T Depth) :
constexpr Box<T>::Box(T X, T Y, T Z, T Width, T Height, T Depth) :
x(X),
y(Y),
z(Z),
@@ -67,7 +66,7 @@ namespace Nz
* \remark Z position is 0 and depth is 1
*/
template<typename T>
Box<T>::Box(const Rect<T>& rect) :
constexpr Box<T>::Box(const Rect<T>& rect) :
x(rect.x),
y(rect.y),
z(0),
@@ -85,7 +84,7 @@ namespace Nz
* \param lengths (Width, Height, Depth) of the box
*/
template<typename T>
Box<T>::Box(const Vector3<T>& lengths) :
constexpr Box<T>::Box(const Vector3<T>& lengths) :
Box(Vector3<T>::Zero(), lengths)
{
}
@@ -97,7 +96,7 @@ namespace Nz
* \param lengths (Width, Height, Depth) of the box
*/
template<typename T>
Box<T>::Box(const Vector3<T>& pos, const Vector3<T>& lengths) :
constexpr Box<T>::Box(const Vector3<T>& pos, const Vector3<T>& lengths) :
x(pos.x),
y(pos.y),
z(pos.z),
@@ -112,10 +111,9 @@ namespace Nz
*
* \param box Box of type U to convert to type T
*/
template<typename T>
template<typename U>
Box<T>::Box(const Box<U>& box) :
constexpr Box<T>::Box(const Box<U>& box) :
x(static_cast<T>(box.x)),
y(static_cast<T>(box.y)),
z(static_cast<T>(box.z)),
@@ -135,16 +133,15 @@ namespace Nz
*
* \see Contains
*/
template<typename T>
bool Box<T>::ApproxEquals(const Box& box, T maxDifference) const
constexpr bool Box<T>::ApproxEqual(const Box& box, T maxDifference) const
{
return NumberEquals(x, box.x, maxDifference) && NumberEquals(y, box.y, maxDifference) && NumberEquals(z, box.z, maxDifference) &&
NumberEquals(width, box.width, maxDifference) && NumberEquals(height, box.height, maxDifference) && NumberEquals(depth, box.depth, maxDifference);
}
template<typename T>
bool Box<T>::Contains(T X, T Y, T Z) const
constexpr bool Box<T>::Contains(T X, T Y, T Z) const
{
return X >= x && X < x + width &&
Y >= y && Y < y + height &&
@@ -159,9 +156,8 @@ namespace Nz
*
* \see Contains
*/
template<typename T>
bool Box<T>::Contains(const Box<T>& box) const
constexpr bool Box<T>::Contains(const Box<T>& box) const
{
return Contains(box.x, box.y, box.z) &&
Contains(box.x + box.width, box.y + box.height, box.z + box.depth);
@@ -175,9 +171,8 @@ namespace Nz
*
* \see Contains
*/
template<typename T>
bool Box<T>::Contains(const Vector3<T>& point) const
constexpr bool Box<T>::Contains(const Vector3<T>& point) const
{
return Contains(point.x, point.y, point.z);
}
@@ -192,9 +187,8 @@ namespace Nz
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(T X, T Y, T Z)
constexpr Box<T>& Box<T>::ExtendTo(T X, T Y, T Z)
{
width = std::max(x + width, X);
height = std::max(y + height, Y);
@@ -219,9 +213,8 @@ namespace Nz
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(const Box& box)
constexpr Box<T>& Box<T>::ExtendTo(const Box& box)
{
width = std::max(x + width, box.x + box.width);
height = std::max(y + height, box.y + box.height);
@@ -246,9 +239,8 @@ namespace Nz
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(const Vector3<T>& point)
constexpr Box<T>& Box<T>::ExtendTo(const Vector3<T>& point)
{
return ExtendTo(point.x, point.y, point.z);
}
@@ -259,9 +251,8 @@ namespace Nz
*
* \see GetSquaredBoundingSphere
*/
template<typename T>
Sphere<T> Box<T>::GetBoundingSphere() const
constexpr Sphere<T> Box<T>::GetBoundingSphere() const
{
return Sphere<T>(GetCenter(), GetRadius());
}
@@ -270,9 +261,8 @@ namespace Nz
* \brief Gets a Vector3 for the center
* \return The position of the center of the box
*/
template<typename T>
Vector3<T> Box<T>::GetCenter() const
constexpr Vector3<T> Box<T>::GetCenter() const
{
return GetPosition() + GetLengths() / T(2.0);
}
@@ -285,9 +275,8 @@ namespace Nz
*
* \remark If enumeration is not defined in BoxCorner, a NazaraError is thrown and a Vector3 uninitialised is returned
*/
template<typename T>
Vector3<T> Box<T>::GetCorner(BoxCorner corner) const
constexpr Vector3<T> Box<T>::GetCorner(BoxCorner corner) const
{
switch (corner)
{
@@ -324,9 +313,8 @@ namespace Nz
* \brief Gets a Vector3 for the lengths
* \return The lengths of the box (width, height, depth)
*/
template<typename T>
Vector3<T> Box<T>::GetLengths() const
constexpr Vector3<T> Box<T>::GetLengths() const
{
return Vector3<T>(width, height, depth);
}
@@ -337,9 +325,8 @@ namespace Nz
*
* \see GetCorner
*/
template<typename T>
Vector3<T> Box<T>::GetMaximum() const
constexpr Vector3<T> Box<T>::GetMaximum() const
{
return GetPosition() + GetLengths();
}
@@ -350,9 +337,8 @@ namespace Nz
*
* \see GetCorner, GetPosition
*/
template<typename T>
Vector3<T> Box<T>::GetMinimum() const
constexpr Vector3<T> Box<T>::GetMinimum() const
{
return GetPosition();
}
@@ -365,9 +351,8 @@ namespace Nz
*
* \see GetPositiveVertex
*/
template<typename T>
Vector3<T> Box<T>::GetNegativeVertex(const Vector3<T>& normal) const
constexpr Vector3<T> Box<T>::GetNegativeVertex(const Vector3<T>& normal) const
{
Vector3<T> neg(GetPosition());
@@ -389,9 +374,8 @@ namespace Nz
*
* \see GetCorner, GetMinimum
*/
template<typename T>
Vector3<T> Box<T>::GetPosition() const
constexpr Vector3<T> Box<T>::GetPosition() const
{
return Vector3<T>(x, y, z);
}
@@ -404,9 +388,8 @@ namespace Nz
*
* \see GetNegativeVertex
*/
template<typename T>
Vector3<T> Box<T>::GetPositiveVertex(const Vector3<T>& normal) const
constexpr Vector3<T> Box<T>::GetPositiveVertex(const Vector3<T>& normal) const
{
Vector3<T> pos(GetPosition());
@@ -426,9 +409,8 @@ namespace Nz
* \brief Gets the radius of the box
* \return Value of the radius which is the biggest distance between a corner and the center
*/
template<typename T>
T Box<T>::GetRadius() const
constexpr T Box<T>::GetRadius() const
{
return std::sqrt(GetSquaredRadius());
}
@@ -439,9 +421,8 @@ namespace Nz
*
* \see GetBoundingSphere
*/
template<typename T>
Sphere<T> Box<T>::GetSquaredBoundingSphere() const
constexpr Sphere<T> Box<T>::GetSquaredBoundingSphere() const
{
return Sphere<T>(GetCenter(), GetSquaredRadius());
}
@@ -450,9 +431,8 @@ namespace Nz
* \brief Gets the squared radius of the box
* \return Value of the squared radius which is the squared of biggest distance between a corner and the center
*/
template<typename T>
T Box<T>::GetSquaredRadius() const
constexpr T Box<T>::GetSquaredRadius() const
{
Vector3<T> size(GetLengths());
size /= T(2.0); // The size only depends on the lengths and not the center
@@ -467,9 +447,8 @@ namespace Nz
* \param box Box to check
* \param intersection Optional argument for the box which represent the intersection
*/
template<typename T>
bool Box<T>::Intersect(const Box& box, Box* intersection) const
constexpr bool Box<T>::Intersect(const Box& box, Box* intersection) const
{
T left = std::max(x, box.x);
T right = std::min(x + width, box.x + box.width);
@@ -499,7 +478,7 @@ namespace Nz
* \return true if the box has a negative or zero width, height and depth
*/
template<typename T>
bool Box<T>::IsNull() const
constexpr bool Box<T>::IsNull() const
{
return width <= T(0.0) && height <= T(0.0) && depth <= T(0.0);
}
@@ -509,7 +488,7 @@ namespace Nz
* \return true if the box has a positive width, height and depth
*/
template<typename T>
bool Box<T>::IsValid() const
constexpr bool Box<T>::IsValid() const
{
return width >= T(0.0) && height >= T(0.0) && depth >= T(0.0);
}
@@ -521,7 +500,7 @@ namespace Nz
* \param scalar The scalar to multiply width, height and depth with
*/
template<typename T>
Box<T>& Box<T>::Scale(T scalar)
constexpr Box<T>& Box<T>::Scale(T scalar)
{
width *= scalar;
height *= scalar;
@@ -537,7 +516,7 @@ namespace Nz
* \param vec The vector where component one multiply width, two height and three depth
*/
template<typename T>
Box<T>& Box<T>::Scale(const Vector3<T>& vec)
constexpr Box<T>& Box<T>::Scale(const Vector3<T>& vec)
{
width *= vec.x;
height *= vec.y;
@@ -553,7 +532,7 @@ namespace Nz
* \param scalar The scalar to multiply width, height and depth with
*/
template<typename T>
Box<T>& Box<T>::ScaleAroundCenter(T scalar)
constexpr Box<T>& Box<T>::ScaleAroundCenter(T scalar)
{
x -= (width * scalar - width) / T(2.0);
y -= (height * scalar - height) / T(2.0);
@@ -573,7 +552,7 @@ namespace Nz
* \param vec The vector where component one multiply width, two height and three depth
*/
template<typename T>
Box<T>& Box<T>::ScaleAroundCenter(const Vector3<T>& vec)
constexpr Box<T>& Box<T>::ScaleAroundCenter(const Vector3<T>& vec)
{
x -= (width * vec.x - width) / T(2.0);
y -= (height * vec.y - height) / T(2.0);
@@ -606,16 +585,15 @@ namespace Nz
* \param matrix Matrix4 representing the transformation
* \param applyTranslation Should transform the position or the direction
*/
template<typename T>
Box<T>& Box<T>::Transform(const Matrix4<T>& matrix, bool applyTranslation)
{
Vector3<T> center = matrix.Transform(GetCenter(), (applyTranslation) ? T(1.0) : T(0.0)); // Value multiplying the translation
Vector3<T> halfSize = GetLengths() / T(2.0);
halfSize.Set(std::abs(matrix(0,0)) * halfSize.x + std::abs(matrix(1,0)) * halfSize.y + std::abs(matrix(2,0)) * halfSize.z,
std::abs(matrix(0,1)) * halfSize.x + std::abs(matrix(1,1)) * halfSize.y + std::abs(matrix(2,1)) * halfSize.z,
std::abs(matrix(0,2)) * halfSize.x + std::abs(matrix(1,2)) * halfSize.y + std::abs(matrix(2,2)) * halfSize.z);
halfSize = Vector3f(std::abs(matrix(0,0)) * halfSize.x + std::abs(matrix(1,0)) * halfSize.y + std::abs(matrix(2,0)) * halfSize.z,
std::abs(matrix(0,1)) * halfSize.x + std::abs(matrix(1,1)) * halfSize.y + std::abs(matrix(2,1)) * halfSize.z,
std::abs(matrix(0,2)) * halfSize.x + std::abs(matrix(1,2)) * halfSize.y + std::abs(matrix(2,2)) * halfSize.z);
return operator=(Boxf::FromExtends(center - halfSize, center + halfSize));
}
@@ -626,9 +604,8 @@ namespace Nz
*
* \param translation Vector3 which is the translation for the position
*/
template<typename T>
Box<T>& Box<T>::Translate(const Vector3<T>& translation)
constexpr Box<T>& Box<T>::Translate(const Vector3<T>& translation)
{
x += translation.x;
y += translation.y;
@@ -645,9 +622,8 @@ namespace Nz
* \remark Produce a NazaraError if you try to access to index greater than 6 with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of you try to acces to index greather than 6
*/
template<typename T>
T& Box<T>::operator[](std::size_t i)
constexpr T& Box<T>::operator[](std::size_t i)
{
NazaraAssert(i < 6, "Index out of range");
@@ -662,9 +638,8 @@ namespace Nz
* \remark Produce a NazaraError if you try to access to index greater than 6 with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of you try to acces to index greather than 6
*/
template<typename T>
const T& Box<T>::operator[](std::size_t i) const
constexpr const T& Box<T>::operator[](std::size_t i) const
{
NazaraAssert(i < 6, "Index out of range");
@@ -677,9 +652,8 @@ namespace Nz
*
* \param box Other box to compare with
*/
template<typename T>
bool Box<T>::operator==(const Box& box) const
constexpr bool Box<T>::operator==(const Box& box) const
{
return x == box.x && y == box.y && z == box.z && width == box.width && height == box.height && depth == box.depth;
}
@@ -690,13 +664,18 @@ namespace Nz
*
* \param box Other box to compare with
*/
template<typename T>
bool Box<T>::operator!=(const Box& box) const
constexpr bool Box<T>::operator!=(const Box& box) const
{
return !operator==(box);
}
template<typename T>
constexpr Box<T> Box<T>::ApproxEqual(const Box& lhs, const Box& rhs, T maxDifference)
{
return lhs.ApproxEqual(rhs, maxDifference);
}
/*!
* \brief Interpolates the box to other one with a factor of interpolation
* \return A new box which is the interpolation of two rectangles
@@ -711,7 +690,7 @@ namespace Nz
* \see Lerp
*/
template<typename T>
Box<T> Box<T>::FromExtends(const Vector3<T>& vec1, const Vector3<T>& vec2)
constexpr Box<T> Box<T>::FromExtends(const Vector3<T>& vec1, const Vector3<T>& vec2)
{
Box box;
box.x = std::min(vec1.x, vec2.x);
@@ -735,7 +714,7 @@ namespace Nz
* \see Lerp
*/
template<typename T>
Box<T> Box<T>::Lerp(const Box& from, const Box& to, T interpolation)
constexpr Box<T> Box<T>::Lerp(const Box& from, const Box& to, T interpolation)
{
Box box;
box.x = Nz::Lerp(from.x, to.x, interpolation);
@@ -751,11 +730,9 @@ namespace Nz
/*!
* \brief Shorthand for the box (0, 0, 0, 0, 0, 0)
* \return A box with position (0, 0, 0) and lengths (0, 0, 0)
*
* \see MakeZero
*/
template<typename T>
Box<T> Box<T>::Invalid()
constexpr Box<T> Box<T>::Invalid()
{
return Box(-1, -1, -1, -1, -1, -1);
}
@@ -763,11 +740,9 @@ namespace Nz
/*!
* \brief Shorthand for the box (0, 0, 0, 0, 0, 0)
* \return A box with position (0, 0, 0) and lengths (0, 0, 0)
*
* \see MakeZero
*/
template<typename T>
Box<T> Box<T>::Zero()
constexpr Box<T> Box<T>::Zero()
{
return Box(Vector3<T>::Zero(), Vector3<T>::Zero());
}