diff --git a/include/Nazara/Math/Angle.hpp b/include/Nazara/Math/Angle.hpp index 58c54b862..6fb3acce6 100644 --- a/include/Nazara/Math/Angle.hpp +++ b/include/Nazara/Math/Angle.hpp @@ -34,18 +34,16 @@ namespace Nz constexpr Angle(Angle&&) noexcept = default; ~Angle() = default; + constexpr bool ApproxEqual(const Angle& angle) const; + constexpr bool ApproxEqual(const Angle& angle, T maxDifference) const; + T GetCos() const; T GetSin() const; std::pair GetSinCos() const; T GetTan() const; - constexpr Angle& MakeZero(); - constexpr Angle& Normalize(); - constexpr Angle& Set(Angle ang); - template constexpr Angle& Set(const Angle& ang); - template T To() const; template Angle ToAngle() const; constexpr T ToDegrees() const; @@ -76,7 +74,13 @@ namespace Nz constexpr bool operator==(Angle other) const; constexpr bool operator!=(Angle other) const; + constexpr bool operator<(Angle other) const; + constexpr bool operator<=(Angle other) const; + constexpr bool operator>(Angle other) const; + constexpr bool operator>=(Angle other) const; + static constexpr bool ApproxEqual(const Angle& lhs, const Angle& rhs); + static constexpr bool ApproxEqual(const Angle& lhs, const Angle& rhs, T maxDifference); template static constexpr Angle From(T value); static constexpr Angle FromDegrees(T degrees); static constexpr Angle FromRadians(T radians); diff --git a/include/Nazara/Math/Angle.inl b/include/Nazara/Math/Angle.inl index 3205f68da..c2c46a653 100644 --- a/include/Nazara/Math/Angle.inl +++ b/include/Nazara/Math/Angle.inl @@ -189,6 +189,13 @@ namespace Nz { } + template + template + constexpr Angle::Angle(const Angle& angle) : + value(static_cast(angle.value)) + { + } + /*! * \brief Constructs an Angle object from a angle in a specific unit, converting if required * @@ -201,6 +208,18 @@ namespace Nz { } + template + constexpr bool Angle::ApproxEqual(const Angle& angle) const + { + return ApproxEqual(angle, Detail::AngleUtils::template GetEpsilon()); + } + + template + constexpr bool Angle::ApproxEqual(const Angle& angle, T maxDifference) const + { + return NumberEquals(value, angle.value, maxDifference); + } + /*! * \brief Computes the cosine of the angle * \return Cosine of angle @@ -254,16 +273,6 @@ namespace Nz return std::tan(ToRadians()); } - /*! - * \brief Changes the angle value to zero - */ - template - constexpr Angle& Angle::MakeZero() - { - value = T(0); - return *this; - } - /*! * \brief Normalizes the angle value * @@ -284,33 +293,6 @@ namespace Nz return *this; } - /*! - * \brief Copies the angle value of an angle - * - * \param Angle Angle which will be copied - */ - template - constexpr Angle& Angle::Set(Angle ang) - { - value = ang.value; - return *this; - } - - /*! - * \brief Changes the angle value to the same as an Angle of a different type - * - * \param Angle Angle which will be casted - * - * \remark Conversion from U to T occurs using static_cast - */ - template - template - constexpr Angle& Angle::Set(const Angle& ang) - { - value = static_cast(ang.value); - return *this; - } - /*! * \brief Returns the ToUnit angle that is equivalent to this one * \return Equivalent ToUnit angle value @@ -586,7 +568,7 @@ namespace Nz template constexpr bool Angle::operator==(Angle other) const { - return NumberEquals(value, other.value, Detail::AngleUtils::template GetEpsilon()); + return value == other.value; } /*! @@ -598,7 +580,43 @@ namespace Nz template constexpr bool Angle::operator!=(Angle other) const { - return !NumberEquals(value, other.value, Detail::AngleUtils::template GetEpsilon()); + return value != other.value; + } + + template + constexpr bool Angle::operator<(Angle other) const + { + return value < other.value; + } + + template + constexpr bool Angle::operator<=(Angle other) const + { + return value <= other.value; + } + + template + constexpr bool Angle::operator>(Angle other) const + { + return value > other.value; + } + + template + constexpr bool Angle::operator>=(Angle other) const + { + return value >= other.value; + } + + template + constexpr bool Angle::ApproxEqual(const Angle& lhs, const Angle& rhs) + { + return lhs.ApproxEqual(rhs); + } + + template + constexpr bool Angle::ApproxEqual(const Angle& lhs, const Angle& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); } /*! diff --git a/include/Nazara/Math/BoundingVolume.hpp b/include/Nazara/Math/BoundingVolume.hpp index 0678cadde..7df0e2c0c 100644 --- a/include/Nazara/Math/BoundingVolume.hpp +++ b/include/Nazara/Math/BoundingVolume.hpp @@ -22,40 +22,46 @@ namespace Nz class BoundingVolume { public: - BoundingVolume(); - BoundingVolume(Extend Extend); - BoundingVolume(const Box& box); - BoundingVolume(const OrientedBox& orientedBox); - template explicit BoundingVolume(const BoundingVolume& volume); - BoundingVolume(const BoundingVolume& volume) = default; + constexpr BoundingVolume(); + constexpr BoundingVolume(Extent Extend); + constexpr BoundingVolume(const Box& box); + constexpr BoundingVolume(const OrientedBox& orientedBox); + template constexpr explicit BoundingVolume(const BoundingVolume& volume); + constexpr BoundingVolume(const BoundingVolume&) = default; + constexpr BoundingVolume(BoundingVolume&&) = default; ~BoundingVolume() = default; - BoundingVolume& ExtendTo(const BoundingVolume& volume); + constexpr bool ApproxEqual(const BoundingVolume& volume, T maxDifference = std::numeric_limits::epsilon()) const; - bool Intersect(const Box& box) const; + constexpr BoundingVolume& ExtendTo(const BoundingVolume& volume); - bool IsFinite() const; - bool IsInfinite() const; - bool IsNull() const; + constexpr bool Intersect(const Box& box) const; + + constexpr bool IsFinite() const; + constexpr bool IsInfinite() const; + constexpr bool IsNull() const; std::string ToString() const; - void Update(const Matrix4& transformMatrix); - void Update(const Vector3& translation); + constexpr void Update(const Matrix4& transformMatrix); + constexpr void Update(const Vector3& translation); - BoundingVolume operator*(T scalar) const; - BoundingVolume& operator=(const BoundingVolume& other) = default; + BoundingVolume& operator=(const BoundingVolume&) = default; + BoundingVolume& operator=(BoundingVolume&&) = default; - BoundingVolume& operator*=(T scalar); + constexpr BoundingVolume operator*(T scalar) const; - bool operator==(const BoundingVolume& volume) const; - bool operator!=(const BoundingVolume& volume) const; + constexpr BoundingVolume& operator*=(T scalar); - static BoundingVolume Infinite(); - static BoundingVolume Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation); - static BoundingVolume Null(); + constexpr bool operator==(const BoundingVolume& volume) const; + constexpr bool operator!=(const BoundingVolume& volume) const; - Extend extend; + static constexpr bool ApproxEqual(const BoundingVolume& lhs, const BoundingVolume& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr BoundingVolume Infinite(); + static constexpr BoundingVolume Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation); + static constexpr BoundingVolume Null(); + + Extent extent; Box aabb; OrientedBox obb; }; diff --git a/include/Nazara/Math/BoundingVolume.inl b/include/Nazara/Math/BoundingVolume.inl index 8d317ac70..06003f0f5 100644 --- a/include/Nazara/Math/BoundingVolume.inl +++ b/include/Nazara/Math/BoundingVolume.inl @@ -24,25 +24,23 @@ namespace Nz /*! * \brief Constructs a BoundingVolume object by default * - * \remark extend is set to Extend::Null, aabb and obb are uninitialized + * \remark extent is set to Extent::Null, aabb and obb are uninitialized */ - template - BoundingVolume::BoundingVolume() : - extend(Extend::Null) + constexpr BoundingVolume::BoundingVolume() : + extent(Extent::Null) { } /*! - * \brief Constructs a BoundingVolume object from Extend - * \param Extend Extend of the volume part of enumeration Extend + * \brief Constructs a BoundingVolume object from Extent + * \param Extent Extent of the volume part of enumeration Extent * * \remark Aabb and obb are uninitialized */ - template - BoundingVolume::BoundingVolume(Extend Extend) : - extend(Extend) + constexpr BoundingVolume::BoundingVolume(Extent Extend) : + extent(Extend) { } @@ -53,10 +51,9 @@ namespace Nz * * \remark Aabb is uninitialized */ - template - BoundingVolume::BoundingVolume(const Box& box) : - extend(Extend::Finite), + constexpr BoundingVolume::BoundingVolume(const Box& box) : + extent(Extent::Finite), obb(box) { } @@ -68,10 +65,9 @@ namespace Nz * * \remark Aabb is uninitialized */ - template - BoundingVolume::BoundingVolume(const OrientedBox& orientedBox) : - extend(Extend::Finite), + constexpr BoundingVolume::BoundingVolume(const OrientedBox& orientedBox) : + extent(Extent::Finite), obb(orientedBox) { } @@ -81,16 +77,27 @@ namespace Nz * * \param volume BoundingVolume of type U to convert to type T */ - template template - BoundingVolume::BoundingVolume(const BoundingVolume& volume) : - extend(volume.extend), + constexpr BoundingVolume::BoundingVolume(const BoundingVolume& volume) : + extent(volume.extent), aabb(volume.aabb), obb(volume.obb) { } + template + constexpr bool BoundingVolume::ApproxEqual(const BoundingVolume& volume, T maxDifference) const + { + if (extent != volume.extent) + return false; + + if (extent != Extent::Finite) + return true; + + return aabb.ApproxEqual(volume.aabb) && obb.ApproxEqual(volume.obb); + } + /*! * \brief Extends the bounding volume to contain another bounding volume * \return A reference to the the bounding volume @@ -100,35 +107,35 @@ namespace Nz * \remark Extending to a null bounding volume has no effect while extending to a infinite bounding volume will set it as infinite */ template - BoundingVolume& BoundingVolume::ExtendTo(const BoundingVolume& volume) + constexpr BoundingVolume& BoundingVolume::ExtendTo(const BoundingVolume& volume) { - switch (extend) + switch (extent) { - case Extend::Finite: + case Extent::Finite: { - switch (volume.extend) + switch (volume.extent) { - case Extend::Finite: + case Extent::Finite: { - // Extend the OBB local box + // Extent the OBB local box obb.localBox.ExtendTo(volume.obb.localBox); break; } - case Extend::Infinite: - extend = Extend::Infinite; + case Extent::Infinite: + extent = Extent::Infinite; break; - case Extend::Null: + case Extent::Null: break; } break; } - case Extend::Infinite: + case Extent::Infinite: break; //< We already contain the bounding volume - case Extend::Null: + case Extent::Null: Set(volume); break; } @@ -137,17 +144,17 @@ namespace Nz } template - bool BoundingVolume::Intersect(const Box& box) const + constexpr bool BoundingVolume::Intersect(const Box& box) const { - switch (extend) + switch (extent) { - case Extend::Infinite: + case Extent::Infinite: return true; - case Extend::Finite: + case Extent::Finite: return aabb.Intersect(box); - case Extend::Null: + case Extent::Null: return false; } @@ -156,43 +163,42 @@ namespace Nz /*! * \brief Checks whether the volume is finite - * \return true if extend is Extend::Finite + * \return true if extent is Extent::Finite */ template - bool BoundingVolume::IsFinite() const + constexpr bool BoundingVolume::IsFinite() const { - return extend == Extend::Finite; + return extent == Extent::Finite; } /*! * \brief Checks whether the volume is infinite - * \return true if extend is Extend::Infinite + * \return true if extent is Extent::Infinite */ template - bool BoundingVolume::IsInfinite() const + constexpr bool BoundingVolume::IsInfinite() const { - return extend == Extend::Infinite; + return extent == Extent::Infinite; } /*! * \brief Checks whether the volume is null - * \return true if extend is Extend::Null + * \return true if extent is Extent::Null */ template - bool BoundingVolume::IsNull() const + constexpr bool BoundingVolume::IsNull() const { - return extend == Extend::Null; + return extent == Extent::Null; } /*! * \brief Gives a string representation * \return A string representation of the object: "BoundingVolume(localBox="")" if finite, or "BoundingVolume(Infinite)" or "BoundingVolume(Null)" * - * \remark If enumeration is not defined in Extend, a NazaraError is thrown and "BoundingVolume(ERROR)" is returned + * \remark If enumeration is not defined in Extent, a NazaraError is thrown and "BoundingVolume(ERROR)" is returned */ - template std::string BoundingVolume::ToString() const { @@ -207,13 +213,12 @@ namespace Nz * * \param transformMatrix Matrix4 which represents the transformation to apply */ - template - void BoundingVolume::Update(const Matrix4& transformMatrix) + constexpr void BoundingVolume::Update(const Matrix4& transformMatrix) { obb.Update(transformMatrix); - aabb = Boxf::FromExtends(obb(0), obb(1)); + aabb = Box::FromExtends(obb(0), obb(1)); for (unsigned int i = 2; i < 8; ++i) aabb.ExtendTo(obb(i)); } @@ -223,13 +228,12 @@ namespace Nz * * \param translation Vector3 which represents the translation to apply */ - template - void BoundingVolume::Update(const Vector3& translation) + constexpr void BoundingVolume::Update(const Vector3& translation) { obb.Update(translation); - aabb = Boxf::FromExtends(obb(0), obb(1)); + aabb = Box::FromExtends(obb(0), obb(1)); for (unsigned int i = 2; i < 8; ++i) aabb.ExtendTo(obb(i)); } @@ -240,9 +244,8 @@ namespace Nz * * \param scale The scalar to multiply width, height and depth with */ - template - BoundingVolume BoundingVolume::operator*(T scalar) const + constexpr BoundingVolume BoundingVolume::operator*(T scalar) const { BoundingVolume volume(*this); volume *= scalar; @@ -256,9 +259,8 @@ namespace Nz * * \param scalar The scalar to multiply width, height and depth with */ - template - BoundingVolume& BoundingVolume::operator*=(T scalar) + constexpr BoundingVolume& BoundingVolume::operator*=(T scalar) { obb *= scalar; @@ -271,17 +273,22 @@ namespace Nz * * \param volume Other bounding volume to compare with */ - template - bool BoundingVolume::operator==(const BoundingVolume& volume) const + constexpr bool BoundingVolume::operator==(const BoundingVolume& volume) const { - if (extend == volume.extend) - if (extend == Extend::Finite) - return obb == volume.obb; - else - return true; - else + if (extent != volume.extent) return false; + + if (extent == Extent::Finite) + { + if (aabb != volume.aabb) + return false; + + if (obb != volume.obb) + return false; + } + + return true; } /*! @@ -290,27 +297,26 @@ namespace Nz * * \param volume Other bounding volume to compare with */ - template - bool BoundingVolume::operator!=(const BoundingVolume& volume) const + constexpr bool BoundingVolume::operator!=(const BoundingVolume& volume) const { return !operator==(volume); } - /*! - * \brief Shorthand for the bounding volume (Extend::Infinite) - * \return A bounding volume with Extend::Infinite - * - * \see MakeInfinite - */ - template - BoundingVolume BoundingVolume::Infinite() + constexpr bool BoundingVolume::ApproxEqual(const BoundingVolume& lhs, const BoundingVolume& rhs, T maxDifference) { - BoundingVolume volume; - volume.extend = Extend::Infinite; + return lhs.ApproxEqual(rhs, maxDifference); + } - return volume; + /*! + * \brief Shorthand for the bounding volume (Extent::Infinite) + * \return A bounding volume with Extent::Infinite + */ + template + constexpr BoundingVolume BoundingVolume::Infinite() + { + return BoundingVolume(Extent::Infinite); } /*! @@ -323,13 +329,12 @@ namespace Nz * * \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior * \remark With NAZARA_DEBUG, a NazaraError is thrown and Null() is returned - * \remark If enumeration is not defined in Extend, a NazaraError is thrown and Null() is returned + * \remark If enumeration is not defined in Extent, a NazaraError is thrown and Null() is returned * * \see Lerp */ - template - BoundingVolume BoundingVolume::Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation) + constexpr BoundingVolume BoundingVolume::Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation) { if (NumberEquals(interpolation, T(0.0))) return from; @@ -337,19 +342,19 @@ namespace Nz if (NumberEquals(interpolation, T(1.0))) return to; - switch (to.extend) + switch (to.extent) { - case Extend::Finite: + case Extent::Finite: { - switch (from.extend) + switch (from.extent) { - case Extend::Finite: + case Extent::Finite: return BoundingVolume{ OrientedBox::Lerp(from.obb, to.obb, interpolation) }; - case Extend::Infinite: + case Extent::Infinite: return Infinite(); - case Extend::Null: + case Extent::Null: { Box destBox = to.obb.localBox; destBox.Scale(interpolation); @@ -358,19 +363,19 @@ namespace Nz } } - // If we arrive here, the extend is invalid - NazaraError("Invalid extend type (From) (0x" + NumberToString(UnderlyingCast(from.extend), 16) + ')'); + // If we arrive here, the extent is invalid + NazaraError("Invalid extent type (From) (0x" + NumberToString(UnderlyingCast(from.extent), 16) + ')'); return Null(); } - case Extend::Infinite: + case Extent::Infinite: return Infinite(); // A little bit of infinity is already too much ;) - case Extend::Null: + case Extent::Null: { - switch (from.extend) + switch (from.extent) { - case Extend::Finite: + case Extent::Finite: { Box fromBox = from.obb.localBox; fromBox.Scale(T(1.0) - interpolation); @@ -378,38 +383,32 @@ namespace Nz return { fromBox }; } - case Extend::Infinite: + case Extent::Infinite: return Infinite(); - case Extend::Null: + case Extent::Null: return Null(); } - // If we arrive here, the extend is invalid - NazaraError("Invalid extend type (From) (0x" + NumberToString(UnderlyingCast(from.extend), 16) + ')'); + // If we arrive here, the extent is invalid + NazaraError("Invalid extent type (From) (0x" + NumberToString(UnderlyingCast(from.extent), 16) + ')'); return Null(); } } - // If we arrive here, the extend is invalid - NazaraError("Invalid extend type (To) (0x" + NumberToString(UnderlyingCast(to.extend), 16) + ')'); + // If we arrive here, the extent is invalid + NazaraError("Invalid extent type (To) (0x" + NumberToString(UnderlyingCast(to.extent), 16) + ')'); return Null(); } /*! - * \brief Shorthand for the bounding volume (Extend::Null) - * \return A bounding volume with Extend::Null - * - * \see MakeNull + * \brief Shorthand for the bounding volume (Extent::Null) + * \return A bounding volume with Extent::Null */ - template - BoundingVolume BoundingVolume::Null() + constexpr BoundingVolume BoundingVolume::Null() { - BoundingVolume volume; - volume.extend = Extend::Null; - - return volume; + return BoundingVolume(Extent::Null); } /*! @@ -424,7 +423,7 @@ namespace Nz template bool Serialize(SerializationContext& context, const BoundingVolume& boundingVolume, TypeTag>) { - if (!Serialize(context, static_cast(boundingVolume.extend))) + if (!Serialize(context, static_cast(boundingVolume.extent))) return false; if (!Serialize(context, boundingVolume.aabb)) @@ -452,10 +451,10 @@ namespace Nz if (!Unserialize(context, &extend)) return false; - if (extend > UnderlyingCast(Extend::Max)) + if (extend > UnderlyingCast(Extent::Max)) return false; - boundingVolume->extend = static_cast(extend); + boundingVolume->extent = static_cast(extend); if (!Unserialize(context, &boundingVolume->aabb)) return false; @@ -476,17 +475,17 @@ namespace Nz template std::ostream& operator<<(std::ostream& out, const Nz::BoundingVolume& volume) { - switch (volume.extend) + switch (volume.extent) { - case Nz::Extend::Finite: + case Nz::Extent::Finite: out << "BoundingVolume(localBox=" << volume.obb.localBox << ')'; break; - case Nz::Extend::Infinite: + case Nz::Extent::Infinite: out << "BoundingVolume(Infinite)"; break; - case Nz::Extend::Null: + case Nz::Extent::Null: out << "BoundingVolume(Null)"; break; } diff --git a/include/Nazara/Math/Box.hpp b/include/Nazara/Math/Box.hpp index 1f06d421d..1b7004134 100644 --- a/include/Nazara/Math/Box.hpp +++ b/include/Nazara/Math/Box.hpp @@ -22,69 +22,70 @@ namespace Nz class Box { public: - Box() = default; - Box(T Width, T Height, T Depth); - Box(T X, T Y, T Z, T Width, T Height, T Depth); - Box(const Rect& rect); - explicit Box(const Vector3& lengths); - explicit Box(const Vector3& pos, const Vector3& lengths); - template explicit Box(const Box& box); - Box(const Box&) = default; - Box(Box&&) noexcept = default; + constexpr Box() = default; + constexpr Box(T Width, T Height, T Depth); + constexpr Box(T X, T Y, T Z, T Width, T Height, T Depth); + constexpr Box(const Rect& rect); + constexpr explicit Box(const Vector3& lengths); + constexpr explicit Box(const Vector3& pos, const Vector3& lengths); + template constexpr explicit Box(const Box& box); + constexpr Box(const Box&) = default; + constexpr Box(Box&&) = default; ~Box() = default; - bool ApproxEquals(const Box& box, T maxDifference = 0) const; + constexpr bool ApproxEqual(const Box& box, T maxDifference = std::numeric_limits::epsilon()) const; - bool Contains(T X, T Y, T Z) const; - bool Contains(const Box& box) const; - bool Contains(const Vector3& point) const; + constexpr bool Contains(T X, T Y, T Z) const; + constexpr bool Contains(const Box& box) const; + constexpr bool Contains(const Vector3& point) const; - Box& ExtendTo(T X, T Y, T Z); - Box& ExtendTo(const Box& box); - Box& ExtendTo(const Vector3& point); + constexpr Box& ExtendTo(T X, T Y, T Z); + constexpr Box& ExtendTo(const Box& box); + constexpr Box& ExtendTo(const Vector3& point); - Sphere GetBoundingSphere() const; - Vector3 GetCenter() const; - Vector3 GetCorner(BoxCorner corner) const; - Vector3 GetLengths() const; - Vector3 GetMaximum() const; - Vector3 GetMinimum() const; - Vector3 GetNegativeVertex(const Vector3& normal) const; - Vector3 GetPosition() const; - Vector3 GetPositiveVertex(const Vector3& normal) const; - T GetRadius() const; - Sphere GetSquaredBoundingSphere() const; - T GetSquaredRadius() const; + constexpr Sphere GetBoundingSphere() const; + constexpr Vector3 GetCenter() const; + constexpr Vector3 GetCorner(BoxCorner corner) const; + constexpr Vector3 GetLengths() const; + constexpr Vector3 GetMaximum() const; + constexpr Vector3 GetMinimum() const; + constexpr Vector3 GetNegativeVertex(const Vector3& normal) const; + constexpr Vector3 GetPosition() const; + constexpr Vector3 GetPositiveVertex(const Vector3& normal) const; + constexpr T GetRadius() const; + constexpr Sphere GetSquaredBoundingSphere() const; + constexpr T GetSquaredRadius() const; - bool Intersect(const Box& box, Box* intersection = nullptr) const; + constexpr bool Intersect(const Box& box, Box* intersection = nullptr) const; - bool IsNull() const; - bool IsValid() const; + constexpr bool IsNull() const; + constexpr bool IsValid() const; - Box& Scale(T scalar); - Box& Scale(const Vector3& vec); + constexpr Box& Scale(T scalar); + constexpr Box& Scale(const Vector3& vec); - Box& ScaleAroundCenter(T scalar); - Box& ScaleAroundCenter(const Vector3& vec); + constexpr Box& ScaleAroundCenter(T scalar); + constexpr Box& ScaleAroundCenter(const Vector3& vec); std::string ToString() const; Box& Transform(const Matrix4& matrix, bool applyTranslation = true); - Box& Translate(const Vector3& translation); + constexpr Box& Translate(const Vector3& translation); - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr const T& operator[](std::size_t i) const; - Box& operator=(const Box&) = default; - Box& operator=(Box&&) noexcept = default; + constexpr Box& operator=(const Box&) = default; + constexpr Box& operator=(Box&&) = default; - bool operator==(const Box& box) const; - bool operator!=(const Box& box) const; + constexpr bool operator==(const Box& box) const; + constexpr bool operator!=(const Box& box) const; - static Box FromExtends(const Vector3& vec1, const Vector3& vec2); - static Box Lerp(const Box& from, const Box& to, T interpolation); - static Box Invalid(); - static Box Zero(); + static constexpr Box ApproxEqual(const Box& lhs, const Box& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Box FromExtends(const Vector3& vec1, const Vector3& vec2); + static constexpr Box Lerp(const Box& from, const Box& to, T interpolation); + static constexpr Box Invalid(); + static constexpr Box Zero(); T x, y, z, width, height, depth; }; diff --git a/include/Nazara/Math/Box.inl b/include/Nazara/Math/Box.inl index 15f1e6811..25b0436f2 100644 --- a/include/Nazara/Math/Box.inl +++ b/include/Nazara/Math/Box.inl @@ -26,9 +26,8 @@ namespace Nz * * \remark Position will be (0, 0, 0) */ - template - Box::Box(T Width, T Height, T Depth) : + constexpr Box::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 - Box::Box(T X, T Y, T Z, T Width, T Height, T Depth) : + constexpr Box::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 - Box::Box(const Rect& rect) : + constexpr Box::Box(const Rect& rect) : x(rect.x), y(rect.y), z(0), @@ -85,7 +84,7 @@ namespace Nz * \param lengths (Width, Height, Depth) of the box */ template - Box::Box(const Vector3& lengths) : + constexpr Box::Box(const Vector3& lengths) : Box(Vector3::Zero(), lengths) { } @@ -97,7 +96,7 @@ namespace Nz * \param lengths (Width, Height, Depth) of the box */ template - Box::Box(const Vector3& pos, const Vector3& lengths) : + constexpr Box::Box(const Vector3& pos, const Vector3& 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 template - Box::Box(const Box& box) : + constexpr Box::Box(const Box& box) : x(static_cast(box.x)), y(static_cast(box.y)), z(static_cast(box.z)), @@ -135,16 +133,15 @@ namespace Nz * * \see Contains */ - template - bool Box::ApproxEquals(const Box& box, T maxDifference) const + constexpr bool Box::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 - bool Box::Contains(T X, T Y, T Z) const + constexpr bool Box::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 - bool Box::Contains(const Box& box) const + constexpr bool Box::Contains(const Box& 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 - bool Box::Contains(const Vector3& point) const + constexpr bool Box::Contains(const Vector3& point) const { return Contains(point.x, point.y, point.z); } @@ -192,9 +187,8 @@ namespace Nz * * \see ExtendTo */ - template - Box& Box::ExtendTo(T X, T Y, T Z) + constexpr Box& Box::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 - Box& Box::ExtendTo(const Box& box) + constexpr Box& Box::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 - Box& Box::ExtendTo(const Vector3& point) + constexpr Box& Box::ExtendTo(const Vector3& point) { return ExtendTo(point.x, point.y, point.z); } @@ -259,9 +251,8 @@ namespace Nz * * \see GetSquaredBoundingSphere */ - template - Sphere Box::GetBoundingSphere() const + constexpr Sphere Box::GetBoundingSphere() const { return Sphere(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 - Vector3 Box::GetCenter() const + constexpr Vector3 Box::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 - Vector3 Box::GetCorner(BoxCorner corner) const + constexpr Vector3 Box::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 - Vector3 Box::GetLengths() const + constexpr Vector3 Box::GetLengths() const { return Vector3(width, height, depth); } @@ -337,9 +325,8 @@ namespace Nz * * \see GetCorner */ - template - Vector3 Box::GetMaximum() const + constexpr Vector3 Box::GetMaximum() const { return GetPosition() + GetLengths(); } @@ -350,9 +337,8 @@ namespace Nz * * \see GetCorner, GetPosition */ - template - Vector3 Box::GetMinimum() const + constexpr Vector3 Box::GetMinimum() const { return GetPosition(); } @@ -365,9 +351,8 @@ namespace Nz * * \see GetPositiveVertex */ - template - Vector3 Box::GetNegativeVertex(const Vector3& normal) const + constexpr Vector3 Box::GetNegativeVertex(const Vector3& normal) const { Vector3 neg(GetPosition()); @@ -389,9 +374,8 @@ namespace Nz * * \see GetCorner, GetMinimum */ - template - Vector3 Box::GetPosition() const + constexpr Vector3 Box::GetPosition() const { return Vector3(x, y, z); } @@ -404,9 +388,8 @@ namespace Nz * * \see GetNegativeVertex */ - template - Vector3 Box::GetPositiveVertex(const Vector3& normal) const + constexpr Vector3 Box::GetPositiveVertex(const Vector3& normal) const { Vector3 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 - T Box::GetRadius() const + constexpr T Box::GetRadius() const { return std::sqrt(GetSquaredRadius()); } @@ -439,9 +421,8 @@ namespace Nz * * \see GetBoundingSphere */ - template - Sphere Box::GetSquaredBoundingSphere() const + constexpr Sphere Box::GetSquaredBoundingSphere() const { return Sphere(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 - T Box::GetSquaredRadius() const + constexpr T Box::GetSquaredRadius() const { Vector3 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 - bool Box::Intersect(const Box& box, Box* intersection) const + constexpr bool Box::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 - bool Box::IsNull() const + constexpr bool Box::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 - bool Box::IsValid() const + constexpr bool Box::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 - Box& Box::Scale(T scalar) + constexpr Box& Box::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 - Box& Box::Scale(const Vector3& vec) + constexpr Box& Box::Scale(const Vector3& 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 - Box& Box::ScaleAroundCenter(T scalar) + constexpr Box& Box::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 - Box& Box::ScaleAroundCenter(const Vector3& vec) + constexpr Box& Box::ScaleAroundCenter(const Vector3& 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 Box& Box::Transform(const Matrix4& matrix, bool applyTranslation) { Vector3 center = matrix.Transform(GetCenter(), (applyTranslation) ? T(1.0) : T(0.0)); // Value multiplying the translation Vector3 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 - Box& Box::Translate(const Vector3& translation) + constexpr Box& Box::Translate(const Vector3& 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 - T& Box::operator[](std::size_t i) + constexpr T& Box::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 - const T& Box::operator[](std::size_t i) const + constexpr const T& Box::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 - bool Box::operator==(const Box& box) const + constexpr bool Box::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 - bool Box::operator!=(const Box& box) const + constexpr bool Box::operator!=(const Box& box) const { return !operator==(box); } + template + constexpr Box Box::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 - Box Box::FromExtends(const Vector3& vec1, const Vector3& vec2) + constexpr Box Box::FromExtends(const Vector3& vec1, const Vector3& vec2) { Box box; box.x = std::min(vec1.x, vec2.x); @@ -735,7 +714,7 @@ namespace Nz * \see Lerp */ template - Box Box::Lerp(const Box& from, const Box& to, T interpolation) + constexpr Box Box::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 - Box Box::Invalid() + constexpr Box Box::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 - Box Box::Zero() + constexpr Box Box::Zero() { return Box(Vector3::Zero(), Vector3::Zero()); } diff --git a/include/Nazara/Math/Enums.hpp b/include/Nazara/Math/Enums.hpp index ec0835777..11b65be36 100644 --- a/include/Nazara/Math/Enums.hpp +++ b/include/Nazara/Math/Enums.hpp @@ -34,7 +34,7 @@ namespace Nz constexpr std::size_t BoxCornerCount = UnderlyingCast(BoxCorner::Max) + 1; - enum class Extend + enum class Extent { Finite, Infinite, diff --git a/include/Nazara/Math/EulerAngles.hpp b/include/Nazara/Math/EulerAngles.hpp index 3d5500ac1..d49e816ba 100644 --- a/include/Nazara/Math/EulerAngles.hpp +++ b/include/Nazara/Math/EulerAngles.hpp @@ -20,46 +20,41 @@ namespace Nz class EulerAngles { public: - EulerAngles() = default; - EulerAngles(DegreeAngle P, DegreeAngle Y, DegreeAngle R); - EulerAngles(const DegreeAngle angles[3]); - template EulerAngles(const Angle& angle); - //EulerAngles(const Matrix3& mat); - EulerAngles(const Quaternion& quat); - template explicit EulerAngles(const EulerAngles& angles); - EulerAngles(const EulerAngles& angles) = default; + constexpr EulerAngles() = default; + constexpr EulerAngles(DegreeAngle P, DegreeAngle Y, DegreeAngle R); + constexpr EulerAngles(const DegreeAngle angles[3]); + template constexpr EulerAngles(const Angle& angle); + constexpr EulerAngles(const Quaternion& quat); + template constexpr explicit EulerAngles(const EulerAngles& angles); + constexpr EulerAngles(const EulerAngles&) = default; + constexpr EulerAngles(EulerAngles&&) = default; ~EulerAngles() = default; - void MakeZero(); + constexpr bool ApproxEqual(const EulerAngles& angles, T maxDifference = std::numeric_limits::epsilon()) const; - EulerAngles& Normalize(); + constexpr EulerAngles& Normalize(); - EulerAngles& Set(DegreeAngle P, DegreeAngle Y, DegreeAngle R); - EulerAngles& Set(const DegreeAngle angles[3]); - template EulerAngles& Set(const Angle& angles); - //EulerAngles& Set(const Matrix3& mat); - EulerAngles& Set(const Quaternion& quat); - template EulerAngles& Set(const EulerAngles& angles); - - //Matrix3 ToRotationMatrix() const; Quaternion ToQuaternion() const; std::string ToString() const; - EulerAngles operator+(const EulerAngles& angles) const; - EulerAngles operator-(const EulerAngles& angles) const; - /*EulerAngles operator*(const EulerAngles& angles) const; - EulerAngles operator/(const EulerAngles& angles) const;*/ - EulerAngles& operator=(const EulerAngles& other) = default; + constexpr EulerAngles operator+(const EulerAngles& angles) const; + constexpr EulerAngles operator-(const EulerAngles& angles) const; - EulerAngles& operator+=(const EulerAngles& angles); - EulerAngles& operator-=(const EulerAngles& angles); - /*EulerAngles operator*=(const EulerAngles& angles); - EulerAngles operator/=(const EulerAngles& angles);*/ + constexpr EulerAngles& operator=(const EulerAngles&) = default; + constexpr EulerAngles& operator=(EulerAngles&&) = default; - bool operator==(const EulerAngles& angles) const; - bool operator!=(const EulerAngles& angles) const; + constexpr EulerAngles& operator+=(const EulerAngles& angles); + constexpr EulerAngles& operator-=(const EulerAngles& angles); - static EulerAngles Zero(); + constexpr bool operator==(const EulerAngles& angles) const; + constexpr bool operator!=(const EulerAngles& angles) const; + constexpr bool operator<(const EulerAngles& angles) const; + constexpr bool operator<=(const EulerAngles& angles) const; + constexpr bool operator>(const EulerAngles& angles) const; + constexpr bool operator>=(const EulerAngles& angles) const; + + static constexpr bool ApproxEqual(const EulerAngles& lhs, const EulerAngles& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr EulerAngles Zero(); DegreeAngle pitch, yaw, roll; }; diff --git a/include/Nazara/Math/EulerAngles.inl b/include/Nazara/Math/EulerAngles.inl index c279692f6..0f2ed7428 100644 --- a/include/Nazara/Math/EulerAngles.inl +++ b/include/Nazara/Math/EulerAngles.inl @@ -29,11 +29,12 @@ namespace Nz * \param Y Yaw component = Y axis * \param R Roll component = Z axis */ - template - EulerAngles::EulerAngles(DegreeAngle P, DegreeAngle Y, DegreeAngle R) + constexpr EulerAngles::EulerAngles(DegreeAngle P, DegreeAngle Y, DegreeAngle R) : + pitch(P), + yaw(Y), + roll(R) { - Set(P, Y, R); } /*! @@ -41,11 +42,10 @@ namespace Nz * * \param angles[3] angles[0] is pitch component, angles[1] is yaw component and angles[2] is roll component */ - template - EulerAngles::EulerAngles(const DegreeAngle angles[3]) + constexpr EulerAngles::EulerAngles(const DegreeAngle angles[3]) : + EulerAngles(angles[0], angles[1], angles[2]) { - Set(angles); } /*! @@ -55,9 +55,9 @@ namespace Nz */ template template - EulerAngles::EulerAngles(const Angle& angle) + constexpr EulerAngles::EulerAngles(const Angle& angle) : + EulerAngles(angle.ToEulerAngles()) { - Set(angle); } /*! @@ -66,9 +66,9 @@ namespace Nz * \param quat Quaternion representing a rotation of space */ template - EulerAngles::EulerAngles(const Quaternion& quat) + constexpr EulerAngles::EulerAngles(const Quaternion& quat) : + EulerAngles(quat.ToEulerAngles()) { - Set(quat); } /*! @@ -79,21 +79,17 @@ namespace Nz template template - EulerAngles::EulerAngles(const EulerAngles& angles) + constexpr EulerAngles::EulerAngles(const EulerAngles& angles) : + pitch(DegreeAngle(angles.pitch)), + yaw(DegreeAngle(angles.yaw)), + roll(DegreeAngle(angles.roll)) { - Set(angles); } - /*! - * \brief Makes the euler angle (0, 0, 0) - * - * \see Zero - */ - template - void EulerAngles::MakeZero() + constexpr bool EulerAngles::ApproxEqual(const EulerAngles& angles, T maxDifference) const { - Set(T(0.0), T(0.0), T(0.0)); + return pitch.ApproxEqual(angles.pitch, maxDifference) && yaw.ApproxEqual(angles.yaw, maxDifference) && roll.ApproxEqual(angles.roll, maxDifference); } /*! @@ -102,9 +98,8 @@ namespace Nz * * \see NormalizeAngle */ - template - EulerAngles& EulerAngles::Normalize() + constexpr EulerAngles& EulerAngles::Normalize() { pitch.Normalize(); yaw.Normalize(); @@ -113,94 +108,10 @@ namespace Nz return *this; } - /*! - * \brief Sets the components of the euler angle - * \return A reference to this euler angle - * - * \param P Pitch component = X axis - * \param Y Yaw component = Y axis - * \param R Roll component = Z axis - */ - - template - EulerAngles& EulerAngles::Set(DegreeAngle P, DegreeAngle Y, DegreeAngle R) - { - pitch = P; - yaw = Y; - roll = R; - - return *this; - } - - /*! - * \brief Sets the components of the euler angle from an array of three elements - * \return A reference to this euler angle - * - * \param angles[3] angles[0] is pitch component, angles[1] is yaw component and angles[2] is roll component - */ - - template - EulerAngles& EulerAngles::Set(const DegreeAngle angles[3]) - { - pitch = angles[0]; - yaw = angles[1]; - roll = angles[2]; - - return *this; - } - - - /*! - * \brief Sets the components of the euler angle from a 2D rotation specified by an Angle - * \return A reference to this euler angle - * - * \param angle 2D angle - * - * \see Angle - */ - template - template - EulerAngles& EulerAngles::Set(const Angle& angle) - { - return Set(angle.ToEulerAngles()); - } - - /*! - * \brief Sets the components of the euler angle from a quaternion - * \return A reference to this euler angle - * - * \param quat Quaternion representing a rotation of space - */ - - template - EulerAngles& EulerAngles::Set(const Quaternion& quat) - { - return Set(quat.ToEulerAngles()); - } - - /*! - * \brief Sets the components of the euler angle from another type of EulerAngles - * \return A reference to this euler angle - * - * \param angles EulerAngles of type U to convert its components - */ - - template - template - EulerAngles& EulerAngles::Set(const EulerAngles& angles) - { - pitch.Set(angles.pitch); - yaw.Set(angles.yaw); - roll.Set(angles.roll); - - return *this; - } - /*! * \brief Converts the euler angle to quaternion * \return A Quaternion which represents the rotation of this euler angle */ - template Quaternion EulerAngles::ToQuaternion() const { @@ -223,7 +134,6 @@ namespace Nz * \brief Gives a string representation * \return A string representation of the object: "EulerAngles(pitch, yaw, roll)" */ - template std::string EulerAngles::ToString() const { @@ -239,9 +149,8 @@ namespace Nz * * \param angles The other euler angle to add components with */ - template - EulerAngles EulerAngles::operator+(const EulerAngles& angles) const + constexpr EulerAngles EulerAngles::operator+(const EulerAngles& angles) const { return EulerAngles(pitch + angles.pitch, yaw + angles.yaw, @@ -254,9 +163,8 @@ namespace Nz * * \param angles The other euler angle to substract components with */ - template - EulerAngles EulerAngles::operator-(const EulerAngles& angles) const + constexpr EulerAngles EulerAngles::operator-(const EulerAngles& angles) const { return EulerAngles(pitch - angles.pitch, yaw - angles.yaw, @@ -269,9 +177,8 @@ namespace Nz * * \param angles The other euler angle to add components with */ - template - EulerAngles& EulerAngles::operator+=(const EulerAngles& angles) + constexpr EulerAngles& EulerAngles::operator+=(const EulerAngles& angles) { pitch += angles.pitch; yaw += angles.yaw; @@ -286,9 +193,8 @@ namespace Nz * * \param angles The other euler angle to substract components with */ - template - EulerAngles& EulerAngles::operator-=(const EulerAngles& angles) + constexpr EulerAngles& EulerAngles::operator-=(const EulerAngles& angles) { pitch -= angles.pitch; yaw -= angles.yaw; @@ -303,9 +209,8 @@ namespace Nz * * \param angles Other euler angle to compare with */ - template - bool EulerAngles::operator==(const EulerAngles& angles) const + constexpr bool EulerAngles::operator==(const EulerAngles& angles) const { return pitch == angles.pitch && yaw == angles.yaw && roll == angles.roll; } @@ -316,27 +221,74 @@ namespace Nz * * \param angles Other euler angle to compare with */ - template - bool EulerAngles::operator!=(const EulerAngles& angles) const + constexpr bool EulerAngles::operator!=(const EulerAngles& angles) const { return !operator==(angles); } + template + constexpr bool EulerAngles::operator<(const EulerAngles& angles) const + { + if (pitch != angles.pitch) + return pitch < angles.pitch; + + if (yaw != angles.yaw) + return yaw < angles.yaw; + + return roll < angles.roll; + } + + template + constexpr bool EulerAngles::operator<=(const EulerAngles& angles) const + { + if (pitch != angles.pitch) + return pitch < angles.pitch; + + if (yaw != angles.yaw) + return yaw < angles.yaw; + + return roll <= angles.roll; + } + + template + constexpr bool EulerAngles::operator>(const EulerAngles& angles) const + { + if (pitch != angles.pitch) + return pitch > angles.pitch; + + if (yaw != angles.yaw) + return yaw > angles.yaw; + + return roll > angles.roll; + } + + template + constexpr bool EulerAngles::operator>=(const EulerAngles& angles) const + { + if (pitch != angles.pitch) + return pitch > angles.pitch; + + if (yaw != angles.yaw) + return yaw > angles.yaw; + + return roll >= angles.roll; + } + + template + constexpr bool EulerAngles::ApproxEqual(const EulerAngles& lhs, const EulerAngles& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + /*! * \brief Shorthand for the euler angle (0, 0, 0) * \return A euler angle with components (0, 0, 0) - * - * \see MakeZero */ - template - EulerAngles EulerAngles::Zero() + constexpr EulerAngles EulerAngles::Zero() { - EulerAngles angles; - angles.MakeZero(); - - return angles; + return EulerAngles(0, 0, 0); } /*! diff --git a/include/Nazara/Math/Frustum.hpp b/include/Nazara/Math/Frustum.hpp index 24226bfaf..ec272d5fe 100644 --- a/include/Nazara/Math/Frustum.hpp +++ b/include/Nazara/Math/Frustum.hpp @@ -27,41 +27,46 @@ namespace Nz class Frustum { public: - Frustum() = default; - explicit Frustum(const EnumArray>& planes); - template explicit Frustum(const Frustum& frustum); - Frustum(const Frustum& frustum) = default; + constexpr Frustum() = default; + constexpr explicit Frustum(const EnumArray>& planes); + template constexpr explicit Frustum(const Frustum& frustum); + constexpr Frustum(const Frustum&) = default; + constexpr Frustum(Frustum&&) = default; ~Frustum() = default; - Vector3 ComputeCorner(BoxCorner corner) const; + constexpr bool ApproxEqual(const Frustum& frustum, T maxDifference = std::numeric_limits::epsilon()) const; - bool Contains(const BoundingVolume& volume) const; - bool Contains(const Box& box) const; - bool Contains(const OrientedBox& orientedBox) const; - bool Contains(const Sphere& sphere) const; - bool Contains(const Vector3& point) const; - bool Contains(const Vector3* points, std::size_t pointCount) const; + constexpr Vector3 ComputeCorner(BoxCorner corner) const; - const Plane& GetPlane(FrustumPlane plane) const; + constexpr bool Contains(const BoundingVolume& volume) const; + constexpr bool Contains(const Box& box) const; + constexpr bool Contains(const OrientedBox& orientedBox) const; + constexpr bool Contains(const Sphere& sphere) const; + constexpr bool Contains(const Vector3& point) const; + constexpr bool Contains(const Vector3* points, std::size_t pointCount) const; - IntersectionSide Intersect(const BoundingVolume& volume) const; - IntersectionSide Intersect(const Box& box) const; - IntersectionSide Intersect(const OrientedBox& orientedBox) const; - IntersectionSide Intersect(const Sphere& sphere) const; - IntersectionSide Intersect(const Vector3* points, std::size_t pointCount) const; + constexpr const Plane& GetPlane(FrustumPlane plane) const; + + constexpr IntersectionSide Intersect(const BoundingVolume& volume) const; + constexpr IntersectionSide Intersect(const Box& box) const; + constexpr IntersectionSide Intersect(const OrientedBox& orientedBox) const; + constexpr IntersectionSide Intersect(const Sphere& sphere) const; + constexpr IntersectionSide Intersect(const Vector3* points, std::size_t pointCount) const; std::string ToString() const; - Frustum& operator=(const Frustum& other) = default; + constexpr Frustum& operator=(const Frustum&) = default; + constexpr Frustum& operator=(Frustum&&) = default; + constexpr bool operator==(const Frustum& angles) const; + constexpr bool operator!=(const Frustum& angles) const; + + static constexpr bool ApproxEqual(const Frustum& lhs, const Frustum& rhs, T maxDifference = std::numeric_limits::epsilon()); static Frustum Build(RadianAngle angle, T ratio, T zNear, T zFar, const Vector3& eye, const Vector3& target, const Vector3& up = Vector3::Up()); static Frustum Extract(const Matrix4& viewProjMatrix); - template - friend bool Serialize(SerializationContext& context, const Frustum& frustum, TypeTag>); - - template - friend bool Unserialize(SerializationContext& context, Frustum* frustum, TypeTag>); + template friend bool Serialize(SerializationContext& context, const Frustum& frustum, TypeTag>); + template friend bool Unserialize(SerializationContext& context, Frustum* frustum, TypeTag>); private: EnumArray> m_planes; diff --git a/include/Nazara/Math/Frustum.inl b/include/Nazara/Math/Frustum.inl index 4c70e7cac..4250b9ec3 100644 --- a/include/Nazara/Math/Frustum.inl +++ b/include/Nazara/Math/Frustum.inl @@ -31,7 +31,7 @@ namespace Nz * \param planes Frustum of type U to convert to type T */ template - Frustum::Frustum(const EnumArray>& planes) : + constexpr Frustum::Frustum(const EnumArray>& planes) : m_planes(planes) { } @@ -43,12 +43,24 @@ namespace Nz */ template template - Frustum::Frustum(const Frustum& frustum) + constexpr Frustum::Frustum(const Frustum& frustum) { - for (auto&& [planeEnum, plane] : m_planes) + for (auto&& [planeEnum, plane] : m_planes.iter_kv()) plane = Frustum(frustum.GetPlane(planeEnum)); } + template + constexpr bool Frustum::ApproxEqual(const Frustum& frustum, T maxDifference) const + { + for (auto&& [planeEnum, plane] : m_planes.iter_kv()) + { + if (!plane.ApproxEqual(frustum.GetPlane(planeEnum))) + return false; + } + + return true; + } + /*! * \brief Computes the position of a frustum corner * \return The corner position @@ -56,7 +68,7 @@ namespace Nz * \param corner Which corner to compute */ template - Vector3 Frustum::ComputeCorner(BoxCorner corner) const + constexpr Vector3 Frustum::ComputeCorner(BoxCorner corner) const { switch (corner) { @@ -82,15 +94,15 @@ namespace Nz * * \remark If volume is infinite, true is returned * \remark If volume is null, false is returned - * \remark If enumeration of the volume is not defined in Extend, a NazaraError is thrown and false is returned + * \remark If enumeration of the volume is not defined in Extent, a NazaraError is thrown and false is returned * \remark If enumeration of the intersection is not defined in IntersectionSide, a NazaraError is thrown and false is returned. This should not never happen for a user of the library */ template - bool Frustum::Contains(const BoundingVolume& volume) const + constexpr bool Frustum::Contains(const BoundingVolume& volume) const { - switch (volume.extend) + switch (volume.extent) { - case Extend::Finite: + case Extent::Finite: { IntersectionSide side = Intersect(volume.aabb); switch (side) @@ -109,14 +121,14 @@ namespace Nz return false; } - case Extend::Infinite: + case Extent::Infinite: return true; - case Extend::Null: + case Extent::Null: return false; } - NazaraError("Invalid extend type (0x" + NumberToString(UnderlyingCast(volume.extend), 16) + ')'); + NazaraError("Invalid extent type (0x" + NumberToString(UnderlyingCast(volume.extent), 16) + ')'); return false; } @@ -127,7 +139,7 @@ namespace Nz * \param box Box to check */ template - bool Frustum::Contains(const Box& box) const + constexpr bool Frustum::Contains(const Box& box) const { // http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/ for (const auto& plane : m_planes) @@ -145,9 +157,8 @@ namespace Nz * * \param orientedbox Oriented box to check */ - template - bool Frustum::Contains(const OrientedBox& orientedbox) const + constexpr bool Frustum::Contains(const OrientedBox& orientedbox) const { return Contains(orientedbox.GetCorners(), 8); } @@ -158,9 +169,8 @@ namespace Nz * * \param sphere Sphere to check */ - template - bool Frustum::Contains(const Sphere& sphere) const + constexpr bool Frustum::Contains(const Sphere& sphere) const { for (const auto& plane : m_planes) { @@ -177,9 +187,8 @@ namespace Nz * * \param point Vector3 which represents a point in the space */ - template - bool Frustum::Contains(const Vector3& point) const + constexpr bool Frustum::Contains(const Vector3& point) const { for (const auto& plane : m_planes) { @@ -197,9 +206,8 @@ namespace Nz * \param points Pointer to Vector3 which represents a set of points in the space * \param pointCount Number of points to check */ - template - bool Frustum::Contains(const Vector3* points, std::size_t pointCount) const + constexpr bool Frustum::Contains(const Vector3* points, std::size_t pointCount) const { for (const auto& plane : m_planes) { @@ -225,9 +233,8 @@ namespace Nz * * \remark If enumeration is not defined in FrustumPlane and NAZARA_DEBUG defined, a NazaraError is thrown and a Plane uninitialised is returned */ - template - const Plane& Frustum::GetPlane(FrustumPlane plane) const + constexpr const Plane& Frustum::GetPlane(FrustumPlane plane) const { NazaraAssert(plane <= FrustumPlane::Max, "invalid plane"); return m_planes[plane]; @@ -241,16 +248,15 @@ namespace Nz * * \remark If volume is infinite, IntersectionSide::Intersecting is returned * \remark If volume is null, IntersectionSide::Outside is returned - * \remark If enumeration of the volume is not defined in Extend, a NazaraError is thrown and IntersectionSide::Outside is returned + * \remark If enumeration of the volume is not defined in Extent, a NazaraError is thrown and IntersectionSide::Outside is returned * \remark If enumeration of the intersection is not defined in IntersectionSide, a NazaraError is thrown and IntersectionSide::Outside is returned. This should not never happen for a user of the library */ - template - IntersectionSide Frustum::Intersect(const BoundingVolume& volume) const + constexpr IntersectionSide Frustum::Intersect(const BoundingVolume& volume) const { - switch (volume.extend) + switch (volume.extent) { - case Extend::Finite: + case Extent::Finite: { IntersectionSide side = Intersect(volume.aabb); switch (side) @@ -269,14 +275,14 @@ namespace Nz return IntersectionSide::Outside; } - case Extend::Infinite: + case Extent::Infinite: return IntersectionSide::Intersecting; // We can not contain infinity - case Extend::Null: + case Extent::Null: return IntersectionSide::Outside; } - NazaraError("Invalid extend type (0x" + NumberToString(UnderlyingCast(volume.extend), 16) + ')'); + NazaraError("Invalid extent type (0x" + NumberToString(UnderlyingCast(volume.extent), 16) + ')'); return IntersectionSide::Outside; } @@ -286,9 +292,8 @@ namespace Nz * * \param box Box to check */ - template - IntersectionSide Frustum::Intersect(const Box& box) const + constexpr IntersectionSide Frustum::Intersect(const Box& box) const { // http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/ IntersectionSide side = IntersectionSide::Inside; @@ -310,9 +315,8 @@ namespace Nz * * \param oriented box OrientedBox to check */ - template - IntersectionSide Frustum::Intersect(const OrientedBox& orientedbox) const + constexpr IntersectionSide Frustum::Intersect(const OrientedBox& orientedbox) const { return Intersect(orientedbox.GetCorners(), 8); } @@ -323,9 +327,8 @@ namespace Nz * * \param sphere Sphere to check */ - template - IntersectionSide Frustum::Intersect(const Sphere& sphere) const + constexpr IntersectionSide Frustum::Intersect(const Sphere& sphere) const { // http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-points-and-spheres/ IntersectionSide side = IntersectionSide::Inside; @@ -349,9 +352,8 @@ namespace Nz * \param points Pointer to Vector3 which represents a set of points in the space * \param pointCount Number of points to check */ - template - IntersectionSide Frustum::Intersect(const Vector3* points, std::size_t pointCount) const + constexpr IntersectionSide Frustum::Intersect(const Vector3* points, std::size_t pointCount) const { std::size_t c = 0; @@ -399,6 +401,30 @@ namespace Nz * \param target Position of the target of the camera * \param up Direction of up vector according to the orientation of camera */ + template + constexpr bool Frustum::operator==(const Frustum& frustum) const + { + for (auto&& [planeEnum, plane] : m_planes.iter_kv()) + { + if (!plane != frustum.GetPlane(planeEnum)) + return false; + } + + return true; + } + + template + constexpr bool Frustum::operator!=(const Frustum& frustum) const + { + return !operator==(frustum); + } + + template + constexpr bool Frustum::ApproxEqual(const Frustum& lhs, const Frustum& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + template Frustum Frustum::Build(RadianAngle angle, T ratio, T zNear, T zFar, const Vector3& eye, const Vector3& target, const Vector3& up) { @@ -609,3 +635,4 @@ namespace Nz } #include +#include "Frustum.hpp" diff --git a/include/Nazara/Math/Matrix4.hpp b/include/Nazara/Math/Matrix4.hpp index be317b181..fa3c5c27c 100644 --- a/include/Nazara/Math/Matrix4.hpp +++ b/include/Nazara/Math/Matrix4.hpp @@ -29,111 +29,95 @@ namespace Nz class Matrix4 { public: - Matrix4() = default; - Matrix4(T r11, T r12, T r13, T r14, - T r21, T r22, T r23, T r24, - T r31, T r32, T r33, T r34, - T r41, T r42, T r43, T r44); - //Matrix4(const Matrix3& matrix); - Matrix4(const T matrix[16]); - template explicit Matrix4(const Matrix4& matrix); - Matrix4(const Matrix4& matrix) = default; + constexpr Matrix4() = default; + constexpr Matrix4(T r11, T r12, T r13, T r14, + T r21, T r22, T r23, T r24, + T r31, T r32, T r33, T r34, + T r41, T r42, T r43, T r44); + constexpr Matrix4(const T matrix[16]); + template constexpr explicit Matrix4(const Matrix4& matrix); + constexpr Matrix4(const Matrix4&) = default; + constexpr Matrix4(Matrix4&&) = default; ~Matrix4() = default; - Matrix4& ApplyRotation(const Quaternion& rotation); - Matrix4& ApplyScale(const Vector3& scale); - Matrix4& ApplyTranslation(const Vector3& translation); + constexpr Matrix4& ApplyRotation(const Quaternion& rotation); + constexpr Matrix4& ApplyScale(const Vector3& scale); + constexpr Matrix4& ApplyTranslation(const Vector3& translation); - Matrix4& Concatenate(const Matrix4& matrix); - Matrix4& ConcatenateTransform(const Matrix4& matrix); + constexpr bool ApproxEqual(const Matrix4& vec, T maxDifference = std::numeric_limits::epsilon()) const; - Vector4 GetColumn(unsigned int column) const; - T GetDeterminant() const; - T GetDeterminantTransform() const; - bool GetInverse(Matrix4* dest) const; - bool GetInverseTransform(Matrix4* dest) const; + constexpr Matrix4& Concatenate(const Matrix4& matrix); + constexpr Matrix4& ConcatenateTransform(const Matrix4& matrix); + + constexpr Vector4 GetColumn(std::size_t column) const; + constexpr T GetDeterminant() const; + constexpr T GetDeterminantTransform() const; + constexpr bool GetInverse(Matrix4* dest) const; + constexpr bool GetInverseTransform(Matrix4* dest) const; Quaternion GetRotation() const; - //Matrix3 GetRotationMatrix() const; - Vector4 GetRow(unsigned int row) const; - Vector3 GetScale() const; - Vector3 GetSquaredScale() const; - Vector3 GetTranslation() const; - void GetTransposed(Matrix4* dest) const; + constexpr Vector4 GetRow(std::size_t row) const; + constexpr Vector3 GetScale() const; + constexpr Vector3 GetSquaredScale() const; + constexpr Vector3 GetTranslation() const; + constexpr void GetTransposed(Matrix4* dest) const; - bool HasNegativeScale() const; - bool HasScale() const; + constexpr bool HasNegativeScale() const; + constexpr bool HasScale() const; - Matrix4& Inverse(bool* succeeded = nullptr); - Matrix4& InverseTransform(bool* succeeded = nullptr); + constexpr Matrix4& Inverse(bool* succeeded = nullptr); + constexpr Matrix4& InverseTransform(bool* succeeded = nullptr); - bool IsTransformMatrix() const; - bool IsIdentity() const; + constexpr bool IsTransformMatrix() const; + constexpr bool IsIdentity() const; - Matrix4& MakeIdentity(); - Matrix4& MakeLookAt(const Vector3& eye, const Vector3& target, const Vector3& up = Vector3::Up()); - Matrix4& MakeOrtho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0); - Matrix4& MakePerspective(RadianAngle angle, T ratio, T zNear, T zFar); - Matrix4& MakeRotation(const Quaternion& rotation); - Matrix4& MakeScale(const Vector3& scale); - Matrix4& MakeTranslation(const Vector3& translation); - Matrix4& MakeTransform(const Vector3& translation, const Quaternion& rotation); - Matrix4& MakeTransform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); - Matrix4& MakeTransformInverse(const Vector3& translation, const Quaternion& rotation); - Matrix4& MakeTransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); - Matrix4& MakeZero(); - - Matrix4& Set(T r11, T r12, T r13, T r14, - T r21, T r22, T r23, T r24, - T r31, T r32, T r33, T r34, - T r41, T r42, T r43, T r44); - //Matrix4(const Matrix3& matrix); - template Matrix4& Set(const Matrix4& matrix); - Matrix4& SetRotation(const Quaternion& rotation); - Matrix4& SetScale(const Vector3& scale); - Matrix4& SetTranslation(const Vector3& translation); + constexpr Matrix4& SetRotation(const Quaternion& rotation); + constexpr Matrix4& SetScale(const Vector3& scale); + constexpr Matrix4& SetTranslation(const Vector3& translation); std::string ToString() const; - Vector2 Transform(const Vector2& vector, T z = 0.0, T w = 1.0) const; - Vector3 Transform(const Vector3& vector, T w = 1.0) const; - Vector4 Transform(const Vector4& vector) const; + constexpr Vector2 Transform(const Vector2& vector, T z = 0.0, T w = 1.0) const; + constexpr Vector3 Transform(const Vector3& vector, T w = 1.0) const; + constexpr Vector4 Transform(const Vector4& vector) const; - Matrix4& Transpose(); + constexpr Matrix4& Transpose(); - T& operator()(std::size_t x, std::size_t y); - const T& operator()(std::size_t x, std::size_t y) const; + constexpr T& operator()(std::size_t x, std::size_t y); + constexpr const T& operator()(std::size_t x, std::size_t y) const; - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr const T& operator[](std::size_t i) const; - Matrix4& operator=(const Matrix4& matrix) = default; + constexpr Matrix4& operator=(const Matrix4&) = default; + constexpr Matrix4& operator=(Matrix4&&) = default; - Matrix4 operator*(const Matrix4& matrix) const; - Vector2 operator*(const Vector2& vector) const; - Vector3 operator*(const Vector3& vector) const; - Vector4 operator*(const Vector4& vector) const; - Matrix4 operator*(T scalar) const; + constexpr Matrix4 operator*(const Matrix4& matrix) const; + constexpr Vector2 operator*(const Vector2& vector) const; + constexpr Vector3 operator*(const Vector3& vector) const; + constexpr Vector4 operator*(const Vector4& vector) const; + constexpr Matrix4 operator*(T scalar) const; - Matrix4& operator*=(const Matrix4& matrix); - Matrix4& operator*=(T scalar); + constexpr Matrix4& operator*=(const Matrix4& matrix); + constexpr Matrix4& operator*=(T scalar); - bool operator==(const Matrix4& mat) const; - bool operator!=(const Matrix4& mat) const; + constexpr bool operator==(const Matrix4& mat) const; + constexpr bool operator!=(const Matrix4& mat) const; - static Matrix4 Concatenate(const Matrix4& left, const Matrix4& right); - static Matrix4 ConcatenateTransform(const Matrix4& left, const Matrix4& right); - static Matrix4 Identity(); - static Matrix4 LookAt(const Vector3& eye, const Vector3& target, const Vector3& up = Vector3::Up()); - static Matrix4 Ortho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0); + static constexpr bool ApproxEqual(const Matrix4& lhs, const Matrix4& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Matrix4 Concatenate(const Matrix4& left, const Matrix4& right); + static constexpr Matrix4 ConcatenateTransform(const Matrix4& left, const Matrix4& right); + static constexpr Matrix4 Identity(); + static constexpr Matrix4 LookAt(const Vector3& eye, const Vector3& target, const Vector3& up = Vector3::Up()); + static constexpr Matrix4 Ortho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0); static Matrix4 Perspective(RadianAngle angle, T ratio, T zNear, T zFar); - static Matrix4 Rotate(const Quaternion& rotation); - static Matrix4 Scale(const Vector3& scale); - static Matrix4 Translate(const Vector3& translation); - static Matrix4 Transform(const Vector3& translation, const Quaternion& rotation); - static Matrix4 Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); - static Matrix4 TransformInverse(const Vector3& translation, const Quaternion& rotation); - static Matrix4 TransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); - static Matrix4 Zero(); + static constexpr Matrix4 Rotate(const Quaternion& rotation); + static constexpr Matrix4 Scale(const Vector3& scale); + static constexpr Matrix4 Translate(const Vector3& translation); + static constexpr Matrix4 Transform(const Vector3& translation, const Quaternion& rotation); + static constexpr Matrix4 Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); + static constexpr Matrix4 TransformInverse(const Vector3& translation, const Quaternion& rotation); + static constexpr Matrix4 TransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); + static constexpr Matrix4 Zero(); T m11, m12, m13, m14, m21, m22, m23, m24, @@ -149,7 +133,7 @@ namespace Nz template std::ostream& operator<<(std::ostream& out, const Matrix4& matrix); - template Matrix4 operator*(T scale, const Matrix4& matrix); + template constexpr Matrix4 operator*(T scale, const Matrix4& matrix); } #include diff --git a/include/Nazara/Math/Matrix4.inl b/include/Nazara/Math/Matrix4.inl index c2efdda9e..57c6c4771 100644 --- a/include/Nazara/Math/Matrix4.inl +++ b/include/Nazara/Math/Matrix4.inl @@ -34,17 +34,28 @@ namespace Nz * * \param rIJ Matrix components at index(I, J) */ - template - Matrix4::Matrix4(T r11, T r12, T r13, T r14, - T r21, T r22, T r23, T r24, - T r31, T r32, T r33, T r34, - T r41, T r42, T r43, T r44) + constexpr Matrix4::Matrix4(T r11, T r12, T r13, T r14, + T r21, T r22, T r23, T r24, + T r31, T r32, T r33, T r34, + T r41, T r42, T r43, T r44) : + m11(r11), + m12(r12), + m13(r13), + m14(r14), + m21(r21), + m22(r22), + m23(r23), + m24(r24), + m31(r31), + m32(r32), + m33(r33), + m34(r34), + m41(r41), + m42(r42), + m43(r43), + m44(r44) { - Set(r11, r12, r13, r14, - r21, r22, r23, r24, - r31, r32, r33, r34, - r41, r42, r43, r44); } /*! @@ -52,9 +63,8 @@ namespace Nz * * \param matrix[16] Matrix components */ - template - Matrix4::Matrix4(const T matrix[16]) : + constexpr Matrix4::Matrix4(const T matrix[16]) : Matrix4(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3], matrix[ 4], matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8], matrix[ 9], matrix[10], matrix[11], @@ -70,9 +80,24 @@ namespace Nz template template - Matrix4::Matrix4(const Matrix4& matrix) + constexpr Matrix4::Matrix4(const Matrix4& matrix) : + m11(static_cast(matrix.m11)), + m12(static_cast(matrix.m12)), + m13(static_cast(matrix.m13)), + m14(static_cast(matrix.m14)), + m21(static_cast(matrix.m21)), + m22(static_cast(matrix.m22)), + m23(static_cast(matrix.m23)), + m24(static_cast(matrix.m24)), + m31(static_cast(matrix.m31)), + m32(static_cast(matrix.m32)), + m33(static_cast(matrix.m33)), + m34(static_cast(matrix.m34)), + m41(static_cast(matrix.m41)), + m42(static_cast(matrix.m42)), + m43(static_cast(matrix.m43)), + m44(static_cast(matrix.m44)) { - Set(matrix); } /*! @@ -81,9 +106,8 @@ namespace Nz * * \param rotation Quaternion representing a rotation of space */ - template - Matrix4& Matrix4::ApplyRotation(const Quaternion& rotation) + constexpr Matrix4& Matrix4::ApplyRotation(const Quaternion& rotation) { return Concatenate(Matrix4::Rotate(rotation)); } @@ -94,9 +118,8 @@ namespace Nz * * \param scale Vector3 representing the homothety */ - template - Matrix4& Matrix4::ApplyScale(const Vector3& scale) + constexpr Matrix4& Matrix4::ApplyScale(const Vector3& scale) { m11 *= scale.x; m12 *= scale.x; @@ -119,9 +142,8 @@ namespace Nz * * \param translation Vector3 representing the translation */ - template - Matrix4& Matrix4::ApplyTranslation(const Vector3& translation) + constexpr Matrix4& Matrix4::ApplyTranslation(const Vector3& translation) { m41 += translation.x; m42 += translation.y; @@ -130,6 +152,16 @@ namespace Nz return *this; } + template + constexpr bool Matrix4::ApproxEqual(const Matrix4& mat, T maxDifference) const + { + for (unsigned int i = 0; i < 16; ++i) + if (!NumberEquals((&m11)[i], (&mat.m11)[i], maxDifference)) + return false; + + return true; + } + /*! * \brief Concatenates this matrix to other one * \return A reference to this matrix which is the product with other one @@ -141,7 +173,7 @@ namespace Nz * \see ConcatenateTransform */ template - Matrix4& Matrix4::Concatenate(const Matrix4& matrix) + constexpr Matrix4& Matrix4::Concatenate(const Matrix4& matrix) { #if NAZARA_MATH_MATRIX4_CHECK_TRANSFORM if (IsTransformMatrix() && matrix.IsTransformMatrix()) @@ -151,25 +183,27 @@ namespace Nz } #endif - return Set(m11*matrix.m11 + m12*matrix.m21 + m13*matrix.m31 + m14*matrix.m41, - m11*matrix.m12 + m12*matrix.m22 + m13*matrix.m32 + m14*matrix.m42, - m11*matrix.m13 + m12*matrix.m23 + m13*matrix.m33 + m14*matrix.m43, - m11*matrix.m14 + m12*matrix.m24 + m13*matrix.m34 + m14*matrix.m44, + return operator=(Matrix4( + m11 * matrix.m11 + m12 * matrix.m21 + m13 * matrix.m31 + m14 * matrix.m41, + m11 * matrix.m12 + m12 * matrix.m22 + m13 * matrix.m32 + m14 * matrix.m42, + m11 * matrix.m13 + m12 * matrix.m23 + m13 * matrix.m33 + m14 * matrix.m43, + m11 * matrix.m14 + m12 * matrix.m24 + m13 * matrix.m34 + m14 * matrix.m44, - m21*matrix.m11 + m22*matrix.m21 + m23*matrix.m31 + m24*matrix.m41, - m21*matrix.m12 + m22*matrix.m22 + m23*matrix.m32 + m24*matrix.m42, - m21*matrix.m13 + m22*matrix.m23 + m23*matrix.m33 + m24*matrix.m43, - m21*matrix.m14 + m22*matrix.m24 + m23*matrix.m34 + m24*matrix.m44, + m21 * matrix.m11 + m22 * matrix.m21 + m23 * matrix.m31 + m24 * matrix.m41, + m21 * matrix.m12 + m22 * matrix.m22 + m23 * matrix.m32 + m24 * matrix.m42, + m21 * matrix.m13 + m22 * matrix.m23 + m23 * matrix.m33 + m24 * matrix.m43, + m21 * matrix.m14 + m22 * matrix.m24 + m23 * matrix.m34 + m24 * matrix.m44, - m31*matrix.m11 + m32*matrix.m21 + m33*matrix.m31 + m34*matrix.m41, - m31*matrix.m12 + m32*matrix.m22 + m33*matrix.m32 + m34*matrix.m42, - m31*matrix.m13 + m32*matrix.m23 + m33*matrix.m33 + m34*matrix.m43, - m31*matrix.m14 + m32*matrix.m24 + m33*matrix.m34 + m34*matrix.m44, + m31 * matrix.m11 + m32 * matrix.m21 + m33 * matrix.m31 + m34 * matrix.m41, + m31 * matrix.m12 + m32 * matrix.m22 + m33 * matrix.m32 + m34 * matrix.m42, + m31 * matrix.m13 + m32 * matrix.m23 + m33 * matrix.m33 + m34 * matrix.m43, + m31 * matrix.m14 + m32 * matrix.m24 + m33 * matrix.m34 + m34 * matrix.m44, - m41*matrix.m11 + m42*matrix.m21 + m43*matrix.m31 + m44*matrix.m41, - m41*matrix.m12 + m42*matrix.m22 + m43*matrix.m32 + m44*matrix.m42, - m41*matrix.m13 + m42*matrix.m23 + m43*matrix.m33 + m44*matrix.m43, - m41*matrix.m14 + m42*matrix.m24 + m43*matrix.m34 + m44*matrix.m44); + m41 * matrix.m11 + m42 * matrix.m21 + m43 * matrix.m31 + m44 * matrix.m41, + m41 * matrix.m12 + m42 * matrix.m22 + m43 * matrix.m32 + m44 * matrix.m42, + m41 * matrix.m13 + m42 * matrix.m23 + m43 * matrix.m33 + m44 * matrix.m43, + m41 * matrix.m14 + m42 * matrix.m24 + m43 * matrix.m34 + m44 * matrix.m44 + )); } /*! @@ -183,7 +217,7 @@ namespace Nz * \see Concatenate */ template - Matrix4& Matrix4::ConcatenateTransform(const Matrix4& matrix) + constexpr Matrix4& Matrix4::ConcatenateTransform(const Matrix4& matrix) { #if NAZARA_MATH_MATRIX4_CHECK_TRANSFORM if (!IsTransformMatrix()) @@ -199,25 +233,27 @@ namespace Nz } #endif - return Set(m11*matrix.m11 + m12*matrix.m21 + m13*matrix.m31, - m11*matrix.m12 + m12*matrix.m22 + m13*matrix.m32, - m11*matrix.m13 + m12*matrix.m23 + m13*matrix.m33, - T(0.0), - - m21*matrix.m11 + m22*matrix.m21 + m23*matrix.m31, - m21*matrix.m12 + m22*matrix.m22 + m23*matrix.m32, - m21*matrix.m13 + m22*matrix.m23 + m23*matrix.m33, - T(0.0), - - m31*matrix.m11 + m32*matrix.m21 + m33*matrix.m31, - m31*matrix.m12 + m32*matrix.m22 + m33*matrix.m32, - m31*matrix.m13 + m32*matrix.m23 + m33*matrix.m33, - T(0.0), - - m41*matrix.m11 + m42*matrix.m21 + m43*matrix.m31 + matrix.m41, - m41*matrix.m12 + m42*matrix.m22 + m43*matrix.m32 + matrix.m42, - m41*matrix.m13 + m42*matrix.m23 + m43*matrix.m33 + matrix.m43, - T(1.0)); + return operator=(Matrix4( + m11*matrix.m11 + m12*matrix.m21 + m13*matrix.m31, + m11*matrix.m12 + m12*matrix.m22 + m13*matrix.m32, + m11*matrix.m13 + m12*matrix.m23 + m13*matrix.m33, + T(0.0), + + m21*matrix.m11 + m22*matrix.m21 + m23*matrix.m31, + m21*matrix.m12 + m22*matrix.m22 + m23*matrix.m32, + m21*matrix.m13 + m22*matrix.m23 + m23*matrix.m33, + T(0.0), + + m31*matrix.m11 + m32*matrix.m21 + m33*matrix.m31, + m31*matrix.m12 + m32*matrix.m22 + m33*matrix.m32, + m31*matrix.m13 + m32*matrix.m23 + m33*matrix.m33, + T(0.0), + + m41*matrix.m11 + m42*matrix.m21 + m43*matrix.m31 + matrix.m41, + m41*matrix.m12 + m42*matrix.m22 + m43*matrix.m32 + matrix.m42, + m41*matrix.m13 + m42*matrix.m23 + m43*matrix.m33 + matrix.m43, + T(1.0) + )); } /*! @@ -225,26 +261,11 @@ namespace Nz * \return Vector4 which is the transformation of this axis * * \param column Index of the column you want - * - * \remark Produce a NazaraError if you try to access index greater than 3 with NAZARA_MATH_SAFE defined - * \throw std::out_of_range if NAZARA_MATH_SAFE is defined and if you try to access index greater than 3 */ - template - Vector4 Matrix4::GetColumn(unsigned int column) const + constexpr Vector4 Matrix4::GetColumn(std::size_t column) const { - ///FIXME: Est-ce une bonne idée de gérer la matrice de cette façon ? - - #if NAZARA_MATH_SAFE - if (column > 3) - { - std::string error("Column out of range: (" + std::to_string(column) + ") > 3"); - - NazaraError(error); - throw std::out_of_range(error); - } - #endif - + NazaraAssert(column < 4, "column index out of range"); const T* ptr = &m11 + column * 4; return Vector4(ptr[0], ptr[1], ptr[2], ptr[3]); } @@ -258,7 +279,7 @@ namespace Nz * \see GetDeterminantTransform */ template - T Matrix4::GetDeterminant() const + constexpr T Matrix4::GetDeterminant() const { #if NAZARA_MATH_MATRIX4_CHECK_TRANSFORM if (IsTransformMatrix()) @@ -285,7 +306,7 @@ namespace Nz * \see GetDeterminant */ template - T Matrix4::GetDeterminantTransform() const + constexpr T Matrix4::GetDeterminantTransform() const { #if NAZARA_MATH_MATRIX4_CHECK_TRANSFORM if (!IsTransformMatrix()) @@ -314,9 +335,8 @@ namespace Nz * * \see GetInverseAffine */ - template - bool Matrix4::GetInverse(Matrix4* dest) const + constexpr bool Matrix4::GetInverse(Matrix4* dest) const { NazaraAssert(dest, "destination matrix must be valid"); @@ -467,7 +487,7 @@ namespace Nz * \see GetInverse */ template - bool Matrix4::GetInverseTransform(Matrix4* dest) const + constexpr bool Matrix4::GetInverseTransform(Matrix4* dest) const { NazaraAssert(dest, "destination matrix must be valid"); @@ -554,7 +574,6 @@ namespace Nz * \brief Gets the rotation from this matrix * \return Quaternion which is the representation of the rotation in this matrix */ - template Quaternion Matrix4::GetRotation() const { @@ -613,21 +632,10 @@ namespace Nz * \remark Produce a NazaraError if you try to access index greater than 3 with NAZARA_MATH_SAFE defined * \throw std::out_of_range if NAZARA_MATH_SAFE is defined and if you try to access index greater than 3 */ - template - Vector4 Matrix4::GetRow(unsigned int row) const + constexpr Vector4 Matrix4::GetRow(std::size_t row) const { - ///FIXME: Est-ce une bonne idée de gérer la matrice de cette façon ? - - #if NAZARA_MATH_SAFE - if (row > 3) - { - std::string error("Row out of range: (" + NumberToString(row) + ") > 3"); - - NazaraError(error); - throw std::out_of_range(error); - } - #endif + NazaraAssert(row < 4, "row index out of range"); const T* ptr = &m11; return Vector4(ptr[row], ptr[row+4], ptr[row+8], ptr[row+12]); @@ -639,9 +647,8 @@ namespace Nz * * \see GetSquaredScale */ - template - Vector3 Matrix4::GetScale() const + constexpr Vector3 Matrix4::GetScale() const { Vector3 squaredScale = GetSquaredScale(); return Vector3(std::sqrt(squaredScale.x), std::sqrt(squaredScale.y), std::sqrt(squaredScale.z)); @@ -653,9 +660,8 @@ namespace Nz * * \see GetScale */ - template - Vector3 Matrix4::GetSquaredScale() const + constexpr Vector3 Matrix4::GetSquaredScale() const { return Vector3(m11 * m11 + m12 * m12 + m13 * m13, m21 * m21 + m22 * m22 + m23 * m23, @@ -666,9 +672,8 @@ namespace Nz * \brief Gets the translation from this matrix * \return Vector3 which is the representation of the translation in this matrix */ - template - Vector3 Matrix4::GetTranslation() const + constexpr Vector3 Matrix4::GetTranslation() const { return Vector3(m41, m42, m43); } @@ -683,9 +688,8 @@ namespace Nz * * \see Transpose */ - template - void Matrix4::GetTransposed(Matrix4* dest) const + constexpr void Matrix4::GetTransposed(Matrix4* dest) const { #ifdef NAZARA_DEBUG if (!dest) @@ -695,10 +699,12 @@ namespace Nz } #endif - dest->Set(m11, m21, m31, m41, - m12, m22, m32, m42, - m13, m23, m33, m43, - m14, m24, m34, m44); + (*dest) = Matrix4f( + m11, m21, m31, m41, + m12, m22, m32, m42, + m13, m23, m33, m43, + m14, m24, m34, m44 + ); } /*! @@ -707,9 +713,8 @@ namespace Nz * * \see GetDeterminant */ - template - bool Matrix4::HasNegativeScale() const + constexpr bool Matrix4::HasNegativeScale() const { return GetDeterminant() < T(0.0); } @@ -720,9 +725,8 @@ namespace Nz * * \see HasNegativeScale */ - template - bool Matrix4::HasScale() const + constexpr bool Matrix4::HasScale() const { T t = m11*m11 + m21*m21 + m31*m31; if (!NumberEquals(t, T(1.0))) @@ -748,7 +752,7 @@ namespace Nz * \see InverseTransform */ template - Matrix4& Matrix4::Inverse(bool* succeeded) + constexpr Matrix4& Matrix4::Inverse(bool* succeeded) { bool result = GetInverse(this); if (succeeded) @@ -766,7 +770,7 @@ namespace Nz * \see Inverse */ template - Matrix4& Matrix4::InverseTransform(bool* succeeded) + constexpr Matrix4& Matrix4::InverseTransform(bool* succeeded) { bool result = GetInverseTransform(this); if (succeeded) @@ -779,9 +783,8 @@ namespace Nz * \brief Checks whether the matrix is affine * \return true if matrix is affine */ - template - bool Matrix4::IsTransformMatrix() const + constexpr bool Matrix4::IsTransformMatrix() const { return NumberEquals(m14, T(0.0)) && NumberEquals(m24, T(0.0)) && NumberEquals(m34, T(0.0)) && NumberEquals(m44, T(1.0)); } @@ -790,9 +793,8 @@ namespace Nz * \brief Checks whether the matrix is identity * \return true if matrix is identity */ - template - bool Matrix4::IsIdentity() const + constexpr bool Matrix4::IsIdentity() const { return (NumberEquals(m11, T(1.0)) && NumberEquals(m12, T(0.0)) && NumberEquals(m13, T(0.0)) && NumberEquals(m14, T(0.0)) && NumberEquals(m21, T(0.0)) && NumberEquals(m22, T(1.0)) && NumberEquals(m23, T(0.0)) && NumberEquals(m24, T(0.0)) && @@ -800,324 +802,6 @@ namespace Nz NumberEquals(m41, T(0.0)) && NumberEquals(m42, T(0.0)) && NumberEquals(m43, T(0.0)) && NumberEquals(m44, T(1.0))); } - /*! - * \brief Makes the matrix identity (with 1 on diagonal and 0 for others) - * \return A reference to this matrix with components (1 on diagonal and 0 for others) - * - * \see Identity - */ - - template - Matrix4& Matrix4::MakeIdentity() - { - Set(T(1.0), T(0.0), T(0.0), T(0.0), - T(0.0), T(1.0), T(0.0), T(0.0), - T(0.0), T(0.0), T(1.0), T(0.0), - T(0.0), T(0.0), T(0.0), T(1.0)); - - return *this; - } - - /*! - * \brief Makes the matrix a 'look at matrix' - * \return A reference to this matrix transformed in 'look at matrix' - * - * \param eye Position of the camera - * \param target Position of the target of the camera - * \param up Direction of up vector according to the orientation of camera - * - * \see LookAt - */ - template - Matrix4& Matrix4::MakeLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) - { - Vector3 f = Vector3::Normalize(target - eye); - Vector3 s = Vector3::Normalize(f.CrossProduct(up)); - Vector3 u = s.CrossProduct(f); - - Set(s.x, u.x, -f.x, T(0.0), - s.y, u.y, -f.y, T(0.0), - s.z, u.z, -f.z, T(0.0), - -s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0)); - - return *this; - } - - /*! - * \brief Makes the matrix a 'orthographic matrix' - * \return A reference to this matrix transformed in 'orthographic matrix' - * - * \param left Distance between center and left - * \param right Distance between center and right - * \param top Distance between center and top - * \param bottom Distance between center and bottom - * \param zNear Distance where 'vision' begins - * \param zFar Distance where 'vision' ends - * - * \see Ortho - */ - - template - Matrix4& Matrix4::MakeOrtho(T left, T right, T top, T bottom, T zNear, T zFar) - { - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb204942(v=vs.85).aspx - Set(T(2.0) / (right - left), T(0.0), T(0.0), T(0.0), - T(0.0), T(2.0) / (top - bottom), T(0.0), T(0.0), - T(0.0), T(0.0), T(1.0) / (zNear - zFar), T(0.0), - (left + right) / (left - right), (top + bottom) / (bottom - top), zNear/(zNear - zFar), T(1.0)); - - return *this; - } - - /*! - * \brief Makes the matrix a 'perspective matrix' - * \return A reference to this matrix transformed in 'perspective matrix' - * - * \param angle FOV angle - * \param ratio Rendering ratio (typically 16/9 or 4/3) - * \param zNear Distance where 'vision' begins - * \param zFar Distance where 'vision' ends - * - * \see Perspective - */ - - template - Matrix4& Matrix4::MakePerspective(RadianAngle angle, T ratio, T zNear, T zFar) - { - angle /= T(2.0); - - T yScale = angle.GetTan(); - - Set(T(1.0) / (ratio * yScale), T(0.0), T(0.0), T(0.0), - T(0.0), T(-1.0) / (yScale), T(0.0), T(0.0), - T(0.0), T(0.0), zFar / (zNear - zFar), T(-1.0), - T(0.0), T(0.0), -(zNear * zFar) / (zFar - zNear), T(0.0)); - - return *this; - } - - /*! - * \brief Makes the matrix the representation of the quaternion - * \return A reference to this matrix which is the rotation of the quaternion - * - * \param rotation Quaternion representing a rotation of space - * - * \see Rotate - */ - - template - Matrix4& Matrix4::MakeRotation(const Quaternion& rotation) - { - SetRotation(rotation); - - // We complete the matrix - m14 = T(0.0); - m24 = T(0.0); - m34 = T(0.0); - m41 = T(0.0); - m42 = T(0.0); - m43 = T(0.0); - m44 = T(1.0); - - return *this; - } - - /*! - * \brief Makes the matrix with the scale - * \return A reference to this matrix which is the scale - * - * \param scale Vector3 representing the homothety - * - * \see Scale - */ - - template - Matrix4& Matrix4::MakeScale(const Vector3& scale) - { - Set(scale.x, T(0.0), T(0.0), T(0.0), - T(0.0), scale.y, T(0.0), T(0.0), - T(0.0), T(0.0), scale.z, T(0.0), - T(0.0), T(0.0), T(0.0), T(1.0)); - - return *this; - } - - /*! - * \brief Makes the matrix with the translation - * \return A reference to this matrix which is the translation - * - * \param translation Vector3 representing the translation - * - * \see Translate - */ - - template - Matrix4& Matrix4::MakeTranslation(const Vector3& translation) - { - Set(T(1.0), T(0.0), T(0.0), T(0.0), - T(0.0), T(1.0), T(0.0), T(0.0), - T(0.0), T(0.0), T(1.0), T(0.0), - translation.x, translation.y, translation.z, T(1.0)); - - return *this; - } - - /*! - * \brief Makes the matrix with the translation and the rotation - * \return A reference to this matrix which is transformation obtained by the translation and the rotation - * - * \param translation Vector3 representing the translation - * \param rotation Quaternion representing a rotation of space - * - * \remark Rotation is applied first - * - * \see Transform - */ - - template - Matrix4& Matrix4::MakeTransform(const Vector3& translation, const Quaternion& rotation) - { - // The rotation and the translation may be directly applied - SetRotation(rotation); - SetTranslation(translation); - - // We complete the matrix (the transformations are affine) - m14 = T(0.0); - m24 = T(0.0); - m34 = T(0.0); - m44 = T(1.0); - - return *this; - } - - /*! - * \brief Makes the matrix with the translation, the rotation and the scale - * \return A reference to this matrix which is transformation obtained by the translation, the rotation and the scale - * - * \param translation Vector3 representing the translation - * \param rotation Quaternion representing a rotation of space - * \param scale Vector3 representing the homothety - * - * \remark Rotation is applied first, then translation - * - * \see Transform - */ - - template - Matrix4& Matrix4::MakeTransform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) - { - MakeTransform(translation, rotation); - - // Then we apply the scale to current values - return ApplyScale(scale); - } - - /*! - * \brief Makes the matrix an inverse transform matrix (aka view matrix) - * \return A reference to this matrix - * - * \param translation Vector3 representing the translation - * \param rotation Quaternion representing a rotation of space - * - * \see InverseTransformMatrix - */ - template - Matrix4& Matrix4::MakeTransformInverse(const Vector3& translation, const Quaternion& rotation) - { - // A view matrix must apply an inverse transformation of the 'world' matrix - Quaternion invRot = rotation.GetConjugate(); // Inverse of the rotation - - return MakeTransform(-(invRot * translation), invRot); - } - - /*! - * \brief Makes the matrix an inverse transform matrix (aka view matrix) - * \return A reference to this matrix - * - * \param translation Vector3 representing the translation - * \param rotation Quaternion representing a rotation of space - * \param scale Vector3 representing the scale - * - * \see InverseTransformMatrix - */ - template - Matrix4& Matrix4::MakeTransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) - { - MakeTransformInverse(translation, rotation); - ConcatenateTransform(Scale(T(1.0) / scale)); - - return *this; - } - - /*! - * \brief Makes the matrix zero (with 0 everywhere) - * \return A reference to this matrix with components (0 everywhere) - * - * \see Zero - */ - template - Matrix4& Matrix4::MakeZero() - { - Set(T(0.0), T(0.0), T(0.0), T(0.0), - T(0.0), T(0.0), T(0.0), T(0.0), - T(0.0), T(0.0), T(0.0), T(0.0), - T(0.0), T(0.0), T(0.0), T(0.0)); - - return *this; - } - - /*! - * \brief Sets the components of the matrix - * \return A reference to this matrix - * - * \param rIJ Matrix components at index(I, J) - */ - - template - Matrix4& Matrix4::Set(T r11, T r12, T r13, T r14, - T r21, T r22, T r23, T r24, - T r31, T r32, T r33, T r34, - T r41, T r42, T r43, T r44) - { - m11 = r11; - m12 = r12; - m13 = r13; - m14 = r14; - m21 = r21; - m22 = r22; - m23 = r23; - m24 = r24; - m31 = r31; - m32 = r32; - m33 = r33; - m34 = r34; - m41 = r41; - m42 = r42; - m43 = r43; - m44 = r44; - - return *this; - } - - /*! - * \brief Sets the components of the matrix from another type of Matrix4 - * \return A reference to this matrix - * - * \param matrix Matrix4 of type U to convert its components - */ - - template - template - Matrix4& Matrix4::Set(const Matrix4& matrix) - { - Set(T(matrix[ 0]), T(matrix[ 1]), T(matrix[ 2]), T(matrix[ 3]), - T(matrix[ 4]), T(matrix[ 5]), T(matrix[ 6]), T(matrix[ 7]), - T(matrix[ 8]), T(matrix[ 9]), T(matrix[10]), T(matrix[11]), - T(matrix[12]), T(matrix[13]), T(matrix[14]), T(matrix[15])); - - return *this; - } - /*! * \brief Sets the components of the matrix from a quaternion * \return A reference to this matrix which is the rotation of the quaternion @@ -1126,9 +810,8 @@ namespace Nz * * \remark 3rd column and row are unchanged. Scale is removed. */ - template - Matrix4& Matrix4::SetRotation(const Quaternion& rotation) + constexpr Matrix4& Matrix4::SetRotation(const Quaternion& rotation) { T qw = rotation.w; T qx = rotation.x; @@ -1162,9 +845,8 @@ namespace Nz * * \remark Components are unchanged, except the three first on the diagonal */ - template - Matrix4& Matrix4::SetScale(const Vector3& scale) + constexpr Matrix4& Matrix4::SetScale(const Vector3& scale) { m11 = scale.x; m22 = scale.y; @@ -1181,9 +863,8 @@ namespace Nz * * \remark Components are unchanged, except the three first on the third row */ - template - Matrix4& Matrix4::SetTranslation(const Vector3& translation) + constexpr Matrix4& Matrix4::SetTranslation(const Vector3& translation) { m41 = translation.x; m42 = translation.y; @@ -1214,9 +895,8 @@ namespace Nz * \param z Z Component of the imaginary Vector4 * \param w W Component of the imaginary Vector4 */ - template - Vector2 Matrix4::Transform(const Vector2& vector, T z, T w) const + constexpr Vector2 Matrix4::Transform(const Vector2& vector, T z, T w) const { return Vector2(m11 * vector.x + m21 * vector.y + m31 * z + m41 * w, m12 * vector.x + m22 * vector.y + m32 * z + m42 * w); @@ -1229,9 +909,8 @@ namespace Nz * \param vector To transform * \param w W Component of the imaginary Vector4 */ - template - Vector3 Matrix4::Transform(const Vector3& vector, T w) const + constexpr Vector3 Matrix4::Transform(const Vector3& vector, T w) const { return Vector3(m11 * vector.x + m21 * vector.y + m31 * vector.z + m41 * w, m12 * vector.x + m22 * vector.y + m32 * vector.z + m42 * w, @@ -1244,9 +923,8 @@ namespace Nz * * \param vector To transform */ - template - Vector4 Matrix4::Transform(const Vector4& vector) const + constexpr Vector4 Matrix4::Transform(const Vector4& vector) const { return Vector4(m11 * vector.x + m21 * vector.y + m31 * vector.z + m41 * vector.w, m12 * vector.x + m22 * vector.y + m32 * vector.z + m42 * vector.w, @@ -1260,9 +938,8 @@ namespace Nz * * \see GetTransposed */ - template - Matrix4& Matrix4::Transpose() + constexpr Matrix4& Matrix4::Transpose() { std::swap(m12, m21); std::swap(m13, m31); @@ -1281,7 +958,7 @@ namespace Nz * \remark x and y must both be comprised in range [0,4[ */ template - T& Matrix4::operator()(std::size_t x, std::size_t y) + constexpr T& Matrix4::operator()(std::size_t x, std::size_t y) { NazaraAssert(x <= 3, "index out of range"); NazaraAssert(y <= 3, "index out of range"); @@ -1296,7 +973,7 @@ namespace Nz * \remark x and y must both be comprised in range [0,4[ */ template - const T& Matrix4::operator()(std::size_t x, std::size_t y) const + constexpr const T& Matrix4::operator()(std::size_t x, std::size_t y) const { NazaraAssert(x <= 3, "index out of range"); NazaraAssert(y <= 3, "index out of range"); @@ -1311,7 +988,7 @@ namespace Nz * \remark i must be comprised in range [0,16[ */ template - T& Matrix4::operator[](std::size_t i) + constexpr T& Matrix4::operator[](std::size_t i) { NazaraAssert(i <= 16, "index out of range"); @@ -1325,7 +1002,7 @@ namespace Nz * \remark i must be comprised in range [0,16[ */ template - const T& Matrix4::operator[](std::size_t i) const + constexpr const T& Matrix4::operator[](std::size_t i) const { NazaraAssert(i <= 16, "index out of range"); @@ -1338,9 +1015,8 @@ namespace Nz * * \param matrix The other matrix to multiply components with */ - template - Matrix4 Matrix4::operator*(const Matrix4& matrix) const + constexpr Matrix4 Matrix4::operator*(const Matrix4& matrix) const { Matrix4 result(*this); return result.Concatenate(matrix); @@ -1352,9 +1028,8 @@ namespace Nz * * \param vector The vector to multiply the matrix with */ - template - Vector2 Matrix4::operator*(const Vector2& vector) const + constexpr Vector2 Matrix4::operator*(const Vector2& vector) const { return Transform(vector); } @@ -1365,9 +1040,8 @@ namespace Nz * * \param vector The vector to multiply the matrix with */ - template - Vector3 Matrix4::operator*(const Vector3& vector) const + constexpr Vector3 Matrix4::operator*(const Vector3& vector) const { return Transform(vector); } @@ -1378,9 +1052,8 @@ namespace Nz * * \param vector The vector to multiply the matrix with */ - template - Vector4 Matrix4::operator*(const Vector4& vector) const + constexpr Vector4 Matrix4::operator*(const Vector4& vector) const { return Transform(vector); } @@ -1391,9 +1064,8 @@ namespace Nz * * \param scalar The scalar to multiply the matrix'components with */ - template - Matrix4 Matrix4::operator*(T scalar) const + constexpr Matrix4 Matrix4::operator*(T scalar) const { Matrix4 mat; for (unsigned int i = 0; i < 16; ++i) @@ -1408,9 +1080,8 @@ namespace Nz * * \param matrix The matrix to multiply with */ - template - Matrix4& Matrix4::operator*=(const Matrix4& matrix) + constexpr Matrix4& Matrix4::operator*=(const Matrix4& matrix) { Concatenate(matrix); @@ -1423,9 +1094,8 @@ namespace Nz * * \param scalar The scalar to multiply with */ - template - Matrix4& Matrix4::operator*=(T scalar) + constexpr Matrix4& Matrix4::operator*=(T scalar) { for (unsigned int i = 0; i < 16; ++i) (&m11)[i] *= scalar; @@ -1439,12 +1109,11 @@ namespace Nz * * \param mat Other matrix to compare with */ - template - bool Matrix4::operator==(const Matrix4& mat) const + constexpr bool Matrix4::operator==(const Matrix4& mat) const { for (unsigned int i = 0; i < 16; ++i) - if (!NumberEquals((&m11)[i], (&mat.m11)[i])) + if ((&m11)[i] != (&mat.m11)[i]) return false; return true; @@ -1456,9 +1125,8 @@ namespace Nz * * \param mat Other matrix to compare with */ - template - bool Matrix4::operator!=(const Matrix4& mat) const + constexpr bool Matrix4::operator!=(const Matrix4& mat) const { return !operator==(mat); } @@ -1472,9 +1140,14 @@ namespace Nz * * \see Concatenate */ + template + constexpr bool Matrix4::ApproxEqual(const Matrix4& lhs, const Matrix4& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } template - Matrix4 Matrix4::Concatenate(const Matrix4& left, const Matrix4& right) + constexpr Matrix4 Matrix4::Concatenate(const Matrix4& left, const Matrix4& right) { Matrix4 matrix(left); // Copy of left-hand side matrix matrix.Concatenate(right); // Concatenation with right-hand side @@ -1492,7 +1165,7 @@ namespace Nz * \see ConcatenateTransform */ template - Matrix4 Matrix4::ConcatenateTransform(const Matrix4& left, const Matrix4& right) + constexpr Matrix4 Matrix4::ConcatenateTransform(const Matrix4& left, const Matrix4& right) { Matrix4 matrix(left); // Copy of left-hand side matrix matrix.ConcatenateTransform(right); // Affine concatenation with right-hand side @@ -1503,17 +1176,16 @@ namespace Nz /*! * \brief Shorthand for the identity matrix * \return A Matrix4 which is the identity matrix - * - * \see MakeIdentity */ - template - Matrix4 Matrix4::Identity() + constexpr Matrix4 Matrix4::Identity() { - Matrix4 matrix; - matrix.MakeIdentity(); - - return matrix; + return Matrix4( + T(1.0), T(0.0), T(0.0), T(0.0), + T(0.0), T(1.0), T(0.0), T(0.0), + T(0.0), T(0.0), T(1.0), T(0.0), + T(0.0), T(0.0), T(0.0), T(1.0) + ); } /*! @@ -1523,17 +1195,20 @@ namespace Nz * \param eye Position of the camera * \param target Position of the target of the camera * \param up Direction of up vector according to the orientation of camera - * - * \see MakeLookAt */ - template - Matrix4 Matrix4::LookAt(const Vector3& eye, const Vector3& target, const Vector3& up) + constexpr Matrix4 Matrix4::LookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { - Matrix4 matrix; - matrix.MakeLookAt(eye, target, up); + Vector3 f = Vector3::Normalize(target - eye); + Vector3 s = Vector3::Normalize(f.CrossProduct(up)); + Vector3 u = s.CrossProduct(f); - return matrix; + return Matrix4( + s.x, u.x, -f.x, T(0.0), + s.y, u.y, -f.y, T(0.0), + s.z, u.z, -f.z, T(0.0), + -s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0) + ); } /*! @@ -1546,17 +1221,17 @@ namespace Nz * \param bottom Distance between center and bottom * \param zNear Distance where 'vision' begins * \param zFar Distance where 'vision' ends - * - * \see MakeOrtho */ - template - Matrix4 Matrix4::Ortho(T left, T right, T top, T bottom, T zNear, T zFar) + constexpr Matrix4 Matrix4::Ortho(T left, T right, T top, T bottom, T zNear, T zFar) { - Matrix4 matrix; - matrix.MakeOrtho(left, right, top, bottom, zNear, zFar); - - return matrix; + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb204942(v=vs.85).aspx + return Matrix4( + T(2.0) / (right - left), T(0.0), T(0.0), T(0.0), + T(0.0), T(2.0) / (top - bottom), T(0.0), T(0.0), + T(0.0), T(0.0), T(1.0) / (zNear - zFar), T(0.0), + (left + right) / (left - right), (top + bottom) / (bottom - top), zNear / (zNear - zFar), T(1.0) + ); } /*! @@ -1567,17 +1242,20 @@ namespace Nz * \param ratio Rendering ratio (typically 16/9 or 4/3) * \param zNear Distance where 'vision' begins * \param zFar Distance where 'vision' ends - * - * \see MakePerspective */ - template Matrix4 Matrix4::Perspective(RadianAngle angle, T ratio, T zNear, T zFar) { - Matrix4 matrix; - matrix.MakePerspective(angle, ratio, zNear, zFar); + angle /= T(2.0); - return matrix; + T yScale = angle.GetTan(); + + return Matrix4( + T(1.0) / (ratio * yScale), T(0.0), T(0.0), T(0.0), + T(0.0), T(-1.0) / (yScale), T(0.0), T(0.0), + T(0.0), T(0.0), zFar / (zNear - zFar), T(-1.0), + T(0.0), T(0.0), -(zNear * zFar) / (zFar - zNear), T(0.0) + ); } /*! @@ -1585,15 +1263,12 @@ namespace Nz * \return A Matrix4 which is the rotation of the quaternion * * \param rotation Quaternion representing a rotation of space - * - * \see MakeRotation */ - template - Matrix4 Matrix4::Rotate(const Quaternion& rotation) + constexpr Matrix4 Matrix4::Rotate(const Quaternion& rotation) { - Matrix4 matrix; - matrix.MakeRotation(rotation); + Matrix4 matrix = Matrix4::Identity(); + matrix.SetRotation(rotation); return matrix; } @@ -1603,17 +1278,16 @@ namespace Nz * \return A Matrix4 which is is the scale * * \param scale Vector3 representing the scale - * - * \see MakeScale */ - template - Matrix4 Matrix4::Scale(const Vector3& scale) + constexpr Matrix4 Matrix4::Scale(const Vector3& scale) { - Matrix4 matrix; - matrix.MakeScale(scale); - - return matrix; + return Matrix4( + scale.x, T(0.0), T(0.0), T(0.0), + T(0.0), scale.y, T(0.0), T(0.0), + T(0.0), T(0.0), scale.z, T(0.0), + T(0.0), T(0.0), T(0.0), T(1.0) + ); } /*! @@ -1621,17 +1295,16 @@ namespace Nz * \return A Matrix4 which is is the translation * * \param translation Vector3 representing the translation - * - * \see MakeTranslation */ - template - Matrix4 Matrix4::Translate(const Vector3& translation) + constexpr Matrix4 Matrix4::Translate(const Vector3& translation) { - Matrix4 mat; - mat.MakeTranslation(translation); - - return mat; + return Matrix4( + T(1.0), T(0.0), T(0.0), T(0.0), + T(0.0), T(1.0), T(0.0), T(0.0), + T(0.0), T(0.0), T(1.0), T(0.0), + translation.x, translation.y, translation.z, T(1.0) + ); } /*! @@ -1642,15 +1315,13 @@ namespace Nz * \param rotation Quaternion representing a rotation of space * * \remark Rotation is applied first - * - * \see MakeTransform */ - template - Matrix4 Matrix4::Transform(const Vector3& translation, const Quaternion& rotation) + constexpr Matrix4 Matrix4::Transform(const Vector3& translation, const Quaternion& rotation) { - Matrix4 mat; - mat.MakeTransform(translation, rotation); + Matrix4 mat = Matrix4f::Identity(); + mat.SetRotation(rotation); + mat.SetTranslation(translation); return mat; } @@ -1664,15 +1335,12 @@ namespace Nz * \param scale Vector3 representing the homothety * * \remark Rotation is applied first, then translation - * - * \see MakeTransform */ - template - Matrix4 Matrix4::Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) + constexpr Matrix4 Matrix4::Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) { - Matrix4 mat; - mat.MakeTransform(translation, rotation, scale); + Matrix4 mat = Transform(translation, rotation); + mat.ApplyScale(scale); return mat; } @@ -1683,16 +1351,14 @@ namespace Nz * * \param translation Vector3 representing the translation * \param rotation Quaternion representing a rotation of space - * - * \see MakeInverseTransformMatrix */ template - Matrix4 Matrix4::TransformInverse(const Vector3& translation, const Quaternion& rotation) + constexpr Matrix4 Matrix4::TransformInverse(const Vector3& translation, const Quaternion& rotation) { - Matrix4 mat; - mat.MakeTransformInverse(translation, rotation); + // A view matrix must apply an inverse transformation of the 'world' matrix + Quaternion invRot = rotation.GetConjugate(); // Inverse of the rotation - return mat; + return Transform(-(invRot * translation), invRot); } /*! @@ -1702,32 +1368,26 @@ namespace Nz * \param translation Vector3 representing the translation * \param rotation Quaternion representing a rotation of space * \param scale Vector3 representing the scale - * - * \see MakeInverseTransformMatrix */ template - Matrix4 Matrix4::TransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) + constexpr Matrix4 Matrix4::TransformInverse(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) { - Matrix4 mat; - mat.MakeTransformInverse(translation, rotation, scale); - - return mat; + return TransformInverse(translation, rotation).ApplyScale(T(1.0) / scale); } /*! * \brief Shorthand for the 'zero' matrix * \return A Matrix4 with components (0 everywhere) - * - * \see MakeZero */ - template - Matrix4 Matrix4::Zero() + constexpr Matrix4 Matrix4::Zero() { - Matrix4 matrix; - matrix.MakeZero(); - - return matrix; + return Matrix4( + T(0.0), T(0.0), T(0.0), T(0.0), + T(0.0), T(0.0), T(0.0), T(0.0), + T(0.0), T(0.0), T(0.0), T(0.0), + T(0.0), T(0.0), T(0.0), T(0.0) + ); } /*! @@ -1794,7 +1454,7 @@ namespace Nz * \param matrix Matrix to multiply with */ template - Matrix4 operator*(T scale, const Matrix4& matrix) + constexpr Matrix4 operator*(T scale, const Matrix4& matrix) { return matrix * scale; } @@ -1802,3 +1462,4 @@ namespace Nz #include +#include "Matrix4.hpp" diff --git a/include/Nazara/Math/OrientedBox.hpp b/include/Nazara/Math/OrientedBox.hpp index 6d019c018..2d9ede6c4 100644 --- a/include/Nazara/Math/OrientedBox.hpp +++ b/include/Nazara/Math/OrientedBox.hpp @@ -22,34 +22,40 @@ namespace Nz class OrientedBox { public: - OrientedBox() = default; - OrientedBox(const Box& box); - template explicit OrientedBox(const OrientedBox& orientedBox); - OrientedBox(const OrientedBox&) = default; - OrientedBox(OrientedBox&&) noexcept = default; + constexpr OrientedBox() = default; + constexpr OrientedBox(const Box& box); + template constexpr explicit OrientedBox(const OrientedBox& orientedBox); + constexpr OrientedBox(const OrientedBox&) = default; + constexpr OrientedBox(OrientedBox&&) noexcept = default; ~OrientedBox() = default; - const Vector3& GetCorner(BoxCorner corner) const; - const Vector3* GetCorners() const; + constexpr bool ApproxEqual(const OrientedBox& obb, T maxDifference = std::numeric_limits::epsilon()) const; - bool IsValid() const; + constexpr const Vector3& GetCorner(BoxCorner corner) const; + constexpr const Vector3* GetCorners() const; + + constexpr bool IsValid() const; std::string ToString() const; - void Update(const Matrix4& transformMatrix); - void Update(const Vector3& transformMatrix); + constexpr void Update(const Matrix4& transformMatrix); + constexpr void Update(const Vector3& transformMatrix); - Vector3& operator()(unsigned int i); - const Vector3& operator()(unsigned int i) const; + constexpr Vector3& operator()(unsigned int i); + constexpr const Vector3& operator()(unsigned int i) const; - OrientedBox& operator=(const OrientedBox&) = default; - OrientedBox& operator=(OrientedBox&&) noexcept = default; + constexpr OrientedBox& operator=(const OrientedBox&) = default; + constexpr OrientedBox& operator=(OrientedBox&&) noexcept = default; - bool operator==(const OrientedBox& box) const; - bool operator!=(const OrientedBox& box) const; + constexpr bool operator==(const OrientedBox& box) const; + constexpr bool operator!=(const OrientedBox& box) const; - static OrientedBox Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation); - static OrientedBox Zero(); + static constexpr bool ApproxEqual(const OrientedBox& lhs, const OrientedBox& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr OrientedBox Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation); + static constexpr OrientedBox Zero(); + + template friend bool Serialize(SerializationContext& context, const OrientedBox& obb, TypeTag>); + template friend bool Unserialize(SerializationContext& context, OrientedBox* obb, TypeTag>); Box localBox; @@ -60,9 +66,6 @@ namespace Nz using OrientedBoxd = OrientedBox; using OrientedBoxf = OrientedBox; - template bool Serialize(SerializationContext& context, const OrientedBox& obb, TypeTag>); - template bool Unserialize(SerializationContext& context, OrientedBox* obb, TypeTag>); - template std::ostream& operator<<(std::ostream& out, const Nz::OrientedBox& orientedBox); } diff --git a/include/Nazara/Math/OrientedBox.inl b/include/Nazara/Math/OrientedBox.inl index a2c4a6340..76b508156 100644 --- a/include/Nazara/Math/OrientedBox.inl +++ b/include/Nazara/Math/OrientedBox.inl @@ -25,9 +25,8 @@ namespace Nz * * \param box Box object */ - template - OrientedBox::OrientedBox(const Box& box) : + constexpr OrientedBox::OrientedBox(const Box& box) : localBox(box) { } @@ -37,16 +36,30 @@ namespace Nz * * \param orientedBox OrientedBox of type U to convert to type T */ - template template - OrientedBox::OrientedBox(const OrientedBox& orientedBox) : + constexpr OrientedBox::OrientedBox(const OrientedBox& orientedBox) : localBox(orientedBox.localBox) { for (auto&& [cornerEnum, corner] : m_corners.iter_kv()) corner = Vector3(orientedBox.GetCorner(cornerEnum)); } + template + constexpr bool OrientedBox::ApproxEqual(const OrientedBox& obb, T maxDifference) const + { + if (!localBox.ApproxEqual(obb.localBox, maxDifference)) + return false; + + for (auto&& [cornerEnum, corner] : m_corners.iter_kv()) + { + if (!corner.ApproxEqual(obb.GetCorner(cornerEnum), maxDifference)) + return false; + } + + return true; + } + /*! * \brief Gets the Vector3 for the corner * \return The position of the corner of the oriented box according to enum BoxCorner @@ -55,16 +68,15 @@ namespace Nz * * \remark If enumeration is not defined in BoxCorner, a NazaraError is thrown and a Vector3 uninitialised is returned */ - template - const Vector3& OrientedBox::GetCorner(BoxCorner corner) const + constexpr const Vector3& OrientedBox::GetCorner(BoxCorner corner) const { NazaraAssert(corner <= BoxCorner::Max, "invalid corner"); return m_corners[corner]; } template - const Vector3* OrientedBox::GetCorners() const + constexpr const Vector3* OrientedBox::GetCorners() const { return &m_corners.front(); } @@ -73,9 +85,8 @@ namespace Nz * \brief Checks whether this oriented box is valid * \return true if the oriented box has a strictly positive width, height and depth */ - template - bool OrientedBox::IsValid() const + constexpr bool OrientedBox::IsValid() const { return localBox.IsValid(); } @@ -84,7 +95,6 @@ namespace Nz * \brief Gives a string representation * \return A string representation of the object: "OrientedBox(...)" */ - template std::string OrientedBox::ToString() const { @@ -99,9 +109,8 @@ namespace Nz * * \param transformMatrix Matrix4 which represents the transformation to apply on the local box */ - template - void OrientedBox::Update(const Matrix4& transformMatrix) + constexpr void OrientedBox::Update(const Matrix4& transformMatrix) { for (auto&& [corner, pos] : m_corners.iter_kv()) pos = transformMatrix.Transform(localBox.GetCorner(corner)); @@ -112,9 +121,8 @@ namespace Nz * * \param translation Vector3 which represents the translation to apply on the local box */ - template - void OrientedBox::Update(const Vector3& translation) + constexpr void OrientedBox::Update(const Vector3& translation) { for (auto&& [corner, pos] : m_corners.iter_kv()) pos = localBox.GetCorner(corner) + translation; @@ -127,9 +135,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greather than BoxCorner::Max with NAZARA_MATH_SAFE defined. If not, it is undefined behaviour * \throw std::out_of_range if NAZARA_MATH_SAFE is defined and you try to acces to index greather than BoxCorner::Max */ - template - Vector3& OrientedBox::operator()(unsigned int i) + constexpr Vector3& OrientedBox::operator()(unsigned int i) { NazaraAssert(i < m_corners.size(), "corner out of range"); return m_corners[static_cast(i)]; @@ -142,9 +149,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greather than BoxCorner::Max with NAZARA_MATH_SAFE defined. If not, it is undefined behaviour * \throw std::out_of_range if NAZARA_MATH_SAFE is defined and you try to acces to index greather than BoxCorner::Max */ - template - const Vector3& OrientedBox::operator()(unsigned int i) const + constexpr const Vector3& OrientedBox::operator()(unsigned int i) const { NazaraAssert(i < m_corners.size(), "corner out of range"); return m_corners[static_cast(i)]; @@ -156,11 +162,10 @@ namespace Nz * * \param box Other oriented box to compare with */ - template - bool OrientedBox::operator==(const OrientedBox& box) const + constexpr bool OrientedBox::operator==(const OrientedBox& box) const { - return localBox == box.localBox; + return localBox == box.localBox && m_corners == box.m_corners; } /*! @@ -169,9 +174,8 @@ namespace Nz * * \param box Other oriented box to compare with */ - template - bool OrientedBox::operator!=(const OrientedBox& box) const + constexpr bool OrientedBox::operator!=(const OrientedBox& box) const { return !operator==(box); } @@ -189,9 +193,14 @@ namespace Nz * * \see Lerp */ + template + constexpr bool OrientedBox::ApproxEqual(const OrientedBox& lhs, const OrientedBox& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } template - OrientedBox OrientedBox::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation) + constexpr OrientedBox OrientedBox::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation) { return OrientedBox{ Box::Lerp(from.localBox, to.localBox, interpolation) }; } @@ -199,12 +208,9 @@ namespace Nz /*! * \brief Shorthand for the oriented box (0, 0, 0, 0, 0, 0) * \return A oriented box with position (0, 0, 0) and lengths (0, 0, 0) - * - * \see MakeZero */ - template - OrientedBox OrientedBox::Zero() + constexpr OrientedBox OrientedBox::Zero() { return OrientedBox{ Box::Zero() }; } @@ -215,8 +221,6 @@ namespace Nz * * \param context Serialization context * \param obb Input oriented box - * - * \remark Does not save OBB corners */ template bool Serialize(SerializationContext& context, const OrientedBox& obb, TypeTag>) @@ -224,6 +228,12 @@ namespace Nz if (!Serialize(context, obb.localBox)) return false; + for (auto&& corner : obb.m_corners) + { + if (!Serialize(context, corner)) + return false; + } + return true; } @@ -233,8 +243,6 @@ namespace Nz * * \param context Serialization context * \param obb Output oriented box - * - * \remark The resulting oriented box corners will *not* be updated, a call to Update is required */ template bool Unserialize(SerializationContext& context, OrientedBox* obb, TypeTag>) @@ -242,6 +250,12 @@ namespace Nz if (!Unserialize(context, &obb->localBox)) return false; + for (auto&& corner : obb->m_corners) + { + if (!Unserialize(context, &corner)) + return false; + } + return true; } @@ -267,3 +281,4 @@ namespace Nz } #include +#include "OrientedBox.hpp" diff --git a/include/Nazara/Math/PidController.hpp b/include/Nazara/Math/PidController.hpp index ac8e36249..850d832c8 100644 --- a/include/Nazara/Math/PidController.hpp +++ b/include/Nazara/Math/PidController.hpp @@ -13,9 +13,9 @@ namespace Nz class PidController { public: - PidController(float p, float i, float d); + constexpr PidController(float p, float i, float d); - T Update(const T& currentError, float elapsedTime); + constexpr T Update(const T& currentError, float elapsedTime); private: T m_lastError; diff --git a/include/Nazara/Math/PidController.inl b/include/Nazara/Math/PidController.inl index ba5067fd5..9f8d87b33 100644 --- a/include/Nazara/Math/PidController.inl +++ b/include/Nazara/Math/PidController.inl @@ -7,7 +7,7 @@ namespace Nz { template - PidController::PidController(float p, float i, float d) : + constexpr PidController::PidController(float p, float i, float d) : m_lastError(0), m_integral(0), m_dFactor(d), @@ -17,7 +17,7 @@ namespace Nz } template - T PidController::Update(const T& currentError, float elapsedTime) + constexpr T PidController::Update(const T& currentError, float elapsedTime) { m_integral += currentError * elapsedTime; T deriv = (currentError - m_lastError) / elapsedTime; diff --git a/include/Nazara/Math/Plane.hpp b/include/Nazara/Math/Plane.hpp index 52c5a0f67..0d1a4cb1d 100644 --- a/include/Nazara/Math/Plane.hpp +++ b/include/Nazara/Math/Plane.hpp @@ -18,42 +18,34 @@ namespace Nz class Plane { public: - Plane() = default; - Plane(T normalX, T normalY, T normalZ, T Distance); - Plane(const T plane[4]); - Plane(const Vector3& Normal, T Distance); - Plane(const Vector3& Normal, const Vector3& point); + constexpr Plane() = default; + constexpr Plane(T normalX, T normalY, T normalZ, T Distance); + constexpr Plane(const T plane[4]); + constexpr Plane(const Vector3& Normal, T Distance); + constexpr Plane(const Vector3& Normal, const Vector3& point); Plane(const Vector3& point1, const Vector3& point2, const Vector3& point3); - template explicit Plane(const Plane& plane); - Plane(const Plane& plane) = default; + template constexpr explicit Plane(const Plane& plane); + constexpr Plane(const Plane& plane) = default; ~Plane() = default; - T Distance(T x, T y, T z) const; - T Distance(const Vector3& point) const; + constexpr bool ApproxEqual(const Plane& plane, T maxDifference = std::numeric_limits::epsilon()) const; - Plane& MakeXY(); - Plane& MakeXZ(); - Plane& MakeYZ(); - - Plane& Set(T normalX, T normalY, T normalZ, T Distance); - Plane& Set(const T plane[4]); - Plane& Set(const Vector3& Normal, T Distance); - Plane& Set(const Vector3& Normal, const Vector3& point); - Plane& Set(const Vector3& point1, const Vector3& point2, const Vector3& point3); - template Plane& Set(const Plane& plane); + constexpr T Distance(T x, T y, T z) const; + constexpr T Distance(const Vector3& point) const; std::string ToString() const; - Plane& operator=(const Plane& other) = default; + constexpr Plane& operator=(const Plane& other) = default; - bool operator==(const Plane& plane) const; - bool operator!=(const Plane& plane) const; + constexpr bool operator==(const Plane& plane) const; + constexpr bool operator!=(const Plane& plane) const; - static Vector3 Intersect(const Plane& p0, const Plane& p1, const Plane& p2); - static Plane Lerp(const Plane& from, const Plane& to, T interpolation); - static Plane XY(); - static Plane XZ(); - static Plane YZ(); + static constexpr bool ApproxEqual(const Plane& lhs, const Plane& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Vector3 Intersect(const Plane& p0, const Plane& p1, const Plane& p2); + static constexpr Plane Lerp(const Plane& from, const Plane& to, T interpolation); + static constexpr Plane XY(); + static constexpr Plane XZ(); + static constexpr Plane YZ(); Vector3 normal; T distance; diff --git a/include/Nazara/Math/Plane.inl b/include/Nazara/Math/Plane.inl index d04f4c042..1c860dfc6 100644 --- a/include/Nazara/Math/Plane.inl +++ b/include/Nazara/Math/Plane.inl @@ -26,11 +26,11 @@ namespace Nz * \param normalZ Z component of the normal * \param D Distance to origin */ - template - Plane::Plane(T normalX, T normalY, T normalZ, T D) + constexpr Plane::Plane(T normalX, T normalY, T normalZ, T D) : + normal(normalX, normalY, normalZ), + distance(D) { - Set(normalX, normalY, normalZ, D); } /*! @@ -38,11 +38,11 @@ namespace Nz * * \param plane[4] plane[0] is X component, plane[1] is Y component, plane[2] is Z component and plane[3] is D */ - template - Plane::Plane(const T plane[4]) + constexpr Plane::Plane(const T plane[4]) : + normal(plane[0], plane[1], plane[2]), + distance(plane[3]) { - Set(plane); } /*! @@ -51,11 +51,11 @@ namespace Nz * \param Normal normal of the vector * \param D Distance to origin */ - template - Plane::Plane(const Vector3& Normal, T D) + constexpr Plane::Plane(const Vector3& Normal, T D) : + normal(Normal), + distance(D) { - Set(Normal, D); } /*! @@ -64,11 +64,11 @@ namespace Nz * \param Normal Normal of the plane * \param point Point which verifies the equation of the plane */ - template - Plane::Plane(const Vector3& Normal, const Vector3& point) + constexpr Plane::Plane(const Vector3& Normal, const Vector3& point) : + normal(Normal), + distance(-Normal.DotProduct(point)) { - Set(Normal, point); } /*! @@ -80,11 +80,15 @@ namespace Nz * * \remark They are expected not to be colinear */ - template Plane::Plane(const Vector3& point1, const Vector3& point2, const Vector3& point3) { - Set(point1, point2, point3); + Vector3 edge1 = point2 - point1; + Vector3 edge2 = point3 - point1; + normal = edge1.CrossProduct(edge2); + normal.Normalize(); + + distance = normal.DotProduct(point3); } /*! @@ -92,12 +96,21 @@ namespace Nz * * \param plane Plane of type U to convert to type T */ - template template - Plane::Plane(const Plane& plane) + constexpr Plane::Plane(const Plane& plane) : + normal(Vector3(plane.normal)), + distance(T(plane.distance)) { - Set(plane); + } + + template + constexpr bool Plane::ApproxEqual(const Plane& plane, T maxDifference) const + { + if (!normal.ApproxEqual(plane.normal, maxDifference)) + return false; + + return NumberEquals(distance, plane.distance, maxDifference); } /*! @@ -112,9 +125,8 @@ namespace Nz * * \see Distance */ - template - T Plane::Distance(T x, T y, T z) const + constexpr T Plane::Distance(T x, T y, T z) const { return Distance(Vector3(x, y, z)); } @@ -129,162 +141,12 @@ namespace Nz * * \see Distance */ - template - T Plane::Distance(const Vector3& point) const + constexpr T Plane::Distance(const Vector3& point) const { return normal.DotProduct(point) - distance; // ax + by + cd - d = 0. } - /*! - * \brief Makes the plane (0, 0, 1, 0) - * \return A reference to this plane with components (0, 0, 1, 0) - * - * \see XY - */ - - template - Plane& Plane::MakeXY() - { - return Set(T(0.0), T(0.0), T(1.0), T(0.0)); - } - - /*! - * \brief Makes the plane (0, 1, 0, 0) - * \return A reference to this plane with components (0, 1, 0, 0) - * - * \see XZ - */ - - template - Plane& Plane::MakeXZ() - { - return Set(T(0.0), T(1.0), T(0.0), T(0.0)); - } - - /*! - * \brief Makes the plane (1, 0, 0, 0) - * \return A reference to this plane with components (1, 0, 0, 0) - * - * \see YZ - */ - - template - Plane& Plane::MakeYZ() - { - return Set(T(1.0), T(0.0), T(0.0), T(0.0)); - } - - /*! - * \brief Sets the components of the plane - * \return A reference to this plane - * - * \param normalX X component of the normal - * \param normalY Y component of the normal - * \param normalZ Z component of the normal - * \param D Distance to origin - */ - - template - Plane& Plane::Set(T normalX, T normalY, T normalZ, T D) - { - distance = D; - normal.Set(normalX, normalY, normalZ); - - return *this; - } - - /*! - * \brief Sets the components of the plane from an array of four elements - * \return A reference to this plane - * - * \param plane[4] plane[0] is X component, plane[1] is Y component, plane[2] is Z component and plane[3] is D - */ - - template - Plane& Plane::Set(const T plane[4]) - { - normal.Set(plane[0], plane[1], plane[2]); - distance = plane[3]; - - return *this; - } - - /*! - * \brief Sets the components of the plane from a normal and a distance - * \return A reference to this plane - * - * \param Normal Normal of the vector - * \param D Distance to origin - */ - - template - Plane& Plane::Set(const Vector3& Normal, T D) - { - distance = D; - normal = Normal; - - return *this; - } - - /*! - * \brief Sets the components of the plane from a normal and a point - * \return A reference to this plane - * - * \param Normal Normal of the plane - * \param point Point which verifies the equation of the plane - */ - - template - Plane& Plane::Set(const Vector3& Normal, const Vector3& point) - { - normal = Normal; - distance = -normal.DotProduct(point); - - return *this; - } - - /*! - * \brief Sets the components of the plane from three points - * \return A reference to this plane - * - * \param point1 First point - * \param point2 Second point - * \param point3 Third point - * - * \remark They are expected not to be colinear - */ - - template - Plane& Plane::Set(const Vector3& point1, const Vector3& point2, const Vector3& point3) - { - Vector3 edge1 = point2 - point1; - Vector3 edge2 = point3 - point1; - normal = edge1.CrossProduct(edge2); - normal.Normalize(); - - distance = normal.DotProduct(point3); - - return *this; - } - - /*! - * \brief Sets the components of the plane from another type of Plane - * \return A reference to this plane - * - * \param plane Plane of type U to convert its components - */ - - template - template - Plane& Plane::Set(const Plane& plane) - { - normal.Set(plane.normal); - distance = T(plane.distance); - - return *this; - } - /*! * \brief Gives a string representation * \return A string representation of the object: "Plane(Normal: Vector3(x, y, z); Distance: w)" @@ -309,9 +171,9 @@ namespace Nz */ template - bool Plane::operator==(const Plane& plane) const + constexpr bool Plane::operator==(const Plane& plane) const { - return (normal == plane.normal && NumberEquals(distance, plane.distance)) || (normal == -plane.normal && NumberEquals(distance, -plane.distance)); + return normal == plane.normal && distance == plane.distance; } /*! @@ -324,11 +186,17 @@ namespace Nz */ template - bool Plane::operator!=(const Plane& plane) const + constexpr bool Plane::operator!=(const Plane& plane) const { return !operator==(plane); } + template + constexpr bool Plane::ApproxEqual(const Plane& lhs, const Plane& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + /*! * \brief Intersects three planes to retrieve a single intersection point * \return The intersection point @@ -340,7 +208,7 @@ namespace Nz * \remark All three planes must have differents normals otherwise result is undefined */ template - Vector3 Plane::Intersect(const Plane& p0, const Plane& p1, const Plane& p2) + constexpr Vector3 Plane::Intersect(const Plane& p0, const Plane& p1, const Plane& p2) { // From https://donw.io/post/frustum-point-extraction/ Vector3f bxc = Vector3f::CrossProduct(p1.normal, p2.normal); @@ -365,7 +233,7 @@ namespace Nz * \see Lerp */ template - Plane Plane::Lerp(const Plane& from, const Plane& to, T interpolation) + constexpr Plane Plane::Lerp(const Plane& from, const Plane& to, T interpolation) { #ifdef NAZARA_DEBUG if (interpolation < T(0.0) || interpolation > T(1.0)) @@ -386,49 +254,31 @@ namespace Nz /*! * \brief Shorthand for the plane (0, 0, 1, 0) * \return A plane with components (0, 0, 1, 0) - * - * \see MakeXY */ - template - Plane Plane::XY() + constexpr Plane Plane::XY() { - Plane plane; - plane.MakeXY(); - - return plane; + return Plane(Vector3::UnitZ(), 0); } /*! * \brief Shorthand for the plane (0, 1, 0, 0) * \return A plane with components (0, 1, 0, 0) - * - * \see MakeXZ */ - template - Plane Plane::XZ() + constexpr Plane Plane::XZ() { - Plane plane; - plane.MakeXZ(); - - return plane; + return Plane(Vector3::UnitY(), 0); } /*! * \brief Shorthand for the plane (1, 0, 0, 0) * \return A plane with components (1, 0, 0, 0) - * - * \see MakeYZ */ - template - Plane Plane::YZ() + constexpr Plane Plane::YZ() { - Plane plane; - plane.MakeYZ(); - - return plane; + return Plane(Vector3::UnitX(), 0); } /*! @@ -484,3 +334,4 @@ namespace Nz } #include +#include "Plane.hpp" diff --git a/include/Nazara/Math/Quaternion.hpp b/include/Nazara/Math/Quaternion.hpp index 79bcfc93e..da7fbb093 100644 --- a/include/Nazara/Math/Quaternion.hpp +++ b/include/Nazara/Math/Quaternion.hpp @@ -20,75 +20,70 @@ namespace Nz template class Quaternion { public: - Quaternion() = default; - Quaternion(T W, T X, T Y, T Z); + constexpr Quaternion() = default; + constexpr Quaternion(T W, T X, T Y, T Z); template Quaternion(const Angle& angle); Quaternion(const EulerAngles& angles); - Quaternion(RadianAngle angle, const Vector3& axis); - Quaternion(const T quat[4]); - //Quaternion(const Matrix3& mat); - template explicit Quaternion(const Quaternion& quat); - Quaternion(const Quaternion& quat) = default; + constexpr Quaternion(RadianAngle angle, const Vector3& axis); + constexpr Quaternion(const T quat[4]); + template constexpr explicit Quaternion(const Quaternion& quat); + constexpr Quaternion(const Quaternion&) = default; + constexpr Quaternion(Quaternion&&) = default; ~Quaternion() = default; + constexpr bool ApproxEqual(const Quaternion& quat, T maxDifference = std::numeric_limits::epsilon()) const; + Quaternion& ComputeW(); - Quaternion& Conjugate(); + constexpr Quaternion& Conjugate(); - T DotProduct(const Quaternion& vec) const; + constexpr T DotProduct(const Quaternion& vec) const; - Quaternion GetConjugate() const; + constexpr Quaternion GetConjugate() const; Quaternion GetInverse() const; Quaternion GetNormal(T* length = nullptr) const; Quaternion& Inverse(); - Quaternion& MakeIdentity(); - Quaternion& MakeRotationBetween(const Vector3& from, const Vector3& to); - Quaternion& MakeZero(); - T Magnitude() const; Quaternion& Normalize(T* length = nullptr); - Quaternion& Set(T W, T X, T Y, T Z); - template Quaternion& Set(const Angle& angle); - Quaternion& Set(const EulerAngles& angles); - Quaternion& Set(RadianAngle angle, const Vector3& normalizedAxis); - Quaternion& Set(const T quat[4]); - //Quaternion& Set(const Matrix3& mat); - template Quaternion& Set(const Quaternion& quat); - - T SquaredMagnitude() const; + constexpr T SquaredMagnitude() const; RadianAngle To2DAngle() const; EulerAngles ToEulerAngles() const; - //Matrix3 ToRotationMatrix() const; std::string ToString() const; - Quaternion& operator=(const Quaternion& quat) = default; + constexpr Quaternion& operator=(const Quaternion& quat) = default; + constexpr Quaternion& operator=(Quaternion&&) = default; - Quaternion operator+(const Quaternion& quat) const; - Quaternion operator*(const Quaternion& quat) const; - Vector3 operator*(const Vector3& vec) const; - Quaternion operator*(T scale) const; - Quaternion operator/(const Quaternion& quat) const; + constexpr Quaternion operator+(const Quaternion& quat) const; + constexpr Quaternion operator*(const Quaternion& quat) const; + constexpr Vector3 operator*(const Vector3& vec) const; + constexpr Quaternion operator*(T scale) const; + constexpr Quaternion operator/(const Quaternion& quat) const; - Quaternion& operator+=(const Quaternion& quat); - Quaternion& operator*=(const Quaternion& quat); - Quaternion& operator*=(T scale); - Quaternion& operator/=(const Quaternion& quat); + constexpr Quaternion& operator+=(const Quaternion& quat); + constexpr Quaternion& operator*=(const Quaternion& quat); + constexpr Quaternion& operator*=(T scale); + constexpr Quaternion& operator/=(const Quaternion& quat); - bool operator==(const Quaternion& quat) const; - bool operator!=(const Quaternion& quat) const; + constexpr bool operator==(const Quaternion& quat) const; + constexpr bool operator!=(const Quaternion& quat) const; + constexpr bool operator<(const Quaternion& quat) const; + constexpr bool operator<=(const Quaternion& quat) const; + constexpr bool operator>(const Quaternion& quat) const; + constexpr bool operator>=(const Quaternion& quat) const; - static Quaternion Identity(); - static Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation); + static constexpr bool ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Quaternion Identity(); + static constexpr Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation); static Quaternion LookAt(const Vector3& forward, const Vector3& up); static Quaternion Normalize(const Quaternion& quat, T* length = nullptr); static Quaternion RotationBetween(const Vector3& from, const Vector3& to); static Quaternion Mirror(Quaternion quat, const Vector3& axis); static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation); - static Quaternion Zero(); + static constexpr Quaternion Zero(); T w, x, y, z; }; diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 3ce61972b..0706c9431 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -30,11 +30,13 @@ namespace Nz * \param Y Y component * \param Z Z component */ - template - Quaternion::Quaternion(T W, T X, T Y, T Z) + constexpr Quaternion::Quaternion(T W, T X, T Y, T Z) : + w(W), + x(X), + y(Y), + z(Z) { - Set(W, X, Y, Z); } /*! @@ -44,9 +46,9 @@ namespace Nz */ template template - Quaternion::Quaternion(const Angle& angle) + Quaternion::Quaternion(const Angle& angle) : + Quaternion(angle.ToQuaternion()) { - Set(angle); } /*! @@ -57,9 +59,9 @@ namespace Nz * \see EulerAngles */ template - Quaternion::Quaternion(const EulerAngles& angles) + Quaternion::Quaternion(const EulerAngles& angles) : + Quaternion(angles.ToQuaternion()) { - Set(angles); } /*! @@ -68,11 +70,21 @@ namespace Nz * \param angle Angle to rotate along the axis * \param axis Vector3 which represents a direction, no need to be normalized */ - template - Quaternion::Quaternion(RadianAngle angle, const Vector3& axis) + constexpr Quaternion::Quaternion(RadianAngle angle, const Vector3& axis) { - Set(angle, axis); + angle /= T(2.0); + + Vector3 normalizedAxis = axis.GetNormal(); + + auto sincos = angle.GetSinCos(); + + w = sincos.second; + x = normalizedAxis.x * sincos.first; + y = normalizedAxis.y * sincos.first; + z = normalizedAxis.z * sincos.first; + + Normalize(); } /*! @@ -80,21 +92,15 @@ namespace Nz * * \param quat[4] quat[0] is W component, quat[1] is X component, quat[2] is Y component and quat[3] is Z component */ - template - Quaternion::Quaternion(const T quat[4]) + constexpr Quaternion::Quaternion(const T quat[4]) : + w(quat[0]), + x(quat[1]), + y(quat[2]), + z(quat[3]) { - Set(quat); } - /* - template - Quaternion::Quaternion(const Matrix3& mat) - { - Set(mat); - } - */ - /*! * \brief Constructs a Quaternion object from another type of Quaternion * @@ -103,16 +109,27 @@ namespace Nz template template - Quaternion::Quaternion(const Quaternion& quat) + constexpr Quaternion::Quaternion(const Quaternion& quat) : + w(static_cast(quat.w)), + x(static_cast(quat.x)), + y(static_cast(quat.y)), + z(static_cast(quat.z)) { - Set(quat); + } + + template + constexpr bool Quaternion::ApproxEqual(const Quaternion& quat, T maxDifference) const + { + return NumberEquals(w, quat.w, maxDifference) && + NumberEquals(x, quat.x, maxDifference) && + NumberEquals(y, quat.y, maxDifference) && + NumberEquals(z, quat.z, maxDifference); } /*! * \brief Computes the w component of the quaternion to make it unit * \return A reference to this quaternion */ - template Quaternion& Quaternion::ComputeW() { @@ -134,9 +151,8 @@ namespace Nz * * \see GetConjugate */ - template - Quaternion& Quaternion::Conjugate() + constexpr Quaternion& Quaternion::Conjugate() { x = -x; y = -y; @@ -151,9 +167,8 @@ namespace Nz * * \param quat The other quaternion to calculate the dot product with */ - template - T Quaternion::DotProduct(const Quaternion& quat) const + constexpr T Quaternion::DotProduct(const Quaternion& quat) const { return w * quat.w + x * quat.x + y * quat.y + z * quat.z; } @@ -166,9 +181,8 @@ namespace Nz * * \see Conjugate */ - template - Quaternion Quaternion::GetConjugate() const + constexpr Quaternion Quaternion::GetConjugate() const { Quaternion quat(*this); quat.Conjugate(); @@ -184,7 +198,6 @@ namespace Nz * * \see Inverse */ - template Quaternion Quaternion::GetInverse() const { @@ -204,7 +217,6 @@ namespace Nz * * \see Normalize */ - template Quaternion Quaternion::GetNormal(T* length) const { @@ -222,7 +234,6 @@ namespace Nz * * \see GetInverse */ - template Quaternion& Quaternion::Inverse() { @@ -240,81 +251,12 @@ namespace Nz return *this; } - /*! - * \brief Makes the quaternion (1, 0, 0, 0) - * \return A reference to this vector with components (1, 0, 0, 0) - * - * \see Unit - */ - - template - Quaternion& Quaternion::MakeIdentity() - { - return Set(T(1.0), T(0.0), T(0.0), T(0.0)); - } - - /*! - * \brief Makes this quaternion to the rotation required to rotate direction Vector3 from to direction Vector3 to - * \return A reference to this vector which is the rotation needed - * - * \param from Initial vector - * \param to Target vector - * - * \remark Vectors are not required to be normalized - * - * \see RotationBetween - */ - - template - Quaternion& Quaternion::MakeRotationBetween(const Vector3& from, const Vector3& to) - { - T dot = from.DotProduct(to); - if (dot < T(-0.999999)) - { - Vector3 crossProduct; - if (from.DotProduct(Vector3::UnitX()) < T(0.999999)) - crossProduct = Vector3::UnitX().CrossProduct(from); - else - crossProduct = Vector3::UnitY().CrossProduct(from); - - crossProduct.Normalize(); - Set(Pi, crossProduct); - return *this; - } - else if (dot > T(0.999999)) - { - Set(T(1.0), T(0.0), T(0.0), T(0.0)); - return *this; - } - else - { - T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength()); - Vector3 crossProduct = from.CrossProduct(to); - Set(norm + dot, crossProduct.x, crossProduct.y, crossProduct.z); - return Normalize(); - } - } - - /*! - * \brief Makes the quaternion (0, 0, 0, 0) - * \return A reference to this vector with components (0, 0, 0, 0) - * - * \see Zero - */ - - template - Quaternion& Quaternion::MakeZero() - { - return Set(T(0.0), T(0.0), T(0.0), T(0.0)); - } - /*! * \brief Calculates the magnitude (length) of the quaternion * \return The magnitude * * \see SquaredMagnitude */ - template T Quaternion::Magnitude() const { @@ -331,7 +273,6 @@ namespace Nz * * \see GetNormal */ - template Quaternion& Quaternion::Normalize(T* length) { @@ -351,127 +292,14 @@ namespace Nz return *this; } - /*! - * \brief Sets the components of the quaternion - * \return A reference to this quaternion - * - * \param W W component - * \param X X component - * \param Y Y component - * \param Z Z component - */ - - template - Quaternion& Quaternion::Set(T W, T X, T Y, T Z) - { - w = W; - x = X; - y = Y; - z = Z; - - return *this; - } - - /*! - * \brief Sets this quaternion from a 2D rotation specified by an Angle - * \return A reference to this quaternion - * - * \param angle 2D angle - * - * \see Angle - */ - template - template - Quaternion& Quaternion::Set(const Angle& angle) - { - return Set(angle.ToQuaternion()); - } - - /*! - * \brief Sets this quaternion from rotation specified by Euler angle - * \return A reference to this quaternion - * - * \param angles Easier representation of rotation of space - * - * \see EulerAngles - */ - template - Quaternion& Quaternion::Set(const EulerAngles& angles) - { - return Set(angles.ToQuaternion()); - } - - /*! - * \brief Sets this quaternion from rotation specified by axis and angle - * \return A reference to this quaternion - * - * \param angle Angle to rotate along the axis - * \param axis Vector3 which represents a direction, no need to be normalized - */ - - template - Quaternion& Quaternion::Set(RadianAngle angle, const Vector3& axis) - { - angle /= T(2.0); - - Vector3 normalizedAxis = axis.GetNormal(); - - auto sincos = angle.GetSinCos(); - - w = sincos.second; - x = normalizedAxis.x * sincos.first; - y = normalizedAxis.y * sincos.first; - z = normalizedAxis.z * sincos.first; - - return Normalize(); - } - - /*! - * \brief Sets the components of the quaternion from an array of four elements - * \return A reference to this quaternion - * - * \param quat[4] quat[0] is W component, quat[1] is X component, quat[2] is Y component and quat[3] is Z component - */ - - template - Quaternion& Quaternion::Set(const T quat[4]) - { - w = quat[0]; - x = quat[1]; - y = quat[2]; - z = quat[3]; - - return *this; - } - - /*! - * \brief Sets the components of the quaternion from another type of Quaternion - * \return A reference to this quaternion - * - * \param quat Quaternion of type U to convert its components - */ - - template - template - Quaternion& Quaternion::Set(const Quaternion& quat) - { - w = T(quat.w); - x = T(quat.x); - y = T(quat.y); - z = T(quat.z); - - return *this; - } - /*! * \brief Calculates the squared magnitude (length) of the quaternion * \return The squared magnitude * * \see Magnitude */ - template - T Quaternion::SquaredMagnitude() const + constexpr T Quaternion::SquaredMagnitude() const { return w * w + x * x + y * y + z * z; } @@ -518,7 +346,6 @@ namespace Nz * \brief Gives a string representation * \return A string representation of the object: "Quaternion(w | x, y, z)" */ - template std::string Quaternion::ToString() const { @@ -534,9 +361,8 @@ namespace Nz * * \param quat The other quaternion to add components with */ - template - Quaternion Quaternion::operator+(const Quaternion& quat) const + constexpr Quaternion Quaternion::operator+(const Quaternion& quat) const { Quaternion result; result.w = w + quat.w; @@ -553,9 +379,8 @@ namespace Nz * * \param quat The other quaternion to multiply with */ - template - Quaternion Quaternion::operator*(const Quaternion& quat) const + constexpr Quaternion Quaternion::operator*(const Quaternion& quat) const { Quaternion result; result.w = w * quat.w - x * quat.x - y * quat.y - z * quat.z; @@ -572,9 +397,8 @@ namespace Nz * * \param vec The vector to multiply with */ - template - Vector3 Quaternion::operator*(const Vector3& vec) const + constexpr Vector3 Quaternion::operator*(const Vector3& vec) const { Vector3 quatVec(x, y, z); Vector3 uv = quatVec.CrossProduct(vec); @@ -591,9 +415,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Quaternion Quaternion::operator*(T scale) const + constexpr Quaternion Quaternion::operator*(T scale) const { return Quaternion(w * scale, x * scale, @@ -607,9 +430,8 @@ namespace Nz * * \param quat The other quaternion to divide with */ - template - Quaternion Quaternion::operator/(const Quaternion& quat) const + constexpr Quaternion Quaternion::operator/(const Quaternion& quat) const { return quat.GetConjugate() * (*this); } @@ -620,9 +442,8 @@ namespace Nz * * \param quat The other quaternion to add components with */ - template - Quaternion& Quaternion::operator+=(const Quaternion& quat) + constexpr Quaternion& Quaternion::operator+=(const Quaternion& quat) { return operator=(operator+(quat)); } @@ -633,9 +454,8 @@ namespace Nz * * \param quat The other quaternion to multiply with */ - template - Quaternion& Quaternion::operator*=(const Quaternion& quat) + constexpr Quaternion& Quaternion::operator*=(const Quaternion& quat) { return operator=(operator*(quat)); } @@ -646,9 +466,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Quaternion& Quaternion::operator*=(T scale) + constexpr Quaternion& Quaternion::operator*=(T scale) { return operator=(operator*(scale)); } @@ -659,9 +478,8 @@ namespace Nz * * \param quat The other quaternion to divide with */ - template - Quaternion& Quaternion::operator/=(const Quaternion& quat) + constexpr Quaternion& Quaternion::operator/=(const Quaternion& quat) { return operator=(operator/(quat)); } @@ -672,14 +490,10 @@ namespace Nz * * \param quat Other quaternion to compare with */ - template - bool Quaternion::operator==(const Quaternion& quat) const + constexpr bool Quaternion::operator==(const Quaternion& quat) const { - return NumberEquals(w, quat.w) && - NumberEquals(x, quat.x) && - NumberEquals(y, quat.y) && - NumberEquals(z, quat.z); + return w == quat.w && x == quat.x && y == quat.y && z == quat.z; } /*! @@ -688,27 +502,90 @@ namespace Nz * * \param quat Other quaternion to compare with */ - template - bool Quaternion::operator!=(const Quaternion& quat) const + constexpr bool Quaternion::operator!=(const Quaternion& quat) const { return !operator==(quat); } + template + constexpr bool Quaternion::operator<(const Quaternion& quat) const + { + if (w != quat.w) + return w < quat.w; + + if (x != quat.x) + return x < quat.x; + + if (y != quat.y) + return y < quat.y; + + if (z != quat.z) + return z < quat.z; + } + + template + constexpr bool Quaternion::operator<=(const Quaternion& quat) const + { + if (w != quat.w) + return w < quat.w; + + if (x != quat.x) + return x < quat.x; + + if (y != quat.y) + return y < quat.y; + + if (z != quat.z) + return z <= quat.z; + } + + template + constexpr bool Quaternion::operator>(const Quaternion& quat) const + { + if (w != quat.w) + return w > quat.w; + + if (x != quat.x) + return x > quat.x; + + if (y != quat.y) + return y > quat.y; + + if (z != quat.z) + return z > quat.z; + } + + template + constexpr bool Quaternion::operator>=(const Quaternion& quat) const + { + if (w != quat.w) + return w > quat.w; + + if (x != quat.x) + return x > quat.x; + + if (y != quat.y) + return y > quat.y; + + if (z != quat.z) + return z >= quat.z; + } + + template + constexpr bool Quaternion::ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + /*! * \brief Shorthand for the quaternion (1, 0, 0, 0) * \return A quaternion with components (1, 0, 0, 0) - * - * \see MakeIdentity */ - template - Quaternion Quaternion::Identity() + constexpr Quaternion Quaternion::Identity() { - Quaternion quaternion; - quaternion.MakeIdentity(); - - return quaternion; + return Quaternion(1, 0, 0, 0); } /*! @@ -725,7 +602,7 @@ namespace Nz * \see Lerp, Slerp */ template - Quaternion Quaternion::Lerp(const Quaternion& from, const Quaternion& to, T interpolation) + constexpr Quaternion Quaternion::Lerp(const Quaternion& from, const Quaternion& to, T interpolation) { #ifdef NAZARA_DEBUG if (interpolation < T(0.0) || interpolation > T(1.0)) @@ -780,7 +657,6 @@ namespace Nz * * \see GetNormal */ - template Quaternion Quaternion::Normalize(const Quaternion& quat, T* length) { @@ -793,17 +669,31 @@ namespace Nz * * \param from Initial vector * \param to Target vector - * - * \see MakeRotationBetween */ - template Quaternion Quaternion::RotationBetween(const Vector3& from, const Vector3& to) { - Quaternion quaternion; - quaternion.MakeRotationBetween(from, to); + T dot = from.DotProduct(to); + if (dot < T(-0.999999)) + { + Vector3 crossProduct; + if (from.DotProduct(Vector3::UnitX()) < T(0.999999)) + crossProduct = Vector3::UnitX().CrossProduct(from); + else + crossProduct = Vector3::UnitY().CrossProduct(from); - return quaternion; + crossProduct.Normalize(); + return Quaternion(Pi, crossProduct); + } + else if (dot > T(0.999999)) + return Quaternion(1, 0, 0, 0); + else + { + T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength()); + Vector3 crossProduct = from.CrossProduct(to); + + return Quaternion(norm + dot, crossProduct.x, crossProduct.y, crossProduct.z).GetNormal(); + } } template @@ -833,7 +723,6 @@ namespace Nz * * \see Lerp */ - template Quaternion Quaternion::Slerp(const Quaternion& from, const Quaternion& to, T interpolation) { @@ -851,11 +740,11 @@ namespace Nz if (cosOmega < T(0.0)) { // We invert everything - q.Set(-to.w, -to.x, -to.y, -to.z); + q = Quaternion(-to.w, -to.x, -to.y, -to.z); cosOmega = -cosOmega; } else - q.Set(to); + q = Quaternion(to); T k0, k1; if (cosOmega > T(0.9999)) @@ -883,20 +772,13 @@ namespace Nz /*! * \brief Shorthand for the quaternion (0, 0, 0, 0) * \return A quaternion with components (0, 0, 0, 0) - * - * \see MakeZero */ - template - Quaternion Quaternion::Zero() + constexpr Quaternion Quaternion::Zero() { - Quaternion quaternion; - quaternion.MakeZero(); - - return quaternion; + return Quaternion(0, 0, 0, 0); } - /*! * \brief Serializes a Quaternion * \return true if successfully serialized @@ -962,3 +844,4 @@ namespace Nz } #include +#include "Quaternion.hpp" diff --git a/include/Nazara/Math/Ray.hpp b/include/Nazara/Math/Ray.hpp index 24a2d7b18..3e8f59b57 100644 --- a/include/Nazara/Math/Ray.hpp +++ b/include/Nazara/Math/Ray.hpp @@ -24,50 +24,49 @@ namespace Nz class Ray { public: - Ray() = default; - Ray(T X, T Y, T Z, T directionX, T directionY, T directionZ); - Ray(const Vector3& origin, const Vector3& direction); - Ray(const T origin[3], const T direction[3]); + constexpr Ray() = default; + constexpr Ray(T X, T Y, T Z, T directionX, T directionY, T directionZ); + constexpr Ray(const Vector3& origin, const Vector3& direction); + constexpr Ray(const T origin[3], const T direction[3]); Ray(const Plane& planeOne, const Plane& planeTwo); - template explicit Ray(const Ray& ray); - template explicit Ray(const Vector3& origin, const Vector3& direction); - Ray(const Ray& ray) = default; + template constexpr explicit Ray(const Ray& ray); + template constexpr explicit Ray(const Vector3& origin, const Vector3& direction); + constexpr Ray(const Ray&) = default; + constexpr Ray(Ray&&) = default; ~Ray() = default; - T ClosestPoint(const Vector3& point) const; + constexpr bool ApproxEqual(const Ray& ray, T maxDifference = std::numeric_limits::epsilon()) const; - Vector3 GetPoint(T lambda) const; + constexpr T ClosestPoint(const Vector3& point) const; - bool Intersect(const BoundingVolume& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const Box& box, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const Box& box, const Matrix4& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const Plane& plane, T* hit = nullptr) const; - bool Intersect(const Sphere& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const Vector3& firstPoint, const Vector3& secondPoint, const Vector3& thirdPoint, T* hit = nullptr) const; + constexpr Vector3 GetPoint(T lambda) const; - Ray& MakeAxisX(); - Ray& MakeAxisY(); - Ray& MakeAxisZ(); - - Ray& Set(T X, T Y, T Z, T directionX, T directionY, T directionZ); - Ray& Set(const Vector3& origin, const Vector3& direction); - Ray& Set(const T origin[3], const T direction[3]); - Ray& Set(const Plane& planeOne, const Plane& planeTwo); - template Ray& Set(const Ray& ray); - template Ray& Set(const Vector3& origin, const Vector3& direction); + constexpr bool Intersect(const BoundingVolume& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const; + constexpr bool Intersect(const Box& box, T* closestHit = nullptr, T* furthestHit = nullptr) const; + constexpr bool Intersect(const Box& box, const Matrix4& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const; + constexpr bool Intersect(const Plane& plane, T* hit = nullptr) const; + constexpr bool Intersect(const Sphere& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const; + constexpr bool Intersect(const Vector3& firstPoint, const Vector3& secondPoint, const Vector3& thirdPoint, T* hit = nullptr) const; std::string ToString() const; - Vector3 operator*(T lambda) const; - Ray& operator=(const Ray& other) = default; + constexpr Ray& operator=(const Ray&) = default; + constexpr Ray& operator=(Ray&&) = default; - bool operator==(const Ray& ray) const; - bool operator!=(const Ray& ray) const; + constexpr Vector3 operator*(T lambda) const; - static Ray AxisX(); - static Ray AxisY(); - static Ray AxisZ(); - static Ray Lerp(const Ray& from, const Ray& to, T interpolation); + constexpr bool operator==(const Ray& ray) const; + constexpr bool operator!=(const Ray& ray) const; + constexpr bool operator<(const Ray& ray) const; + constexpr bool operator<=(const Ray& ray) const; + constexpr bool operator>(const Ray& ray) const; + constexpr bool operator>=(const Ray& ray) const; + + static constexpr bool ApproxEqual(const Ray& lhs, const Ray& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Ray AxisX(); + static constexpr Ray AxisY(); + static constexpr Ray AxisZ(); + static constexpr Ray Lerp(const Ray& from, const Ray& to, T interpolation); Vector3 direction, origin; }; diff --git a/include/Nazara/Math/Ray.inl b/include/Nazara/Math/Ray.inl index 9cb6af026..10acd149b 100644 --- a/include/Nazara/Math/Ray.inl +++ b/include/Nazara/Math/Ray.inl @@ -27,11 +27,11 @@ namespace Nz * \param DirectionY Y component of the vector direction * \param DirectionY Y component of the vector direction */ - template - Ray::Ray(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ) + constexpr Ray::Ray(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ) : + direction(DirectionX, DirectionY, DirectionZ), + origin(X, Y, Z) { - Set(X, Y, Z, DirectionX, DirectionY, DirectionZ); } /*! @@ -40,11 +40,11 @@ namespace Nz * \param Origin Vector which represents the origin of the ray * \param Direction Vector which represents the direction of the ray */ - template - Ray::Ray(const Vector3& Origin, const Vector3& Direction) + constexpr Ray::Ray(const Vector3& Origin, const Vector3& Direction) : + direction(Direction), + origin(Origin) { - Set(Origin, Direction); } /*! @@ -53,11 +53,11 @@ namespace Nz * \param Origin[3] Origin[0] is X position, Origin[1] is Y position and Origin[2] is Z position * \param Direction[3] Direction[0] is X direction, Direction[1] is Y direction and Direction[2] is Z direction */ - template - Ray::Ray(const T Origin[3], const T Direction[3]) + constexpr Ray::Ray(const T Origin[3], const T Direction[3]) : + direction(Direction), + origin(Origin) { - Set(Origin, Direction); } /*! @@ -69,11 +69,30 @@ namespace Nz * \remark Produce a NazaraError if planes are parallel with NAZARA_MATH_SAFE defined * \throw std::domain_error if NAZARA_MATH_SAFE is defined and planes are parallel */ - template Ray::Ray(const Plane& planeOne, const Plane& planeTwo) { - Set(planeOne, planeTwo); + T termOne = planeOne.normal.GetLength(); + T termTwo = planeOne.normal.DotProduct(planeTwo.normal); + T termFour = planeTwo.normal.GetLength(); + T det = termOne * termFour - termTwo * termTwo; + + #if NAZARA_MATH_SAFE + if (NumberEquals(det, T(0.0))) + { + std::string error("Planes are parallel"); + + NazaraError(error); + throw std::domain_error(error); + } + #endif + + T invdet = T(1.0) / det; + T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet; + T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet; + + direction = planeOne.normal.CrossProduct(planeTwo.normal); + origin = planeOne.normal * fc0 + planeTwo.normal * fc1; } /*! @@ -84,9 +103,10 @@ namespace Nz template template - Ray::Ray(const Ray& ray) + constexpr Ray::Ray(const Ray& ray) : + direction(ray.direction), + origin(ray.origin) { - Set(ray); } /*! @@ -98,9 +118,16 @@ namespace Nz template template - Ray::Ray(const Vector3& Origin, const Vector3& Direction) + constexpr Ray::Ray(const Vector3& Origin, const Vector3& Direction) : + direction(Direction), + origin(Origin) { - Set(Origin, Direction); + } + + template + constexpr bool Ray::ApproxEqual(const Ray& ray, T maxDifference) const + { + return direction.ApproxEqual(ray.direction, maxDifference) && origin.ApproxEqual(ray.origin, maxDifference); } /*! @@ -109,9 +136,8 @@ namespace Nz * * \param point The point to get the closest approach to */ - template - T Ray::ClosestPoint(const Vector3& point) const + constexpr T Ray::ClosestPoint(const Vector3& point) const { Vector3 delta = point - origin; T vsq = direction.GetSquaredLength(); @@ -126,9 +152,8 @@ namespace Nz * * \param lambda Parameter to obtain a particular point on the ray */ - template - Vector3 Ray::GetPoint(T lambda) const + constexpr Vector3 Ray::GetPoint(T lambda) const { return origin + lambda * direction; } @@ -141,19 +166,18 @@ namespace Nz * \param closestHit Optional argument to get the closest parameter where the intersection is only if it happened * \param furthestHit Optional argument to get the furthest parameter where the intersection is only if it happened * - * \remark If BoundingVolume is Extend::Infinite, then closestHit and furthestHit are equal to 0 et infinity - * \remark If BoundingVolume is Extend::Null, then closestHit and furthestHit are unchanged - * \remark If enumeration of BoundingVolume is not defined in Extend, a NazaraError is thrown and closestHit and furthestHit are unchanged + * \remark If BoundingVolume is Extent::Infinite, then closestHit and furthestHit are equal to 0 et infinity + * \remark If BoundingVolume is Extent::Null, then closestHit and furthestHit are unchanged + * \remark If enumeration of BoundingVolume is not defined in Extent, a NazaraError is thrown and closestHit and furthestHit are unchanged * * \see Intersect */ - template - bool Ray::Intersect(const BoundingVolume& volume, T* closestHit, T* furthestHit) const + constexpr bool Ray::Intersect(const BoundingVolume& volume, T* closestHit, T* furthestHit) const { - switch (volume.extend) + switch (volume.extent) { - case Extend::Finite: + case Extent::Finite: { if (Intersect(volume.aabb)) return Intersect(volume.obb, closestHit, furthestHit); @@ -161,7 +185,7 @@ namespace Nz return false; } - case Extend::Infinite: + case Extent::Infinite: { if (closestHit) *closestHit = T(0.0); @@ -172,11 +196,11 @@ namespace Nz return true; } - case Extend::Null: + case Extent::Null: return false; } - NazaraError("Invalid extend type (0x" + NumberToString(UnderlyingCast(volume.extend), 16) + ')'); + NazaraError("Invalid extent type (0x" + NumberToString(UnderlyingCast(volume.extent), 16) + ')'); return false; } @@ -190,9 +214,8 @@ namespace Nz * * \see Intersect */ - template - bool Ray::Intersect(const Box& box, T* closestHit, T* furthestHit) const + constexpr bool Ray::Intersect(const Box& box, T* closestHit, T* furthestHit) const { // http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/ T tfirst = T(0.0); @@ -248,9 +271,8 @@ namespace Nz * * \see Intersect */ - template - bool Ray::Intersect(const Box& box, const Matrix4& transform, T* closestHit, T* furthestHit) const + constexpr bool Ray::Intersect(const Box& box, const Matrix4& transform, T* closestHit, T* furthestHit) const { // http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/ // Intersection method from Real-Time Rendering and Essential Mathematics for Games @@ -316,9 +338,8 @@ namespace Nz * * \see Intersect */ - template - bool Ray::Intersect(const Plane& plane, T* hit) const + constexpr bool Ray::Intersect(const Plane& plane, T* hit) const { T divisor = plane.normal.DotProduct(direction); if (NumberEquals(divisor, T(0.0))) @@ -344,9 +365,8 @@ namespace Nz * * \see Intersect */ - template - bool Ray::Intersect(const Sphere& sphere, T* closestHit, T* furthestHit) const + constexpr bool Ray::Intersect(const Sphere& sphere, T* closestHit, T* furthestHit) const { Vector3 sphereRay = sphere.GetPosition() - origin; T length = sphereRay.DotProduct(direction); @@ -386,9 +406,8 @@ namespace Nz * * \see Intersect */ - template - bool Ray::Intersect(const Vector3& firstPoint, const Vector3& secondPoint, const Vector3& thirdPoint, T* hit) const + constexpr bool Ray::Intersect(const Vector3& firstPoint, const Vector3& secondPoint, const Vector3& thirdPoint, T* hit) const { // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm Vector3 firstEdge = secondPoint - firstPoint; @@ -420,179 +439,10 @@ namespace Nz return false; } - /*! - * \brief Makes the ray with position (0, 0, 0) and direction (1, 0, 0) - * \return A reference to this ray with position (0, 0, 0) and direction (1, 0, 0) - * - * \see AxisX - */ - - template - Ray& Ray::MakeAxisX() - { - return Set(Vector3::Zero(), Vector3::UnitX()); - } - - /*! - * \brief Makes the ray with position (0, 0, 0) and direction (0, 1, 0) - * \return A reference to this ray with position (0, 0, 0) and direction (0, 1, 0) - * - * \see AxisY - */ - - template - Ray& Ray::MakeAxisY() - { - return Set(Vector3::Zero(), Vector3::UnitY()); - } - - /*! - * \brief Makes the ray with position (0, 0, 0) and direction (0, 0, 1) - * \return A reference to this ray with position (0, 0, 0) and direction (0, 0, 1) - * - * \see AxisZ - */ - - template - Ray& Ray::MakeAxisZ() - { - return Set(Vector3::Zero(), Vector3::UnitZ()); - } - - /*! - * \brief Sets the components of the ray with position and direction - * \return A reference to this ray - * - * \param X X position - * \param Y Y position - * \param Z Z position - * \param DirectionX X component of the vector direction - * \param DirectionY Y component of the vector direction - * \param DirectionY Y component of the vector direction - */ - - template - Ray& Ray::Set(T X, T Y, T Z, T directionX, T directionY, T directionZ) - { - direction.Set(directionX, directionY, directionZ); - origin.Set(X, Y, Z); - - return *this; - } - - /*! - * \brief Sets the components of the ray with position and direction - * \return A reference to this ray - * - * \param Origin Vector which represents the origin of the ray - * \param Direction Vector which represents the direction of the ray - */ - - template - Ray& Ray::Set(const Vector3& Origin, const Vector3& Direction) - { - direction = Direction; - origin = Origin; - - return *this; - } - - /*! - * \brief Sets the components of this ray from two arrays of three elements - * \return A reference to this ray - * - * \param Origin[3] Origin[0] is X position, Origin[1] is Y position and Origin[2] is Z position - * \param Direction[3] Direction[0] is X direction, Direction[1] is Y direction and Direction[2] is Z direction - */ - - template - Ray& Ray::Set(const T Origin[3], const T Direction[3]) - { - direction.Set(Direction); - origin.Set(Origin); - - return *this; - } - - /*! - * \brief Sets the components of this ray from the intersection of two planes - * \return A reference to this ray - * - * \param planeOne First plane - * \param planeTwo Second secant plane - * - * \remark Produce a NazaraError if planes are parallel with NAZARA_MATH_SAFE defined - * \throw std::domain_error if NAZARA_MATH_SAFE is defined and planes are parallel - */ - - template - Ray& Ray::Set(const Plane& planeOne, const Plane& planeTwo) - { - T termOne = planeOne.normal.GetLength(); - T termTwo = planeOne.normal.DotProduct(planeTwo.normal); - T termFour = planeTwo.normal.GetLength(); - T det = termOne * termFour - termTwo * termTwo; - - #if NAZARA_MATH_SAFE - if (NumberEquals(det, T(0.0))) - { - std::string error("Planes are parallel"); - - NazaraError(error); - throw std::domain_error(error); - } - #endif - - T invdet = T(1.0) / det; - T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet; - T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet; - - direction = planeOne.normal.CrossProduct(planeTwo.normal); - origin = planeOne.normal * fc0 + planeTwo.normal * fc1; - - return *this; - } - - /*! - * \brief Sets the components of the ray from another type of Ray - * \return A reference to this ray - * - * \param ray Ray of type U to convert its components - */ - - template - template - Ray& Ray::Set(const Ray& ray) - { - direction.Set(ray.direction); - origin.Set(ray.origin); - - return *this; - } - - /*! - * \brief Sets the components of the ray from another type of Ray - * \return A reference to this ray - * - * \param Origin Origin of type U to convert to type T - * \param Direction Direction of type U to convert to type T - */ - - template - template - Ray& Ray::Set(const Vector3& Origin, const Vector3& Direction) - { - direction.Set(Direction); - origin.Set(Origin); - - return *this; - } - /*! * \brief Gives a string representation * \return A string representation of the object: "Ray(origin: Vector3(origin.x, origin.y, origin.z), direction: Vector3(direction.x, direction.y, direction.z))" */ - template std::string Ray::ToString() const { @@ -610,9 +460,8 @@ namespace Nz * * \see GetPoint */ - template - Vector3 Ray::operator*(T lambda) const + constexpr Vector3 Ray::operator*(T lambda) const { return GetPoint(lambda); } @@ -623,9 +472,8 @@ namespace Nz * * \param rec Other ray to compare with */ - template - bool Ray::operator==(const Ray& ray) const + constexpr bool Ray::operator==(const Ray& ray) const { return direction == ray.direction && origin == ray.origin; } @@ -636,59 +484,84 @@ namespace Nz * * \param rec Other ray to compare with */ - template - bool Ray::operator!=(const Ray& ray) const + constexpr bool Ray::operator!=(const Ray& ray) const { return !operator==(ray); } + template + constexpr bool Ray::operator<(const Ray& ray) const + { + if (origin != ray.origin) + return origin < ray.origin; + + return direction < ray.direction; + } + + template + constexpr bool Ray::operator<=(const Ray& ray) const + { + if (origin != ray.origin) + return origin < ray.origin; + + return direction <= ray.direction; + } + + template + constexpr bool Ray::operator>(const Ray& ray) const + { + if (origin != ray.origin) + return origin > ray.origin; + + return direction > ray.direction; + } + + template + constexpr bool Ray::operator>=(const Ray& ray) const + { + if (origin != ray.origin) + return origin > ray.origin; + + return direction >= ray.direction; + } + + template + constexpr bool Ray::ApproxEqual(const Ray& lhs, const Ray& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + /*! * \brief Shorthand for the ray (0, 0, 0), (1, 0, 0) * \return A ray with position (0, 0, 0) and direction (1, 0, 0) - * - * \see MakeAxisX */ - template - Ray Ray::AxisX() + constexpr Ray Ray::AxisX() { - Ray axis; - axis.MakeAxisX(); - - return axis; + return Ray(Vector3::Zero(), Vector3::UnitX()); } /*! * \brief Shorthand for the ray (0, 0, 0), (0, 1, 0) * \return A ray with position (0, 0, 0) and direction (0, 1, 0) - * - * \see MakeAxisY */ template - Ray Ray::AxisY() + constexpr Ray Ray::AxisY() { - Ray axis; - axis.MakeAxisY(); - - return axis; + return Ray(Vector3::Zero(), Vector3::UnitY()); } /*! * \brief Shorthand for the ray (0, 0, 0), (0, 0, 1) * \return A ray with position (0, 0, 0) and direction (0, 0, 1) - * - * \see MakeAxisZ */ template - Ray Ray::AxisZ() + constexpr Ray Ray::AxisZ() { - Ray axis; - axis.MakeAxisZ(); - - return axis; + return Ray(Vector3::Zero(), Vector3::UnitZ()); } /*! @@ -703,11 +576,10 @@ namespace Nz * * \see Lerp */ - template - Ray Ray::Lerp(const Ray& from, const Ray& to, T interpolation) + constexpr Ray Ray::Lerp(const Ray& from, const Ray& to, T interpolation) { - return Ray(Nz::Vector3::Lerp(from.origin, to.origin, interpolation), Nz::Vector3::Lerp(from.direction, to.direction, interpolation)); + return Ray(Vector3::Lerp(from.origin, to.origin, interpolation), Vector3::Lerp(from.direction, to.direction, interpolation)); } /*! @@ -764,3 +636,4 @@ namespace Nz } #include +#include "Ray.hpp" diff --git a/include/Nazara/Math/Rect.hpp b/include/Nazara/Math/Rect.hpp index 6ca5d7bb2..fa372b505 100644 --- a/include/Nazara/Math/Rect.hpp +++ b/include/Nazara/Math/Rect.hpp @@ -19,62 +19,64 @@ namespace Nz class Rect { public: - Rect() = default; - Rect(T Width, T Height); - Rect(T X, T Y, T Width, T Height); - explicit Rect(const Vector2& lengths); - explicit Rect(const Vector2& pos, const Vector2& lengths); - template explicit Rect(const Rect& rect); - Rect(const Rect&) = default; - Rect(Rect&&) noexcept = default; + constexpr Rect() = default; + constexpr Rect(T Width, T Height); + constexpr Rect(T X, T Y, T Width, T Height); + constexpr explicit Rect(const Vector2& lengths); + constexpr explicit Rect(const Vector2& pos, const Vector2& lengths); + template constexpr explicit Rect(const Rect& rect); + constexpr Rect(const Rect&) = default; + constexpr Rect(Rect&&) noexcept = default; ~Rect() = default; - bool ApproxEquals(const Rect& rect, T maxDifference = 0) const; + constexpr bool ApproxEqual(const Rect& rect, T maxDifference = std::numeric_limits::epsilon()) const; - bool Contains(T X, T Y) const; - bool Contains(const Rect& rect) const; - bool Contains(const Vector2& point) const; + constexpr bool Contains(T X, T Y) const; + constexpr bool Contains(const Rect& rect) const; + constexpr bool Contains(const Vector2& point) const; - Rect& ExtendTo(T X, T Y); - Rect& ExtendTo(const Rect& rect); - Rect& ExtendTo(const Vector2& point); + constexpr Rect& ExtendTo(T X, T Y); + constexpr Rect& ExtendTo(const Rect& rect); + constexpr Rect& ExtendTo(const Vector2& point); - Vector2 GetCenter() const; - Vector2 GetCorner(RectCorner corner) const; - Vector2 GetLengths() const; - Vector2 GetMaximum() const; - Vector2 GetMinimum() const; - Vector2 GetNegativeVertex(const Vector2& normal) const; - Vector2 GetPosition() const; - Vector2 GetPositiveVertex(const Vector2& normal) const; + constexpr Vector2 GetCenter() const; + constexpr Vector2 GetCorner(RectCorner corner) const; + constexpr Vector2 GetLengths() const; + constexpr Vector2 GetMaximum() const; + constexpr Vector2 GetMinimum() const; + constexpr Vector2 GetNegativeVertex(const Vector2& normal) const; + constexpr Vector2 GetPosition() const; + constexpr Vector2 GetPositiveVertex(const Vector2& normal) const; - bool Intersect(const Rect& rect, Rect* intersection = nullptr) const; + constexpr bool Intersect(const Rect& rect, Rect* intersection = nullptr) const; - bool IsNull() const; - bool IsValid() const; + constexpr bool IsNull() const; + constexpr bool IsValid() const; - Rect& MakeZero(); + constexpr Rect& Scale(T scalar); + constexpr Rect& Scale(const Vector2& vec); - Rect& Scale(T scalar); - Rect& Scale(const Vector2& vec); + constexpr Rect& ScaleAroundCenter(T scalar); + constexpr Rect& ScaleAroundCenter(const Vector2& vec); std::string ToString() const; - Rect& Translate(const Vector2& translation); + constexpr Rect& Translate(const Vector2& translation); - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr const T& operator[](std::size_t i) const; - Rect& operator=(const Rect&) = default; - Rect& operator=(Rect&&) noexcept = default; + constexpr Rect& operator=(const Rect&) = default; + constexpr Rect& operator=(Rect&&) noexcept = default; - bool operator==(const Rect& rect) const; - bool operator!=(const Rect& rect) const; + constexpr bool operator==(const Rect& rect) const; + constexpr bool operator!=(const Rect& rect) const; - static Rect FromExtends(const Vector2& vec1, const Vector2& vec2); - static Rect Lerp(const Rect& from, const Rect& to, T interpolation); - static Rect Invalid(); - static Rect Zero(); + static constexpr bool ApproxEqual(const Rect& lhs, const Rect& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Rect FromExtends(const Vector2& vec1, const Vector2& vec2); + static constexpr Rect Lerp(const Rect& from, const Rect& to, T interpolation); + static constexpr Rect Invalid(); + static constexpr Rect Zero(); T x, y, width, height; }; diff --git a/include/Nazara/Math/Rect.inl b/include/Nazara/Math/Rect.inl index 4e086f7ca..6f8b5e534 100644 --- a/include/Nazara/Math/Rect.inl +++ b/include/Nazara/Math/Rect.inl @@ -27,9 +27,8 @@ namespace Nz * * \remark Position will be (0, 0) */ - template - Rect::Rect(T Width, T Height) : + constexpr Rect::Rect(T Width, T Height) : x(0), y(0), width(Width), @@ -46,7 +45,7 @@ namespace Nz * \param Height Height of the rectangle (following Y) */ template - Rect::Rect(T X, T Y, T Width, T Height) : + constexpr Rect::Rect(T X, T Y, T Width, T Height) : x(X), y(Y), width(Width), @@ -61,7 +60,7 @@ namespace Nz * \param lengths (Width, Height) of the rect */ template - Rect::Rect(const Vector2& lengths) : + constexpr Rect::Rect(const Vector2& lengths) : Rect(Vector2::Zero(), lengths) { } @@ -73,13 +72,14 @@ namespace Nz * \param lengths (Width, Height) of the rect */ template - Rect::Rect(const Vector2& pos, const Vector2& lengths) : + constexpr Rect::Rect(const Vector2& pos, const Vector2& lengths) : x(pos.x), y(pos.y), width(lengths.x), height(lengths.y) { } + /*! * \brief Constructs a Rect object from another type of Rect * @@ -88,7 +88,7 @@ namespace Nz template template - Rect::Rect(const Rect& rect) : + constexpr Rect::Rect(const Rect& rect) : x(static_cast(rect.x)), y(static_cast(rect.y)), width(static_cast(rect.width)), @@ -97,7 +97,7 @@ namespace Nz } template - bool Rect::ApproxEquals(const Rect& rect, T maxDifference) const + constexpr bool Rect::ApproxEqual(const Rect& rect, T maxDifference) const { return NumberEquals(x, rect.x, maxDifference) && NumberEquals(y, rect.y, maxDifference) && NumberEquals(width, rect.width, maxDifference) && NumberEquals(height, rect.height, maxDifference); @@ -112,9 +112,8 @@ namespace Nz * * \see Contains */ - template - bool Rect::Contains(T X, T Y) const + constexpr bool Rect::Contains(T X, T Y) const { return X >= x && X < (x + width) && Y >= y && Y < (y + height); @@ -129,7 +128,7 @@ namespace Nz * \see Contains */ template - bool Rect::Contains(const Rect& rect) const + constexpr bool Rect::Contains(const Rect& rect) const { return Contains(rect.x, rect.y) && Contains(rect.x + rect.width, rect.y + rect.height); @@ -144,7 +143,7 @@ namespace Nz * \see Contains */ template - bool Rect::Contains(const Vector2& point) const + constexpr bool Rect::Contains(const Vector2& point) const { return Contains(point.x, point.y); } @@ -159,7 +158,7 @@ namespace Nz * \see ExtendTo */ template - Rect& Rect::ExtendTo(T X, T Y) + constexpr Rect& Rect::ExtendTo(T X, T Y) { width = std::max(x + width, X); height = std::max(y + height, Y); @@ -182,7 +181,7 @@ namespace Nz * \see ExtendTo */ template - Rect& Rect::ExtendTo(const Rect& rect) + constexpr Rect& Rect::ExtendTo(const Rect& rect) { width = std::max(x + width, rect.x + rect.width); height = std::max(y + height, rect.y + rect.height); @@ -204,9 +203,8 @@ namespace Nz * * \see ExtendTo */ - template - Rect& Rect::ExtendTo(const Vector2& point) + constexpr Rect& Rect::ExtendTo(const Vector2& point) { return ExtendTo(point.x, point.y); } @@ -217,7 +215,7 @@ namespace Nz */ template - Vector2 Rect::GetCenter() const + constexpr Vector2 Rect::GetCenter() const { return GetPosition() + GetLengths() / T(2.0); } @@ -230,9 +228,8 @@ namespace Nz * * \remark If enumeration is not defined in RectCorner, a NazaraError is thrown and a Vector2 uninitialised is returned */ - template - Vector2 Rect::GetCorner(RectCorner corner) const + constexpr Vector2 Rect::GetCorner(RectCorner corner) const { switch (corner) { @@ -257,9 +254,8 @@ namespace Nz * \brief Gets a Vector2 for the lengths * \return The lengths of the rectangle (width, height) */ - template - Vector2 Rect::GetLengths() const + constexpr Vector2 Rect::GetLengths() const { return Vector2(width, height); } @@ -270,9 +266,8 @@ namespace Nz * * \see GetCorner */ - template - Vector2 Rect::GetMaximum() const + constexpr Vector2 Rect::GetMaximum() const { return GetPosition() + GetLengths(); } @@ -283,9 +278,8 @@ namespace Nz * * \see GetCorner, GetPosition */ - template - Vector2 Rect::GetMinimum() const + constexpr Vector2 Rect::GetMinimum() const { return GetPosition(); } @@ -298,9 +292,8 @@ namespace Nz * * \see GetPositiveVertex */ - template - Vector2 Rect::GetNegativeVertex(const Vector2& normal) const + constexpr Vector2 Rect::GetNegativeVertex(const Vector2& normal) const { Vector2 neg(GetPosition()); @@ -319,9 +312,8 @@ namespace Nz * * \see GetCorner, GetMinimum */ - template - Vector2 Rect::GetPosition() const + constexpr Vector2 Rect::GetPosition() const { return Vector2(x, y); } @@ -334,9 +326,8 @@ namespace Nz * * \see GetNegativeVertex */ - template - Vector2 Rect::GetPositiveVertex(const Vector2& normal) const + constexpr Vector2 Rect::GetPositiveVertex(const Vector2& normal) const { Vector2 pos(GetPosition()); @@ -356,9 +347,8 @@ namespace Nz * \param rect Rectangle to check * \param intersection Optional argument for the rectangle which represent the intersection */ - template - bool Rect::Intersect(const Rect& rect, Rect* intersection) const + constexpr bool Rect::Intersect(const Rect& rect, Rect* intersection) const { T left = std::max(x, rect.x); T right = std::min(x + width, rect.x + rect.width); @@ -384,7 +374,7 @@ namespace Nz * \return true if the rectangle has a positive width and height */ template - bool Rect::IsNull() const + constexpr bool Rect::IsNull() const { return width <= T(0.0) && height <= T(0.0); } @@ -394,38 +384,19 @@ namespace Nz * \return true if the rectangle has a positive width and height */ template - bool Rect::IsValid() const + constexpr bool Rect::IsValid() const { return width >= T(0.0) && height >= T(0.0); } - /*! - * \brief Makes the rectangle position (0, 0) and lengths (0, 0) - * \return A reference to this box with position (0, 0) and lengths (0, 0) - * - * \see Zero - */ - - template - Rect& Rect::MakeZero() - { - x = T(0.0); - y = T(0.0); - width = T(0.0); - height = T(0.0); - - return *this; - } - /*! * \brief Multiplies the lengths of this rectangle with the scalar * \return A reference to this rectangle where lengths are the product of these lengths and the scalar * * \param scalar The scalar to multiply width and height with */ - template - Rect& Rect::Scale(T scalar) + constexpr Rect& Rect::Scale(T scalar) { width *= scalar; height *= scalar; @@ -439,9 +410,8 @@ namespace Nz * * \param vec The vector where component one multiply width and two height */ - template - Rect& Rect::Scale(const Vector2& vec) + constexpr Rect& Rect::Scale(const Vector2& vec) { width *= vec.x; height *= vec.y; @@ -449,6 +419,42 @@ namespace Nz return *this; } + /*! + * \brief Multiplies the lengths of this box with the scalar (the box center doesn't move) + * \return A reference to this box where lengths are the product of these lengths and the scalar + * + * \param scalar The scalar to multiply width, height and depth with + */ + template + constexpr Rect& Rect::ScaleAroundCenter(T scalar) + { + x -= (width * scalar - width) / T(2.0); + y -= (height * scalar - height) / T(2.0); + + width *= scalar; + height *= scalar; + + return *this; + } + + /*! + * \brief Multiplies the lengths of this box with the vector but changes the origin (the box center doesn't move) + * \return A reference to this box where width, height and depth are the product of the old width, height and depth with the vec + * + * \param vec The vector where component one multiply width, two height and three depth + */ + template + constexpr Rect& Rect::ScaleAroundCenter(const Vector2& vec) + { + x -= (width * vec.x - width) / T(2.0); + y -= (height * vec.y - height) / T(2.0); + + width *= vec.x; + height *= vec.y; + + return *this; + } + /*! * \brief Gives a string representation * \return A string representation of the object: "Rect(x, y, width, height)" @@ -469,9 +475,8 @@ namespace Nz * * \param translation Vector2 which is the translation for the position */ - template - Rect& Rect::Translate(const Vector2& translation) + constexpr Rect& Rect::Translate(const Vector2& translation) { x += translation.x; y += translation.y; @@ -487,9 +492,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greater than 4 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 4 */ - template - T& Rect::operator[](std::size_t i) + constexpr T& Rect::operator[](std::size_t i) { NazaraAssert(i < 4, "Index out of range"); @@ -504,9 +508,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greater than 4 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 4 */ - template - const T& Rect::operator[](std::size_t i) const + constexpr const T& Rect::operator[](std::size_t i) const { NazaraAssert(i < 4, "Index out of range"); @@ -521,7 +524,7 @@ namespace Nz */ template - bool Rect::operator==(const Rect& rect) const + constexpr bool Rect::operator==(const Rect& rect) const { return x == rect.x && y == rect.y && width == rect.width && height == rect.height; } @@ -532,13 +535,18 @@ namespace Nz * * \param rect Other rectangle to compare with */ - template - bool Rect::operator!=(const Rect& rect) const + constexpr bool Rect::operator!=(const Rect& rect) const { return !operator==(rect); } + template + constexpr bool Rect::ApproxEqual(const Rect& lhs, const Rect& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); + } + /*! * \brief Sets a Rect object from two vectors representing point of the space * (X, Y) will be the components minimum of the two vectors and the width and height will be the components maximum - minimum @@ -548,7 +556,7 @@ namespace Nz * \param vec2 Second point */ template - Rect Rect::FromExtends(const Vector2& vec1, const Vector2& vec2) + constexpr Rect Rect::FromExtends(const Vector2& vec1, const Vector2& vec2) { Rect rect; rect.x = std::min(vec1.x, vec2.x); @@ -570,7 +578,7 @@ namespace Nz * \see Lerp */ template - Rect Rect::Lerp(const Rect& from, const Rect& to, T interpolation) + constexpr Rect Rect::Lerp(const Rect& from, const Rect& to, T interpolation) { Rect rect; rect.x = Nz::Lerp(from.x, to.x, interpolation); @@ -584,11 +592,9 @@ namespace Nz /*! * \brief Shorthand for the rectangle (0, 0, 0, 0) * \return A rectangle with position (0, 0) and lengths (0, 0) - * - * \see MakeZero */ template - Rect Rect::Invalid() + constexpr Rect Rect::Invalid() { return Rect(-1, -1, -1, -1); } @@ -596,11 +602,9 @@ namespace Nz /*! * \brief Shorthand for the rectangle (0, 0, 0, 0) * \return A rectangle with position (0, 0) and lengths (0, 0) - * - * \see MakeZero */ template - Rect Rect::Zero() + constexpr Rect Rect::Zero() { return Rect(0, 0, 0, 0); } @@ -671,3 +675,4 @@ namespace Nz } #include +#include "Rect.hpp" diff --git a/include/Nazara/Math/Sphere.hpp b/include/Nazara/Math/Sphere.hpp index 63f8d4a01..7872ec0a2 100644 --- a/include/Nazara/Math/Sphere.hpp +++ b/include/Nazara/Math/Sphere.hpp @@ -20,18 +20,20 @@ namespace Nz class Sphere { public: - Sphere() = default; - Sphere(T X, T Y, T Z, T Radius); - //Sphere(const Circle& circle); - Sphere(const Vector3& center, T Radius); - Sphere(const T sphere[4]); - template explicit Sphere(const Sphere& sphere); - Sphere(const Sphere& sphere) = default; + constexpr Sphere() = default; + constexpr Sphere(T X, T Y, T Z, T Radius); + constexpr Sphere(const Vector3& center, T Radius); + constexpr Sphere(const T sphere[4]); + template constexpr explicit Sphere(const Sphere& sphere); + constexpr Sphere(const Sphere&) = default; + constexpr Sphere(Sphere&&) = default; ~Sphere() = default; - bool Contains(T X, T Y, T Z) const; - bool Contains(const Box& box) const; - bool Contains(const Vector3& point) const; + constexpr bool ApproxEqual(const Sphere& sphere, T maxDifference = std::numeric_limits::epsilon()) const; + + constexpr bool Contains(T X, T Y, T Z) const; + constexpr bool Contains(const Box& box) const; + constexpr bool Contains(const Vector3& point) const; T Distance(T X, T Y, T Z) const; T Distance(const Vector3& point) const; @@ -39,40 +41,38 @@ namespace Nz Sphere& ExtendTo(T X, T Y, T Z); Sphere& ExtendTo(const Vector3& point); - Vector3 GetNegativeVertex(const Vector3& normal) const; - Vector3 GetPosition() const; - Vector3 GetPositiveVertex(const Vector3& normal) const; + constexpr Vector3 GetNegativeVertex(const Vector3& normal) const; + constexpr Vector3 GetPosition() const; + constexpr Vector3 GetPositiveVertex(const Vector3& normal) const; - bool Intersect(const Box& box) const; - bool Intersect(const Sphere& sphere) const; + constexpr bool Intersect(const Box& box) const; + constexpr bool Intersect(const Sphere& sphere) const; - bool IsValid() const; - - Sphere& MakeUnit(); - Sphere& MakeZero(); - - Sphere& Set(T X, T Y, T Z, T Radius); - //Sphere& Set(const Circle& rect); - Sphere& Set(const Vector3& center, T Radius); - Sphere& Set(const T sphere[4]); - template Sphere& Set(const Sphere& sphere); + constexpr bool IsValid() const; std::string ToString() const; - T& operator[](std::size_t i); - T operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr T operator[](std::size_t i) const; - Sphere operator*(T scalar) const; - Sphere& operator=(const Sphere& other) = default; + constexpr Sphere operator*(T scalar) const; - Sphere& operator*=(T scalar); + constexpr Sphere& operator=(const Sphere& other) = default; + constexpr Sphere& operator=(Sphere&&) = default; - bool operator==(const Sphere& sphere) const; - bool operator!=(const Sphere& sphere) const; + constexpr Sphere& operator*=(T scalar); - static Sphere Lerp(const Sphere& from, const Sphere& to, T interpolation); - static Sphere Unit(); - static Sphere Zero(); + constexpr bool operator==(const Sphere& sphere) const; + constexpr bool operator!=(const Sphere& sphere) const; + constexpr bool operator<(const Sphere& sphere) const; + constexpr bool operator<=(const Sphere& sphere) const; + constexpr bool operator>(const Sphere& sphere) const; + constexpr bool operator>=(const Sphere& sphere) const; + + static constexpr bool ApproxEqual(const Sphere& lhs, const Sphere& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Sphere Lerp(const Sphere& from, const Sphere& to, T interpolation); + static constexpr Sphere Unit(); + static constexpr Sphere Zero(); T x, y, z, radius; }; diff --git a/include/Nazara/Math/Sphere.inl b/include/Nazara/Math/Sphere.inl index 1cb704265..1eb52fc76 100644 --- a/include/Nazara/Math/Sphere.inl +++ b/include/Nazara/Math/Sphere.inl @@ -26,19 +26,14 @@ namespace Nz * \param Z Z position * \param Radius half of the diameter */ - template - Sphere::Sphere(T X, T Y, T Z, T Radius) + constexpr Sphere::Sphere(T X, T Y, T Z, T Radius) : + x(X), + y(Y), + z(Z), + radius(Radius) { - Set(X, Y, Z, Radius); } - /* - template - Sphere::Sphere(const Circle& circle) - { - Set(rect); - } - */ /*! * \brief Constructs a Sphere object from its position and radius @@ -46,11 +41,13 @@ namespace Nz * \param center Center of the sphere * \param Radius Half of the diameter */ - template - Sphere::Sphere(const Vector3& center, T Radius) + constexpr Sphere::Sphere(const Vector3& center, T Radius) : + x(center.x), + y(center.y), + z(center.z), + radius(Radius) { - Set(center, Radius); } /*! @@ -58,11 +55,13 @@ namespace Nz * * \param sphere[4] sphere[0] is X component, sphere[1] is Y component, sphere[2] is Z component and sphere[3] is radius */ - template - Sphere::Sphere(const T sphere[4]) + constexpr Sphere::Sphere(const T sphere[4]) : + x(sphere[0]), + y(sphere[1]), + z(sphere[2]), + radius(sphere[3]) { - Set(sphere); } /*! @@ -70,12 +69,20 @@ namespace Nz * * \param sphere Sphere of type U to convert to type T */ - template template - Sphere::Sphere(const Sphere& sphere) + constexpr Sphere::Sphere(const Sphere& sphere) : + x(static_cast(sphere.x)), + y(static_cast(sphere.y)), + z(static_cast(sphere.z)), + radius(static_cast(sphere.radius)) { - Set(sphere); + } + + template + constexpr bool Sphere::ApproxEqual(const Sphere& sphere, T maxDifference) const + { + return NumberEquals(x, sphere.x, maxDifference) && NumberEquals(y, sphere.y, maxDifference) && NumberEquals(z, sphere.z, maxDifference) && NumberEquals(radius, sphere.radius, maxDifference); } /*! @@ -88,9 +95,8 @@ namespace Nz * * \see Contains */ - template - bool Sphere::Contains(T X, T Y, T Z) const + constexpr bool Sphere::Contains(T X, T Y, T Z) const { return Contains(Vector3(X, Y, Z)); } @@ -103,9 +109,8 @@ namespace Nz * * \see Contains */ - template - bool Sphere::Contains(const Box& box) const + constexpr bool Sphere::Contains(const Box& box) const { if (Contains(box.GetMinimum()) && Contains(box.GetMaximum())) return true; @@ -119,9 +124,8 @@ namespace Nz * * \param point Position of the point */ - template - bool Sphere::Contains(const Vector3& point) const + constexpr bool Sphere::Contains(const Vector3& point) const { return GetPosition().SquaredDistance(point) <= radius * radius; } @@ -134,7 +138,6 @@ namespace Nz * \param Y Y position of the point * \param Z Z position of the point */ - template T Sphere::Distance(T X, T Y, T Z) const { @@ -147,7 +150,6 @@ namespace Nz * * \param point Position of the point */ - template T Sphere::Distance(const Vector3& point) const { @@ -164,7 +166,6 @@ namespace Nz * * \see ExtendTo */ - template Sphere& Sphere::ExtendTo(T X, T Y, T Z) { @@ -181,7 +182,6 @@ namespace Nz * * \see ExtendTo */ - template Sphere& Sphere::ExtendTo(const Vector3& point) { @@ -196,9 +196,8 @@ namespace Nz * * \see GetPositiveVertex */ - template - Vector3 Sphere::GetNegativeVertex(const Vector3& normal) const + constexpr Vector3 Sphere::GetNegativeVertex(const Vector3& normal) const { Vector3 neg(GetPosition()); neg -= normal * radius; @@ -210,9 +209,8 @@ namespace Nz * \brief Gets a Vector3 of the position * \return The position of the center of the sphere */ - template - Vector3 Sphere::GetPosition() const + constexpr Vector3 Sphere::GetPosition() const { return Vector3(x, y, z); } @@ -225,9 +223,8 @@ namespace Nz * * \see GetNegativeVertex */ - template - Vector3 Sphere::GetPositiveVertex(const Vector3& normal) const + constexpr Vector3 Sphere::GetPositiveVertex(const Vector3& normal) const { Vector3 pos(GetPosition()); pos += normal * radius; @@ -241,9 +238,8 @@ namespace Nz * * \param box Box to check */ - template - bool Sphere::Intersect(const Box& box) const + constexpr bool Sphere::Intersect(const Box& box) const { // Arvo's algorithm. T squaredDistance = T(0.0); @@ -289,9 +285,8 @@ namespace Nz * * \param sphere Sphere to check */ - template - bool Sphere::Intersect(const Sphere& sphere) const + constexpr bool Sphere::Intersect(const Sphere& sphere) const { return GetPosition().SquaredDistance(Vector3(sphere.x, sphere.y, sphere.z)) <= IntegralPow(radius + sphere.radius, 2); } @@ -300,138 +295,12 @@ namespace Nz * \brief Checks whether this sphere is valid * \return true if the sphere has a strictly positive radius */ - template - bool Sphere::IsValid() const + constexpr bool Sphere::IsValid() const { return radius > T(0.0); } - /*! - * \brief Makes the sphere position (0, 0, 0) and radius 1 - * \return A reference to this vector with position (0, 0, 0) and radius 1 - * - * \see Unit - */ - - template - Sphere& Sphere::MakeUnit() - { - x = T(0.0); - y = T(0.0); - z = T(0.0); - radius = T(1.0); - - return *this; - } - - /*! - * \brief Makes the sphere position (0, 0, 0) and radius 0 - * \return A reference to this vector with position (0, 0, 0) and radius 0 - * - * \see Zero - */ - - template - Sphere& Sphere::MakeZero() - { - x = T(0.0); - y = T(0.0); - z = T(0.0); - radius = T(0.0); - - return *this; - } - - /*! - * \brief Sets the components of the sphere with center and radius - * \return A reference to this sphere - * - * \param X X position - * \param Y Y position - * \param Z Z position - * \param Radius half of the diameter - */ - - template - Sphere& Sphere::Set(T X, T Y, T Z, T Radius) - { - x = X; - y = Y; - z = Z; - radius = Radius; - - return *this; - } - - /*! - * \brief Sets the components of the sphere with center and radius - * \return A reference to this sphere - * - * \param center Center of the sphere - * \param Radius Half of the diameter - */ - - template - Sphere& Sphere::Set(const Vector3& center, T Radius) - { - x = center.x; - y = center.y; - z = center.z; - radius = Radius; - - return *this; - } - /* - template - Sphere& Sphere::Set(const Circle& circle) - { - x = circle.x; - y = circle.y; - z = T(0.0); - radius = circle.radius; - - return *this; - } - */ - - /*! - * \brief Sets the components of the sphere from an array of four elements - * \return A reference to this sphere - * - * \param sphere[4] sphere[0] is X position, sphere[1] is Y position, sphere[2] is Z position and sphere[3] is radius - */ - - template - Sphere& Sphere::Set(const T sphere[4]) - { - x = sphere[0]; - y = sphere[1]; - z = sphere[2]; - radius = sphere[3]; - - return *this; - } - - /*! - * \brief Sets the components of the sphere from another type of Sphere - * \return A reference to this sphere - * - * \param sphere Sphere of type U to convert its components - */ - - template - template - Sphere& Sphere::Set(const Sphere& sphere) - { - x = T(sphere.x); - y = T(sphere.y); - z = T(sphere.z); - radius = T(sphere.radius); - - return *this; - } - /*! * \brief Gives a string representation * \return A string representation of the object: "Sphere(x, y, z; radius)" @@ -454,9 +323,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greater than 4 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 4 */ - template - T& Sphere::operator[](std::size_t i) + constexpr T& Sphere::operator[](std::size_t i) { NazaraAssert(i < 4, "Index out of range"); @@ -471,9 +339,8 @@ namespace Nz * \remark Produce a NazaraError if you try to access to index greater than 4 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 4 */ - template - T Sphere::operator[](std::size_t i) const + constexpr T Sphere::operator[](std::size_t i) const { NazaraAssert(i < 4, "Index out of range"); @@ -486,9 +353,8 @@ namespace Nz * * \param scalar The scalar to multiply radius with */ - template - Sphere Sphere::operator*(T scalar) const + constexpr Sphere Sphere::operator*(T scalar) const { return Sphere(x, y, z, radius * scalar); } @@ -499,9 +365,8 @@ namespace Nz * * \param scalar The scalar to multiply radius with */ - template - Sphere& Sphere::operator*=(T scalar) + constexpr Sphere& Sphere::operator*=(T scalar) { radius *= scalar; } @@ -512,12 +377,10 @@ namespace Nz * * \param sphere Other sphere to compare with */ - template - bool Sphere::operator==(const Sphere& sphere) const + constexpr bool Sphere::operator==(const Sphere& sphere) const { - return NumberEquals(x, sphere.x) && NumberEquals(y, sphere.y) && NumberEquals(z, sphere.z) && - NumberEquals(radius, sphere.radius); + return x == sphere.x && y == sphere.y && z == sphere.z && radius == sphere.radius; } /*! @@ -526,27 +389,86 @@ namespace Nz * * \param sphere Other sphere to compare with */ - template - bool Sphere::operator!=(const Sphere& sphere) const + constexpr bool Sphere::operator!=(const Sphere& sphere) const { return !operator==(sphere); } + template + constexpr bool Sphere::operator<(const Sphere& sphere) const + { + if (x != sphere.x) + return x < sphere.x; + + if (y != sphere.y) + return y < sphere.y; + + if (z != sphere.z) + return z < sphere.z; + + return radius < sphere.radius; + } + + template + constexpr bool Sphere::operator<=(const Sphere& sphere) const + { + if (x != sphere.x) + return x < sphere.x; + + if (y != sphere.y) + return y < sphere.y; + + if (z != sphere.z) + return z < sphere.z; + + return radius <= sphere.radius; + } + + template + constexpr bool Sphere::operator>(const Sphere& sphere) const + { + if (x != sphere.x) + return x > sphere.x; + + if (y != sphere.y) + return y > sphere.y; + + if (z != sphere.z) + return z > sphere.z; + + return radius > sphere.radius; + } + + template + constexpr bool Sphere::operator>=(const Sphere& sphere) const + { + if (x != sphere.x) + return x > sphere.x; + + if (y != sphere.y) + return y > sphere.y; + + if (z != sphere.z) + return z > sphere.z; + + return radius >= sphere.radius; + } + /*! * \brief Shorthand for the sphere (0, 0, 0, 1) * \return A sphere with center (0, 0, 0) and radius 1 - * - * \see MakeUnit */ + template + constexpr Sphere Sphere::Unit() + { + return Sphere(0, 0, 0, 1); + } template - Sphere Sphere::Unit() + constexpr bool Sphere::ApproxEqual(const Sphere& lhs, const Sphere& rhs, T maxDifference) { - Sphere sphere; - sphere.MakeUnit(); - - return sphere; + return lhs.ApproxEqual(rhs, maxDifference); } /*! @@ -562,9 +484,8 @@ namespace Nz * * \see Lerp */ - template - Sphere Sphere::Lerp(const Sphere& from, const Sphere& to, T interpolation) + constexpr Sphere Sphere::Lerp(const Sphere& from, const Sphere& to, T interpolation) { #ifdef NAZARA_DEBUG if (interpolation < T(0.0) || interpolation > T(1.0)) @@ -586,17 +507,11 @@ namespace Nz /*! * \brief Shorthand for the sphere (0, 0, 0, 0) * \return A sphere with center (0, 0, 0) and radius 0 - * - * \see MakeZero */ - template - Sphere Sphere::Zero() + constexpr Sphere Sphere::Zero() { - Sphere sphere; - sphere.MakeZero(); - - return sphere; + return Sphere(0, 0, 0, 0); } /*! @@ -664,3 +579,4 @@ namespace Nz } #include +#include "Sphere.hpp" diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index e8316d38c..9e6fa53e9 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.hpp @@ -24,84 +24,75 @@ namespace Nz class Vector2 { public: - Vector2() = default; - Vector2(T X, T Y); - explicit Vector2(T scale); - template explicit Vector2(const Vector2& vec); - Vector2(const Vector2& vec) = default; - explicit Vector2(const Vector3& vec); - explicit Vector2(const Vector4& vec); + constexpr Vector2() = default; + constexpr Vector2(T X, T Y); + constexpr explicit Vector2(T scale); + template constexpr explicit Vector2(const Vector2& vec); + constexpr Vector2(const Vector2&) = default; + constexpr Vector2(Vector2&&) = default; + constexpr explicit Vector2(const Vector3& vec); + constexpr explicit Vector2(const Vector4& vec); ~Vector2() = default; T AbsDotProduct(const Vector2& vec) const; RadianAngle AngleBetween(const Vector2& vec) const; + constexpr bool ApproxEqual(const Vector2& vec, T maxDifference = std::numeric_limits::epsilon()) const; - template - U Distance(const Vector2& vec) const; - T DotProduct(const Vector2& vec) const; + template U Distance(const Vector2& vec) const; + constexpr T DotProduct(const Vector2& vec) const; - T GetLength() const; - float GetLengthf() const; + template T GetLength() const; Vector2 GetNormal(T* length = nullptr) const; - T GetSquaredLength() const; + constexpr T GetSquaredLength() const; - Vector2& MakeUnit(); - Vector2& MakeUnitX(); - Vector2& MakeUnitY(); - Vector2& MakeZero(); - - Vector2& Maximize(const Vector2& vec); - Vector2& Minimize(const Vector2& vec); + constexpr Vector2& Maximize(const Vector2& vec); + constexpr Vector2& Minimize(const Vector2& vec); Vector2& Normalize(T* length = nullptr); - Vector2& Set(T X, T Y); - Vector2& Set(T scale); - Vector2& Set(const T* vec); - Vector2& Set(const Vector3& vec); - Vector2& Set(const Vector4& vec); - template Vector2& Set(const Vector2& vec); - - T SquaredDistance(const Vector2& vec) const; + constexpr T SquaredDistance(const Vector2& vec) const; std::string ToString() const; - T& operator[](std::size_t i); - T operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr T operator[](std::size_t i) const; - const Vector2& operator+() const; - Vector2 operator-() const; + constexpr const Vector2& operator+() const; + constexpr Vector2 operator-() const; - Vector2 operator+(const Vector2& vec) const; - Vector2 operator-(const Vector2& vec) const; - Vector2 operator*(const Vector2& vec) const; - Vector2 operator*(T scale) const; - Vector2 operator/(const Vector2& vec) const; - Vector2 operator/(T scale) const; - Vector2& operator=(const Vector2& other) = default; + constexpr Vector2 operator+(const Vector2& vec) const; + constexpr Vector2 operator-(const Vector2& vec) const; + constexpr Vector2 operator*(const Vector2& vec) const; + constexpr Vector2 operator*(T scale) const; + constexpr Vector2 operator/(const Vector2& vec) const; + constexpr Vector2 operator/(T scale) const; - Vector2& operator+=(const Vector2& vec); - Vector2& operator-=(const Vector2& vec); - Vector2& operator*=(const Vector2& vec); - Vector2& operator*=(T scale); - Vector2& operator/=(const Vector2& vec); - Vector2& operator/=(T scale); + constexpr Vector2& operator=(const Vector2&) = default; + constexpr Vector2& operator=(Vector2&&) = default; - bool operator==(const Vector2& vec) const; - bool operator!=(const Vector2& vec) const; - bool operator<(const Vector2& vec) const; - bool operator<=(const Vector2& vec) const; - bool operator>(const Vector2& vec) const; - bool operator>=(const Vector2& vec) const; + constexpr Vector2& operator+=(const Vector2& vec); + constexpr Vector2& operator-=(const Vector2& vec); + constexpr Vector2& operator*=(const Vector2& vec); + constexpr Vector2& operator*=(T scale); + constexpr Vector2& operator/=(const Vector2& vec); + constexpr Vector2& operator/=(T scale); + constexpr bool operator==(const Vector2& vec) const; + constexpr bool operator!=(const Vector2& vec) const; + constexpr bool operator<(const Vector2& vec) const; + constexpr bool operator<=(const Vector2& vec) const; + constexpr bool operator>(const Vector2& vec) const; + constexpr bool operator>=(const Vector2& vec) const; + + static constexpr bool ApproxEqual(const Vector2& lhs, const Vector2& rhs, T maxDifference = std::numeric_limits::epsilon()); template static U Distance(const Vector2& vec1, const Vector2& vec2); - static T DotProduct(const Vector2& vec1, const Vector2& vec2); - static Vector2 Lerp(const Vector2& from, const Vector2& to, T interpolation); + static constexpr T DotProduct(const Vector2& vec1, const Vector2& vec2); + static constexpr Vector2 Lerp(const Vector2& from, const Vector2& to, T interpolation); static Vector2 Normalize(const Vector2& vec); - static Vector2 Unit(); - static Vector2 UnitX(); - static Vector2 UnitY(); - static Vector2 Zero(); + static constexpr Vector2 Unit(); + static constexpr Vector2 UnitX(); + static constexpr Vector2 UnitY(); + static constexpr Vector2 Zero(); T x, y; }; @@ -120,8 +111,8 @@ namespace Nz template std::ostream& operator<<(std::ostream& out, const Vector2& vec); - template Vector2 operator*(T scale, const Nz::Vector2& vec); - template Vector2 operator/(T scale, const Nz::Vector2& vec); + template constexpr Vector2 operator*(T scale, const Nz::Vector2& vec); + template constexpr Vector2 operator/(T scale, const Nz::Vector2& vec); } namespace std diff --git a/include/Nazara/Math/Vector2.inl b/include/Nazara/Math/Vector2.inl index 9a3fac0a5..85dd540d0 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -24,11 +24,11 @@ namespace Nz * \param X X component * \param Y Y component */ - template - Vector2::Vector2(T X, T Y) + constexpr Vector2::Vector2(T X, T Y) : + x(X), + y(Y) { - Set(X, Y); } /*! @@ -36,11 +36,11 @@ namespace Nz * * \param scale X component = Y component */ - template - Vector2::Vector2(T scale) + constexpr Vector2::Vector2(T scale) : + x(scale), + y(scale) { - Set(scale); } /*! @@ -48,12 +48,12 @@ namespace Nz * * \param vec Vector of type U to convert to type T */ - template template - Vector2::Vector2(const Vector2& vec) + constexpr Vector2::Vector2(const Vector2& vec) : + x(static_cast(vec.x)), + y(static_cast(vec.y)) { - Set(vec); } /*! @@ -61,11 +61,11 @@ namespace Nz * * \param vec Vector3 where only the first two components are taken */ - template - Vector2::Vector2(const Vector3& vec) + constexpr Vector2::Vector2(const Vector3& vec) : + x(vec.x), + y(vec.y) { - Set(vec); } /*! @@ -73,11 +73,11 @@ namespace Nz * * \param vec Vector4 where only the first two components are taken */ - template - Vector2::Vector2(const Vector4& vec) + constexpr Vector2::Vector2(const Vector4& vec) : + x(vec.x), + y(vec.y) { - Set(vec); } /*! @@ -88,7 +88,6 @@ namespace Nz * * \see DotProduct */ - template T Vector2::AbsDotProduct(const Vector2& vec) const { @@ -105,13 +104,18 @@ namespace Nz * * \see NormalizeAngle */ - template RadianAngle Vector2::AngleBetween(const Vector2& vec) const { return std::atan2(vec.y, vec.x) - std::atan2(y, x); } + template + constexpr bool Vector2::ApproxEqual(const Vector2& vec, T maxDifference) const + { + return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference); + } + /*! * \brief Calculates the distance between two vectors * \return The metric distance between two vectors with euclidean norm @@ -120,7 +124,6 @@ namespace Nz * * \see SquaredDistance */ - template template U Vector2::Distance(const Vector2& vec) const @@ -136,9 +139,8 @@ namespace Nz * * \see AbsDotProduct, DotProduct */ - template - T Vector2::DotProduct(const Vector2& vec) const + constexpr T Vector2::DotProduct(const Vector2& vec) const { return x*vec.x + y*vec.y; } @@ -149,22 +151,11 @@ namespace Nz * * \see GetSquaredLength */ - template + template T Vector2::GetLength() const { - return static_cast(std::sqrt(GetSquaredLength())); - } - - /*! - * \brief Calculates the length (magnitude) of the vector - * \return The length in float of the vector - */ - - template - float Vector2::GetLengthf() const - { - return std::sqrt(static_cast(GetSquaredLength())); + return static_cast(std::sqrt(static_cast(GetSquaredLength()))); } /*! @@ -177,7 +168,6 @@ namespace Nz * * \see Normalize */ - template Vector2 Vector2::GetNormal(T* length) const { @@ -193,65 +183,12 @@ namespace Nz * * \see GetLength */ - template - T Vector2::GetSquaredLength() const + constexpr T Vector2::GetSquaredLength() const { return x*x + y*y; } - /*! - * \brief Makes the vector (1, 1) - * \return A reference to this vector with components (1, 1) - * - * \see Unit - */ - - template - Vector2& Vector2::MakeUnit() - { - return Set(T(1.0), T(1.0)); - } - - /*! - * \brief Makes the vector (1, 0) - * \return A reference to this vector with components (1, 0) - * - * \see UnitX - */ - - template - Vector2& Vector2::MakeUnitX() - { - return Set(T(1.0), T(0.0)); - } - - /*! - * \brief Makes the vector (0, 1) - * \return A reference to this vector with components (0, 1) - * - * \see UnitY - */ - - template - Vector2& Vector2::MakeUnitY() - { - return Set(T(0.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, 0) - * \return A reference to this vector with components (0, 0) - * - * \see Zero - */ - - template - Vector2& Vector2::MakeZero() - { - return Set(T(0.0), T(0.0)); - } - /*! * \brief Sets this vector's components to the maximum of its own and other components * \return A reference to this vector with replaced values with the corresponding max value @@ -260,9 +197,8 @@ namespace Nz * * \see Minimize */ - template - Vector2& Vector2::Maximize(const Vector2& vec) + constexpr Vector2& Vector2::Maximize(const Vector2& vec) { if (vec.x > x) x = vec.x; @@ -281,9 +217,8 @@ namespace Nz * * \see Maximize */ - template - Vector2& Vector2::Minimize(const Vector2& vec) + constexpr Vector2& Vector2::Minimize(const Vector2& vec) { if (vec.x < x) x = vec.x; @@ -304,7 +239,6 @@ namespace Nz * * \see GetNormal */ - template Vector2& Vector2::Normalize(T* length) { @@ -322,103 +256,6 @@ namespace Nz return *this; } - /*! - * \brief Sets the components of the vector - * \return A reference to this vector - * - * \param X X component - * \param Y Y component - */ - - template - Vector2& Vector2::Set(T X, T Y) - { - x = X; - y = Y; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a "scale" - * \return A reference to this vector - * - * \param scale X component = Y component - */ - - template - Vector2& Vector2::Set(T scale) - { - x = scale; - y = scale; - - return *this; - } - - /*! - * \brief Sets the components of the vector from an array of two elements - * \return A reference to this vector - * - * \param vec[2] vec[0] is X component and vec[1] is Y component - */ - template - Vector2& Vector2::Set(const T* vec) - { - x = vec[0]; - y = vec[1]; - - return *this; - } - - /*! - * \brief Sets the components of the vector from another type of Vector2 - * \return A reference to this vector - * - * \param vec Vector of type U to convert its components - */ - - template - template - Vector2& Vector2::Set(const Vector2& vec) - { - x = T(vec.x); - y = T(vec.y); - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector3 - * \return A reference to this vector - * - * \param vec Vector3 where only the first two components are taken - */ - - template - Vector2& Vector2::Set(const Vector3& vec) - { - x = vec.x; - y = vec.y; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector4 - * \return A reference to this vector - * - * \param vec Vector4 where only the first two components are taken - */ - - template - Vector2& Vector2::Set(const Vector4& vec) - { - x = vec.x; - y = vec.y; - - return *this; - } - /*! * \brief Calculates the squared distance between two vectors * \return The metric distance between two vectors with the squared euclidean norm @@ -427,9 +264,8 @@ namespace Nz * * \see Distance */ - template - T Vector2::SquaredDistance(const Vector2& vec) const + constexpr T Vector2::SquaredDistance(const Vector2& vec) const { return (*this - vec).GetSquaredLength(); } @@ -450,7 +286,7 @@ namespace Nz * \return X, Y depending on index (0, 1) */ template - T& Vector2::operator[](std::size_t i) + constexpr T& Vector2::operator[](std::size_t i) { NazaraAssert(i < 2, "index out of range"); return *(&x + i); @@ -461,7 +297,7 @@ namespace Nz * \return X, Y depending on index (0, 1) */ template - T Vector2::operator[](std::size_t i) const + constexpr T Vector2::operator[](std::size_t i) const { NazaraAssert(i < 2, "index out of range"); return *(&x + i); @@ -471,9 +307,8 @@ namespace Nz * \brief Helps to represent the sign of the vector * \return A constant reference to this vector */ - template - const Vector2& Vector2::operator+() const + constexpr const Vector2& Vector2::operator+() const { return *this; } @@ -482,9 +317,8 @@ namespace Nz * \brief Negates the components of the vector * \return A constant reference to this vector with negate components */ - template - Vector2 Vector2::operator-() const + constexpr Vector2 Vector2::operator-() const { return Vector2(-x, -y); } @@ -495,9 +329,8 @@ namespace Nz * * \param vec The other vector to add components with */ - template - Vector2 Vector2::operator+(const Vector2& vec) const + constexpr Vector2 Vector2::operator+(const Vector2& vec) const { return Vector2(x + vec.x, y + vec.y); } @@ -508,9 +341,8 @@ namespace Nz * * \param vec The other vector to substract components with */ - template - Vector2 Vector2::operator-(const Vector2& vec) const + constexpr Vector2 Vector2::operator-(const Vector2& vec) const { return Vector2(x - vec.x, y - vec.y); } @@ -521,9 +353,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector2 Vector2::operator*(const Vector2& vec) const + constexpr Vector2 Vector2::operator*(const Vector2& vec) const { return Vector2(x * vec.x, y * vec.y); } @@ -534,9 +365,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Vector2 Vector2::operator*(T scale) const + constexpr Vector2 Vector2::operator*(T scale) const { return Vector2(x * scale, y * scale); } @@ -547,9 +377,8 @@ namespace Nz * * \param vec The other vector to divide components with */ - template - Vector2 Vector2::operator/(const Vector2& vec) const + constexpr Vector2 Vector2::operator/(const Vector2& vec) const { return Vector2(x / vec.x, y / vec.y); } @@ -560,9 +389,8 @@ namespace Nz * * \param scale The scalar to divide components with */ - template - Vector2 Vector2::operator/(T scale) const + constexpr Vector2 Vector2::operator/(T scale) const { return Vector2(x / scale, y / scale); } @@ -573,9 +401,8 @@ namespace Nz * * \param vec The other vector to add components with */ - template - Vector2& Vector2::operator+=(const Vector2& vec) + constexpr Vector2& Vector2::operator+=(const Vector2& vec) { x += vec.x; y += vec.y; @@ -589,9 +416,8 @@ namespace Nz * * \param vec The other vector to substract components with */ - template - Vector2& Vector2::operator-=(const Vector2& vec) + constexpr Vector2& Vector2::operator-=(const Vector2& vec) { x -= vec.x; y -= vec.y; @@ -605,9 +431,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector2& Vector2::operator*=(const Vector2& vec) + constexpr Vector2& Vector2::operator*=(const Vector2& vec) { x *= vec.x; y *= vec.y; @@ -621,9 +446,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Vector2& Vector2::operator*=(T scale) + constexpr Vector2& Vector2::operator*=(T scale) { x *= scale; y *= scale; @@ -637,9 +461,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector2& Vector2::operator/=(const Vector2& vec) + constexpr Vector2& Vector2::operator/=(const Vector2& vec) { x /= vec.x; y /= vec.y; @@ -653,9 +476,8 @@ namespace Nz * * \param scale The scalar to divide components with */ - template - Vector2& Vector2::operator/=(T scale) + constexpr Vector2& Vector2::operator/=(T scale) { x /= scale; y /= scale; @@ -669,12 +491,10 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector2::operator==(const Vector2& vec) const + constexpr bool Vector2::operator==(const Vector2& vec) const { - return NumberEquals(x, vec.x) && - NumberEquals(y, vec.y); + return x == vec.x && y == vec.y; } /*! @@ -683,9 +503,8 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector2::operator!=(const Vector2& vec) const + constexpr bool Vector2::operator!=(const Vector2& vec) const { return !operator==(vec); } @@ -696,14 +515,13 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector2::operator<(const Vector2& vec) const + constexpr bool Vector2::operator<(const Vector2& vec) const { - if (x == vec.x) - return y < vec.y; - else + if (x != vec.x) return x < vec.x; + + return y < vec.y; } /*! @@ -712,14 +530,13 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector2::operator<=(const Vector2& vec) const + constexpr bool Vector2::operator<=(const Vector2& vec) const { - if (x == vec.x) - return y <= vec.y; - else + if (x != vec.x) return x < vec.x; + + return y <= vec.y; } /*! @@ -728,11 +545,13 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector2::operator>(const Vector2& vec) const + constexpr bool Vector2::operator>(const Vector2& vec) const { - return !operator<=(vec); + if (x != vec.x) + return x > vec.x; + + return y > vec.y; } /*! @@ -741,11 +560,19 @@ namespace Nz * * \param vec Other vector to compare with */ + template + constexpr bool Vector2::operator>=(const Vector2& vec) const + { + if (x != vec.x) + return x > vec.x; + + return y >= vec.y; + } template - bool Vector2::operator>=(const Vector2& vec) const + constexpr bool Vector2::ApproxEqual(const Vector2& lhs, const Vector2& rhs, T maxDifference) { - return !operator<(vec); + return lhs.ApproxEqual(rhs, maxDifference); } /*! @@ -775,9 +602,8 @@ namespace Nz * * \see AbsDotProduct, DotProduct */ - template - T Vector2::DotProduct(const Vector2& vec1, const Vector2& vec2) + constexpr T Vector2::DotProduct(const Vector2& vec1, const Vector2& vec2) { return vec1.DotProduct(vec2); } @@ -794,9 +620,8 @@ namespace Nz * * \see Lerp */ - template - Vector2 Vector2::Lerp(const Vector2& from, const Vector2& to, T interpolation) + constexpr Vector2 Vector2::Lerp(const Vector2& from, const Vector2& to, T interpolation) { Vector2 dummy; dummy.x = Nz::Lerp(from.x, to.x, interpolation); @@ -815,7 +640,6 @@ namespace Nz * * \see GetNormal */ - template Vector2 Vector2::Normalize(const Vector2& vec) { @@ -825,63 +649,41 @@ namespace Nz /*! * \brief Shorthand for the vector (1, 1) * \return A vector with components (1, 1) - * - * \see MakeUnit */ - template - Vector2 Vector2::Unit() + constexpr Vector2 Vector2::Unit() { - Vector2 vector; - vector.MakeUnit(); - - return vector; + return Vector2(1, 1); } /*! * \brief Shorthand for the vector (1, 0) * \return A vector with components (1, 0) - * - * \see MakeUnitX */ - template - Vector2 Vector2::UnitX() + constexpr Vector2 Vector2::UnitX() { - Vector2 vector; - vector.MakeUnitX(); - - return vector; + return Vector2(1, 0); } /*! * \brief Shorthand for the vector (0, 1) * \return A vector with components (0, 1) - * - * \see MakeUnitY */ template - Vector2 Vector2::UnitY() + constexpr Vector2 Vector2::UnitY() { - Vector2 vector; - vector.MakeUnitY(); - - return vector; + return Vector2(0, 1); } /*! * \brief Shorthand for the vector (0, 0) * \return A vector with components (0, 0) - * - * \see MakeZero */ template - Vector2 Vector2::Zero() + constexpr Vector2 Vector2::Zero() { - Vector2 vector; - vector.MakeZero(); - - return vector; + return Vector2(0, 0); } /*! @@ -904,7 +706,7 @@ namespace Nz * \param scale The scalar to multiply components with */ template - Vector2 operator*(T scale, const Vector2& vec) + constexpr Vector2 operator*(T scale, const Vector2& vec) { return Vector2(scale * vec.x, scale * vec.y); } @@ -916,7 +718,7 @@ namespace Nz * \param scale The scalar to divide components with */ template - Vector2 operator/(T scale, const Vector2& vec) + constexpr Vector2 operator/(T scale, const Vector2& vec) { return Vector2(scale / vec.x, scale / vec.y); } @@ -984,3 +786,4 @@ namespace std } #include +#include "Vector2.hpp" diff --git a/include/Nazara/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index 438227a83..db1a7b54a 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -24,105 +24,91 @@ namespace Nz class Vector3 { public: - Vector3() = default; - Vector3(T X, T Y, T Z); - Vector3(T X, const Vector2& vec); - explicit Vector3(T scale); - Vector3(const Vector2& vec, T Z = 0.0); - template explicit Vector3(const Vector3& vec); - Vector3(const Vector3& vec) = default; - explicit Vector3(const Vector4& vec); + constexpr Vector3() = default; + constexpr Vector3(T X, T Y, T Z); + constexpr Vector3(T X, const Vector2& vec); + constexpr explicit Vector3(T scale); + constexpr Vector3(const Vector2& vec, T Z = 0.0); + template constexpr explicit Vector3(const Vector3& vec); + constexpr Vector3(const Vector3&) = default; + constexpr Vector3(Vector3&&) = default; + constexpr explicit Vector3(const Vector4& vec); ~Vector3() = default; T AbsDotProduct(const Vector3& vec) const; RadianAngle AngleBetween(const Vector3& vec) const; + constexpr bool ApproxEqual(const Vector3& vec, T maxDifference = std::numeric_limits::epsilon()) const; - Vector3 CrossProduct(const Vector3& vec) const; + constexpr Vector3 CrossProduct(const Vector3& vec) const; - template - U Distance(const Vector3& vec) const; - T DotProduct(const Vector3& vec) const; + template U Distance(const Vector3& vec) const; + constexpr T DotProduct(const Vector3& vec) const; Vector3 GetAbs() const; - T GetLength() const; - float GetLengthf() const; + template U GetLength() const; Vector3 GetNormal(T* length = nullptr) const; - T GetSquaredLength() const; + constexpr T GetSquaredLength() const; - Vector3& MakeBackward(); - Vector3& MakeDown(); - Vector3& MakeForward(); - Vector3& MakeLeft(); - Vector3& MakeRight(); - Vector3& MakeUnit(); - Vector3& MakeUnitX(); - Vector3& MakeUnitY(); - Vector3& MakeUnitZ(); - Vector3& MakeUp(); - Vector3& MakeZero(); - - Vector3& Maximize(const Vector3& vec); - Vector3& Minimize(const Vector3& vec); + constexpr Vector3& Maximize(const Vector3& vec); + constexpr Vector3& Minimize(const Vector3& vec); Vector3& Normalize(T* length = nullptr); - Vector3& Set(T X, T Y, T Z); - Vector3& Set(T X, const Vector2& vec); - Vector3& Set(T scale); - Vector3& Set(const T* vec); - Vector3& Set(const Vector2& vec, T Z = 0.0); - template Vector3& Set(const Vector3& vec); - Vector3& Set(const Vector4& vec); - - T SquaredDistance(const Vector3& vec) const; + constexpr T SquaredDistance(const Vector3& vec) const; std::string ToString() const; - T& operator[](std::size_t i); - T operator[](std::size_t i) const; + constexpr T& operator[](std::size_t i); + constexpr const T& operator[](std::size_t i) const; - const Vector3& operator+() const; - Vector3 operator-() const; + constexpr const Vector3& operator+() const; + constexpr Vector3 operator-() const; - Vector3 operator+(const Vector3& vec) const; - Vector3 operator-(const Vector3& vec) const; - Vector3 operator*(const Vector3& vec) const; - Vector3 operator*(T scale) const; - Vector3 operator/(const Vector3& vec) const; - Vector3 operator/(T scale) const; - Vector3& operator=(const Vector3& vec) = default; + constexpr Vector3 operator+(const Vector3& vec) const; + constexpr Vector3 operator-(const Vector3& vec) const; + constexpr Vector3 operator*(const Vector3& vec) const; + constexpr Vector3 operator*(T scale) const; + constexpr Vector3 operator/(const Vector3& vec) const; + constexpr Vector3 operator/(T scale) const; - Vector3& operator+=(const Vector3& vec); - Vector3& operator-=(const Vector3& vec); - Vector3& operator*=(const Vector3& vec); - Vector3& operator*=(T scale); - Vector3& operator/=(const Vector3& vec); - Vector3& operator/=(T scale); + constexpr Vector3& operator=(const Vector3&) = default; + constexpr Vector3& operator=(Vector3&&) = default; - bool operator==(const Vector3& vec) const; - bool operator!=(const Vector3& vec) const; - bool operator<(const Vector3& vec) const; - bool operator<=(const Vector3& vec) const; - bool operator>(const Vector3& vec) const; - bool operator>=(const Vector3& vec) const; + constexpr Vector3& operator+=(const Vector3& vec); + constexpr Vector3& operator-=(const Vector3& vec); + constexpr Vector3& operator*=(const Vector3& vec); + constexpr Vector3& operator*=(T scale); + constexpr Vector3& operator/=(const Vector3& vec); + constexpr Vector3& operator/=(T scale); - static Vector3 Backward(); - static Vector3 CrossProduct(const Vector3& vec1, const Vector3& vec2); - static T DotProduct(const Vector3& vec1, const Vector3& vec2); + constexpr bool operator==(const Vector3& vec) const; + constexpr bool operator!=(const Vector3& vec) const; + constexpr bool operator<(const Vector3& vec) const; + constexpr bool operator<=(const Vector3& vec) const; + constexpr bool operator>(const Vector3& vec) const; + constexpr bool operator>=(const Vector3& vec) const; + + static constexpr bool ApproxEqual(const Vector3& lhs, const Vector3& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr Vector3 Backward(); + static constexpr Vector3 Clamp(const Vector3& vec, const Vector3& min, const Vector3& max); + static constexpr Vector3 CrossProduct(const Vector3& vec1, const Vector3& vec2); template static U Distance(const Vector3& vec1, const Vector3& vec2); - static Vector3 Down(); - static Vector3 Forward(); - static Vector3 Left(); - static Vector3 Lerp(const Vector3& from, const Vector3& to, T interpolation); + static constexpr T DotProduct(const Vector3& vec1, const Vector3& vec2); + static constexpr Vector3 Down(); + static constexpr Vector3 Forward(); + static constexpr Vector3 Left(); + static constexpr Vector3 Lerp(const Vector3& from, const Vector3& to, T interpolation); + static constexpr Vector3 Max(const Vector3& lhs, const Vector3& rhs); + static constexpr Vector3 Min(const Vector3& lhs, const Vector3& rhs); static Vector3 Normalize(const Vector3& vec); - static Vector3 Right(); - static T SquaredDistance(const Vector3& vec1, const Vector3& vec2); - static Vector3 Unit(); - static Vector3 UnitX(); - static Vector3 UnitY(); - static Vector3 UnitZ(); - static Vector3 Up(); - static Vector3 Zero(); + static constexpr Vector3 Right(); + static constexpr T SquaredDistance(const Vector3& vec1, const Vector3& vec2); + static constexpr Vector3 Unit(); + static constexpr Vector3 UnitX(); + static constexpr Vector3 UnitY(); + static constexpr Vector3 UnitZ(); + static constexpr Vector3 Up(); + static constexpr Vector3 Zero(); T x, y, z; }; @@ -141,8 +127,8 @@ namespace Nz template std::ostream& operator<<(std::ostream& out, const Vector3& vec); - template Vector3 operator*(T scale, const Vector3& vec); - template Vector3 operator/(T scale, const Vector3& vec); + template constexpr Vector3 operator*(T scale, const Vector3& vec); + template constexpr Vector3 operator/(T scale, const Vector3& vec); } namespace std diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index 898d255a5..280905305 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -27,9 +27,11 @@ namespace Nz * \param Z Z component */ template - Vector3::Vector3(T X, T Y, T Z) + constexpr Vector3::Vector3(T X, T Y, T Z) : + x(X), + y(Y), + z(Z) { - Set(X, Y, Z); } /*! @@ -39,9 +41,11 @@ namespace Nz * \param vec vec.X = Y component and vec.y = Z component */ template - Vector3::Vector3(T X, const Vector2& vec) + constexpr Vector3::Vector3(T X, const Vector2& vec) : + x(X), + y(vec.x), + z(vec.y) { - Set(X, vec); } /*! @@ -50,9 +54,11 @@ namespace Nz * \param scale X component = Y component = Z component */ template - Vector3::Vector3(T scale) + constexpr Vector3::Vector3(T scale) : + x(scale), + y(scale), + z(scale) { - Set(scale); } /*! @@ -62,9 +68,11 @@ namespace Nz * \param Z Z component */ template - Vector3::Vector3(const Vector2& vec, T Z) + constexpr Vector3::Vector3(const Vector2& vec, T Z) : + x(vec.x), + y(vec.y), + z(Z) { - Set(vec, Z); } /*! @@ -74,9 +82,11 @@ namespace Nz */ template template - Vector3::Vector3(const Vector3& vec) + constexpr Vector3::Vector3(const Vector3& vec) : + x(static_cast(vec.x)), + y(static_cast(vec.y)), + z(static_cast(vec.z)) { - Set(vec); } /*! @@ -85,9 +95,11 @@ namespace Nz * \param vec Vector4 where only the first three components are taken */ template - Vector3::Vector3(const Vector4& vec) + constexpr Vector3::Vector3(const Vector4& vec): + x(vec.x), + y(vec.y), + z(vec.z) { - Set(vec); } /*! @@ -133,7 +145,13 @@ namespace Nz #endif T alpha = DotProduct(vec) / divisor; - return std::acos(Clamp(alpha, T(-1.0), T(1.0))); + return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0))); + } + + template + constexpr bool Vector3::ApproxEqual(const Vector3& vec, T maxDifference) const + { + return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference) && NumberEquals(z, vec.z, maxDifference); } /*! @@ -145,7 +163,7 @@ namespace Nz * \see CrossProduct */ template - Vector3 Vector3::CrossProduct(const Vector3& vec) const + constexpr Vector3 Vector3::CrossProduct(const Vector3& vec) const { return Vector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x); } @@ -162,7 +180,7 @@ namespace Nz template U Vector3::Distance(const Vector3& vec) const { - return static_cast(std::sqrt(SquaredDistance(vec))); + return static_cast(std::sqrt(static_cast(SquaredDistance(vec)))); } /*! @@ -174,7 +192,7 @@ namespace Nz * \see AbsDotProduct, DotProduct */ template - T Vector3::DotProduct(const Vector3& vec) const + constexpr T Vector3::DotProduct(const Vector3& vec) const { return x * vec.x + y * vec.y + z * vec.z; } @@ -196,19 +214,10 @@ namespace Nz * \see GetSquaredLength */ template - T Vector3::GetLength() const + template + U Vector3::GetLength() const { - return static_cast(std::sqrt(GetSquaredLength())); - } - - /*! - * \brief Calculates the length (magnitude) of the vector - * \return The length in float of the vector - */ - template - float Vector3::GetLengthf() const - { - return std::sqrt(static_cast(GetSquaredLength())); + return static_cast(std::sqrt(static_cast(GetSquaredLength()))); } /*! @@ -237,143 +246,11 @@ namespace Nz * \see GetLength */ template - T Vector3::GetSquaredLength() const + constexpr T Vector3::GetSquaredLength() const { return x*x + y*y + z*z; } - /*! - * \brief Makes the vector (0, 0, 1) - * \return A reference to this vector with components (0, 0, 1) - * - * \see Backward - */ - template - Vector3& Vector3::MakeBackward() - { - return Set(T(0.0), T(0.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, -1, 0) - * \return A reference to this vector with components (0, -1, 0) - * - * \see Down - */ - template - Vector3& Vector3::MakeDown() - { - return Set(T(0.0), T(-1.0), T(0.0)); - } - - /*! - * \brief Makes the vector (0, 0, -1) - * \return A reference to this vector with components (0, 0, -1) - * - * \see Forward - */ - template - Vector3& Vector3::MakeForward() - { - return Set(T(0.0), T(0.0), T(-1.0)); - } - - /*! - * \brief Makes the vector (-1, 0, 0) - * \return A reference to this vector with components (-1, 0, 0) - * - * \see Left - */ - template - Vector3& Vector3::MakeLeft() - { - return Set(T(-1.0), T(0.0), T(0.0)); - } - - /*! - * \brief Makes the vector (1, 0, 0) - * \return A reference to this vector with components (1, 0, 0) - * - * \see Right - */ - template - Vector3& Vector3::MakeRight() - { - return Set(T(1.0), T(0.0), T(0.0)); - } - - /*! - * \brief Makes the vector (1, 1, 1) - * \return A reference to this vector with components (1, 1, 1) - * - * \see Unit - */ - template - Vector3& Vector3::MakeUnit() - { - return Set(T(1.0), T(1.0), T(1.0)); - } - - /*! - * \brief Makes the vector (1, 0, 0) - * \return A reference to this vector with components (1, 0, 0) - * - * \see UnitX - */ - template - Vector3& Vector3::MakeUnitX() - { - return Set(T(1.0), T(0.0), T(0.0)); - } - - /*! - * \brief Makes the vector (0, 1, 0) - * \return A reference to this vector with components (0, 1, 0) - * - * \see UnitY - */ - template - Vector3& Vector3::MakeUnitY() - { - return Set(T(0.0), T(1.0), T(0.0)); - } - - /*! - * \brief Makes the vector (0, 0, 1) - * \return A reference to this vector with components (0, 0, 1) - * - * \see UnitZ - */ - template - Vector3& Vector3::MakeUnitZ() - { - return Set(T(0.0), T(0.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, 1, 0) - * \return A reference to this vector with components (0, 1, 0) - * - * \see Up - */ - template - Vector3& Vector3::MakeUp() - { - return Set(T(0.0), T(1.0), T(0.0)); - } - - /*! - * \brief Makes the vector (0, 0, 0) - * \return A reference to this vector with components (0, 0, 0) - * - * \see Zero - */ - template - Vector3& Vector3::MakeZero() - { - return Set(T(0.0), T(0.0), T(0.0)); - } - /*! * \brief Sets this vector's components to the maximum of its own and other components * \return A reference to this vector with replaced values with the corresponding max value @@ -383,7 +260,7 @@ namespace Nz * \see Minimize */ template - Vector3& Vector3::Maximize(const Vector3& vec) + constexpr Vector3& Vector3::Maximize(const Vector3& vec) { if (vec.x > x) x = vec.x; @@ -406,7 +283,7 @@ namespace Nz * \see Maximize */ template - Vector3& Vector3::Minimize(const Vector3& vec) + constexpr Vector3& Vector3::Minimize(const Vector3& vec) { if (vec.x < x) x = vec.x; @@ -448,121 +325,6 @@ namespace Nz return *this; } - /*! - * \brief Sets the components of the vector - * \return A reference to this vector - * - * \param X X component - * \param Y Y component - * \param Z Z component - */ - template - Vector3& Vector3::Set(T X, T Y, T Z) - { - x = X; - y = Y; - z = Z; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a component and a Vector2 - * - * \param X X component - * \param vec vec.X = Y component and vec.y = Z component - */ - template - Vector3& Vector3::Set(T X, const Vector2& vec) - { - x = X; - y = vec.x; - z = vec.y; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a "scale" - * \return A reference to this vector - * - * \param scale X component = Y component = Z component - */ - template - Vector3& Vector3::Set(T scale) - { - x = scale; - y = scale; - z = scale; - - return *this; - } - - /*! - * \brief Sets the components of the vector from an array of three elements - * \return A reference to this vector - * - * \param vec[3] vec[0] is X component, vec[1] is Y component and vec[2] is Z component - */ - template - Vector3& Vector3::Set(const T* vec) - { - x = vec[0]; - y = vec[1]; - z = vec[2]; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector2 and a component - * - * \param vec vec.X = X component and vec.y = Y component - * \param Z Z component - */ - template - Vector3& Vector3::Set(const Vector2& vec, T Z) - { - x = vec.x; - y = vec.y; - z = Z; - - return *this; - } - - /*! - * \brief Sets the components of the vector from another type of Vector3 - * \return A reference to this vector - * - * \param vec Vector of type U to convert its components - */ - template - template - Vector3& Vector3::Set(const Vector3& vec) - { - x = T(vec.x); - y = T(vec.y); - z = T(vec.z); - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector4 - * \return A reference to this vector - * - * \param vec Vector4 where only the first three components are taken - */ - template - Vector3& Vector3::Set(const Vector4& vec) - { - x = vec.x; - y = vec.y; - z = vec.z; - - return *this; - } - /*! * \brief Calculates the squared distance between two vectors * \return The metric distance between two vectors with the squared euclidean norm @@ -572,7 +334,7 @@ namespace Nz * \see Distance */ template - T Vector3::SquaredDistance(const Vector3& vec) const + constexpr T Vector3::SquaredDistance(const Vector3& vec) const { return (*this - vec).GetSquaredLength(); } @@ -592,7 +354,7 @@ namespace Nz * \return X, Y, Z depending on index (0, 1, 2) */ template - T& Vector3::operator[](std::size_t i) + constexpr T& Vector3::operator[](std::size_t i) { NazaraAssert(i < 3, "index out of range"); return *(&x + i); @@ -603,7 +365,7 @@ namespace Nz * \return X, Y, Z depending on index (0, 1, 2) */ template - T Vector3::operator[](std::size_t i) const + constexpr const T& Vector3::operator[](std::size_t i) const { NazaraAssert(i < 3, "index out of range"); return *(&x + i); @@ -614,7 +376,7 @@ namespace Nz * \return A constant reference to this vector */ template - const Vector3& Vector3::operator+() const + constexpr const Vector3& Vector3::operator+() const { return *this; } @@ -624,7 +386,7 @@ namespace Nz * \return A constant reference to this vector with negate components */ template - Vector3 Vector3::operator-() const + constexpr Vector3 Vector3::operator-() const { return Vector3(-x, -y, -z); } @@ -636,7 +398,7 @@ namespace Nz * \param vec The other vector to add components with */ template - Vector3 Vector3::operator+(const Vector3& vec) const + constexpr Vector3 Vector3::operator+(const Vector3& vec) const { return Vector3(x + vec.x, y + vec.y, z + vec.z); } @@ -648,7 +410,7 @@ namespace Nz * \param vec The other vector to substract components with */ template - Vector3 Vector3::operator-(const Vector3& vec) const + constexpr Vector3 Vector3::operator-(const Vector3& vec) const { return Vector3(x - vec.x, y - vec.y, z - vec.z); } @@ -660,7 +422,7 @@ namespace Nz * \param vec The other vector to multiply components with */ template - Vector3 Vector3::operator*(const Vector3& vec) const + constexpr Vector3 Vector3::operator*(const Vector3& vec) const { return Vector3(x * vec.x, y * vec.y, z * vec.z); } @@ -672,7 +434,7 @@ namespace Nz * \param scale The scalar to multiply components with */ template - Vector3 Vector3::operator*(T scale) const + constexpr Vector3 Vector3::operator*(T scale) const { return Vector3(x * scale, y * scale, z * scale); } @@ -684,7 +446,7 @@ namespace Nz * \param vec The other vector to divide components with */ template - Vector3 Vector3::operator/(const Vector3& vec) const + constexpr Vector3 Vector3::operator/(const Vector3& vec) const { return Vector3(x / vec.x, y / vec.y, z / vec.z); } @@ -696,7 +458,7 @@ namespace Nz * \param scale The scalar to divide components with */ template - Vector3 Vector3::operator/(T scale) const + constexpr Vector3 Vector3::operator/(T scale) const { return Vector3(x / scale, y / scale, z / scale); } @@ -708,7 +470,7 @@ namespace Nz * \param vec The other vector to add components with */ template - Vector3& Vector3::operator+=(const Vector3& vec) + constexpr Vector3& Vector3::operator+=(const Vector3& vec) { x += vec.x; y += vec.y; @@ -724,7 +486,7 @@ namespace Nz * \param vec The other vector to substract components with */ template - Vector3& Vector3::operator-=(const Vector3& vec) + constexpr Vector3& Vector3::operator-=(const Vector3& vec) { x -= vec.x; y -= vec.y; @@ -740,7 +502,7 @@ namespace Nz * \param vec The other vector to multiply components with */ template - Vector3& Vector3::operator*=(const Vector3& vec) + constexpr Vector3& Vector3::operator*=(const Vector3& vec) { x *= vec.x; y *= vec.y; @@ -756,7 +518,7 @@ namespace Nz * \param scale The scalar to multiply components with */ template - Vector3& Vector3::operator*=(T scale) + constexpr Vector3& Vector3::operator*=(T scale) { x *= scale; y *= scale; @@ -772,7 +534,7 @@ namespace Nz * \param vec The other vector to multiply components with */ template - Vector3& Vector3::operator/=(const Vector3& vec) + constexpr Vector3& Vector3::operator/=(const Vector3& vec) { x /= vec.x; y /= vec.y; @@ -788,7 +550,7 @@ namespace Nz * \param scale The scalar to divide components with */ template - Vector3& Vector3::operator/=(T scale) + constexpr Vector3& Vector3::operator/=(T scale) { x /= scale; y /= scale; @@ -804,11 +566,9 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator==(const Vector3& vec) const + constexpr bool Vector3::operator==(const Vector3& vec) const { - return NumberEquals(x, vec.x) && - NumberEquals(y, vec.y) && - NumberEquals(z, vec.z); + return x == vec.x && y == vec.y && z == vec.z; } /*! @@ -818,7 +578,7 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator!=(const Vector3& vec) const + constexpr bool Vector3::operator!=(const Vector3& vec) const { return !operator==(vec); } @@ -830,17 +590,15 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator<(const Vector3& vec) const + constexpr bool Vector3::operator<(const Vector3& vec) const { - if (NumberEquals(x, vec.x)) - { - if (NumberEquals(y, vec.y)) - return z < vec.z; - else - return y < vec.y; - } - else + if (x != vec.x) return x < vec.x; + + if (y != vec.y) + return y < vec.y; + + return z < vec.z; } /*! @@ -850,17 +608,15 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator<=(const Vector3& vec) const + constexpr bool Vector3::operator<=(const Vector3& vec) const { - if (NumberEquals(x, vec.x)) - { - if (NumberEquals(y, vec.y)) - return NumberEquals(z, vec.z) || z < vec.z; - else - return y < vec.y; - } - else + if (x != vec.x) return x < vec.x; + + if (y != vec.y) + return y < vec.y; + + return z <= vec.z; } /*! @@ -870,9 +626,15 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator>(const Vector3& vec) const + constexpr bool Vector3::operator>(const Vector3& vec) const { - return !operator<=(vec); + if (x != vec.x) + return x > vec.x; + + if (y != vec.y) + return y > vec.y; + + return z > vec.z; } /*! @@ -882,9 +644,21 @@ namespace Nz * \param vec Other vector to compare with */ template - bool Vector3::operator>=(const Vector3& vec) const + constexpr bool Vector3::operator>=(const Vector3& vec) const { - return !operator<(vec); + if (x != vec.x) + return x > vec.x; + + if (y != vec.y) + return y > vec.y; + + return z >= vec.z; + } + + template + constexpr bool Vector3::ApproxEqual(const Vector3& lhs, const Vector3& rhs, T maxDifference) + { + return lhs.ApproxEqual(rhs, maxDifference); } /*! @@ -897,7 +671,7 @@ namespace Nz * \see CrossProduct */ template - Vector3 Vector3::CrossProduct(const Vector3& vec1, const Vector3& vec2) + constexpr Vector3 Vector3::CrossProduct(const Vector3& vec1, const Vector3& vec2) { return vec1.CrossProduct(vec2); } @@ -912,7 +686,7 @@ namespace Nz * \see AbsDotProduct, DotProduct */ template - T Vector3::DotProduct(const Vector3& vec1, const Vector3& vec2) + constexpr T Vector3::DotProduct(const Vector3& vec1, const Vector3& vec2) { return vec1.DotProduct(vec2); } @@ -920,16 +694,21 @@ namespace Nz /*! * \brief Shorthand for the vector (0, 0, 1) * \return A vector with components (0, 0, 1) - * - * \see MakeBackward */ template - Vector3 Vector3::Backward() + constexpr Vector3 Vector3::Backward() { - Vector3 vector; - vector.MakeBackward(); + return Vector3(0, 0, 1); + } - return vector; + template + constexpr Vector3 Vector3::Clamp(const Vector3& vec, const Vector3& min, const Vector3& max) + { + return Vector3( + std::clamp(vec.x, min.x, max.x), + std::clamp(vec.y, min.y, max.y), + std::clamp(vec.z, min.z, max.z) + ); } /*! @@ -940,8 +719,6 @@ namespace Nz * param vec2 the second point * * \return The distance between the two vectors - * - * \see SquaredDistance */ template template @@ -953,46 +730,31 @@ namespace Nz /*! * \brief Shorthand for the vector (0, -1, 0) * \return A vector with components (0, -1, 0) - * - * \see MakeDown */ template - Vector3 Vector3::Down() + constexpr Vector3 Vector3::Down() { - Vector3 vector; - vector.MakeDown(); - - return vector; + return Vector3(0, -1, 0); } /*! * \brief Shorthand for the vector (0, 0, -1) * \return A vector with components (0, 0, -1) - * - * \see Forward */ template - Vector3 Vector3::Forward() + constexpr Vector3 Vector3::Forward() { - Vector3 vector; - vector.MakeForward(); - - return vector; + return Vector3(0, 0, -1); } /*! * \brief Shorthand for the vector (-1, 0, 0) * \return A vector with components (-1, 0, 0) - * - * \see MakeLeft */ template - Vector3 Vector3::Left() + constexpr Vector3 Vector3::Left() { - Vector3 vector; - vector.MakeLeft(); - - return vector; + return Vector3(-1, 0, 0); } /*! @@ -1004,18 +766,34 @@ namespace Nz * \param interpolation Factor of interpolation * * \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior - * - * \see Lerp */ template - Vector3 Vector3::Lerp(const Vector3& from, const Vector3& to, T interpolation) + constexpr Vector3 Vector3::Lerp(const Vector3& from, const Vector3& to, T interpolation) { - Vector3 dummy; - dummy.x = Nz::Lerp(from.x, to.x, interpolation); - dummy.y = Nz::Lerp(from.y, to.y, interpolation); - dummy.z = Nz::Lerp(from.z, to.z, interpolation); + Vector3 result; + result.x = Nz::Lerp(from.x, to.x, interpolation); + result.y = Nz::Lerp(from.y, to.y, interpolation); + result.z = Nz::Lerp(from.z, to.z, interpolation); - return dummy; + return result; + } + + template + constexpr Vector3 Vector3::Max(const Vector3& lhs, const Vector3& rhs) + { + Vector3 max = lhs; + max.Maximize(rhs); + + return max; + } + + template + constexpr Vector3 Vector3::Min(const Vector3& lhs, const Vector3& rhs) + { + Vector3 min = lhs; + min.Minimize(rhs); + + return min; } /*! @@ -1025,8 +803,6 @@ namespace Nz * \param vec Vector to normalize * * \remark If the vector is (0, 0, 0), then it returns (0, 0, 0) - * - * \see GetNormal */ template Vector3 Vector3::Normalize(const Vector3& vec) @@ -1037,16 +813,11 @@ namespace Nz /*! * \brief Shorthand for the vector (1, 0, 0) * \return A vector with components (1, 0, 0) - * - * \see MakeRight */ template - Vector3 Vector3::Right() + constexpr Vector3 Vector3::Right() { - Vector3 vector; - vector.MakeRight(); - - return vector; + return Vector3(1, 0, 0); } /*! @@ -1059,7 +830,7 @@ namespace Nz * \see Distance */ template - T Vector3::SquaredDistance(const Vector3& vec1, const Vector3& vec2) + constexpr T Vector3::SquaredDistance(const Vector3& vec1, const Vector3& vec2) { return vec1.SquaredDistance(vec2); } @@ -1067,91 +838,61 @@ namespace Nz /*! * \brief Shorthand for the vector (1, 1, 1) * \return A vector with components (1, 1, 1) - * - * \see MakeUnit */ template - Vector3 Vector3::Unit() + constexpr Vector3 Vector3::Unit() { - Vector3 vector; - vector.MakeUnit(); - - return vector; + return Vector3(1); } /*! * \brief Shorthand for the vector (1, 0, 0) * \return A vector with components (1, 0, 0) - * - * \see MakeUnitX */ template - Vector3 Vector3::UnitX() + constexpr Vector3 Vector3::UnitX() { - Vector3 vector; - vector.MakeUnitX(); - - return vector; + return Vector3(1, 0, 0); } /*! * \brief Shorthand for the vector (0, 1, 0) * \return A vector with components (0, 1, 0) - * - * \see MakeUnitY */ template - Vector3 Vector3::UnitY() + constexpr Vector3 Vector3::UnitY() { - Vector3 vector; - vector.MakeUnitY(); - - return vector; + return Vector3(0, 1, 0); } /*! * \brief Shorthand for the vector (0, 0, 1) * \return A vector with components (0, 0, 1) - * - * \see MakeUnitZ */ template - Vector3 Vector3::UnitZ() + constexpr Vector3 Vector3::UnitZ() { - Vector3 vector; - vector.MakeUnitZ(); - - return vector; + return Vector3(0, 0, 1); } /*! * \brief Shorthand for the vector (0, 1, 0) * \return A vector with components (0, 1, 0) - * - * \see MakeUp */ template - Vector3 Vector3::Up() + constexpr Vector3 Vector3::Up() { - Vector3 vector; - vector.MakeUp(); - - return vector; + return Vector3(0, 1, 0); } /*! * \brief Shorthand for the vector (0, 0, 0) * \return A vector with components (0, 0, 0) - * - * \see MakeZero */ template - Vector3 Vector3::Zero() + constexpr Vector3 Vector3::Zero() { - Vector3 vector; - vector.MakeZero(); - - return vector; + return Vector3(0, 0, 0); } /*! @@ -1218,7 +959,7 @@ namespace Nz * \param scale The scalar to multiply components with */ template - Vector3 operator*(T scale, const Vector3& vec) + constexpr Vector3 operator*(T scale, const Vector3& vec) { return Vector3(scale * vec.x, scale * vec.y, scale * vec.z); } @@ -1230,7 +971,7 @@ namespace Nz * \param scale The scalar to divide components with */ template - Vector3 operator/(T scale, const Vector3& vec) + constexpr Vector3 operator/(T scale, const Vector3& vec) { return Vector3(scale / vec.x, scale / vec.y, scale / vec.z); } diff --git a/include/Nazara/Math/Vector4.hpp b/include/Nazara/Math/Vector4.hpp index b090a2a01..cfb83b3b9 100644 --- a/include/Nazara/Math/Vector4.hpp +++ b/include/Nazara/Math/Vector4.hpp @@ -23,81 +23,71 @@ namespace Nz class Vector4 { public: - Vector4() = default; - Vector4(T X, T Y, T Z, T W = 1.0); - Vector4(T X, T Y, const Vector2& vec); - Vector4(T X, const Vector2& vec, T W); - Vector4(T X, const Vector3& vec); - explicit Vector4(T scale); - Vector4(const Vector2& vec, T Z = 0.0, T W = 1.0); - Vector4(const Vector3& vec, T W = 1.0); - template explicit Vector4(const Vector4& vec); - Vector4(const Vector4& vec) = default; + constexpr Vector4() = default; + constexpr Vector4(T X, T Y, T Z, T W = 1.0); + constexpr Vector4(T X, T Y, const Vector2& vec); + constexpr Vector4(T X, const Vector2& vec, T W); + constexpr Vector4(T X, const Vector3& vec); + constexpr explicit Vector4(T scale); + constexpr Vector4(const Vector2& vec, T Z = 0.0, T W = 1.0); + constexpr Vector4(const Vector3& vec, T W = 1.0); + template constexpr explicit Vector4(const Vector4& vec); + constexpr Vector4(const Vector4&) = default; + constexpr Vector4(Vector4&&) = default; ~Vector4() = default; T AbsDotProduct(const Vector4& vec) const; + constexpr bool ApproxEqual(const Vector4& vec, T maxDifference = std::numeric_limits::epsilon()) const; - T DotProduct(const Vector4& vec) const; + constexpr T DotProduct(const Vector4& vec) const; Vector4 GetNormal(T* length = nullptr) const; - Vector4& MakeUnitX(); - Vector4& MakeUnitY(); - Vector4& MakeUnitZ(); - Vector4& MakeZero(); - - Vector4& Maximize(const Vector4& vec); - Vector4& Minimize(const Vector4& vec); + constexpr Vector4& Maximize(const Vector4& vec); + constexpr Vector4& Minimize(const Vector4& vec); Vector4& Normalize(T* length = nullptr); - Vector4& Set(T X, T Y, T Z, T W = 1.0); - Vector4& Set(T X, T Y, const Vector2& vec); - Vector4& Set(T X, const Vector2& vec, T W); - Vector4& Set(T X, const Vector3& vec); - Vector4& Set(T scale); - Vector4& Set(const T* vec); - Vector4& Set(const Vector2& vec, T Z = 0.0, T W = 1.0); - Vector4& Set(const Vector3& vec, T W = 1.0); - template Vector4& Set(const Vector4& vec); - std::string ToString() const; - T& operator[](std::size_t i); - T operator[](std::size_t i) const; + constexpr Vector4& operator=(const Vector4&) = default; + constexpr Vector4& operator=(Vector4&&) = default; - const Vector4& operator+() const; - Vector4 operator-() const; + constexpr T& operator[](std::size_t i); + constexpr const T& operator[](std::size_t i) const; - Vector4 operator+(const Vector4& vec) const; - Vector4 operator-(const Vector4& vec) const; - Vector4 operator*(const Vector4& vec) const; - Vector4 operator*(T scale) const; - Vector4 operator/(const Vector4& vec) const; - Vector4 operator/(T scale) const; - Vector4& operator=(const Vector4& other) = default; + constexpr const Vector4& operator+() const; + constexpr Vector4 operator-() const; - Vector4& operator+=(const Vector4& vec); - Vector4& operator-=(const Vector4& vec); - Vector4& operator*=(const Vector4& vec); - Vector4& operator*=(T scale); - Vector4& operator/=(const Vector4& vec); - Vector4& operator/=(T scale); + constexpr Vector4 operator+(const Vector4& vec) const; + constexpr Vector4 operator-(const Vector4& vec) const; + constexpr Vector4 operator*(const Vector4& vec) const; + constexpr Vector4 operator*(T scale) const; + constexpr Vector4 operator/(const Vector4& vec) const; + constexpr Vector4 operator/(T scale) const; - bool operator==(const Vector4& vec) const; - bool operator!=(const Vector4& vec) const; - bool operator<(const Vector4& vec) const; - bool operator<=(const Vector4& vec) const; - bool operator>(const Vector4& vec) const; - bool operator>=(const Vector4& vec) const; + constexpr Vector4& operator+=(const Vector4& vec); + constexpr Vector4& operator-=(const Vector4& vec); + constexpr Vector4& operator*=(const Vector4& vec); + constexpr Vector4& operator*=(T scale); + constexpr Vector4& operator/=(const Vector4& vec); + constexpr Vector4& operator/=(T scale); - static T DotProduct(const Vector4& vec1, const Vector4& vec2); - static Vector4 Lerp(const Vector4& from, const Vector4& to, T interpolation); + constexpr bool operator==(const Vector4& vec) const; + constexpr bool operator!=(const Vector4& vec) const; + constexpr bool operator<(const Vector4& vec) const; + constexpr bool operator<=(const Vector4& vec) const; + constexpr bool operator>(const Vector4& vec) const; + constexpr bool operator>=(const Vector4& vec) const; + + static constexpr bool ApproxEqual(const Vector4& lhs, const Vector4& rhs, T maxDifference = std::numeric_limits::epsilon()); + static constexpr T DotProduct(const Vector4& vec1, const Vector4& vec2); + static constexpr Vector4 Lerp(const Vector4& from, const Vector4& to, T interpolation); static Vector4 Normalize(const Vector4& vec); - static Vector4 UnitX(); - static Vector4 UnitY(); - static Vector4 UnitZ(); - static Vector4 Zero(); + static constexpr Vector4 UnitX(); + static constexpr Vector4 UnitY(); + static constexpr Vector4 UnitZ(); + static constexpr Vector4 Zero(); T x, y, z, w; }; @@ -116,8 +106,8 @@ namespace Nz template std::ostream& operator<<(std::ostream& out, const Vector4& vec); - template Vector4 operator*(T scale, const Vector4& vec); - template Vector4 operator/(T scale, const Vector4& vec); + template constexpr Vector4 operator*(T scale, const Vector4& vec); + template constexpr Vector4 operator/(T scale, const Vector4& vec); } namespace std diff --git a/include/Nazara/Math/Vector4.inl b/include/Nazara/Math/Vector4.inl index b1aedc168..8ea3dac55 100644 --- a/include/Nazara/Math/Vector4.inl +++ b/include/Nazara/Math/Vector4.inl @@ -28,11 +28,13 @@ namespace Nz * \param Z Z component * \param W W component */ - template - Vector4::Vector4(T X, T Y, T Z, T W) + constexpr Vector4::Vector4(T X, T Y, T Z, T W) : + x(X), + y(Y), + z(Z), + w(W) { - Set(X, Y, Z, W); } /*! @@ -42,11 +44,13 @@ namespace Nz * \param Y Y component * \param vec vec.X = Z component and vec.y = W component */ - template - Vector4::Vector4(T X, T Y, const Vector2& vec) + constexpr Vector4::Vector4(T X, T Y, const Vector2& vec) : + x(X), + y(Y), + z(vec.x), + w(vec.y) { - Set(X, Y, vec); } /*! @@ -56,11 +60,13 @@ namespace Nz * \param vec vec.X = Y component and vec.y = Z component * \param W W component */ - template - Vector4::Vector4(T X, const Vector2& vec, T W) + constexpr Vector4::Vector4(T X, const Vector2& vec, T W) : + x(X), + y(vec.x), + z(vec.y), + w(W) { - Set(X, vec, W); } /*! @@ -69,11 +75,13 @@ namespace Nz * \param X X component * \param vec vec.X = Y component, vec.y = Z component and vec.z = W component */ - template - Vector4::Vector4(T X, const Vector3& vec) + constexpr Vector4::Vector4(T X, const Vector3& vec) : + x(X), + y(vec.x), + z(vec.y), + w(vec.z) { - Set(X, vec); } /*! @@ -81,11 +89,13 @@ namespace Nz * * \param scale X component = Y component = Z component = W component */ - template - Vector4::Vector4(T scale) + constexpr Vector4::Vector4(T scale) : + x(scale), + y(scale), + z(scale), + w(scale) { - Set(scale); } /*! @@ -95,11 +105,13 @@ namespace Nz * \param Z Z component * \param W W component */ - template - Vector4::Vector4(const Vector2& vec, T Z, T W) + constexpr Vector4::Vector4(const Vector2& vec, T Z, T W) : + x(vec.x), + y(vec.y), + z(Z), + w(W) { - Set(vec, Z, W); } /*! @@ -108,11 +120,13 @@ namespace Nz * \param vec vec.X = X component, vec.y = Y component and vec.z = Z component * \param W W component */ - template - Vector4::Vector4(const Vector3& vec, T W) + constexpr Vector4::Vector4(const Vector3& vec, T W) : + x(vec.x), + y(vec.y), + z(vec.z), + w(W) { - Set(vec, W); } /*! @@ -123,9 +137,12 @@ namespace Nz template template - Vector4::Vector4(const Vector4& vec) + constexpr Vector4::Vector4(const Vector4& vec) : + x(static_cast(vec.x)), + y(static_cast(vec.y)), + z(static_cast(vec.z)), + w(static_cast(vec.w)) { - Set(vec); } /*! @@ -136,13 +153,18 @@ namespace Nz * * \see DotProduct */ - template T Vector4::AbsDotProduct(const Vector4& vec) const { return std::abs(x * vec.x) + std::abs(y * vec.y) + std::abs(z * vec.z) + std::abs(w * vec.w); } + template + constexpr bool Vector4::ApproxEqual(const Vector4& vec, T maxDifference) const + { + return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference) && NumberEquals(z, vec.z, maxDifference) && NumberEquals(w, vec.w, maxDifference); + } + /*! * \brief Calculates the dot (scalar) product with two vectors * \return The value of the dot product @@ -151,9 +173,8 @@ namespace Nz * * \see AbsDotProduct, DotProduct */ - template - T Vector4::DotProduct(const Vector4& vec) const + constexpr T Vector4::DotProduct(const Vector4& vec) const { return x*vec.x + y*vec.y + z*vec.z + w*vec.w; } @@ -166,7 +187,6 @@ namespace Nz * * \see Normalize */ - template Vector4 Vector4::GetNormal(T* length) const { @@ -176,58 +196,6 @@ namespace Nz return vec; } - /*! - * \brief Makes the vector (1, 0, 0, 1) - * \return A reference to this vector with components (1, 0, 0, 1) - * - * \see UnitX - */ - - template - Vector4& Vector4::MakeUnitX() - { - return Set(T(1.0), T(0.0), T(0.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, 1, 0, 1) - * \return A reference to this vector with components (0, 1, 0, 1) - * - * \see UnitY - */ - - template - Vector4& Vector4::MakeUnitY() - { - return Set(T(0.0), T(1.0), T(0.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, 0, 1, 1) - * \return A reference to this vector with components (0, 0, 1, 1) - * - * \see UnitZ - */ - - template - Vector4& Vector4::MakeUnitZ() - { - return Set(T(0.0), T(0.0), T(1.0), T(1.0)); - } - - /*! - * \brief Makes the vector (0, 0, 0, 1) - * \return A reference to this vector with components (0, 0, 0, 1) - * - * \see Zero - */ - - template - Vector4& Vector4::MakeZero() - { - return Set(T(0.0), T(0.0), T(0.0), T(1.0)); - } - /*! * \brief Sets this vector's components to the maximum of its own and other components * \return A reference to this vector with replaced values with the corresponding max value @@ -236,9 +204,8 @@ namespace Nz * * \see Minimize */ - template - Vector4& Vector4::Maximize(const Vector4& vec) + constexpr Vector4& Vector4::Maximize(const Vector4& vec) { if (vec.x > x) x = vec.x; @@ -263,9 +230,8 @@ namespace Nz * * \see Maximize */ - template - Vector4& Vector4::Minimize(const Vector4& vec) + constexpr Vector4& Vector4::Minimize(const Vector4& vec) { if (vec.x < x) x = vec.x; @@ -290,11 +256,10 @@ namespace Nz * * \see GetNormal */ - template Vector4& Vector4::Normalize(T* length) { - T invLength = T(1.0)/w; + T invLength = T(1.0) / w; x *= invLength; // Warning, change this logic will break Frustum::Extract y *= invLength; z *= invLength; @@ -307,182 +272,10 @@ namespace Nz return *this; } - /*! - * \brief Sets the components of the vector - * \return A reference to this vector - * - * \param X X component - * \param Y Y component - * \param Z Z component - * \param W W component - */ - - template - Vector4& Vector4::Set(T X, T Y, T Z, T W) - { - x = X; - y = Y; - z = Z; - w = W; - - return *this; - } - - /*! - * \brief Sets the components of the vector from two components and a Vector2 - * \return A reference to this vector - * - * \param X X component - * \param Y Y component - * \param vec vec.X = Z component and vec.y = W component - */ - - template - Vector4& Vector4::Set(T X, T Y, const Vector2& vec) - { - x = X; - y = Y; - z = vec.x; - w = vec.y; - - return *this; - } - - /*! - * \brief Sets the components of the vector from one component, a Vector2 and one component - * \return A reference to this vector - * - * \param X X component - * \param vec vec.X = Y component and vec.y = Z component - * \param W W component - */ - - template - Vector4& Vector4::Set(T X, const Vector2& vec, T W) - { - x = X; - y = vec.x; - z = vec.y; - w = W; - - return *this; - } - - /*! - * \brief Sets the components of the vector from one component and a Vector3 - * \return A reference to this vector - * - * \param X X component - * \param vec vec.X = Y component, vec.y = Z component and vec.z = W component - */ - - template - Vector4& Vector4::Set(T X, const Vector3& vec) - { - x = X; - y = vec.x; - z = vec.y; - w = vec.z; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a "scale" - * \return A reference to this vector - * - * \param scale X component = Y component = Z component = W component - */ - - template - Vector4& Vector4::Set(T scale) - { - x = scale; - y = scale; - z = scale; - w = scale; - - return *this; - } - - /*! - * \brief Sets the components of the vector from an array of four elements - * \return A reference to this vector - * - * \param vec[4] vec[0] is X component, vec[1] is Y component, vec[2] is Z component and vec[3] is W component - */ - template - Vector4& Vector4::Set(const T* vec) - { - x = vec[0]; - y = vec[1]; - z = vec[2]; - w = vec[3]; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector2 and two components - * - * \param vec vec.X = X component and vec.y = Y component - * \param Z Z component - * \param W W component - */ - - template - Vector4& Vector4::Set(const Vector2& vec, T Z, T W) - { - x = vec.x; - y = vec.y; - z = Z; - w = W; - - return *this; - } - - /*! - * \brief Sets the components of the vector from a Vector3 and one components - * - * \param vec vec.X = X component, vec.y = Y component and vec.z = Z component - * \param W W component - */ - - template - Vector4& Vector4::Set(const Vector3& vec, T W) - { - x = vec.x; - y = vec.y; - z = vec.z; - w = W; - - return *this; - } - - /*! - * \brief Sets the components of the vector from another type of Vector4 - * \return A reference to this vector - * - * \param vec Vector of type U to convert its components - */ - - template - template - Vector4& Vector4::Set(const Vector4& vec) - { - x = T(vec.x); - y = T(vec.y); - z = T(vec.z); - w = T(vec.w); - - return *this; - } - /*! * \brief Gives a string representation * \return A string representation of the object: "Vector4(x, y, z, w)" */ - template std::string Vector4::ToString() const { @@ -497,7 +290,7 @@ namespace Nz * \return X, Y, Z depending on index (0, 1, 2) */ template - T& Vector4::operator[](std::size_t i) + constexpr T& Vector4::operator[](std::size_t i) { NazaraAssert(i < 4, "index out of range"); return *(&x + i); @@ -508,7 +301,7 @@ namespace Nz * \return X, Y, Z depending on index (0, 1, 2) */ template - T Vector4::operator[](std::size_t i) const + constexpr const T& Vector4::operator[](std::size_t i) const { NazaraAssert(i < 4, "index out of range"); return *(&x + i); @@ -518,9 +311,8 @@ namespace Nz * \brief Helps to represent the sign of the vector * \return A constant reference to this vector */ - template - const Vector4& Vector4::operator+() const + constexpr const Vector4& Vector4::operator+() const { return *this; } @@ -529,9 +321,8 @@ namespace Nz * \brief Negates the components of the vector * \return A constant reference to this vector with negate components */ - template - Vector4 Vector4::operator-() const + constexpr Vector4 Vector4::operator-() const { return Vector4(-x, -y, -z, -w); } @@ -542,9 +333,8 @@ namespace Nz * * \param vec The other vector to add components with */ - template - Vector4 Vector4::operator+(const Vector4& vec) const + constexpr Vector4 Vector4::operator+(const Vector4& vec) const { return Vector4(x + vec.x, y + vec.y, z + vec.z, w + vec.w); } @@ -555,9 +345,8 @@ namespace Nz * * \param vec The other vector to substract components with */ - template - Vector4 Vector4::operator-(const Vector4& vec) const + constexpr Vector4 Vector4::operator-(const Vector4& vec) const { return Vector4(x - vec.x, y - vec.y, z - vec.z, w - vec.w); } @@ -568,9 +357,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector4 Vector4::operator*(const Vector4& vec) const + constexpr Vector4 Vector4::operator*(const Vector4& vec) const { return Vector4(x * vec.x, y * vec.y, z * vec.z, w * vec.w); } @@ -581,9 +369,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Vector4 Vector4::operator*(T scale) const + constexpr Vector4 Vector4::operator*(T scale) const { return Vector4(x * scale, y * scale, z * scale, w * scale); } @@ -594,9 +381,8 @@ namespace Nz * * \param vec The other vector to divide components with */ - template - Vector4 Vector4::operator/(const Vector4& vec) const + constexpr Vector4 Vector4::operator/(const Vector4& vec) const { return Vector4(x / vec.x, y / vec.y, z / vec.z, w / vec.w); } @@ -607,9 +393,8 @@ namespace Nz * * \param scale The scalar to divide components with */ - template - Vector4 Vector4::operator/(T scale) const + constexpr Vector4 Vector4::operator/(T scale) const { return Vector4(x / scale, y / scale, z / scale, w / scale); } @@ -620,9 +405,8 @@ namespace Nz * * \param vec The other vector to add components with */ - template - Vector4& Vector4::operator+=(const Vector4& vec) + constexpr Vector4& Vector4::operator+=(const Vector4& vec) { x += vec.x; y += vec.y; @@ -638,9 +422,8 @@ namespace Nz * * \param vec The other vector to substract components with */ - template - Vector4& Vector4::operator-=(const Vector4& vec) + constexpr Vector4& Vector4::operator-=(const Vector4& vec) { x -= vec.x; y -= vec.y; @@ -656,9 +439,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector4& Vector4::operator*=(const Vector4& vec) + constexpr Vector4& Vector4::operator*=(const Vector4& vec) { x *= vec.x; y *= vec.y; @@ -674,9 +456,8 @@ namespace Nz * * \param scale The scalar to multiply components with */ - template - Vector4& Vector4::operator*=(T scale) + constexpr Vector4& Vector4::operator*=(T scale) { x *= scale; y *= scale; @@ -692,9 +473,8 @@ namespace Nz * * \param vec The other vector to multiply components with */ - template - Vector4& Vector4::operator/=(const Vector4& vec) + constexpr Vector4& Vector4::operator/=(const Vector4& vec) { x /= vec.x; y /= vec.y; @@ -710,9 +490,8 @@ namespace Nz * * \param scale The scalar to divide components with */ - template - Vector4& Vector4::operator/=(T scale) + constexpr Vector4& Vector4::operator/=(T scale) { x /= scale; y /= scale; @@ -728,14 +507,10 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector4::operator==(const Vector4& vec) const + constexpr bool Vector4::operator==(const Vector4& vec) const { - return NumberEquals(x, vec.x) && - NumberEquals(y, vec.y) && - NumberEquals(z, vec.z) && - NumberEquals(w, vec.w); + return x == vec.x && y == vec.y && z == vec.z && w == vec.w; } /*! @@ -744,9 +519,8 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector4::operator!=(const Vector4& vec) const + constexpr bool Vector4::operator!=(const Vector4& vec) const { return !operator==(vec); } @@ -757,24 +531,19 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector4::operator<(const Vector4& vec) const + constexpr bool Vector4::operator<(const Vector4& vec) const { - if (NumberEquals(x, vec.x)) - { - if (NumberEquals(y, vec.y)) - { - if (NumberEquals(z, vec.z)) - return w < vec.w; - else - return z < vec.z; - } - else - return y < vec.y; - } - else + if (x != vec.x) return x < vec.x; + + if (y != vec.y) + return y < vec.y; + + if (z != vec.z) + return z < vec.z; + + return w < vec.w; } /*! @@ -783,24 +552,19 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector4::operator<=(const Vector4& vec) const + constexpr bool Vector4::operator<=(const Vector4& vec) const { - if (NumberEquals(x, vec.x)) - { - if (NumberEquals(y, vec.y)) - { - if (NumberEquals(z, vec.z)) - return NumberEquals(w, vec.w) || w < vec.w; - else - return z < vec.z; - } - else - return y < vec.y; - } - else + if (x != vec.x) return x < vec.x; + + if (y != vec.y) + return y < vec.y; + + if (z != vec.z) + return z < vec.z; + + return w <= vec.w; } /*! @@ -809,11 +573,19 @@ namespace Nz * * \param vec Other vector to compare with */ - template - bool Vector4::operator>(const Vector4& vec) const + constexpr bool Vector4::operator>(const Vector4& vec) const { - return !operator<=(vec); + if (x != vec.x) + return x > vec.x; + + if (y != vec.y) + return y > vec.y; + + if (z != vec.z) + return z > vec.z; + + return w > vec.w; } /*! @@ -822,11 +594,25 @@ namespace Nz * * \param vec Other vector to compare with */ + template + constexpr bool Vector4::operator>=(const Vector4& vec) const + { + if (x != vec.x) + return x > vec.x; + + if (y != vec.y) + return y > vec.y; + + if (z != vec.z) + return z > vec.z; + + return w >= vec.w; + } template - bool Vector4::operator>=(const Vector4& vec) const + constexpr bool Vector4::ApproxEqual(const Vector4& lhs, const Vector4& rhs, T maxDifference) { - return !operator<(vec); + return lhs.ApproxEqual(rhs, maxDifference); } /*! @@ -839,7 +625,7 @@ namespace Nz * \see AbsDotProduct, DotProduct */ template - T Vector4::DotProduct(const Vector4& vec1, const Vector4& vec2) + constexpr T Vector4::DotProduct(const Vector4& vec1, const Vector4& vec2) { return vec1.DotProduct(vec2); } @@ -857,7 +643,7 @@ namespace Nz * \see Lerp */ template - Vector4 Vector4::Lerp(const Vector4& from, const Vector4& to, T interpolation) + constexpr Vector4 Vector4::Lerp(const Vector4& from, const Vector4& to, T interpolation) { Vector4 dummy; dummy.x = Nz::Lerp(from.x, to.x, interpolation); @@ -876,7 +662,6 @@ namespace Nz * * \see GetNormal */ - template Vector4 Vector4::Normalize(const Vector4& vec) { @@ -886,65 +671,41 @@ namespace Nz /*! * \brief Shorthand for the vector (1, 0, 0, 1) * \return A vector with components (1, 0, 0, 1) - * - * \see MakeUnitX */ - template - Vector4 Vector4::UnitX() + constexpr Vector4 Vector4::UnitX() { - Vector4 vector; - vector.MakeUnitX(); - - return vector; + return Vector4(1, 0, 0, 1); } /*! * \brief Shorthand for the vector (0, 1, 0, 1) * \return A vector with components (0, 1, 0, 1) - * - * \see MakeUnitY */ - template - Vector4 Vector4::UnitY() + constexpr Vector4 Vector4::UnitY() { - Vector4 vector; - vector.MakeUnitY(); - - return vector; + return Vector4(0, 1, 0, 1); } /*! * \brief Shorthand for the vector (0, 0, 1, 1) * \return A vector with components (0, 0, 1, 1) - * - * \see MakeUnitZ */ - template - Vector4 Vector4::UnitZ() + constexpr Vector4 Vector4::UnitZ() { - Vector4 vector; - vector.MakeUnitZ(); - - return vector; + return Vector4(0, 0, 1, 1); } /*! * \brief Shorthand for the vector (0, 0, 0, 1) * \return A vector with components (0, 0, 0, 1) - * - * \see MakeZero */ - template - Vector4 Vector4::Zero() + constexpr Vector4 Vector4::Zero() { - Vector4 vector; - vector.MakeZero(); - - return vector; + return Vector4(0, 0, 0, 1); } /*! @@ -1017,7 +778,7 @@ namespace Nz * \param scale The scalar to multiply components with */ template - Vector4 operator*(T scale, const Vector4& vec) + constexpr Vector4 operator*(T scale, const Vector4& vec) { return Nz::Vector4(scale * vec.x, scale * vec.y, scale * vec.z, scale * vec.w); } @@ -1029,7 +790,7 @@ namespace Nz * \param scale The scalar to divide components with */ template - Vector4 operator/(T scale, const Vector4& vec) + constexpr Vector4 operator/(T scale, const Vector4& vec) { return Nz::Vector4(scale / vec.x, scale / vec.y, scale / vec.z, scale / vec.w); } @@ -1061,3 +822,4 @@ namespace std } #include +#include "Vector4.hpp" diff --git a/include/Nazara/Utility/Node.inl b/include/Nazara/Utility/Node.inl index 23d49f9cc..5aa3de42b 100644 --- a/include/Nazara/Utility/Node.inl +++ b/include/Nazara/Utility/Node.inl @@ -300,7 +300,7 @@ namespace Nz inline void Node::SetInitialPosition(float positionX, float positionY, float positionZ, Invalidation invalidation) { - m_initialPosition.Set(positionX, positionY, positionZ); + m_initialPosition = Vector3f(positionX, positionY, positionZ); Invalidate(invalidation); } @@ -321,14 +321,14 @@ namespace Nz inline void Node::SetInitialScale(float scale, Invalidation invalidation) { - m_initialScale.Set(scale); + m_initialScale = Vector3f(scale); Invalidate(invalidation); } inline void Node::SetInitialScale(float scaleX, float scaleY, float scaleZ, Invalidation invalidation) { - m_initialScale.Set(scaleX, scaleY, scaleZ); + m_initialScale = Vector3f(scaleX, scaleY, scaleZ); Invalidate(invalidation); } diff --git a/include/Nazara/Utility/RichTextDrawer.inl b/include/Nazara/Utility/RichTextDrawer.inl index acf112a0f..3b57d593c 100644 --- a/include/Nazara/Utility/RichTextDrawer.inl +++ b/include/Nazara/Utility/RichTextDrawer.inl @@ -170,12 +170,11 @@ namespace Nz inline void RichTextDrawer::ClearGlyphs() const { - m_bounds.MakeZero(); + m_bounds = Rectf::Zero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly) m_lastSeparatorGlyph = InvalidGlyph; m_lines.clear(); m_glyphs.clear(); m_glyphUpdated = true; - m_bounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly) } inline void RichTextDrawer::ConnectFontSlots() diff --git a/src/Nazara/Audio/OpenALDevice.cpp b/src/Nazara/Audio/OpenALDevice.cpp index 421c91c2b..7a85ec0df 100644 --- a/src/Nazara/Audio/OpenALDevice.cpp +++ b/src/Nazara/Audio/OpenALDevice.cpp @@ -132,7 +132,7 @@ namespace Nz m_library.alGetListenerfv(AL_ORIENTATION, orientation); if (up) - up->Set(orientation[3], orientation[4], orientation[5]); + (*up) = Vector3f(orientation[3], orientation[4], orientation[5]); return Vector3f(orientation[0], orientation[1], orientation[2]); } diff --git a/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp b/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp index 616b5232d..05106d32d 100644 --- a/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp +++ b/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp @@ -386,7 +386,7 @@ namespace Nz void BulletNullCollider3D::ComputeInertia(float /*mass*/, Vector3f* inertia) const { - inertia->Set(1.f, 1.f, 1.f); + *inertia = Vector3f::Unit(); } btCollisionShape* BulletNullCollider3D::GetShape() const diff --git a/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp b/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp index 979ce3d61..a994f77fe 100644 --- a/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp +++ b/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp @@ -117,7 +117,7 @@ namespace Nz StackArray nVertices = NazaraStackArray(Vector2f, vertexCount); for (int i = 0; i < vertexCount; ++i) - nVertices[i].Set(float(vertices[i].x), float(vertices[i].y)); + nVertices[i] = Vector2f(float(vertices[i].x), float(vertices[i].y)); callback(nVertices.data(), nVertices.size()); }; @@ -282,7 +282,7 @@ namespace Nz { m_vertices.resize(vertexCount); for (std::size_t i = 0; i < vertexCount; ++i) - m_vertices[i].Set(*vertices++); + m_vertices[i] = Vector2(*vertices++); } Vector2f ChipmunkConvexCollider2D::ComputeCenterOfMass() const diff --git a/src/Nazara/ChipmunkPhysics2D/ChipmunkPhysWorld2D.cpp b/src/Nazara/ChipmunkPhysics2D/ChipmunkPhysWorld2D.cpp index 6b372efc7..8e70a0592 100644 --- a/src/Nazara/ChipmunkPhysics2D/ChipmunkPhysWorld2D.cpp +++ b/src/Nazara/ChipmunkPhysics2D/ChipmunkPhysWorld2D.cpp @@ -45,7 +45,7 @@ namespace Nz StackArray nVertices = NazaraStackArray(Vector2f, vertexCount); for (int i = 0; i < vertexCount; ++i) - nVertices[i].Set(float(vertices[i].x), float(vertices[i].y)); + nVertices[i] = Vector2f(float(vertices[i].x), float(vertices[i].y)); drawOptions->polygonCallback(nVertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); } @@ -184,9 +184,9 @@ namespace Nz if (cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo)) { - result->closestPoint.Set(Vector2(queryInfo.point.x, queryInfo.point.y)); + result->closestPoint = Vector2f(Vector2(queryInfo.point.x, queryInfo.point.y)); result->distance = float(queryInfo.distance); - result->fraction.Set(Vector2(queryInfo.gradient.x, queryInfo.gradient.y)); + result->fraction = Vector2f(Vector2(queryInfo.gradient.x, queryInfo.gradient.y)); result->nearestBody = static_cast(cpShapeGetUserData(queryInfo.shape)); return true; @@ -213,8 +213,8 @@ namespace Nz RaycastHit hitInfo; hitInfo.fraction = float(alpha); - hitInfo.hitNormal.Set(Vector2(normal.x, normal.y)); - hitInfo.hitPos.Set(Vector2(point.x, point.y)); + hitInfo.hitNormal = Vector2f(Vector2(normal.x, normal.y)); + hitInfo.hitPos = Vector2f(Vector2(point.x, point.y)); hitInfo.nearestBody = static_cast(cpShapeGetUserData(shape)); callback(hitInfo); @@ -234,8 +234,8 @@ namespace Nz RaycastHit hitInfo; hitInfo.fraction = float(alpha); - hitInfo.hitNormal.Set(Vector2(normal.x, normal.y)); - hitInfo.hitPos.Set(Vector2(point.x, point.y)); + hitInfo.hitNormal = Vector2f(Vector2(normal.x, normal.y)); + hitInfo.hitPos = Vector2f(Vector2(point.x, point.y)); hitInfo.nearestBody = static_cast(cpShapeGetUserData(shape)); results->emplace_back(std::move(hitInfo)); @@ -260,8 +260,8 @@ namespace Nz if (cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo)) { hitInfo->fraction = float(queryInfo.alpha); - hitInfo->hitNormal.Set(Vector2(queryInfo.normal.x, queryInfo.normal.y)); - hitInfo->hitPos.Set(Vector2(queryInfo.point.x, queryInfo.point.y)); + hitInfo->hitNormal = Vector2f(Vector2(queryInfo.normal.x, queryInfo.normal.y)); + hitInfo->hitPos = Vector2f(Vector2(queryInfo.point.x, queryInfo.point.y)); hitInfo->nearestBody = static_cast(cpShapeGetUserData(queryInfo.shape)); return true; diff --git a/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp b/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp index befb610aa..112c65b6e 100644 --- a/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp +++ b/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp @@ -149,7 +149,7 @@ namespace Nz float resultDistance = float(result.distance); if (resultDistance < minDistance) { - closest.Set(float(result.point.x), float(result.point.y)); + closest = Vector2f(float(result.point.x), float(result.point.y)); minDistance = resultDistance; } } diff --git a/src/Nazara/Core/StdLogger.cpp b/src/Nazara/Core/StdLogger.cpp index af44f2bb1..f545fd1d4 100644 --- a/src/Nazara/Core/StdLogger.cpp +++ b/src/Nazara/Core/StdLogger.cpp @@ -82,7 +82,7 @@ namespace Nz { NAZARA_USE_ANONYMOUS_NAMESPACE - fprintf(stderr, "%s: ", s_errorTypes[type]); + fprintf(stderr, "%s: ", s_errorTypes[type].data()); fwrite(error.data(), sizeof(char), error.size(), stdout); if (line != 0 && file && function) diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 2be1e82d6..2118f4bc9 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -206,7 +206,7 @@ namespace Nz m_vertices[offset].position = glyph.corners[cornerIndex]; m_vertices[offset].position.y = bounds.height - m_vertices[offset].position.y; m_vertices[offset].position *= scale; - m_vertices[offset].uv.Set(uvRect.GetCorner((glyph.flipped) ? flippedCorners[cornerIndex] : normalCorners[cornerIndex])); + m_vertices[offset].uv = uvRect.GetCorner((glyph.flipped) ? flippedCorners[cornerIndex] : normalCorners[cornerIndex]); offset++; } diff --git a/src/Nazara/Graphics/Tilemap.cpp b/src/Nazara/Graphics/Tilemap.cpp index 90ad9a7b9..0ef6c4897 100644 --- a/src/Nazara/Graphics/Tilemap.cpp +++ b/src/Nazara/Graphics/Tilemap.cpp @@ -143,9 +143,9 @@ namespace Nz Vector3f tileLeftBottom; if (m_isometricModeEnabled) - tileLeftBottom.Set(x * m_tileSize.x + m_tileSize.x / 2.f * (y % 2), topCorner - y / 2.f * m_tileSize.y, 0.f); + tileLeftBottom = Vector3f(x * m_tileSize.x + m_tileSize.x / 2.f * (y % 2), topCorner - y / 2.f * m_tileSize.y, 0.f); else - tileLeftBottom.Set(x * m_tileSize.x, topCorner - y * m_tileSize.y, 0.f); + tileLeftBottom = Vector3f(x * m_tileSize.x, topCorner - y * m_tileSize.y, 0.f); for (RectCorner corner : { RectCorner::LeftBottom, RectCorner::RightBottom, RectCorner::LeftTop, RectCorner::RightTop }) { diff --git a/src/Nazara/Utility/AlgorithmUtility.cpp b/src/Nazara/Utility/AlgorithmUtility.cpp index b1cfa2769..8a7249c5a 100644 --- a/src/Nazara/Utility/AlgorithmUtility.cpp +++ b/src/Nazara/Utility/AlgorithmUtility.cpp @@ -120,7 +120,7 @@ namespace Nz triangles.emplace_back(triangle.y, b, a); triangles.emplace_back(triangle.z, c, b); - triangle.Set(a, b, c); // Reuse triangle + triangle = { a, b, c }; // Reuse triangle } } @@ -747,7 +747,7 @@ namespace Nz Vector3f halfLengths = lengths/2.f; // Face +X - transform.MakeTransform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, -90.f, 180.f)); + transform = Matrix4f::Transform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, -90.f, 180.f)); GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += xVertexCount; indices += xIndexCount; @@ -764,7 +764,7 @@ namespace Nz vertexPointers.uvPtr += xVertexCount; // Face +Y - transform.MakeTransform(Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 0.f, 0.f)); + transform = Matrix4f::Transform(Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 0.f, 0.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.z), Vector2f(lengths.x, lengths.z), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += yVertexCount; indices += yIndexCount; @@ -781,7 +781,7 @@ namespace Nz vertexPointers.uvPtr += yVertexCount; // Face +Z - transform.MakeTransform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 0.f, 0.f)); + transform = Matrix4f::Transform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 0.f, 0.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += zVertexCount; indices += zIndexCount; @@ -798,7 +798,7 @@ namespace Nz vertexPointers.uvPtr += zVertexCount; // Face -X - transform.MakeTransform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 90.f, 180.f)); + transform = Matrix4f::Transform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 90.f, 180.f)); GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += xVertexCount; indices += xIndexCount; @@ -815,7 +815,7 @@ namespace Nz vertexPointers.uvPtr += xVertexCount; // Face -Y - transform.MakeTransform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 180.f, 180.f)); + transform = Matrix4f::Transform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 180.f, 180.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.z), Vector2f(lengths.x, lengths.z), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += yVertexCount; indices += yIndexCount; @@ -832,7 +832,7 @@ namespace Nz vertexPointers.uvPtr += yVertexCount; // Face -Z - transform.MakeTransform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 180.f, 0.f)); + transform = Matrix4f::Transform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 180.f, 0.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateTransform(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += zVertexCount; indices += zIndexCount; diff --git a/src/Nazara/Utility/Formats/MD2Loader.cpp b/src/Nazara/Utility/Formats/MD2Loader.cpp index 84ee23a24..cf73635df 100644 --- a/src/Nazara/Utility/Formats/MD2Loader.cpp +++ b/src/Nazara/Utility/Formats/MD2Loader.cpp @@ -197,7 +197,7 @@ namespace Nz Vector2f uv(texC.u, texC.v); uv *= invSkinSize; - uvPtr[triangles[i].vertices[fixedIndex]].Set(parameters.texCoordOffset + uv * parameters.texCoordScale); + uvPtr[triangles[i].vertices[fixedIndex]] = parameters.texCoordOffset + uv * parameters.texCoordScale; } } } diff --git a/src/Nazara/Utility/Formats/MD5AnimLoader.cpp b/src/Nazara/Utility/Formats/MD5AnimLoader.cpp index 85924b2bf..bd430ff3b 100644 --- a/src/Nazara/Utility/Formats/MD5AnimLoader.cpp +++ b/src/Nazara/Utility/Formats/MD5AnimLoader.cpp @@ -83,7 +83,7 @@ namespace Nz sequenceJoint.rotation = rotationQuat * frames[frameIndex].joints[jointIndex].orient; } - sequenceJoint.scale.Set(1.f); + sequenceJoint.scale = Vector3f::Unit(); } } diff --git a/src/Nazara/Utility/GuillotineImageAtlas.cpp b/src/Nazara/Utility/GuillotineImageAtlas.cpp index 653a4651a..609d39477 100644 --- a/src/Nazara/Utility/GuillotineImageAtlas.cpp +++ b/src/Nazara/Utility/GuillotineImageAtlas.cpp @@ -10,7 +10,7 @@ namespace Nz { namespace { - const unsigned int s_guillotineAtlasStartSize = 512; + constexpr Vector2ui s_guillotineAtlasStartSize(512); } GuillotineImageAtlas::GuillotineImageAtlas() : @@ -119,7 +119,7 @@ namespace Nz // Dernière couche, et le glyphe ne rentre pas, peut-on agrandir la taille de l'image ? Vector2ui newSize = layer.binPack.GetSize()*2; if (newSize == Vector2ui::Zero()) - newSize.Set(s_guillotineAtlasStartSize); + newSize = s_guillotineAtlasStartSize; // Limit image atlas size to prevent allocating too much contiguous memory blocks if (newSize.x <= m_maxLayerSize && newSize.y <= m_maxLayerSize && ResizeLayer(layer, newSize)) @@ -133,7 +133,7 @@ namespace Nz else { // On ne peut plus agrandir la dernière couche, il est temps d'en créer une nouvelle - newSize.Set(s_guillotineAtlasStartSize); + newSize = s_guillotineAtlasStartSize; Layer newLayer; if (!ResizeLayer(newLayer, newSize)) diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index b003d8c37..d7ac5357f 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -367,7 +367,7 @@ namespace Nz { EnsureDerivedUpdate(); - m_transformMatrix.MakeTransform(m_derivedPosition, m_derivedRotation, m_derivedScale); + m_transformMatrix = Matrix4f::Transform(m_derivedPosition, m_derivedRotation, m_derivedScale); m_transformMatrixUpdated = true; } } diff --git a/src/Nazara/Utility/RichTextDrawer.cpp b/src/Nazara/Utility/RichTextDrawer.cpp index ebfcbcee8..d39f5d1e6 100644 --- a/src/Nazara/Utility/RichTextDrawer.cpp +++ b/src/Nazara/Utility/RichTextDrawer.cpp @@ -330,7 +330,7 @@ namespace Nz lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition; // Regenerate bounds - m_bounds.MakeZero(); + m_bounds = Rectf::Zero(); for (auto& line : m_lines) m_bounds.ExtendTo(line.bounds); } @@ -362,10 +362,10 @@ namespace Nz float italicTop = italic * glyph.bounds.y; float italicBottom = italic * glyph.bounds.GetMaximum().y; - glyph.corners[0].Set(glyph.bounds.x - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); - glyph.corners[1].Set(glyph.bounds.x + glyph.bounds.width - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); - glyph.corners[2].Set(glyph.bounds.x - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); - glyph.corners[3].Set(glyph.bounds.x + glyph.bounds.width - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); + glyph.corners[0] = Vector2f(glyph.bounds.x - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); + glyph.corners[1] = Vector2f(glyph.bounds.x + glyph.bounds.width - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); + glyph.corners[2] = Vector2f(glyph.bounds.x - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); + glyph.corners[3] = Vector2f(glyph.bounds.x + glyph.bounds.width - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); if (advance) *advance = fontGlyph.advance; @@ -460,10 +460,10 @@ namespace Nz glyph.atlas = nullptr; glyph.bounds = Rectf(m_drawPos.x, m_lines.back().bounds.y, advance, lineHeight); - glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner::LeftTop)); - glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner::RightTop)); - glyph.corners[2].Set(glyph.bounds.GetCorner(RectCorner::LeftBottom)); - glyph.corners[3].Set(glyph.bounds.GetCorner(RectCorner::RightBottom)); + glyph.corners[0] = glyph.bounds.GetCorner(RectCorner::LeftTop); + glyph.corners[1] = glyph.bounds.GetCorner(RectCorner::RightTop); + glyph.corners[2] = glyph.bounds.GetCorner(RectCorner::LeftBottom); + glyph.corners[3] = glyph.bounds.GetCorner(RectCorner::RightBottom); } m_lines.back().bounds.ExtendTo(glyph.bounds); @@ -566,7 +566,7 @@ namespace Nz else m_lines.emplace_back(Line{ Rectf::Zero(), 0 }); - m_drawPos.Set(0, float(firstBlock.characterSize)); + m_drawPos = Vector2f(0.f, SafeCast(firstBlock.characterSize)); for (const Block& block : m_blocks) { diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index 66b7fbc2a..3e80501d5 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -119,7 +119,7 @@ namespace Nz lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition; // Regenerate bounds - m_bounds.MakeZero(); + m_bounds = Rectf::Zero(); for (auto& line : m_lines) m_bounds.ExtendTo(line.bounds); } @@ -127,9 +127,9 @@ namespace Nz void SimpleTextDrawer::ClearGlyphs() const { - m_bounds.MakeZero(); + m_bounds = Rectf::Zero(); m_colorUpdated = true; - m_drawPos.Set(0, float(m_characterSize)); //< Our draw "cursor" + m_drawPos = Vector2f(0.f, SafeCast(m_characterSize)); //< Our draw "cursor" m_lastSeparatorGlyph = InvalidGlyph; m_lines.clear(); m_glyphs.clear(); @@ -168,10 +168,10 @@ namespace Nz float italicTop = italic * glyph.bounds.y; float italicBottom = italic * glyph.bounds.GetMaximum().y; - glyph.corners[0].Set(glyph.bounds.x - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); - glyph.corners[1].Set(glyph.bounds.x + glyph.bounds.width - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); - glyph.corners[2].Set(glyph.bounds.x - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); - glyph.corners[3].Set(glyph.bounds.x + glyph.bounds.width - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); + glyph.corners[0] = Vector2f(glyph.bounds.x - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); + glyph.corners[1] = Vector2f(glyph.bounds.x + glyph.bounds.width - italicTop - outlineThickness, glyph.bounds.y - outlineThickness); + glyph.corners[2] = Vector2f(glyph.bounds.x - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); + glyph.corners[3] = Vector2f(glyph.bounds.x + glyph.bounds.width - italicBottom - outlineThickness, glyph.bounds.y + glyph.bounds.height - outlineThickness); if (advance) *advance = fontGlyph.advance; @@ -249,10 +249,10 @@ namespace Nz glyph.atlas = nullptr; glyph.bounds = Rectf(m_drawPos.x, m_lines.back().bounds.y, advance, GetLineHeight(sizeInfo)); - glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner::LeftTop)); - glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner::RightTop)); - glyph.corners[2].Set(glyph.bounds.GetCorner(RectCorner::LeftBottom)); - glyph.corners[3].Set(glyph.bounds.GetCorner(RectCorner::RightBottom)); + glyph.corners[0] = glyph.bounds.GetCorner(RectCorner::LeftTop); + glyph.corners[1] = glyph.bounds.GetCorner(RectCorner::RightTop); + glyph.corners[2] = glyph.bounds.GetCorner(RectCorner::LeftBottom); + glyph.corners[3] = glyph.bounds.GetCorner(RectCorner::RightBottom); } m_lines.back().bounds.ExtendTo(glyph.bounds); diff --git a/src/Nazara/Utility/SubMesh.cpp b/src/Nazara/Utility/SubMesh.cpp index b88dbfb20..090770728 100644 --- a/src/Nazara/Utility/SubMesh.cpp +++ b/src/Nazara/Utility/SubMesh.cpp @@ -30,7 +30,7 @@ namespace Nz return; for (UInt32 i = 0; i < vertexCount; ++i) - normals[i].MakeZero(); + normals[i] = Vector3f::Zero(); TriangleIterator iterator(*this); do @@ -66,8 +66,8 @@ namespace Nz for (UInt32 i = 0; i < vertexCount; ++i) { - normals[i].MakeZero(); - tangents[i].MakeZero(); + normals[i] = Vector3f::Zero(); + tangents[i] = Vector3f::Zero(); } TriangleIterator iterator(*this); diff --git a/src/Nazara/Widgets/AbstractTextAreaWidget.cpp b/src/Nazara/Widgets/AbstractTextAreaWidget.cpp index 32fd7cb54..60639fb2e 100644 --- a/src/Nazara/Widgets/AbstractTextAreaWidget.cpp +++ b/src/Nazara/Widgets/AbstractTextAreaWidget.cpp @@ -56,8 +56,8 @@ namespace Nz textDrawer.Clear(); UpdateTextSprite(); - m_cursorPositionBegin.MakeZero(); - m_cursorPositionEnd.MakeZero(); + m_cursorPositionBegin = Vector2ui::Zero(); + m_cursorPositionEnd = Vector2ui::Zero(); RefreshCursor(); } diff --git a/src/Nazara/Widgets/SimpleWidgetStyles.cpp b/src/Nazara/Widgets/SimpleWidgetStyles.cpp index df7d8ab3e..e19a13a27 100644 --- a/src/Nazara/Widgets/SimpleWidgetStyles.cpp +++ b/src/Nazara/Widgets/SimpleWidgetStyles.cpp @@ -33,8 +33,8 @@ namespace Nz UInt32 renderMask = GetRenderMask(); SlicedSprite::Corner corner; - corner.size.Set(config.cornerSize); - corner.textureCoords.Set(config.cornerTexCoords); + corner.size = Vector2f(config.cornerSize); + corner.textureCoords = Vector2f(config.cornerTexCoords); m_sprite = std::make_shared(m_material); m_sprite->SetCorners(corner, corner); @@ -122,8 +122,8 @@ namespace Nz UInt32 renderMask = GetRenderMask(); SlicedSprite::Corner corner; - corner.size.Set(config.backgroundCornerSize); - corner.textureCoords.Set(config.backgroundCornerTexCoords); + corner.size = Vector2f(config.backgroundCornerSize); + corner.textureCoords = Vector2f(config.backgroundCornerTexCoords); m_backgroundSprite = std::make_shared(m_material); m_backgroundSprite->SetCorners(corner, corner); @@ -447,8 +447,8 @@ namespace Nz UInt32 renderMask = GetRenderMask(); SlicedSprite::Corner corner; - corner.size.Set(config.cornerSize); - corner.textureCoords.Set(config.cornerTexCoords); + corner.size = Vector2f(config.cornerSize); + corner.textureCoords = Vector2f(config.cornerTexCoords); m_sprite = std::make_shared(m_material); m_sprite->SetCorners(corner, corner); diff --git a/tests/UnitTests/Engine/Math/AngleTest.cpp b/tests/UnitTests/Engine/Math/AngleTest.cpp index b9d3a0738..b246cfd7d 100644 --- a/tests/UnitTests/Engine/Math/AngleTest.cpp +++ b/tests/UnitTests/Engine/Math/AngleTest.cpp @@ -196,7 +196,7 @@ SCENARIO("Angle", "[MATH][ANGLE]") { Nz::RadianAnglef expectedResult(Nz::Pi); - CHECK(angle == expectedResult); + CHECK(angle.ApproxEqual(expectedResult)); } } } @@ -213,7 +213,7 @@ SCENARIO("Angle", "[MATH][ANGLE]") { Nz::RadianAnglef expectedResult(0.f); - CHECK(angle == expectedResult); + CHECK(angle.ApproxEqual(expectedResult)); } } } @@ -230,7 +230,7 @@ SCENARIO("Angle", "[MATH][ANGLE]") { Nz::TurnAnglef expectedResult(0.5f); - CHECK(angle == expectedResult); + CHECK(angle.ApproxEqual(expectedResult)); } } } diff --git a/tests/UnitTests/Engine/Math/BoundingVolumeTest.cpp b/tests/UnitTests/Engine/Math/BoundingVolumeTest.cpp index 0dcb94c66..da7593c21 100644 --- a/tests/UnitTests/Engine/Math/BoundingVolumeTest.cpp +++ b/tests/UnitTests/Engine/Math/BoundingVolumeTest.cpp @@ -65,8 +65,10 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]") THEN("There's no problem") { Nz::BoundingVolume intVolumeCenterAndUnit(Nz::Boxi(Nz::Vector3i::Zero(), Nz::Vector3i::Unit())); + intVolumeCenterAndUnit.Update(Nz::Vector3i::Zero()); + Nz::BoundingVolumef thirdCenterAndUnit(intVolumeCenterAndUnit); - REQUIRE(thirdCenterAndUnit == secondCenterAndUnit); + REQUIRE(thirdCenterAndUnit.ApproxEqual(secondCenterAndUnit)); } } @@ -92,7 +94,10 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]") Nz::BoundingVolumef result(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f)); result.Update(Nz::Matrix4f::Identity()); - REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f) == result); + Nz::BoundingVolumef lerpVolume = Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f); + lerpVolume.Update(Nz::Matrix4f::Identity()); + + REQUIRE(Nz::BoundingVolumef::ApproxEqual(lerpVolume, result)); } } @@ -103,20 +108,23 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]") Nz::BoundingVolumef centerAndUnit(centerAndUnitOBB); - Nz::BoundingVolumef nullBoundingVolume(Nz::Extend::Null); - Nz::BoundingVolumef infiniteBoundingVolume(Nz::Extend::Infinite); + Nz::BoundingVolumef nullBoundingVolume(Nz::Extent::Null); + Nz::BoundingVolumef infiniteBoundingVolume(Nz::Extent::Infinite); THEN("Normal to null should give a smaller volume") { Nz::BoundingVolumef result(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f)); result.Update(Nz::Matrix4f::Identity()); - REQUIRE(Nz::BoundingVolumef::Lerp(centerAndUnit, nullBoundingVolume, 0.5f) == result); + Nz::BoundingVolumef lerpVolume = Nz::BoundingVolumef::Lerp(centerAndUnit, nullBoundingVolume, 0.5f); + lerpVolume.Update(Nz::Matrix4f::Identity()); + + REQUIRE(lerpVolume.ApproxEqual(result)); } THEN("Normal to infinite should give an infinite volume") { - REQUIRE(Nz::BoundingVolumef::Lerp(centerAndUnit, infiniteBoundingVolume, 0.5f) == infiniteBoundingVolume); + REQUIRE(Nz::BoundingVolumef::Lerp(centerAndUnit, infiniteBoundingVolume, 0.5f).ApproxEqual(infiniteBoundingVolume)); } THEN("Null to normal should give a small volume") @@ -124,7 +132,10 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]") Nz::BoundingVolumef result(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f)); result.Update(Nz::Matrix4f::Identity()); - REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f) == result); + Nz::BoundingVolumef lerpVolume = Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f); + lerpVolume.Update(Nz::Matrix4f::Identity()); + + REQUIRE(lerpVolume.ApproxEqual(result)); } THEN("Infinite to normal should give an infinite volume") diff --git a/tests/UnitTests/Engine/Math/EulerAnglesTest.cpp b/tests/UnitTests/Engine/Math/EulerAnglesTest.cpp index c2d91fd87..886eae930 100644 --- a/tests/UnitTests/Engine/Math/EulerAnglesTest.cpp +++ b/tests/UnitTests/Engine/Math/EulerAnglesTest.cpp @@ -58,9 +58,9 @@ SCENARIO("EulerAngles", "[MATH][EULERANGLES]") Nz::Vector3f rotation90Y = euler90Y.ToQuaternion() * Nz::Vector3f::UnitZ(); Nz::Vector3f rotation90R = euler90R.ToQuaternion() * Nz::Vector3f::UnitX(); - CHECK(rotation90P == Nz::Vector3f::UnitZ()); - CHECK(rotation90Y == Nz::Vector3f::UnitX()); - CHECK(rotation90R == Nz::Vector3f::UnitY()); + CHECK(rotation90P.ApproxEqual(Nz::Vector3f::UnitZ())); + CHECK(rotation90Y.ApproxEqual(Nz::Vector3f::UnitX())); + CHECK(rotation90R.ApproxEqual(Nz::Vector3f::UnitY())); } } } @@ -71,9 +71,9 @@ SCENARIO("EulerAngles", "[MATH][EULERANGLES]") { THEN("These results are expected") { - CHECK(Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f) == Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.382683455944f, 0.f, 0.f).ToEulerAngles())); - CHECK(Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f) == Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.f, 0.382683455944f, 0.f).ToEulerAngles())); - CHECK(Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)) == Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.f, 0.f, 0.382683455944f).ToEulerAngles())); + CHECK(Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f).ApproxEqual(Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.382683455944f, 0.f, 0.f).ToEulerAngles()), 0.0001f)); + CHECK(Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f).ApproxEqual(Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.f, 0.382683455944f, 0.f).ToEulerAngles()), 0.0001f)); + CHECK(Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)).ApproxEqual(Nz::EulerAnglesf(Nz::Quaternionf(0.923879504204f, 0.f, 0.f, 0.382683455944f).ToEulerAngles()), 0.0001f)); } } } diff --git a/tests/UnitTests/Engine/Math/Matrix4Test.cpp b/tests/UnitTests/Engine/Math/Matrix4Test.cpp index 157189c97..012d20c06 100644 --- a/tests/UnitTests/Engine/Math/Matrix4Test.cpp +++ b/tests/UnitTests/Engine/Math/Matrix4Test.cpp @@ -103,44 +103,44 @@ SCENARIO("Matrix4", "[MATH][MATRIX4]") { THEN("Rotation around X") { - transformedMatrix.MakeTransform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f).ToQuaternion()); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f).ToQuaternion()); Nz::Matrix4f rotation45X(1.f, 0.f, 0.f, 0.f, 0.f, std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, -std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, 0.f, 0.f, 1.f); - CHECK(transformedMatrix == rotation45X); - transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f).ToQuaternion()); + CHECK(transformedMatrix.ApproxEqual(rotation45X)); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::DegreeAnglef(45.f), 0.f, 0.f).ToQuaternion()); rotation45X.ApplyTranslation(Nz::Vector3f::Unit()); - CHECK(transformedMatrix == rotation45X); + CHECK(transformedMatrix.ApproxEqual(rotation45X)); } THEN("Rotation around Y") { - transformedMatrix.MakeTransform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f).ToQuaternion()); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f).ToQuaternion()); Nz::Matrix4f rotation45Y(std::sqrt(2.f) / 2.f, 0.f, -std::sqrt(2.f) / 2.f, 0.f, 0.f, 1.f, 0.f, 0.f, std::sqrt(2.f) / 2.f, 0.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, 0.f, 0.f, 1.f); - CHECK(transformedMatrix == rotation45Y); - transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f).ToQuaternion()); + CHECK(transformedMatrix.ApproxEqual(rotation45Y)); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(0.f, Nz::DegreeAnglef(45.f), 0.f).ToQuaternion()); rotation45Y.ApplyTranslation(Nz::Vector3f::Unit()); - CHECK(transformedMatrix == rotation45Y); + CHECK(transformedMatrix.ApproxEqual(rotation45Y)); } THEN("Rotation around Z") { - transformedMatrix.MakeTransform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)).ToQuaternion()); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Zero(), Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)).ToQuaternion()); Nz::Matrix4f rotation45Z( std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, -std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f); - CHECK(transformedMatrix == rotation45Z); - transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)).ToQuaternion())); + CHECK(transformedMatrix.ApproxEqual(rotation45Z)); + transformedMatrix = Nz::Matrix4f::Transform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::EulerAnglesf(0.f, 0.f, Nz::DegreeAnglef(45.f)).ToQuaternion())); rotation45Z.ApplyTranslation(Nz::Vector3f::Unit()); - CHECK(transformedMatrix == rotation45Z); + CHECK(transformedMatrix.ApproxEqual(rotation45Z)); } } } @@ -196,7 +196,7 @@ SCENARIO("Matrix4", "[MATH][MATRIX4]") THEN("We should retrieve it") { - REQUIRE(identity.GetRotation() == rotation); + REQUIRE(identity.GetRotation().ApproxEqual(rotation)); } } diff --git a/tests/UnitTests/Engine/Math/OrientedBoxTest.cpp b/tests/UnitTests/Engine/Math/OrientedBoxTest.cpp index be4536888..7a1ebc8be 100644 --- a/tests/UnitTests/Engine/Math/OrientedBoxTest.cpp +++ b/tests/UnitTests/Engine/Math/OrientedBoxTest.cpp @@ -56,7 +56,10 @@ SCENARIO("OrientedBox", "[MATH][ORIENTEDBOX]") Nz::OrientedBoxf result(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f)); result.Update(Nz::Matrix4f::Identity()); - REQUIRE(Nz::OrientedBoxf::Lerp(nullOrientedBox, centerAndUnit, 0.5f) == result); + Nz::OrientedBoxf lerpObb = Nz::OrientedBoxf::Lerp(nullOrientedBox, centerAndUnit, 0.5f); + lerpObb.Update(Nz::Vector3f::Zero()); + + REQUIRE(lerpObb.ApproxEqual(result)); } } } diff --git a/tests/UnitTests/Engine/Math/PlaneTest.cpp b/tests/UnitTests/Engine/Math/PlaneTest.cpp index 92969ca4e..bee01f807 100644 --- a/tests/UnitTests/Engine/Math/PlaneTest.cpp +++ b/tests/UnitTests/Engine/Math/PlaneTest.cpp @@ -16,11 +16,6 @@ SCENARIO("Plane", "[MATH][PLANE]") REQUIRE(firstPlane == secondPlane); } - AND_THEN("We compare with normal(-1, -1, -1), distance -1") - { - REQUIRE(firstPlane == Nz::Planef(-Nz::Vector3f::Unit().Normalize(), -1.f)); - } - AND_THEN("They have the same distance from the same point") { Nz::Vector3f point(-2.f, 3.f, 1.f); diff --git a/tests/UnitTests/Engine/Math/QuaternionTest.cpp b/tests/UnitTests/Engine/Math/QuaternionTest.cpp index 44aca4b1d..45f50c9b9 100644 --- a/tests/UnitTests/Engine/Math/QuaternionTest.cpp +++ b/tests/UnitTests/Engine/Math/QuaternionTest.cpp @@ -13,7 +13,7 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") { THEN("They are the same and the proprieties of quaternions are respected") { - REQUIRE(firstQuaternion == secondQuaternion); + REQUIRE(firstQuaternion.ApproxEqual(secondQuaternion)); REQUIRE(firstQuaternion.ComputeW() == secondQuaternion.Normalize()); REQUIRE(firstQuaternion.Conjugate() == secondQuaternion.Inverse()); REQUIRE(firstQuaternion.DotProduct(secondQuaternion) == Catch::Approx(1.f)); @@ -24,13 +24,13 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") { THEN("Multiply with a vectorX is identity") { - REQUIRE((firstQuaternion * Nz::Vector3f::UnitX()) == Nz::Vector3f::UnitX()); + REQUIRE((firstQuaternion * Nz::Vector3f::UnitX()).ApproxEqual(Nz::Vector3f::UnitX())); } AND_THEN("Multiply with a vectorY or Z is opposite") { - REQUIRE((firstQuaternion * Nz::Vector3f::UnitY()) == -Nz::Vector3f::UnitY()); - REQUIRE((firstQuaternion * Nz::Vector3f::UnitZ()) == -Nz::Vector3f::UnitZ()); + REQUIRE((firstQuaternion * Nz::Vector3f::UnitY()).ApproxEqual(-Nz::Vector3f::UnitY())); + REQUIRE((firstQuaternion * Nz::Vector3f::UnitZ()).ApproxEqual(-Nz::Vector3f::UnitZ())); } } @@ -108,7 +108,7 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") { THEN("These results are expected") { - REQUIRE(x20 == Nz::Quaternionf(Nz::DegreeAnglef(20.f), Nz::Vector3f::UnitX())); + REQUIRE(x20.ApproxEqual(Nz::Quaternionf(Nz::DegreeAnglef(20.f), Nz::Vector3f::UnitX()))); REQUIRE(x30a == x30b); } } @@ -136,7 +136,7 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") Nz::Quaternionf tmp(1.f, 1.f, 0.f, 0.f); tmp.Normalize(); - REQUIRE(tmp == tmp.ToEulerAngles().ToQuaternion()); + REQUIRE(tmp.ApproxEqual(tmp.ToEulerAngles().ToQuaternion())); } } @@ -154,8 +154,8 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") REQUIRE(slerpx10x30b.x == Catch::Approx(x20.x)); REQUIRE(slerpx10x30b.y == Catch::Approx(x20.y)); REQUIRE(slerpx10x30b.z == Catch::Approx(x20.z)); - REQUIRE(Nz::Quaternionf::Slerp(x10, x30a, 0.f) == x10); - REQUIRE(Nz::Quaternionf::Slerp(x10, x30a, 1.f) == x30a); + REQUIRE(Nz::Quaternionf::Slerp(x10, x30a, 0.f).ApproxEqual(x10)); + REQUIRE(Nz::Quaternionf::Slerp(x10, x30a, 1.f).ApproxEqual(x30a)); } AND_THEN("The half of 45 is 22.5") @@ -178,21 +178,21 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") { Nz::Quaternionf rotationBetweenXY = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitY()); Nz::Quaternionf rotation90Z(Nz::DegreeAnglef(90.f), Nz::Vector3f::UnitZ()); - REQUIRE(rotation90Z == rotationBetweenXY); + REQUIRE(rotation90Z.ApproxEqual(rotationBetweenXY)); } THEN("The rotation in right-handed is 90 degree on y") { Nz::Quaternionf rotationBetweenXZ = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitZ()); Nz::Quaternionf rotation90Y(Nz::DegreeAnglef(-90.f), Nz::Vector3f::UnitY()); - REQUIRE(rotation90Y == rotationBetweenXZ); + REQUIRE(rotation90Y.ApproxEqual(rotationBetweenXZ)); } THEN("The rotation in right-handed is 90 degree on x") { Nz::Quaternionf rotationBetweenYZ = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitY(), Nz::Vector3f::UnitZ()); Nz::Quaternionf rotation90X(Nz::DegreeAnglef(90.f), Nz::Vector3f::UnitX()); - REQUIRE(rotation90X == rotationBetweenYZ); + REQUIRE(rotation90X.ApproxEqual(rotationBetweenYZ)); } THEN("The rotation in right-handed is 90 degree on y with non-unit vectors") @@ -200,7 +200,7 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") Nz::Vector3f origin(1.f, 0.f, 1.f); Nz::Vector3f extremity(-1.f, 0.f, 1.f); Nz::Quaternionf rotation = Nz::Quaternionf::RotationBetween(origin, extremity); - REQUIRE(rotation * origin == extremity); + REQUIRE((rotation * origin).ApproxEqual(extremity)); } } } @@ -229,9 +229,9 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]") CHECK(Nz::NumberEquals(rotation90Y.ToEulerAngles().yaw.ToDegrees(), 90.f, 0.1f)); CHECK(Nz::NumberEquals(rotation90Z.ToEulerAngles().roll.ToDegrees(), 90.f, 0.1f)); - CHECK(rotation180X == Nz::EulerAnglesf(180.f, 0.f, 0.f)); - CHECK(rotation180Y == Nz::EulerAnglesf(0.f, 180.f, 0.f)); - CHECK(rotation180Z == Nz::EulerAnglesf(0.f, 0.f, 180.f)); + CHECK(rotation180X.ApproxEqual(Nz::EulerAnglesf(180.f, 0.f, 0.f))); + CHECK(rotation180Y.ApproxEqual(Nz::EulerAnglesf(0.f, 180.f, 0.f))); + CHECK(rotation180Z.ApproxEqual(Nz::EulerAnglesf(0.f, 0.f, 180.f))); CHECK(Nz::NumberEquals(rotation270X.ToEulerAngles().pitch.ToDegrees(), -90.f, 0.1f)); CHECK(Nz::NumberEquals(rotation270Y.ToEulerAngles().yaw.ToDegrees(), -90.f, 0.1f)); diff --git a/tests/UnitTests/Engine/Math/RayTest.cpp b/tests/UnitTests/Engine/Math/RayTest.cpp index 1ea9cdf45..6f8a2ae08 100644 --- a/tests/UnitTests/Engine/Math/RayTest.cpp +++ b/tests/UnitTests/Engine/Math/RayTest.cpp @@ -67,12 +67,12 @@ SCENARIO("Ray", "[MATH][RAY]") THEN("For the bounding volume collision's") { - Nz::BoundingVolumef nullVolume(Nz::Extend::Null); + Nz::BoundingVolumef nullVolume(Nz::Extent::Null); CHECK(!ray.Intersect(nullVolume)); float tmpClosest = -1.f; float tmpFurthest = -1.f; - Nz::BoundingVolumef infiniteVolume(Nz::Extend::Infinite); + Nz::BoundingVolumef infiniteVolume(Nz::Extent::Infinite); CHECK(ray.Intersect(infiniteVolume, &tmpClosest, &tmpFurthest)); CHECK(tmpClosest == Catch::Approx(0.f)); CHECK(tmpFurthest == std::numeric_limits::infinity()); diff --git a/tests/UnitTests/Engine/Math/Vector2Test.cpp b/tests/UnitTests/Engine/Math/Vector2Test.cpp index 881016c6b..ae66cc972 100644 --- a/tests/UnitTests/Engine/Math/Vector2Test.cpp +++ b/tests/UnitTests/Engine/Math/Vector2Test.cpp @@ -28,9 +28,9 @@ SCENARIO("Vector2", "[MATH][VECTOR2]") { REQUIRE(firstUnit.AbsDotProduct(tmp) == Catch::Approx(2.f)); REQUIRE(firstUnit.DotProduct(tmp) == Catch::Approx(0.f)); - REQUIRE(firstUnit.AngleBetween(tmp) == Nz::DegreeAnglef(90.f)); + REQUIRE(firstUnit.AngleBetween(tmp).ApproxEqual(Nz::DegreeAnglef(90.f))); Nz::Vector2f negativeUnitX = -Nz::Vector2f::UnitX(); - REQUIRE(negativeUnitX.AngleBetween(negativeUnitX + Nz::Vector2f(0, 0.0000001f)) == Nz::DegreeAnglef(360.f)); + REQUIRE(negativeUnitX.AngleBetween(negativeUnitX + Nz::Vector2f(0, 0.0000001f)).ApproxEqual(Nz::DegreeAnglef(360.f))); } } diff --git a/tests/UnitTests/Engine/Math/Vector3Test.cpp b/tests/UnitTests/Engine/Math/Vector3Test.cpp index 5952fba1d..0fb4490e5 100644 --- a/tests/UnitTests/Engine/Math/Vector3Test.cpp +++ b/tests/UnitTests/Engine/Math/Vector3Test.cpp @@ -27,8 +27,8 @@ SCENARIO("Vector3", "[MATH][VECTOR3]") { REQUIRE(firstUnit.AbsDotProduct(tmp) == Catch::Approx(2.f)); REQUIRE(firstUnit.DotProduct(tmp) == Catch::Approx(0.f)); - REQUIRE(firstUnit.AngleBetween(tmp) == Nz::DegreeAnglef(90.f)); - REQUIRE(firstUnit.AngleBetween(-firstUnit) == Nz::DegreeAnglef(180.f)); + REQUIRE(firstUnit.AngleBetween(tmp).ApproxEqual(Nz::DegreeAnglef(90.f))); + REQUIRE(firstUnit.AngleBetween(-firstUnit).ApproxEqual(Nz::DegreeAnglef(180.f))); } } @@ -61,7 +61,7 @@ SCENARIO("Vector3", "[MATH][VECTOR3]") THEN("For normal cases should be normal") { Nz::Vector3f normalized = firstUnit.GetNormal(&ratio); - REQUIRE(normalized == (Nz::Vector3f::Unit() / std::sqrt(3.f))); + REQUIRE(normalized.ApproxEqual(Nz::Vector3f::Unit() / std::sqrt(3.f))); REQUIRE(ratio == Catch::Approx(std::sqrt(3.f))); } diff --git a/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp b/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp index d533c782b..2c4a6f7cf 100644 --- a/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp +++ b/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp @@ -181,15 +181,15 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") { CHECK(body.GetAngularVelocity() == angularSpeed); CHECK(body.GetRotation() == angularSpeed); - CHECK(body.GetAABB().ApproxEquals(Nz::Rectf(-6.f, 3.f, 2.f, 1.f), 0.00001f)); + CHECK(body.GetAABB().ApproxEqual(Nz::Rectf(-6.f, 3.f, 2.f, 1.f), 0.00001f)); world.Step(Nz::Time::Second()); CHECK(body.GetRotation() == 2.f * angularSpeed); - CHECK(body.GetAABB().ApproxEquals(Nz::Rectf(-4.f, -6.f, 1.f, 2.f), 0.00001f)); + CHECK(body.GetAABB().ApproxEqual(Nz::Rectf(-4.f, -6.f, 1.f, 2.f), 0.00001f)); world.Step(Nz::Time::Second()); CHECK(body.GetRotation() == 3.f * angularSpeed); - CHECK(body.GetAABB().ApproxEquals(Nz::Rectf(4.f, -4.f, 2.f, 1.f), 0.00001f)); + CHECK(body.GetAABB().ApproxEqual(Nz::Rectf(4.f, -4.f, 2.f, 1.f), 0.00001f)); world.Step(Nz::Time::Second()); CHECK(body.GetRotation() == 4.f * angularSpeed);