Improve math module (#396)

* Improve math module

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

View File

@ -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<T, T> GetSinCos() const;
T GetTan() const;
constexpr Angle& MakeZero();
constexpr Angle& Normalize();
constexpr Angle& Set(Angle ang);
template<typename U> constexpr Angle& Set(const Angle<Unit, U>& ang);
template<AngleUnit ToUnit> T To() const;
template<AngleUnit ToUnit> Angle<ToUnit, T> 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<AngleUnit FromUnit> static constexpr Angle From(T value);
static constexpr Angle FromDegrees(T degrees);
static constexpr Angle FromRadians(T radians);

View File

@ -189,6 +189,13 @@ namespace Nz
{
}
template<AngleUnit Unit, typename T>
template<typename U>
constexpr Angle<Unit, T>::Angle(const Angle<Unit, U>& angle) :
value(static_cast<T>(angle.value))
{
}
/*!
* \brief Constructs an Angle object from a angle in a specific unit, converting if required
*
@ -201,6 +208,18 @@ namespace Nz
{
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& angle) const
{
return ApproxEqual(angle, Detail::AngleUtils<Unit>::template GetEpsilon<T>());
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::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<AngleUnit Unit, typename T>
constexpr Angle<Unit, T>& Angle<Unit, T>::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<AngleUnit Unit, typename T>
constexpr Angle<Unit, T>& Angle<Unit, T>::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<AngleUnit Unit, typename T>
template<typename U>
constexpr Angle<Unit, T>& Angle<Unit, T>::Set(const Angle<Unit, U>& ang)
{
value = static_cast<T>(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<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator==(Angle other) const
{
return NumberEquals(value, other.value, Detail::AngleUtils<Unit>::template GetEpsilon<T>());
return value == other.value;
}
/*!
@ -598,7 +580,43 @@ namespace Nz
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator!=(Angle other) const
{
return !NumberEquals(value, other.value, Detail::AngleUtils<Unit>::template GetEpsilon<T>());
return value != other.value;
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator<(Angle other) const
{
return value < other.value;
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator<=(Angle other) const
{
return value <= other.value;
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator>(Angle other) const
{
return value > other.value;
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::operator>=(Angle other) const
{
return value >= other.value;
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& lhs, const Angle& rhs)
{
return lhs.ApproxEqual(rhs);
}
template<AngleUnit Unit, typename T>
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& lhs, const Angle& rhs, T maxDifference)
{
return lhs.ApproxEqual(rhs, maxDifference);
}
/*!

View File

@ -22,40 +22,46 @@ namespace Nz
class BoundingVolume
{
public:
BoundingVolume();
BoundingVolume(Extend Extend);
BoundingVolume(const Box<T>& box);
BoundingVolume(const OrientedBox<T>& orientedBox);
template<typename U> explicit BoundingVolume(const BoundingVolume<U>& volume);
BoundingVolume(const BoundingVolume& volume) = default;
constexpr BoundingVolume();
constexpr BoundingVolume(Extent Extend);
constexpr BoundingVolume(const Box<T>& box);
constexpr BoundingVolume(const OrientedBox<T>& orientedBox);
template<typename U> constexpr explicit BoundingVolume(const BoundingVolume<U>& 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<T>::epsilon()) const;
bool Intersect(const Box<T>& box) const;
constexpr BoundingVolume& ExtendTo(const BoundingVolume& volume);
bool IsFinite() const;
bool IsInfinite() const;
bool IsNull() const;
constexpr bool Intersect(const Box<T>& box) const;
constexpr bool IsFinite() const;
constexpr bool IsInfinite() const;
constexpr bool IsNull() const;
std::string ToString() const;
void Update(const Matrix4<T>& transformMatrix);
void Update(const Vector3<T>& translation);
constexpr void Update(const Matrix4<T>& transformMatrix);
constexpr void Update(const Vector3<T>& 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<T>::epsilon());
static constexpr BoundingVolume Infinite();
static constexpr BoundingVolume Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation);
static constexpr BoundingVolume Null();
Extent extent;
Box<T> aabb;
OrientedBox<T> obb;
};

View File

@ -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<typename T>
BoundingVolume<T>::BoundingVolume() :
extend(Extend::Null)
constexpr BoundingVolume<T>::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<typename T>
BoundingVolume<T>::BoundingVolume(Extend Extend) :
extend(Extend)
constexpr BoundingVolume<T>::BoundingVolume(Extent Extend) :
extent(Extend)
{
}
@ -53,10 +51,9 @@ namespace Nz
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(const Box<T>& box) :
extend(Extend::Finite),
constexpr BoundingVolume<T>::BoundingVolume(const Box<T>& box) :
extent(Extent::Finite),
obb(box)
{
}
@ -68,10 +65,9 @@ namespace Nz
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(const OrientedBox<T>& orientedBox) :
extend(Extend::Finite),
constexpr BoundingVolume<T>::BoundingVolume(const OrientedBox<T>& orientedBox) :
extent(Extent::Finite),
obb(orientedBox)
{
}
@ -81,16 +77,27 @@ namespace Nz
*
* \param volume BoundingVolume of type U to convert to type T
*/
template<typename T>
template<typename U>
BoundingVolume<T>::BoundingVolume(const BoundingVolume<U>& volume) :
extend(volume.extend),
constexpr BoundingVolume<T>::BoundingVolume(const BoundingVolume<U>& volume) :
extent(volume.extent),
aabb(volume.aabb),
obb(volume.obb)
{
}
template<typename T>
constexpr bool BoundingVolume<T>::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<typename T>
BoundingVolume<T>& BoundingVolume<T>::ExtendTo(const BoundingVolume& volume)
constexpr BoundingVolume<T>& BoundingVolume<T>::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<typename T>
bool BoundingVolume<T>::Intersect(const Box<T>& box) const
constexpr bool BoundingVolume<T>::Intersect(const Box<T>& 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<typename T>
bool BoundingVolume<T>::IsFinite() const
constexpr bool BoundingVolume<T>::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<typename T>
bool BoundingVolume<T>::IsInfinite() const
constexpr bool BoundingVolume<T>::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<typename T>
bool BoundingVolume<T>::IsNull() const
constexpr bool BoundingVolume<T>::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<typename T>
std::string BoundingVolume<T>::ToString() const
{
@ -207,13 +213,12 @@ namespace Nz
*
* \param transformMatrix Matrix4 which represents the transformation to apply
*/
template<typename T>
void BoundingVolume<T>::Update(const Matrix4<T>& transformMatrix)
constexpr void BoundingVolume<T>::Update(const Matrix4<T>& transformMatrix)
{
obb.Update(transformMatrix);
aabb = Boxf::FromExtends(obb(0), obb(1));
aabb = Box<T>::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<typename T>
void BoundingVolume<T>::Update(const Vector3<T>& translation)
constexpr void BoundingVolume<T>::Update(const Vector3<T>& translation)
{
obb.Update(translation);
aabb = Boxf::FromExtends(obb(0), obb(1));
aabb = Box<T>::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<typename T>
BoundingVolume<T> BoundingVolume<T>::operator*(T scalar) const
constexpr BoundingVolume<T> BoundingVolume<T>::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<typename T>
BoundingVolume<T>& BoundingVolume<T>::operator*=(T scalar)
constexpr BoundingVolume<T>& BoundingVolume<T>::operator*=(T scalar)
{
obb *= scalar;
@ -271,17 +273,22 @@ namespace Nz
*
* \param volume Other bounding volume to compare with
*/
template<typename T>
bool BoundingVolume<T>::operator==(const BoundingVolume& volume) const
constexpr bool BoundingVolume<T>::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<typename T>
bool BoundingVolume<T>::operator!=(const BoundingVolume& volume) const
constexpr bool BoundingVolume<T>::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<typename T>
BoundingVolume<T> BoundingVolume<T>::Infinite()
constexpr bool BoundingVolume<T>::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<typename T>
constexpr BoundingVolume<T> BoundingVolume<T>::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<typename T>
BoundingVolume<T> BoundingVolume<T>::Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation)
constexpr BoundingVolume<T> BoundingVolume<T>::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<T>::Lerp(from.obb, to.obb, interpolation) };
case Extend::Infinite:
case Extent::Infinite:
return Infinite();
case Extend::Null:
case Extent::Null:
{
Box<T> 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<T> 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<typename T>
BoundingVolume<T> BoundingVolume<T>::Null()
constexpr BoundingVolume<T> BoundingVolume<T>::Null()
{
BoundingVolume volume;
volume.extend = Extend::Null;
return volume;
return BoundingVolume(Extent::Null);
}
/*!
@ -424,7 +423,7 @@ namespace Nz
template<typename T>
bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume, TypeTag<BoundingVolume<T>>)
{
if (!Serialize(context, static_cast<UInt8>(boundingVolume.extend)))
if (!Serialize(context, static_cast<UInt8>(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>(extend);
boundingVolume->extent = static_cast<Extent>(extend);
if (!Unserialize(context, &boundingVolume->aabb))
return false;
@ -476,17 +475,17 @@ namespace Nz
template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::BoundingVolume<T>& 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;
}

View File

@ -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<T>& rect);
explicit Box(const Vector3<T>& lengths);
explicit Box(const Vector3<T>& pos, const Vector3<T>& lengths);
template<typename U> explicit Box(const Box<U>& 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<T>& rect);
constexpr explicit Box(const Vector3<T>& lengths);
constexpr explicit Box(const Vector3<T>& pos, const Vector3<T>& lengths);
template<typename U> constexpr explicit Box(const Box<U>& 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<T>::epsilon()) const;
bool Contains(T X, T Y, T Z) const;
bool Contains(const Box& box) const;
bool Contains(const Vector3<T>& point) const;
constexpr bool Contains(T X, T Y, T Z) const;
constexpr bool Contains(const Box& box) const;
constexpr bool Contains(const Vector3<T>& point) const;
Box& ExtendTo(T X, T Y, T Z);
Box& ExtendTo(const Box& box);
Box& ExtendTo(const Vector3<T>& point);
constexpr Box& ExtendTo(T X, T Y, T Z);
constexpr Box& ExtendTo(const Box& box);
constexpr Box& ExtendTo(const Vector3<T>& point);
Sphere<T> GetBoundingSphere() const;
Vector3<T> GetCenter() const;
Vector3<T> GetCorner(BoxCorner corner) const;
Vector3<T> GetLengths() const;
Vector3<T> GetMaximum() const;
Vector3<T> GetMinimum() const;
Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
Vector3<T> GetPosition() const;
Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
T GetRadius() const;
Sphere<T> GetSquaredBoundingSphere() const;
T GetSquaredRadius() const;
constexpr Sphere<T> GetBoundingSphere() const;
constexpr Vector3<T> GetCenter() const;
constexpr Vector3<T> GetCorner(BoxCorner corner) const;
constexpr Vector3<T> GetLengths() const;
constexpr Vector3<T> GetMaximum() const;
constexpr Vector3<T> GetMinimum() const;
constexpr Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
constexpr Vector3<T> GetPosition() const;
constexpr Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
constexpr T GetRadius() const;
constexpr Sphere<T> 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<T>& vec);
constexpr Box& Scale(T scalar);
constexpr Box& Scale(const Vector3<T>& vec);
Box& ScaleAroundCenter(T scalar);
Box& ScaleAroundCenter(const Vector3<T>& vec);
constexpr Box& ScaleAroundCenter(T scalar);
constexpr Box& ScaleAroundCenter(const Vector3<T>& vec);
std::string ToString() const;
Box& Transform(const Matrix4<T>& matrix, bool applyTranslation = true);
Box& Translate(const Vector3<T>& translation);
constexpr Box& Translate(const Vector3<T>& 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<T>& vec1, const Vector3<T>& 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<T>::epsilon());
static constexpr Box FromExtends(const Vector3<T>& vec1, const Vector3<T>& 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;
};

View File

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

View File

@ -34,7 +34,7 @@ namespace Nz
constexpr std::size_t BoxCornerCount = UnderlyingCast(BoxCorner::Max) + 1;
enum class Extend
enum class Extent
{
Finite,
Infinite,

View File

@ -20,46 +20,41 @@ namespace Nz
class EulerAngles
{
public:
EulerAngles() = default;
EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R);
EulerAngles(const DegreeAngle<T> angles[3]);
template<AngleUnit Unit> EulerAngles(const Angle<Unit, T>& angle);
//EulerAngles(const Matrix3<T>& mat);
EulerAngles(const Quaternion<T>& quat);
template<typename U> explicit EulerAngles(const EulerAngles<U>& angles);
EulerAngles(const EulerAngles& angles) = default;
constexpr EulerAngles() = default;
constexpr EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R);
constexpr EulerAngles(const DegreeAngle<T> angles[3]);
template<AngleUnit Unit> constexpr EulerAngles(const Angle<Unit, T>& angle);
constexpr EulerAngles(const Quaternion<T>& quat);
template<typename U> constexpr explicit EulerAngles(const EulerAngles<U>& 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<T>::epsilon()) const;
EulerAngles& Normalize();
constexpr EulerAngles& Normalize();
EulerAngles& Set(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R);
EulerAngles& Set(const DegreeAngle<T> angles[3]);
template<AngleUnit Unit> EulerAngles& Set(const Angle<Unit, T>& angles);
//EulerAngles& Set(const Matrix3<T>& mat);
EulerAngles& Set(const Quaternion<T>& quat);
template<typename U> EulerAngles& Set(const EulerAngles<U>& angles);
//Matrix3<T> ToRotationMatrix() const;
Quaternion<T> 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<T>::epsilon());
static constexpr EulerAngles Zero();
DegreeAngle<T> pitch, yaw, roll;
};

View File

@ -29,11 +29,12 @@ namespace Nz
* \param Y Yaw component = Y axis
* \param R Roll component = Z axis
*/
template<typename T>
EulerAngles<T>::EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R)
constexpr EulerAngles<T>::EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> 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<typename T>
EulerAngles<T>::EulerAngles(const DegreeAngle<T> angles[3])
constexpr EulerAngles<T>::EulerAngles(const DegreeAngle<T> angles[3]) :
EulerAngles(angles[0], angles[1], angles[2])
{
Set(angles);
}
/*!
@ -55,9 +55,9 @@ namespace Nz
*/
template<typename T>
template<AngleUnit Unit>
EulerAngles<T>::EulerAngles(const Angle<Unit, T>& angle)
constexpr EulerAngles<T>::EulerAngles(const Angle<Unit, T>& angle) :
EulerAngles(angle.ToEulerAngles())
{
Set(angle);
}
/*!
@ -66,9 +66,9 @@ namespace Nz
* \param quat Quaternion representing a rotation of space
*/
template<typename T>
EulerAngles<T>::EulerAngles(const Quaternion<T>& quat)
constexpr EulerAngles<T>::EulerAngles(const Quaternion<T>& quat) :
EulerAngles(quat.ToEulerAngles())
{
Set(quat);
}
/*!
@ -79,21 +79,17 @@ namespace Nz
template<typename T>
template<typename U>
EulerAngles<T>::EulerAngles(const EulerAngles<U>& angles)
constexpr EulerAngles<T>::EulerAngles(const EulerAngles<U>& angles) :
pitch(DegreeAngle<T>(angles.pitch)),
yaw(DegreeAngle<T>(angles.yaw)),
roll(DegreeAngle<T>(angles.roll))
{
Set(angles);
}
/*!
* \brief Makes the euler angle (0, 0, 0)
*
* \see Zero
*/
template<typename T>
void EulerAngles<T>::MakeZero()
constexpr bool EulerAngles<T>::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<typename T>
EulerAngles<T>& EulerAngles<T>::Normalize()
constexpr EulerAngles<T>& EulerAngles<T>::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<typename T>
EulerAngles<T>& EulerAngles<T>::Set(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> 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<typename T>
EulerAngles<T>& EulerAngles<T>::Set(const DegreeAngle<T> 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<typename T>
template<AngleUnit Unit>
EulerAngles<T>& EulerAngles<T>::Set(const Angle<Unit, T>& 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<typename T>
EulerAngles<T>& EulerAngles<T>::Set(const Quaternion<T>& 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<typename T>
template<typename U>
EulerAngles<T>& EulerAngles<T>::Set(const EulerAngles<U>& 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<typename T>
Quaternion<T> EulerAngles<T>::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<typename T>
std::string EulerAngles<T>::ToString() const
{
@ -239,9 +149,8 @@ namespace Nz
*
* \param angles The other euler angle to add components with
*/
template<typename T>
EulerAngles<T> EulerAngles<T>::operator+(const EulerAngles& angles) const
constexpr EulerAngles<T> EulerAngles<T>::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<typename T>
EulerAngles<T> EulerAngles<T>::operator-(const EulerAngles& angles) const
constexpr EulerAngles<T> EulerAngles<T>::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<typename T>
EulerAngles<T>& EulerAngles<T>::operator+=(const EulerAngles& angles)
constexpr EulerAngles<T>& EulerAngles<T>::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<typename T>
EulerAngles<T>& EulerAngles<T>::operator-=(const EulerAngles& angles)
constexpr EulerAngles<T>& EulerAngles<T>::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<typename T>
bool EulerAngles<T>::operator==(const EulerAngles& angles) const
constexpr bool EulerAngles<T>::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<typename T>
bool EulerAngles<T>::operator!=(const EulerAngles& angles) const
constexpr bool EulerAngles<T>::operator!=(const EulerAngles& angles) const
{
return !operator==(angles);
}
template<typename T>
constexpr bool EulerAngles<T>::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<typename T>
constexpr bool EulerAngles<T>::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<typename T>
constexpr bool EulerAngles<T>::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<typename T>
constexpr bool EulerAngles<T>::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<typename T>
constexpr bool EulerAngles<T>::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<typename T>
EulerAngles<T> EulerAngles<T>::Zero()
constexpr EulerAngles<T> EulerAngles<T>::Zero()
{
EulerAngles angles;
angles.MakeZero();
return angles;
return EulerAngles(0, 0, 0);
}
/*!

View File

@ -27,41 +27,46 @@ namespace Nz
class Frustum
{
public:
Frustum() = default;
explicit Frustum(const EnumArray<FrustumPlane, Plane<T>>& planes);
template<typename U> explicit Frustum(const Frustum<U>& frustum);
Frustum(const Frustum& frustum) = default;
constexpr Frustum() = default;
constexpr explicit Frustum(const EnumArray<FrustumPlane, Plane<T>>& planes);
template<typename U> constexpr explicit Frustum(const Frustum<U>& frustum);
constexpr Frustum(const Frustum&) = default;
constexpr Frustum(Frustum&&) = default;
~Frustum() = default;
Vector3<T> ComputeCorner(BoxCorner corner) const;
constexpr bool ApproxEqual(const Frustum& frustum, T maxDifference = std::numeric_limits<T>::epsilon()) const;
bool Contains(const BoundingVolume<T>& volume) const;
bool Contains(const Box<T>& box) const;
bool Contains(const OrientedBox<T>& orientedBox) const;
bool Contains(const Sphere<T>& sphere) const;
bool Contains(const Vector3<T>& point) const;
bool Contains(const Vector3<T>* points, std::size_t pointCount) const;
constexpr Vector3<T> ComputeCorner(BoxCorner corner) const;
const Plane<T>& GetPlane(FrustumPlane plane) const;
constexpr bool Contains(const BoundingVolume<T>& volume) const;
constexpr bool Contains(const Box<T>& box) const;
constexpr bool Contains(const OrientedBox<T>& orientedBox) const;
constexpr bool Contains(const Sphere<T>& sphere) const;
constexpr bool Contains(const Vector3<T>& point) const;
constexpr bool Contains(const Vector3<T>* points, std::size_t pointCount) const;
IntersectionSide Intersect(const BoundingVolume<T>& volume) const;
IntersectionSide Intersect(const Box<T>& box) const;
IntersectionSide Intersect(const OrientedBox<T>& orientedBox) const;
IntersectionSide Intersect(const Sphere<T>& sphere) const;
IntersectionSide Intersect(const Vector3<T>* points, std::size_t pointCount) const;
constexpr const Plane<T>& GetPlane(FrustumPlane plane) const;
constexpr IntersectionSide Intersect(const BoundingVolume<T>& volume) const;
constexpr IntersectionSide Intersect(const Box<T>& box) const;
constexpr IntersectionSide Intersect(const OrientedBox<T>& orientedBox) const;
constexpr IntersectionSide Intersect(const Sphere<T>& sphere) const;
constexpr IntersectionSide Intersect(const Vector3<T>* 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<T>::epsilon());
static Frustum Build(RadianAngle<T> angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());
static Frustum Extract(const Matrix4<T>& viewProjMatrix);
template<typename U>
friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum, TypeTag<Frustum<U>>);
template<typename U>
friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum, TypeTag<Frustum<U>>);
template<typename U> friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum, TypeTag<Frustum<U>>);
template<typename U> friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum, TypeTag<Frustum<U>>);
private:
EnumArray<FrustumPlane, Plane<T>> m_planes;

View File

@ -31,7 +31,7 @@ namespace Nz
* \param planes Frustum of type U to convert to type T
*/
template<typename T>
Frustum<T>::Frustum(const EnumArray<FrustumPlane, Plane<T>>& planes) :
constexpr Frustum<T>::Frustum(const EnumArray<FrustumPlane, Plane<T>>& planes) :
m_planes(planes)
{
}
@ -43,12 +43,24 @@ namespace Nz
*/
template<typename T>
template<typename U>
Frustum<T>::Frustum(const Frustum<U>& frustum)
constexpr Frustum<T>::Frustum(const Frustum<U>& frustum)
{
for (auto&& [planeEnum, plane] : m_planes)
for (auto&& [planeEnum, plane] : m_planes.iter_kv())
plane = Frustum(frustum.GetPlane(planeEnum));
}
template<typename T>
constexpr bool Frustum<T>::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<typename T>
Vector3<T> Frustum<T>::ComputeCorner(BoxCorner corner) const
constexpr Vector3<T> Frustum<T>::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<typename T>
bool Frustum<T>::Contains(const BoundingVolume<T>& volume) const
constexpr bool Frustum<T>::Contains(const BoundingVolume<T>& 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<typename T>
bool Frustum<T>::Contains(const Box<T>& box) const
constexpr bool Frustum<T>::Contains(const Box<T>& 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<typename T>
bool Frustum<T>::Contains(const OrientedBox<T>& orientedbox) const
constexpr bool Frustum<T>::Contains(const OrientedBox<T>& orientedbox) const
{
return Contains(orientedbox.GetCorners(), 8);
}
@ -158,9 +169,8 @@ namespace Nz
*
* \param sphere Sphere to check
*/
template<typename T>
bool Frustum<T>::Contains(const Sphere<T>& sphere) const
constexpr bool Frustum<T>::Contains(const Sphere<T>& 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<typename T>
bool Frustum<T>::Contains(const Vector3<T>& point) const
constexpr bool Frustum<T>::Contains(const Vector3<T>& 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<typename T>
bool Frustum<T>::Contains(const Vector3<T>* points, std::size_t pointCount) const
constexpr bool Frustum<T>::Contains(const Vector3<T>* 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<typename T>
const Plane<T>& Frustum<T>::GetPlane(FrustumPlane plane) const
constexpr const Plane<T>& Frustum<T>::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<typename T>
IntersectionSide Frustum<T>::Intersect(const BoundingVolume<T>& volume) const
constexpr IntersectionSide Frustum<T>::Intersect(const BoundingVolume<T>& 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<typename T>
IntersectionSide Frustum<T>::Intersect(const Box<T>& box) const
constexpr IntersectionSide Frustum<T>::Intersect(const Box<T>& 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<typename T>
IntersectionSide Frustum<T>::Intersect(const OrientedBox<T>& orientedbox) const
constexpr IntersectionSide Frustum<T>::Intersect(const OrientedBox<T>& orientedbox) const
{
return Intersect(orientedbox.GetCorners(), 8);
}
@ -323,9 +327,8 @@ namespace Nz
*
* \param sphere Sphere to check
*/
template<typename T>
IntersectionSide Frustum<T>::Intersect(const Sphere<T>& sphere) const
constexpr IntersectionSide Frustum<T>::Intersect(const Sphere<T>& 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<typename T>
IntersectionSide Frustum<T>::Intersect(const Vector3<T>* points, std::size_t pointCount) const
constexpr IntersectionSide Frustum<T>::Intersect(const Vector3<T>* 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<typename T>
constexpr bool Frustum<T>::operator==(const Frustum& frustum) const
{
for (auto&& [planeEnum, plane] : m_planes.iter_kv())
{
if (!plane != frustum.GetPlane(planeEnum))
return false;
}
return true;
}
template<typename T>
constexpr bool Frustum<T>::operator!=(const Frustum& frustum) const
{
return !operator==(frustum);
}
template<typename T>
constexpr bool Frustum<T>::ApproxEqual(const Frustum& lhs, const Frustum& rhs, T maxDifference)
{
return lhs.ApproxEqual(rhs, maxDifference);
}
template<typename T>
Frustum<T> Frustum<T>::Build(RadianAngle<T> angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up)
{
@ -609,3 +635,4 @@ namespace Nz
}
#include <Nazara/Core/DebugOff.hpp>
#include "Frustum.hpp"

View File

@ -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<T>& matrix);
Matrix4(const T matrix[16]);
template<typename U> explicit Matrix4(const Matrix4<U>& 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<typename U> constexpr explicit Matrix4(const Matrix4<U>& matrix);
constexpr Matrix4(const Matrix4&) = default;
constexpr Matrix4(Matrix4&&) = default;
~Matrix4() = default;
Matrix4& ApplyRotation(const Quaternion<T>& rotation);
Matrix4& ApplyScale(const Vector3<T>& scale);
Matrix4& ApplyTranslation(const Vector3<T>& translation);
constexpr Matrix4& ApplyRotation(const Quaternion<T>& rotation);
constexpr Matrix4& ApplyScale(const Vector3<T>& scale);
constexpr Matrix4& ApplyTranslation(const Vector3<T>& translation);
Matrix4& Concatenate(const Matrix4& matrix);
Matrix4& ConcatenateTransform(const Matrix4& matrix);
constexpr bool ApproxEqual(const Matrix4& vec, T maxDifference = std::numeric_limits<T>::epsilon()) const;
Vector4<T> 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<T> 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<T> GetRotation() const;
//Matrix3 GetRotationMatrix() const;
Vector4<T> GetRow(unsigned int row) const;
Vector3<T> GetScale() const;
Vector3<T> GetSquaredScale() const;
Vector3<T> GetTranslation() const;
void GetTransposed(Matrix4* dest) const;
constexpr Vector4<T> GetRow(std::size_t row) const;
constexpr Vector3<T> GetScale() const;
constexpr Vector3<T> GetSquaredScale() const;
constexpr Vector3<T> 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<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());
Matrix4& MakeOrtho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
Matrix4& MakePerspective(RadianAngle<T> angle, T ratio, T zNear, T zFar);
Matrix4& MakeRotation(const Quaternion<T>& rotation);
Matrix4& MakeScale(const Vector3<T>& scale);
Matrix4& MakeTranslation(const Vector3<T>& translation);
Matrix4& MakeTransform(const Vector3<T>& translation, const Quaternion<T>& rotation);
Matrix4& MakeTransform(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
Matrix4& MakeTransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation);
Matrix4& MakeTransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& 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<T>& matrix);
template<typename U> Matrix4& Set(const Matrix4<U>& matrix);
Matrix4& SetRotation(const Quaternion<T>& rotation);
Matrix4& SetScale(const Vector3<T>& scale);
Matrix4& SetTranslation(const Vector3<T>& translation);
constexpr Matrix4& SetRotation(const Quaternion<T>& rotation);
constexpr Matrix4& SetScale(const Vector3<T>& scale);
constexpr Matrix4& SetTranslation(const Vector3<T>& translation);
std::string ToString() const;
Vector2<T> Transform(const Vector2<T>& vector, T z = 0.0, T w = 1.0) const;
Vector3<T> Transform(const Vector3<T>& vector, T w = 1.0) const;
Vector4<T> Transform(const Vector4<T>& vector) const;
constexpr Vector2<T> Transform(const Vector2<T>& vector, T z = 0.0, T w = 1.0) const;
constexpr Vector3<T> Transform(const Vector3<T>& vector, T w = 1.0) const;
constexpr Vector4<T> Transform(const Vector4<T>& 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<T> operator*(const Vector2<T>& vector) const;
Vector3<T> operator*(const Vector3<T>& vector) const;
Vector4<T> operator*(const Vector4<T>& vector) const;
Matrix4 operator*(T scalar) const;
constexpr Matrix4 operator*(const Matrix4& matrix) const;
constexpr Vector2<T> operator*(const Vector2<T>& vector) const;
constexpr Vector3<T> operator*(const Vector3<T>& vector) const;
constexpr Vector4<T> operator*(const Vector4<T>& 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<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::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<T>::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<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::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<T> angle, T ratio, T zNear, T zFar);
static Matrix4 Rotate(const Quaternion<T>& rotation);
static Matrix4 Scale(const Vector3<T>& scale);
static Matrix4 Translate(const Vector3<T>& translation);
static Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation);
static Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
static Matrix4 TransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation);
static Matrix4 TransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
static Matrix4 Zero();
static constexpr Matrix4 Rotate(const Quaternion<T>& rotation);
static constexpr Matrix4 Scale(const Vector3<T>& scale);
static constexpr Matrix4 Translate(const Vector3<T>& translation);
static constexpr Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation);
static constexpr Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
static constexpr Matrix4 TransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation);
static constexpr Matrix4 TransformInverse(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
static constexpr Matrix4 Zero();
T m11, m12, m13, m14,
m21, m22, m23, m24,
@ -149,7 +133,7 @@ namespace Nz
template<typename T> std::ostream& operator<<(std::ostream& out, const Matrix4<T>& matrix);
template<typename T> Matrix4<T> operator*(T scale, const Matrix4<T>& matrix);
template<typename T> constexpr Matrix4<T> operator*(T scale, const Matrix4<T>& matrix);
}
#include <Nazara/Math/Matrix4.inl>

File diff suppressed because it is too large Load Diff

View File

@ -22,34 +22,40 @@ namespace Nz
class OrientedBox
{
public:
OrientedBox() = default;
OrientedBox(const Box<T>& box);
template<typename U> explicit OrientedBox(const OrientedBox<U>& orientedBox);
OrientedBox(const OrientedBox&) = default;
OrientedBox(OrientedBox&&) noexcept = default;
constexpr OrientedBox() = default;
constexpr OrientedBox(const Box<T>& box);
template<typename U> constexpr explicit OrientedBox(const OrientedBox<U>& orientedBox);
constexpr OrientedBox(const OrientedBox&) = default;
constexpr OrientedBox(OrientedBox&&) noexcept = default;
~OrientedBox() = default;
const Vector3<T>& GetCorner(BoxCorner corner) const;
const Vector3<T>* GetCorners() const;
constexpr bool ApproxEqual(const OrientedBox& obb, T maxDifference = std::numeric_limits<T>::epsilon()) const;
bool IsValid() const;
constexpr const Vector3<T>& GetCorner(BoxCorner corner) const;
constexpr const Vector3<T>* GetCorners() const;
constexpr bool IsValid() const;
std::string ToString() const;
void Update(const Matrix4<T>& transformMatrix);
void Update(const Vector3<T>& transformMatrix);
constexpr void Update(const Matrix4<T>& transformMatrix);
constexpr void Update(const Vector3<T>& transformMatrix);
Vector3<T>& operator()(unsigned int i);
const Vector3<T>& operator()(unsigned int i) const;
constexpr Vector3<T>& operator()(unsigned int i);
constexpr const Vector3<T>& 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<T>::epsilon());
static constexpr OrientedBox Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation);
static constexpr OrientedBox Zero();
template<typename U> friend bool Serialize(SerializationContext& context, const OrientedBox<U>& obb, TypeTag<OrientedBox<U>>);
template<typename U> friend bool Unserialize(SerializationContext& context, OrientedBox<U>* obb, TypeTag<OrientedBox<U>>);
Box<T> localBox;
@ -60,9 +66,6 @@ namespace Nz
using OrientedBoxd = OrientedBox<double>;
using OrientedBoxf = OrientedBox<float>;
template<typename T> bool Serialize(SerializationContext& context, const OrientedBox<T>& obb, TypeTag<OrientedBox<T>>);
template<typename T> bool Unserialize(SerializationContext& context, OrientedBox<T>* obb, TypeTag<OrientedBox<T>>);
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::OrientedBox<T>& orientedBox);
}

View File

@ -25,9 +25,8 @@ namespace Nz
*
* \param box Box<T> object
*/
template<typename T>
OrientedBox<T>::OrientedBox(const Box<T>& box) :
constexpr OrientedBox<T>::OrientedBox(const Box<T>& box) :
localBox(box)
{
}
@ -37,16 +36,30 @@ namespace Nz
*
* \param orientedBox OrientedBox of type U to convert to type T
*/
template<typename T>
template<typename U>
OrientedBox<T>::OrientedBox(const OrientedBox<U>& orientedBox) :
constexpr OrientedBox<T>::OrientedBox(const OrientedBox<U>& orientedBox) :
localBox(orientedBox.localBox)
{
for (auto&& [cornerEnum, corner] : m_corners.iter_kv())
corner = Vector3<T>(orientedBox.GetCorner(cornerEnum));
}
template<typename T>
constexpr bool OrientedBox<T>::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<typename T>
const Vector3<T>& OrientedBox<T>::GetCorner(BoxCorner corner) const
constexpr const Vector3<T>& OrientedBox<T>::GetCorner(BoxCorner corner) const
{
NazaraAssert(corner <= BoxCorner::Max, "invalid corner");
return m_corners[corner];
}
template<typename T>
const Vector3<T>* OrientedBox<T>::GetCorners() const
constexpr const Vector3<T>* OrientedBox<T>::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<typename T>
bool OrientedBox<T>::IsValid() const
constexpr bool OrientedBox<T>::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<typename T>
std::string OrientedBox<T>::ToString() const
{
@ -99,9 +109,8 @@ namespace Nz
*
* \param transformMatrix Matrix4 which represents the transformation to apply on the local box
*/
template<typename T>
void OrientedBox<T>::Update(const Matrix4<T>& transformMatrix)
constexpr void OrientedBox<T>::Update(const Matrix4<T>& 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<typename T>
void OrientedBox<T>::Update(const Vector3<T>& translation)
constexpr void OrientedBox<T>::Update(const Vector3<T>& 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<typename T>
Vector3<T>& OrientedBox<T>::operator()(unsigned int i)
constexpr Vector3<T>& OrientedBox<T>::operator()(unsigned int i)
{
NazaraAssert(i < m_corners.size(), "corner out of range");
return m_corners[static_cast<BoxCorner>(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<typename T>
const Vector3<T>& OrientedBox<T>::operator()(unsigned int i) const
constexpr const Vector3<T>& OrientedBox<T>::operator()(unsigned int i) const
{
NazaraAssert(i < m_corners.size(), "corner out of range");
return m_corners[static_cast<BoxCorner>(i)];
@ -156,11 +162,10 @@ namespace Nz
*
* \param box Other oriented box to compare with
*/
template<typename T>
bool OrientedBox<T>::operator==(const OrientedBox& box) const
constexpr bool OrientedBox<T>::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<typename T>
bool OrientedBox<T>::operator!=(const OrientedBox& box) const
constexpr bool OrientedBox<T>::operator!=(const OrientedBox& box) const
{
return !operator==(box);
}
@ -189,9 +193,14 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
constexpr bool OrientedBox<T>::ApproxEqual(const OrientedBox& lhs, const OrientedBox& rhs, T maxDifference)
{
return lhs.ApproxEqual(rhs, maxDifference);
}
template<typename T>
OrientedBox<T> OrientedBox<T>::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation)
constexpr OrientedBox<T> OrientedBox<T>::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation)
{
return OrientedBox{ Box<T>::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<typename T>
OrientedBox<T> OrientedBox<T>::Zero()
constexpr OrientedBox<T> OrientedBox<T>::Zero()
{
return OrientedBox{ Box<T>::Zero() };
}
@ -215,8 +221,6 @@ namespace Nz
*
* \param context Serialization context
* \param obb Input oriented box
*
* \remark Does not save OBB corners
*/
template<typename T>
bool Serialize(SerializationContext& context, const OrientedBox<T>& obb, TypeTag<OrientedBox<T>>)
@ -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<typename T>
bool Unserialize(SerializationContext& context, OrientedBox<T>* obb, TypeTag<OrientedBox<T>>)
@ -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 <Nazara/Core/DebugOff.hpp>
#include "OrientedBox.hpp"

View File

@ -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;

View File

@ -7,7 +7,7 @@
namespace Nz
{
template<typename T>
PidController<T>::PidController(float p, float i, float d) :
constexpr PidController<T>::PidController(float p, float i, float d) :
m_lastError(0),
m_integral(0),
m_dFactor(d),
@ -17,7 +17,7 @@ namespace Nz
}
template<typename T>
T PidController<T>::Update(const T& currentError, float elapsedTime)
constexpr T PidController<T>::Update(const T& currentError, float elapsedTime)
{
m_integral += currentError * elapsedTime;
T deriv = (currentError - m_lastError) / elapsedTime;

View File

@ -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<T>& Normal, T Distance);
Plane(const Vector3<T>& Normal, const Vector3<T>& point);
constexpr Plane() = default;
constexpr Plane(T normalX, T normalY, T normalZ, T Distance);
constexpr Plane(const T plane[4]);
constexpr Plane(const Vector3<T>& Normal, T Distance);
constexpr Plane(const Vector3<T>& Normal, const Vector3<T>& point);
Plane(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3);
template<typename U> explicit Plane(const Plane<U>& plane);
Plane(const Plane& plane) = default;
template<typename U> constexpr explicit Plane(const Plane<U>& plane);
constexpr Plane(const Plane& plane) = default;
~Plane() = default;
T Distance(T x, T y, T z) const;
T Distance(const Vector3<T>& point) const;
constexpr bool ApproxEqual(const Plane& plane, T maxDifference = std::numeric_limits<T>::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<T>& Normal, T Distance);
Plane& Set(const Vector3<T>& Normal, const Vector3<T>& point);
Plane& Set(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3);
template<typename U> Plane& Set(const Plane<U>& plane);
constexpr T Distance(T x, T y, T z) const;
constexpr T Distance(const Vector3<T>& 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<T> 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<T>::epsilon());
static constexpr Vector3<T> 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<T> normal;
T distance;

View File

@ -26,11 +26,11 @@ namespace Nz
* \param normalZ Z component of the normal
* \param D Distance to origin
*/
template<typename T>
Plane<T>::Plane(T normalX, T normalY, T normalZ, T D)
constexpr Plane<T>::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<typename T>
Plane<T>::Plane(const T plane[4])
constexpr Plane<T>::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<typename T>
Plane<T>::Plane(const Vector3<T>& Normal, T D)
constexpr Plane<T>::Plane(const Vector3<T>& 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<typename T>
Plane<T>::Plane(const Vector3<T>& Normal, const Vector3<T>& point)
constexpr Plane<T>::Plane(const Vector3<T>& Normal, const Vector3<T>& 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<typename T>
Plane<T>::Plane(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3)
{
Set(point1, point2, point3);
Vector3<T> edge1 = point2 - point1;
Vector3<T> 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<typename T>
template<typename U>
Plane<T>::Plane(const Plane<U>& plane)
constexpr Plane<T>::Plane(const Plane<U>& plane) :
normal(Vector3<T>(plane.normal)),
distance(T(plane.distance))
{
Set(plane);
}
template<typename T>
constexpr bool Plane<T>::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<typename T>
T Plane<T>::Distance(T x, T y, T z) const
constexpr T Plane<T>::Distance(T x, T y, T z) const
{
return Distance(Vector3<T>(x, y, z));
}
@ -129,162 +141,12 @@ namespace Nz
*
* \see Distance
*/
template<typename T>
T Plane<T>::Distance(const Vector3<T>& point) const
constexpr T Plane<T>::Distance(const Vector3<T>& 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<typename T>
Plane<T>& Plane<T>::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<typename T>
Plane<T>& Plane<T>::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<typename T>
Plane<T>& Plane<T>::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<typename T>
Plane<T>& Plane<T>::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<typename T>
Plane<T>& Plane<T>::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<typename T>
Plane<T>& Plane<T>::Set(const Vector3<T>& 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<typename T>
Plane<T>& Plane<T>::Set(const Vector3<T>& Normal, const Vector3<T>& 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<typename T>
Plane<T>& Plane<T>::Set(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3)
{
Vector3<T> edge1 = point2 - point1;
Vector3<T> 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<typename T>
template<typename U>
Plane<T>& Plane<T>::Set(const Plane<U>& 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<typename T>
bool Plane<T>::operator==(const Plane& plane) const
constexpr bool Plane<T>::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<typename T>
bool Plane<T>::operator!=(const Plane& plane) const
constexpr bool Plane<T>::operator!=(const Plane& plane) const
{
return !operator==(plane);
}
template<typename T>
constexpr bool Plane<T>::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<typename T>
Vector3<T> Plane<T>::Intersect(const Plane& p0, const Plane& p1, const Plane& p2)
constexpr Vector3<T> Plane<T>::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<typename T>
Plane<T> Plane<T>::Lerp(const Plane& from, const Plane& to, T interpolation)
constexpr Plane<T> Plane<T>::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<typename T>
Plane<T> Plane<T>::XY()
constexpr Plane<T> Plane<T>::XY()
{
Plane plane;
plane.MakeXY();
return plane;
return Plane(Vector3<T>::UnitZ(), 0);
}
/*!
* \brief Shorthand for the plane (0, 1, 0, 0)
* \return A plane with components (0, 1, 0, 0)
*
* \see MakeXZ
*/
template<typename T>
Plane<T> Plane<T>::XZ()
constexpr Plane<T> Plane<T>::XZ()
{
Plane plane;
plane.MakeXZ();
return plane;
return Plane(Vector3<T>::UnitY(), 0);
}
/*!
* \brief Shorthand for the plane (1, 0, 0, 0)
* \return A plane with components (1, 0, 0, 0)
*
* \see MakeYZ
*/
template<typename T>
Plane<T> Plane<T>::YZ()
constexpr Plane<T> Plane<T>::YZ()
{
Plane plane;
plane.MakeYZ();
return plane;
return Plane(Vector3<T>::UnitX(), 0);
}
/*!
@ -484,3 +334,4 @@ namespace Nz
}
#include <Nazara/Core/DebugOff.hpp>
#include "Plane.hpp"

View File

@ -20,75 +20,70 @@ namespace Nz
template<typename T> 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<AngleUnit Unit> Quaternion(const Angle<Unit, T>& angle);
Quaternion(const EulerAngles<T>& angles);
Quaternion(RadianAngle<T> angle, const Vector3<T>& axis);
Quaternion(const T quat[4]);
//Quaternion(const Matrix3<T>& mat);
template<typename U> explicit Quaternion(const Quaternion<U>& quat);
Quaternion(const Quaternion& quat) = default;
constexpr Quaternion(RadianAngle<T> angle, const Vector3<T>& axis);
constexpr Quaternion(const T quat[4]);
template<typename U> constexpr explicit Quaternion(const Quaternion<U>& quat);
constexpr Quaternion(const Quaternion&) = default;
constexpr Quaternion(Quaternion&&) = default;
~Quaternion() = default;
constexpr bool ApproxEqual(const Quaternion& quat, T maxDifference = std::numeric_limits<T>::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<T>& from, const Vector3<T>& to);
Quaternion& MakeZero();
T Magnitude() const;
Quaternion& Normalize(T* length = nullptr);
Quaternion& Set(T W, T X, T Y, T Z);
template<AngleUnit Unit> Quaternion& Set(const Angle<Unit, T>& angle);
Quaternion& Set(const EulerAngles<T>& angles);
Quaternion& Set(RadianAngle<T> angle, const Vector3<T>& normalizedAxis);
Quaternion& Set(const T quat[4]);
//Quaternion& Set(const Matrix3<T>& mat);
template<typename U> Quaternion& Set(const Quaternion<U>& quat);
T SquaredMagnitude() const;
constexpr T SquaredMagnitude() const;
RadianAngle<T> To2DAngle() const;
EulerAngles<T> ToEulerAngles() const;
//Matrix3<T> 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<T> operator*(const Vector3<T>& 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<T> operator*(const Vector3<T>& 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<T>::epsilon());
static constexpr Quaternion Identity();
static constexpr Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation);
static Quaternion LookAt(const Vector3<T>& forward, const Vector3<T>& up);
static Quaternion Normalize(const Quaternion& quat, T* length = nullptr);
static Quaternion RotationBetween(const Vector3<T>& from, const Vector3<T>& to);
static Quaternion Mirror(Quaternion quat, const Vector3<T>& axis);
static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation);
static Quaternion Zero();
static constexpr Quaternion Zero();
T w, x, y, z;
};

View File

@ -30,11 +30,13 @@ namespace Nz
* \param Y Y component
* \param Z Z component
*/
template<typename T>
Quaternion<T>::Quaternion(T W, T X, T Y, T Z)
constexpr Quaternion<T>::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<typename T>
template<AngleUnit Unit>
Quaternion<T>::Quaternion(const Angle<Unit, T>& angle)
Quaternion<T>::Quaternion(const Angle<Unit, T>& angle) :
Quaternion(angle.ToQuaternion())
{
Set(angle);
}
/*!
@ -57,9 +59,9 @@ namespace Nz
* \see EulerAngles
*/
template<typename T>
Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
Quaternion<T>::Quaternion(const EulerAngles<T>& 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<typename T>
Quaternion<T>::Quaternion(RadianAngle<T> angle, const Vector3<T>& axis)
constexpr Quaternion<T>::Quaternion(RadianAngle<T> angle, const Vector3<T>& axis)
{
Set(angle, axis);
angle /= T(2.0);
Vector3<T> 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<typename T>
Quaternion<T>::Quaternion(const T quat[4])
constexpr Quaternion<T>::Quaternion(const T quat[4]) :
w(quat[0]),
x(quat[1]),
y(quat[2]),
z(quat[3])
{
Set(quat);
}
/*
template<typename T>
Quaternion<T>::Quaternion(const Matrix3<T>& mat)
{
Set(mat);
}
*/
/*!
* \brief Constructs a Quaternion object from another type of Quaternion
*
@ -103,16 +109,27 @@ namespace Nz
template<typename T>
template<typename U>
Quaternion<T>::Quaternion(const Quaternion<U>& quat)
constexpr Quaternion<T>::Quaternion(const Quaternion<U>& quat) :
w(static_cast<T>(quat.w)),
x(static_cast<T>(quat.x)),
y(static_cast<T>(quat.y)),
z(static_cast<T>(quat.z))
{
Set(quat);
}
template<typename T>
constexpr bool Quaternion<T>::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<typename T>
Quaternion<T>& Quaternion<T>::ComputeW()
{
@ -134,9 +151,8 @@ namespace Nz
*
* \see GetConjugate
*/
template<typename T>
Quaternion<T>& Quaternion<T>::Conjugate()
constexpr Quaternion<T>& Quaternion<T>::Conjugate()
{
x = -x;
y = -y;
@ -151,9 +167,8 @@ namespace Nz
*
* \param quat The other quaternion to calculate the dot product with
*/
template<typename T>
T Quaternion<T>::DotProduct(const Quaternion& quat) const
constexpr T Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::GetConjugate() const
constexpr Quaternion<T> Quaternion<T>::GetConjugate() const
{
Quaternion<T> quat(*this);
quat.Conjugate();
@ -184,7 +198,6 @@ namespace Nz
*
* \see Inverse
*/
template<typename T>
Quaternion<T> Quaternion<T>::GetInverse() const
{
@ -204,7 +217,6 @@ namespace Nz
*
* \see Normalize
*/
template<typename T>
Quaternion<T> Quaternion<T>::GetNormal(T* length) const
{
@ -222,7 +234,6 @@ namespace Nz
*
* \see GetInverse
*/
template<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to)
{
T dot = from.DotProduct(to);
if (dot < T(-0.999999))
{
Vector3<T> crossProduct;
if (from.DotProduct(Vector3<T>::UnitX()) < T(0.999999))
crossProduct = Vector3<T>::UnitX().CrossProduct(from);
else
crossProduct = Vector3<T>::UnitY().CrossProduct(from);
crossProduct.Normalize();
Set(Pi<T>, 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<T> 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<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
T Quaternion<T>::Magnitude() const
{
@ -331,7 +273,6 @@ namespace Nz
*
* \see GetNormal
*/
template<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
template<AngleUnit Unit>
Quaternion<T>& Quaternion<T>::Set(const Angle<Unit, T>& 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<typename T>
Quaternion<T>& Quaternion<T>::Set(const EulerAngles<T>& 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<typename T>
Quaternion<T>& Quaternion<T>::Set(RadianAngle<T> angle, const Vector3<T>& axis)
{
angle /= T(2.0);
Vector3<T> 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<typename T>
Quaternion<T>& Quaternion<T>::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<typename T>
template<typename U>
Quaternion<T>& Quaternion<T>::Set(const Quaternion<U>& 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<typename T>
T Quaternion<T>::SquaredMagnitude() const
constexpr T Quaternion<T>::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<typename T>
std::string Quaternion<T>::ToString() const
{
@ -534,9 +361,8 @@ namespace Nz
*
* \param quat The other quaternion to add components with
*/
template<typename T>
Quaternion<T> Quaternion<T>::operator+(const Quaternion& quat) const
constexpr Quaternion<T> Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::operator*(const Quaternion& quat) const
constexpr Quaternion<T> Quaternion<T>::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<typename T>
Vector3<T> Quaternion<T>::operator*(const Vector3<T>& vec) const
constexpr Vector3<T> Quaternion<T>::operator*(const Vector3<T>& vec) const
{
Vector3<T> quatVec(x, y, z);
Vector3<T> uv = quatVec.CrossProduct(vec);
@ -591,9 +415,8 @@ namespace Nz
*
* \param scale The scalar to multiply components with
*/
template<typename T>
Quaternion<T> Quaternion<T>::operator*(T scale) const
constexpr Quaternion<T> Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::operator/(const Quaternion& quat) const
constexpr Quaternion<T> Quaternion<T>::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<typename T>
Quaternion<T>& Quaternion<T>::operator+=(const Quaternion& quat)
constexpr Quaternion<T>& Quaternion<T>::operator+=(const Quaternion& quat)
{
return operator=(operator+(quat));
}
@ -633,9 +454,8 @@ namespace Nz
*
* \param quat The other quaternion to multiply with
*/
template<typename T>
Quaternion<T>& Quaternion<T>::operator*=(const Quaternion& quat)
constexpr Quaternion<T>& Quaternion<T>::operator*=(const Quaternion& quat)
{
return operator=(operator*(quat));
}
@ -646,9 +466,8 @@ namespace Nz
*
* \param scale The scalar to multiply components with
*/
template<typename T>
Quaternion<T>& Quaternion<T>::operator*=(T scale)
constexpr Quaternion<T>& Quaternion<T>::operator*=(T scale)
{
return operator=(operator*(scale));
}
@ -659,9 +478,8 @@ namespace Nz
*
* \param quat The other quaternion to divide with
*/
template<typename T>
Quaternion<T>& Quaternion<T>::operator/=(const Quaternion& quat)
constexpr Quaternion<T>& Quaternion<T>::operator/=(const Quaternion& quat)
{
return operator=(operator/(quat));
}
@ -672,14 +490,10 @@ namespace Nz
*
* \param quat Other quaternion to compare with
*/
template<typename T>
bool Quaternion<T>::operator==(const Quaternion& quat) const
constexpr bool Quaternion<T>::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<typename T>
bool Quaternion<T>::operator!=(const Quaternion& quat) const
constexpr bool Quaternion<T>::operator!=(const Quaternion& quat) const
{
return !operator==(quat);
}
template<typename T>
constexpr bool Quaternion<T>::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<typename T>
constexpr bool Quaternion<T>::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<typename T>
constexpr bool Quaternion<T>::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<typename T>
constexpr bool Quaternion<T>::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<typename T>
constexpr bool Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::Identity()
constexpr Quaternion<T> Quaternion<T>::Identity()
{
Quaternion quaternion;
quaternion.MakeIdentity();
return quaternion;
return Quaternion(1, 0, 0, 0);
}
/*!
@ -725,7 +602,7 @@ namespace Nz
* \see Lerp, Slerp
*/
template<typename T>
Quaternion<T> Quaternion<T>::Lerp(const Quaternion& from, const Quaternion& to, T interpolation)
constexpr Quaternion<T> Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::Normalize(const Quaternion& quat, T* length)
{
@ -793,17 +669,31 @@ namespace Nz
*
* \param from Initial vector
* \param to Target vector
*
* \see MakeRotationBetween
*/
template<typename T>
Quaternion<T> Quaternion<T>::RotationBetween(const Vector3<T>& from, const Vector3<T>& to)
{
Quaternion quaternion;
quaternion.MakeRotationBetween(from, to);
T dot = from.DotProduct(to);
if (dot < T(-0.999999))
{
Vector3<T> crossProduct;
if (from.DotProduct(Vector3<T>::UnitX()) < T(0.999999))
crossProduct = Vector3<T>::UnitX().CrossProduct(from);
else
crossProduct = Vector3<T>::UnitY().CrossProduct(from);
return quaternion;
crossProduct.Normalize();
return Quaternion(Pi<T>, crossProduct);
}
else if (dot > T(0.999999))
return Quaternion(1, 0, 0, 0);
else
{
T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength());
Vector3<T> crossProduct = from.CrossProduct(to);
return Quaternion(norm + dot, crossProduct.x, crossProduct.y, crossProduct.z).GetNormal();
}
}
template<typename T>
@ -833,7 +723,6 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
Quaternion<T> Quaternion<T>::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<typename T>
Quaternion<T> Quaternion<T>::Zero()
constexpr Quaternion<T> Quaternion<T>::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 <Nazara/Core/DebugOff.hpp>
#include "Quaternion.hpp"

View File

@ -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<T>& origin, const Vector3<T>& 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<T>& origin, const Vector3<T>& direction);
constexpr Ray(const T origin[3], const T direction[3]);
Ray(const Plane<T>& planeOne, const Plane<T>& planeTwo);
template<typename U> explicit Ray(const Ray<U>& ray);
template<typename U> explicit Ray(const Vector3<U>& origin, const Vector3<U>& direction);
Ray(const Ray<T>& ray) = default;
template<typename U> constexpr explicit Ray(const Ray<U>& ray);
template<typename U> constexpr explicit Ray(const Vector3<U>& origin, const Vector3<U>& direction);
constexpr Ray(const Ray&) = default;
constexpr Ray(Ray&&) = default;
~Ray() = default;
T ClosestPoint(const Vector3<T>& point) const;
constexpr bool ApproxEqual(const Ray& ray, T maxDifference = std::numeric_limits<T>::epsilon()) const;
Vector3<T> GetPoint(T lambda) const;
constexpr T ClosestPoint(const Vector3<T>& point) const;
bool Intersect(const BoundingVolume<T>& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const;
bool Intersect(const Box<T>& box, T* closestHit = nullptr, T* furthestHit = nullptr) const;
bool Intersect(const Box<T>& box, const Matrix4<T>& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const;
bool Intersect(const Plane<T>& plane, T* hit = nullptr) const;
bool Intersect(const Sphere<T>& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const;
bool Intersect(const Vector3<T>& firstPoint, const Vector3<T>& secondPoint, const Vector3<T>& thirdPoint, T* hit = nullptr) const;
constexpr Vector3<T> 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<T>& origin, const Vector3<T>& direction);
Ray& Set(const T origin[3], const T direction[3]);
Ray& Set(const Plane<T>& planeOne, const Plane<T>& planeTwo);
template<typename U> Ray& Set(const Ray<U>& ray);
template<typename U> Ray& Set(const Vector3<U>& origin, const Vector3<U>& direction);
constexpr bool Intersect(const BoundingVolume<T>& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const;
constexpr bool Intersect(const Box<T>& box, T* closestHit = nullptr, T* furthestHit = nullptr) const;
constexpr bool Intersect(const Box<T>& box, const Matrix4<T>& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const;
constexpr bool Intersect(const Plane<T>& plane, T* hit = nullptr) const;
constexpr bool Intersect(const Sphere<T>& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const;
constexpr bool Intersect(const Vector3<T>& firstPoint, const Vector3<T>& secondPoint, const Vector3<T>& thirdPoint, T* hit = nullptr) const;
std::string ToString() const;
Vector3<T> 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<T> 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<T>::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<T> direction, origin;
};

View File

@ -27,11 +27,11 @@ namespace Nz
* \param DirectionY Y component of the vector direction
* \param DirectionY Y component of the vector direction
*/
template<typename T>
Ray<T>::Ray(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ)
constexpr Ray<T>::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<typename T>
Ray<T>::Ray(const Vector3<T>& Origin, const Vector3<T>& Direction)
constexpr Ray<T>::Ray(const Vector3<T>& Origin, const Vector3<T>& 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<typename T>
Ray<T>::Ray(const T Origin[3], const T Direction[3])
constexpr Ray<T>::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<typename T>
Ray<T>::Ray(const Plane<T>& planeOne, const Plane<T>& 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<typename T>
template<typename U>
Ray<T>::Ray(const Ray<U>& ray)
constexpr Ray<T>::Ray(const Ray<U>& ray) :
direction(ray.direction),
origin(ray.origin)
{
Set(ray);
}
/*!
@ -98,9 +118,16 @@ namespace Nz
template<typename T>
template<typename U>
Ray<T>::Ray(const Vector3<U>& Origin, const Vector3<U>& Direction)
constexpr Ray<T>::Ray(const Vector3<U>& Origin, const Vector3<U>& Direction) :
direction(Direction),
origin(Origin)
{
Set(Origin, Direction);
}
template<typename T>
constexpr bool Ray<T>::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<typename T>
T Ray<T>::ClosestPoint(const Vector3<T>& point) const
constexpr T Ray<T>::ClosestPoint(const Vector3<T>& point) const
{
Vector3<T> 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<typename T>
Vector3<T> Ray<T>::GetPoint(T lambda) const
constexpr Vector3<T> Ray<T>::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<typename T>
bool Ray<T>::Intersect(const BoundingVolume<T>& volume, T* closestHit, T* furthestHit) const
constexpr bool Ray<T>::Intersect(const BoundingVolume<T>& 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<typename T>
bool Ray<T>::Intersect(const Box<T>& box, T* closestHit, T* furthestHit) const
constexpr bool Ray<T>::Intersect(const Box<T>& 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<typename T>
bool Ray<T>::Intersect(const Box<T>& box, const Matrix4<T>& transform, T* closestHit, T* furthestHit) const
constexpr bool Ray<T>::Intersect(const Box<T>& box, const Matrix4<T>& 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<typename T>
bool Ray<T>::Intersect(const Plane<T>& plane, T* hit) const
constexpr bool Ray<T>::Intersect(const Plane<T>& 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<typename T>
bool Ray<T>::Intersect(const Sphere<T>& sphere, T* closestHit, T* furthestHit) const
constexpr bool Ray<T>::Intersect(const Sphere<T>& sphere, T* closestHit, T* furthestHit) const
{
Vector3<T> sphereRay = sphere.GetPosition() - origin;
T length = sphereRay.DotProduct(direction);
@ -386,9 +406,8 @@ namespace Nz
*
* \see Intersect
*/
template<typename T>
bool Ray<T>::Intersect(const Vector3<T>& firstPoint, const Vector3<T>& secondPoint, const Vector3<T>& thirdPoint, T* hit) const
constexpr bool Ray<T>::Intersect(const Vector3<T>& firstPoint, const Vector3<T>& secondPoint, const Vector3<T>& thirdPoint, T* hit) const
{
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
Vector3<T> 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<typename T>
Ray<T>& Ray<T>::MakeAxisX()
{
return Set(Vector3<T>::Zero(), Vector3<T>::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<typename T>
Ray<T>& Ray<T>::MakeAxisY()
{
return Set(Vector3<T>::Zero(), Vector3<T>::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<typename T>
Ray<T>& Ray<T>::MakeAxisZ()
{
return Set(Vector3<T>::Zero(), Vector3<T>::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<typename T>
Ray<T>& Ray<T>::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<typename T>
Ray<T>& Ray<T>::Set(const Vector3<T>& Origin, const Vector3<T>& 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<typename T>
Ray<T>& Ray<T>::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<typename T>
Ray<T>& Ray<T>::Set(const Plane<T>& planeOne, const Plane<T>& 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<typename T>
template<typename U>
Ray<T>& Ray<T>::Set(const Ray<U>& 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<typename T>
template<typename U>
Ray<T>& Ray<T>::Set(const Vector3<U>& Origin, const Vector3<U>& 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<typename T>
std::string Ray<T>::ToString() const
{
@ -610,9 +460,8 @@ namespace Nz
*
* \see GetPoint
*/
template<typename T>
Vector3<T> Ray<T>::operator*(T lambda) const
constexpr Vector3<T> Ray<T>::operator*(T lambda) const
{
return GetPoint(lambda);
}
@ -623,9 +472,8 @@ namespace Nz
*
* \param rec Other ray to compare with
*/
template<typename T>
bool Ray<T>::operator==(const Ray& ray) const
constexpr bool Ray<T>::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<typename T>
bool Ray<T>::operator!=(const Ray& ray) const
constexpr bool Ray<T>::operator!=(const Ray& ray) const
{
return !operator==(ray);
}
template<typename T>
constexpr bool Ray<T>::operator<(const Ray& ray) const
{
if (origin != ray.origin)
return origin < ray.origin;
return direction < ray.direction;
}
template<typename T>
constexpr bool Ray<T>::operator<=(const Ray& ray) const
{
if (origin != ray.origin)
return origin < ray.origin;
return direction <= ray.direction;
}
template<typename T>
constexpr bool Ray<T>::operator>(const Ray& ray) const
{
if (origin != ray.origin)
return origin > ray.origin;
return direction > ray.direction;
}
template<typename T>
constexpr bool Ray<T>::operator>=(const Ray& ray) const
{
if (origin != ray.origin)
return origin > ray.origin;
return direction >= ray.direction;
}
template<typename T>
constexpr bool Ray<T>::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<typename T>
Ray<T> Ray<T>::AxisX()
constexpr Ray<T> Ray<T>::AxisX()
{
Ray axis;
axis.MakeAxisX();
return axis;
return Ray(Vector3<T>::Zero(), Vector3<T>::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<typename T>
Ray<T> Ray<T>::AxisY()
constexpr Ray<T> Ray<T>::AxisY()
{
Ray axis;
axis.MakeAxisY();
return axis;
return Ray(Vector3<T>::Zero(), Vector3<T>::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<typename T>
Ray<T> Ray<T>::AxisZ()
constexpr Ray<T> Ray<T>::AxisZ()
{
Ray axis;
axis.MakeAxisZ();
return axis;
return Ray(Vector3<T>::Zero(), Vector3<T>::UnitZ());
}
/*!
@ -703,11 +576,10 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
Ray<T> Ray<T>::Lerp(const Ray& from, const Ray& to, T interpolation)
constexpr Ray<T> Ray<T>::Lerp(const Ray& from, const Ray& to, T interpolation)
{
return Ray<T>(Nz::Vector3<T>::Lerp(from.origin, to.origin, interpolation), Nz::Vector3<T>::Lerp(from.direction, to.direction, interpolation));
return Ray<T>(Vector3<T>::Lerp(from.origin, to.origin, interpolation), Vector3<T>::Lerp(from.direction, to.direction, interpolation));
}
/*!
@ -764,3 +636,4 @@ namespace Nz
}
#include <Nazara/Core/DebugOff.hpp>
#include "Ray.hpp"

View File

@ -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<T>& lengths);
explicit Rect(const Vector2<T>& pos, const Vector2<T>& lengths);
template<typename U> explicit Rect(const Rect<U>& 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<T>& lengths);
constexpr explicit Rect(const Vector2<T>& pos, const Vector2<T>& lengths);
template<typename U> constexpr explicit Rect(const Rect<U>& 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<T>::epsilon()) const;
bool Contains(T X, T Y) const;
bool Contains(const Rect& rect) const;
bool Contains(const Vector2<T>& point) const;
constexpr bool Contains(T X, T Y) const;
constexpr bool Contains(const Rect& rect) const;
constexpr bool Contains(const Vector2<T>& point) const;
Rect& ExtendTo(T X, T Y);
Rect& ExtendTo(const Rect& rect);
Rect& ExtendTo(const Vector2<T>& point);
constexpr Rect& ExtendTo(T X, T Y);
constexpr Rect& ExtendTo(const Rect& rect);
constexpr Rect& ExtendTo(const Vector2<T>& point);
Vector2<T> GetCenter() const;
Vector2<T> GetCorner(RectCorner corner) const;
Vector2<T> GetLengths() const;
Vector2<T> GetMaximum() const;
Vector2<T> GetMinimum() const;
Vector2<T> GetNegativeVertex(const Vector2<T>& normal) const;
Vector2<T> GetPosition() const;
Vector2<T> GetPositiveVertex(const Vector2<T>& normal) const;
constexpr Vector2<T> GetCenter() const;
constexpr Vector2<T> GetCorner(RectCorner corner) const;
constexpr Vector2<T> GetLengths() const;
constexpr Vector2<T> GetMaximum() const;
constexpr Vector2<T> GetMinimum() const;
constexpr Vector2<T> GetNegativeVertex(const Vector2<T>& normal) const;
constexpr Vector2<T> GetPosition() const;
constexpr Vector2<T> GetPositiveVertex(const Vector2<T>& 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<T>& vec);
Rect& Scale(T scalar);
Rect& Scale(const Vector2<T>& vec);
constexpr Rect& ScaleAroundCenter(T scalar);
constexpr Rect& ScaleAroundCenter(const Vector2<T>& vec);
std::string ToString() const;
Rect& Translate(const Vector2<T>& translation);
constexpr Rect& Translate(const Vector2<T>& 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<T>& vec1, const Vector2<T>& 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<T>::epsilon());
static constexpr Rect FromExtends(const Vector2<T>& vec1, const Vector2<T>& 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;
};

View File

@ -27,9 +27,8 @@ namespace Nz
*
* \remark Position will be (0, 0)
*/
template<typename T>
Rect<T>::Rect(T Width, T Height) :
constexpr Rect<T>::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<typename T>
Rect<T>::Rect(T X, T Y, T Width, T Height) :
constexpr Rect<T>::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<typename T>
Rect<T>::Rect(const Vector2<T>& lengths) :
constexpr Rect<T>::Rect(const Vector2<T>& lengths) :
Rect(Vector2<T>::Zero(), lengths)
{
}
@ -73,13 +72,14 @@ namespace Nz
* \param lengths (Width, Height) of the rect
*/
template<typename T>
Rect<T>::Rect(const Vector2<T>& pos, const Vector2<T>& lengths) :
constexpr Rect<T>::Rect(const Vector2<T>& pos, const Vector2<T>& 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<typename T>
template<typename U>
Rect<T>::Rect(const Rect<U>& rect) :
constexpr Rect<T>::Rect(const Rect<U>& rect) :
x(static_cast<T>(rect.x)),
y(static_cast<T>(rect.y)),
width(static_cast<T>(rect.width)),
@ -97,7 +97,7 @@ namespace Nz
}
template<typename T>
bool Rect<T>::ApproxEquals(const Rect& rect, T maxDifference) const
constexpr bool Rect<T>::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<typename T>
bool Rect<T>::Contains(T X, T Y) const
constexpr bool Rect<T>::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<typename T>
bool Rect<T>::Contains(const Rect<T>& rect) const
constexpr bool Rect<T>::Contains(const Rect<T>& 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<typename T>
bool Rect<T>::Contains(const Vector2<T>& point) const
constexpr bool Rect<T>::Contains(const Vector2<T>& point) const
{
return Contains(point.x, point.y);
}
@ -159,7 +158,7 @@ namespace Nz
* \see ExtendTo
*/
template<typename T>
Rect<T>& Rect<T>::ExtendTo(T X, T Y)
constexpr Rect<T>& Rect<T>::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<typename T>
Rect<T>& Rect<T>::ExtendTo(const Rect& rect)
constexpr Rect<T>& Rect<T>::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<typename T>
Rect<T>& Rect<T>::ExtendTo(const Vector2<T>& point)
constexpr Rect<T>& Rect<T>::ExtendTo(const Vector2<T>& point)
{
return ExtendTo(point.x, point.y);
}
@ -217,7 +215,7 @@ namespace Nz
*/
template<typename T>
Vector2<T> Rect<T>::GetCenter() const
constexpr Vector2<T> Rect<T>::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<typename T>
Vector2<T> Rect<T>::GetCorner(RectCorner corner) const
constexpr Vector2<T> Rect<T>::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<typename T>
Vector2<T> Rect<T>::GetLengths() const
constexpr Vector2<T> Rect<T>::GetLengths() const
{
return Vector2<T>(width, height);
}
@ -270,9 +266,8 @@ namespace Nz
*
* \see GetCorner
*/
template<typename T>
Vector2<T> Rect<T>::GetMaximum() const
constexpr Vector2<T> Rect<T>::GetMaximum() const
{
return GetPosition() + GetLengths();
}
@ -283,9 +278,8 @@ namespace Nz
*
* \see GetCorner, GetPosition
*/
template<typename T>
Vector2<T> Rect<T>::GetMinimum() const
constexpr Vector2<T> Rect<T>::GetMinimum() const
{
return GetPosition();
}
@ -298,9 +292,8 @@ namespace Nz
*
* \see GetPositiveVertex
*/
template<typename T>
Vector2<T> Rect<T>::GetNegativeVertex(const Vector2<T>& normal) const
constexpr Vector2<T> Rect<T>::GetNegativeVertex(const Vector2<T>& normal) const
{
Vector2<T> neg(GetPosition());
@ -319,9 +312,8 @@ namespace Nz
*
* \see GetCorner, GetMinimum
*/
template<typename T>
Vector2<T> Rect<T>::GetPosition() const
constexpr Vector2<T> Rect<T>::GetPosition() const
{
return Vector2<T>(x, y);
}
@ -334,9 +326,8 @@ namespace Nz
*
* \see GetNegativeVertex
*/
template<typename T>
Vector2<T> Rect<T>::GetPositiveVertex(const Vector2<T>& normal) const
constexpr Vector2<T> Rect<T>::GetPositiveVertex(const Vector2<T>& normal) const
{
Vector2<T> 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<typename T>
bool Rect<T>::Intersect(const Rect& rect, Rect* intersection) const
constexpr bool Rect<T>::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<typename T>
bool Rect<T>::IsNull() const
constexpr bool Rect<T>::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<typename T>
bool Rect<T>::IsValid() const
constexpr bool Rect<T>::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<typename T>
Rect<T>& Rect<T>::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<typename T>
Rect<T>& Rect<T>::Scale(T scalar)
constexpr Rect<T>& Rect<T>::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<typename T>
Rect<T>& Rect<T>::Scale(const Vector2<T>& vec)
constexpr Rect<T>& Rect<T>::Scale(const Vector2<T>& 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<typename T>
constexpr Rect<T>& Rect<T>::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<typename T>
constexpr Rect<T>& Rect<T>::ScaleAroundCenter(const Vector2<T>& 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<typename T>
Rect<T>& Rect<T>::Translate(const Vector2<T>& translation)
constexpr Rect<T>& Rect<T>::Translate(const Vector2<T>& 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<typename T>
T& Rect<T>::operator[](std::size_t i)
constexpr T& Rect<T>::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<typename T>
const T& Rect<T>::operator[](std::size_t i) const
constexpr const T& Rect<T>::operator[](std::size_t i) const
{
NazaraAssert(i < 4, "Index out of range");
@ -521,7 +524,7 @@ namespace Nz
*/
template<typename T>
bool Rect<T>::operator==(const Rect& rect) const
constexpr bool Rect<T>::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<typename T>
bool Rect<T>::operator!=(const Rect& rect) const
constexpr bool Rect<T>::operator!=(const Rect& rect) const
{
return !operator==(rect);
}
template<typename T>
constexpr bool Rect<T>::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<typename T>
Rect<T> Rect<T>::FromExtends(const Vector2<T>& vec1, const Vector2<T>& vec2)
constexpr Rect<T> Rect<T>::FromExtends(const Vector2<T>& vec1, const Vector2<T>& vec2)
{
Rect rect;
rect.x = std::min(vec1.x, vec2.x);
@ -570,7 +578,7 @@ namespace Nz
* \see Lerp
*/
template<typename T>
Rect<T> Rect<T>::Lerp(const Rect& from, const Rect& to, T interpolation)
constexpr Rect<T> Rect<T>::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<typename T>
Rect<T> Rect<T>::Invalid()
constexpr Rect<T> Rect<T>::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<typename T>
Rect<T> Rect<T>::Zero()
constexpr Rect<T> Rect<T>::Zero()
{
return Rect(0, 0, 0, 0);
}
@ -671,3 +675,4 @@ namespace Nz
}
#include <Nazara/Core/DebugOff.hpp>
#include "Rect.hpp"

View File

@ -20,18 +20,20 @@ namespace Nz
class Sphere
{
public:
Sphere() = default;
Sphere(T X, T Y, T Z, T Radius);
//Sphere(const Circle<T>& circle);
Sphere(const Vector3<T>& center, T Radius);
Sphere(const T sphere[4]);
template<typename U> explicit Sphere(const Sphere<U>& sphere);
Sphere(const Sphere& sphere) = default;
constexpr Sphere() = default;
constexpr Sphere(T X, T Y, T Z, T Radius);
constexpr Sphere(const Vector3<T>& center, T Radius);
constexpr Sphere(const T sphere[4]);
template<typename U> constexpr explicit Sphere(const Sphere<U>& 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<T>& box) const;
bool Contains(const Vector3<T>& point) const;
constexpr bool ApproxEqual(const Sphere& sphere, T maxDifference = std::numeric_limits<T>::epsilon()) const;
constexpr bool Contains(T X, T Y, T Z) const;
constexpr bool Contains(const Box<T>& box) const;
constexpr bool Contains(const Vector3<T>& point) const;
T Distance(T X, T Y, T Z) const;
T Distance(const Vector3<T>& point) const;
@ -39,40 +41,38 @@ namespace Nz
Sphere& ExtendTo(T X, T Y, T Z);
Sphere& ExtendTo(const Vector3<T>& point);
Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
Vector3<T> GetPosition() const;
Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
constexpr Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
constexpr Vector3<T> GetPosition() const;
constexpr Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
bool Intersect(const Box<T>& box) const;
bool Intersect(const Sphere& sphere) const;
constexpr bool Intersect(const Box<T>& 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<T>& rect);
Sphere& Set(const Vector3<T>& center, T Radius);
Sphere& Set(const T sphere[4]);
template<typename U> Sphere& Set(const Sphere<U>& 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<T>::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;
};

View File

@ -26,19 +26,14 @@ namespace Nz
* \param Z Z position
* \param Radius half of the diameter
*/
template<typename T>
Sphere<T>::Sphere(T X, T Y, T Z, T Radius)
constexpr Sphere<T>::Sphere(T X, T Y, T Z, T Radius) :
x(X),
y(Y),
z(Z),
radius(Radius)
{
Set(X, Y, Z, Radius);
}
/*
template<typename T>
Sphere<T>::Sphere(const Circle<T>& 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<typename T>
Sphere<T>::Sphere(const Vector3<T>& center, T Radius)
constexpr Sphere<T>::Sphere(const Vector3<T>& 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<typename T>
Sphere<T>::Sphere(const T sphere[4])
constexpr Sphere<T>::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<typename T>
template<typename U>
Sphere<T>::Sphere(const Sphere<U>& sphere)
constexpr Sphere<T>::Sphere(const Sphere<U>& sphere) :
x(static_cast<T>(sphere.x)),
y(static_cast<T>(sphere.y)),
z(static_cast<T>(sphere.z)),
radius(static_cast<T>(sphere.radius))
{
Set(sphere);
}
template<typename T>
constexpr bool Sphere<T>::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<typename T>
bool Sphere<T>::Contains(T X, T Y, T Z) const
constexpr bool Sphere<T>::Contains(T X, T Y, T Z) const
{
return Contains(Vector3<T>(X, Y, Z));
}
@ -103,9 +109,8 @@ namespace Nz
*
* \see Contains
*/
template<typename T>
bool Sphere<T>::Contains(const Box<T>& box) const
constexpr bool Sphere<T>::Contains(const Box<T>& box) const
{
if (Contains(box.GetMinimum()) && Contains(box.GetMaximum()))
return true;
@ -119,9 +124,8 @@ namespace Nz
*
* \param point Position of the point
*/
template<typename T>
bool Sphere<T>::Contains(const Vector3<T>& point) const
constexpr bool Sphere<T>::Contains(const Vector3<T>& 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<typename T>
T Sphere<T>::Distance(T X, T Y, T Z) const
{
@ -147,7 +150,6 @@ namespace Nz
*
* \param point Position of the point
*/
template<typename T>
T Sphere<T>::Distance(const Vector3<T>& point) const
{
@ -164,7 +166,6 @@ namespace Nz
*
* \see ExtendTo
*/
template<typename T>
Sphere<T>& Sphere<T>::ExtendTo(T X, T Y, T Z)
{
@ -181,7 +182,6 @@ namespace Nz
*
* \see ExtendTo
*/
template<typename T>
Sphere<T>& Sphere<T>::ExtendTo(const Vector3<T>& point)
{
@ -196,9 +196,8 @@ namespace Nz
*
* \see GetPositiveVertex
*/
template<typename T>
Vector3<T> Sphere<T>::GetNegativeVertex(const Vector3<T>& normal) const
constexpr Vector3<T> Sphere<T>::GetNegativeVertex(const Vector3<T>& normal) const
{
Vector3<T> 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<typename T>
Vector3<T> Sphere<T>::GetPosition() const
constexpr Vector3<T> Sphere<T>::GetPosition() const
{
return Vector3<T>(x, y, z);
}
@ -225,9 +223,8 @@ namespace Nz
*
* \see GetNegativeVertex
*/
template<typename T>
Vector3<T> Sphere<T>::GetPositiveVertex(const Vector3<T>& normal) const
constexpr Vector3<T> Sphere<T>::GetPositiveVertex(const Vector3<T>& normal) const
{
Vector3<T> pos(GetPosition());
pos += normal * radius;
@ -241,9 +238,8 @@ namespace Nz
*
* \param box Box to check
*/
template<typename T>
bool Sphere<T>::Intersect(const Box<T>& box) const
constexpr bool Sphere<T>::Intersect(const Box<T>& box) const
{
// Arvo's algorithm.
T squaredDistance = T(0.0);
@ -289,9 +285,8 @@ namespace Nz
*
* \param sphere Sphere to check
*/
template<typename T>
bool Sphere<T>::Intersect(const Sphere& sphere) const
constexpr bool Sphere<T>::Intersect(const Sphere& sphere) const
{
return GetPosition().SquaredDistance(Vector3<T>(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<typename T>
bool Sphere<T>::IsValid() const
constexpr bool Sphere<T>::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<typename T>
Sphere<T>& Sphere<T>::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<typename T>
Sphere<T>& Sphere<T>::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<typename T>
Sphere<T>& Sphere<T>::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<typename T>
Sphere<T>& Sphere<T>::Set(const Vector3<T>& center, T Radius)
{
x = center.x;
y = center.y;
z = center.z;
radius = Radius;
return *this;
}
/*
template<typename T>
Sphere<T>& Sphere<T>::Set(const Circle<T>& 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<typename T>
Sphere<T>& Sphere<T>::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<typename T>
template<typename U>
Sphere<T>& Sphere<T>::Set(const Sphere<U>& 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<typename T>
T& Sphere<T>::operator[](std::size_t i)
constexpr T& Sphere<T>::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<typename T>
T Sphere<T>::operator[](std::size_t i) const
constexpr T Sphere<T>::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<typename T>
Sphere<T> Sphere<T>::operator*(T scalar) const
constexpr Sphere<T> Sphere<T>::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<typename T>
Sphere<T>& Sphere<T>::operator*=(T scalar)
constexpr Sphere<T>& Sphere<T>::operator*=(T scalar)
{
radius *= scalar;
}
@ -512,12 +377,10 @@ namespace Nz
*
* \param sphere Other sphere to compare with
*/
template<typename T>
bool Sphere<T>::operator==(const Sphere& sphere) const
constexpr bool Sphere<T>::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<typename T>
bool Sphere<T>::operator!=(const Sphere& sphere) const
constexpr bool Sphere<T>::operator!=(const Sphere& sphere) const
{
return !operator==(sphere);
}
template<typename T>
constexpr bool Sphere<T>::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<typename T>
constexpr bool Sphere<T>::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<typename T>
constexpr bool Sphere<T>::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<typename T>
constexpr bool Sphere<T>::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<typename T>
constexpr Sphere<T> Sphere<T>::Unit()
{
return Sphere(0, 0, 0, 1);
}
template<typename T>
Sphere<T> Sphere<T>::Unit()
constexpr bool Sphere<T>::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<typename T>
Sphere<T> Sphere<T>::Lerp(const Sphere& from, const Sphere& to, T interpolation)
constexpr Sphere<T> Sphere<T>::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<typename T>
Sphere<T> Sphere<T>::Zero()
constexpr Sphere<T> Sphere<T>::Zero()
{
Sphere sphere;
sphere.MakeZero();
return sphere;
return Sphere(0, 0, 0, 0);
}
/*!
@ -664,3 +579,4 @@ namespace Nz
}
#include <Nazara/Core/DebugOff.hpp>
#include "Sphere.hpp"

View File

@ -24,84 +24,75 @@ namespace Nz
class Vector2
{
public:
Vector2() = default;
Vector2(T X, T Y);
explicit Vector2(T scale);
template<typename U> explicit Vector2(const Vector2<U>& vec);
Vector2(const Vector2& vec) = default;
explicit Vector2(const Vector3<T>& vec);
explicit Vector2(const Vector4<T>& vec);
constexpr Vector2() = default;
constexpr Vector2(T X, T Y);
constexpr explicit Vector2(T scale);
template<typename U> constexpr explicit Vector2(const Vector2<U>& vec);
constexpr Vector2(const Vector2&) = default;
constexpr Vector2(Vector2&&) = default;
constexpr explicit Vector2(const Vector3<T>& vec);
constexpr explicit Vector2(const Vector4<T>& vec);
~Vector2() = default;
T AbsDotProduct(const Vector2& vec) const;
RadianAngle<T> AngleBetween(const Vector2& vec) const;
constexpr bool ApproxEqual(const Vector2& vec, T maxDifference = std::numeric_limits<T>::epsilon()) const;
template<typename U = T>
U Distance(const Vector2& vec) const;
T DotProduct(const Vector2& vec) const;
template<typename U = T> U Distance(const Vector2& vec) const;
constexpr T DotProduct(const Vector2& vec) const;
T GetLength() const;
float GetLengthf() const;
template<typename U = T> 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<T>& vec);
Vector2& Set(const Vector4<T>& vec);
template<typename U> Vector2& Set(const Vector2<U>& 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<T>::epsilon());
template<typename U = T> 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<typename T> std::ostream& operator<<(std::ostream& out, const Vector2<T>& vec);
template<typename T> Vector2<T> operator*(T scale, const Nz::Vector2<T>& vec);
template<typename T> Vector2<T> operator/(T scale, const Nz::Vector2<T>& vec);
template<typename T> constexpr Vector2<T> operator*(T scale, const Nz::Vector2<T>& vec);
template<typename T> constexpr Vector2<T> operator/(T scale, const Nz::Vector2<T>& vec);
}
namespace std

View File

@ -24,11 +24,11 @@ namespace Nz
* \param X X component
* \param Y Y component
*/
template<typename T>
Vector2<T>::Vector2(T X, T Y)
constexpr Vector2<T>::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<typename T>
Vector2<T>::Vector2(T scale)
constexpr Vector2<T>::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<typename T>
template<typename U>
Vector2<T>::Vector2(const Vector2<U>& vec)
constexpr Vector2<T>::Vector2(const Vector2<U>& vec) :
x(static_cast<T>(vec.x)),
y(static_cast<T>(vec.y))
{
Set(vec);
}
/*!
@ -61,11 +61,11 @@ namespace Nz
*
* \param vec Vector3 where only the first two components are taken
*/
template<typename T>
Vector2<T>::Vector2(const Vector3<T>& vec)
constexpr Vector2<T>::Vector2(const Vector3<T>& 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<typename T>
Vector2<T>::Vector2(const Vector4<T>& vec)
constexpr Vector2<T>::Vector2(const Vector4<T>& vec) :
x(vec.x),
y(vec.y)
{
Set(vec);
}
/*!
@ -88,7 +88,6 @@ namespace Nz
*
* \see DotProduct
*/
template<typename T>
T Vector2<T>::AbsDotProduct(const Vector2& vec) const
{
@ -105,13 +104,18 @@ namespace Nz
*
* \see NormalizeAngle
*/
template<typename T>
RadianAngle<T> Vector2<T>::AngleBetween(const Vector2& vec) const
{
return std::atan2(vec.y, vec.x) - std::atan2(y, x);
}
template<typename T>
constexpr bool Vector2<T>::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<typename T>
template<typename U>
U Vector2<T>::Distance(const Vector2& vec) const
@ -136,9 +139,8 @@ namespace Nz
*
* \see AbsDotProduct, DotProduct
*/
template<typename T>
T Vector2<T>::DotProduct(const Vector2& vec) const
constexpr T Vector2<T>::DotProduct(const Vector2& vec) const
{
return x*vec.x + y*vec.y;
}
@ -149,22 +151,11 @@ namespace Nz
*
* \see GetSquaredLength
*/
template<typename T>
template<typename U>
T Vector2<T>::GetLength() const
{
return static_cast<T>(std::sqrt(GetSquaredLength()));
}
/*!
* \brief Calculates the length (magnitude) of the vector
* \return The length in float of the vector
*/
template<typename T>
float Vector2<T>::GetLengthf() const
{
return std::sqrt(static_cast<float>(GetSquaredLength()));
return static_cast<U>(std::sqrt(static_cast<U>(GetSquaredLength())));
}
/*!
@ -177,7 +168,6 @@ namespace Nz
*
* \see Normalize
*/
template<typename T>
Vector2<T> Vector2<T>::GetNormal(T* length) const
{
@ -193,65 +183,12 @@ namespace Nz
*
* \see GetLength
*/
template<typename T>
T Vector2<T>::GetSquaredLength() const
constexpr T Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::Maximize(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::Maximize(const Vector2& vec)
{
if (vec.x > x)
x = vec.x;
@ -281,9 +217,8 @@ namespace Nz
*
* \see Maximize
*/
template<typename T>
Vector2<T>& Vector2<T>::Minimize(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::Minimize(const Vector2& vec)
{
if (vec.x < x)
x = vec.x;
@ -304,7 +239,6 @@ namespace Nz
*
* \see GetNormal
*/
template<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::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<typename T>
template<typename U>
Vector2<T>& Vector2<T>::Set(const Vector2<U>& 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<typename T>
Vector2<T>& Vector2<T>::Set(const Vector3<T>& 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<typename T>
Vector2<T>& Vector2<T>::Set(const Vector4<T>& 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<typename T>
T Vector2<T>::SquaredDistance(const Vector2& vec) const
constexpr T Vector2<T>::SquaredDistance(const Vector2& vec) const
{
return (*this - vec).GetSquaredLength();
}
@ -450,7 +286,7 @@ namespace Nz
* \return X, Y depending on index (0, 1)
*/
template<typename T>
T& Vector2<T>::operator[](std::size_t i)
constexpr T& Vector2<T>::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<typename T>
T Vector2<T>::operator[](std::size_t i) const
constexpr T Vector2<T>::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<typename T>
const Vector2<T>& Vector2<T>::operator+() const
constexpr const Vector2<T>& Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator-() const
constexpr Vector2<T> Vector2<T>::operator-() const
{
return Vector2(-x, -y);
}
@ -495,9 +329,8 @@ namespace Nz
*
* \param vec The other vector to add components with
*/
template<typename T>
Vector2<T> Vector2<T>::operator+(const Vector2& vec) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator-(const Vector2& vec) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator*(const Vector2& vec) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator*(T scale) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator/(const Vector2& vec) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::operator/(T scale) const
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::operator+=(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::operator-=(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::operator*=(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::operator*=(T scale)
constexpr Vector2<T>& Vector2<T>::operator*=(T scale)
{
x *= scale;
y *= scale;
@ -637,9 +461,8 @@ namespace Nz
*
* \param vec The other vector to multiply components with
*/
template<typename T>
Vector2<T>& Vector2<T>::operator/=(const Vector2& vec)
constexpr Vector2<T>& Vector2<T>::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<typename T>
Vector2<T>& Vector2<T>::operator/=(T scale)
constexpr Vector2<T>& Vector2<T>::operator/=(T scale)
{
x /= scale;
y /= scale;
@ -669,12 +491,10 @@ namespace Nz
*
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector2<T>::operator==(const Vector2& vec) const
constexpr bool Vector2<T>::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<typename T>
bool Vector2<T>::operator!=(const Vector2& vec) const
constexpr bool Vector2<T>::operator!=(const Vector2& vec) const
{
return !operator==(vec);
}
@ -696,14 +515,13 @@ namespace Nz
*
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector2<T>::operator<(const Vector2& vec) const
constexpr bool Vector2<T>::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<typename T>
bool Vector2<T>::operator<=(const Vector2& vec) const
constexpr bool Vector2<T>::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<typename T>
bool Vector2<T>::operator>(const Vector2& vec) const
constexpr bool Vector2<T>::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<typename T>
constexpr bool Vector2<T>::operator>=(const Vector2& vec) const
{
if (x != vec.x)
return x > vec.x;
return y >= vec.y;
}
template<typename T>
bool Vector2<T>::operator>=(const Vector2& vec) const
constexpr bool Vector2<T>::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<typename T>
T Vector2<T>::DotProduct(const Vector2& vec1, const Vector2& vec2)
constexpr T Vector2<T>::DotProduct(const Vector2& vec1, const Vector2& vec2)
{
return vec1.DotProduct(vec2);
}
@ -794,9 +620,8 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
Vector2<T> Vector2<T>::Lerp(const Vector2& from, const Vector2& to, T interpolation)
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::Unit()
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::UnitX()
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::UnitY()
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> Vector2<T>::Zero()
constexpr Vector2<T> Vector2<T>::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<typename T>
Vector2<T> operator*(T scale, const Vector2<T>& vec)
constexpr Vector2<T> operator*(T scale, const Vector2<T>& vec)
{
return Vector2<T>(scale * vec.x, scale * vec.y);
}
@ -916,7 +718,7 @@ namespace Nz
* \param scale The scalar to divide components with
*/
template<typename T>
Vector2<T> operator/(T scale, const Vector2<T>& vec)
constexpr Vector2<T> operator/(T scale, const Vector2<T>& vec)
{
return Vector2<T>(scale / vec.x, scale / vec.y);
}
@ -984,3 +786,4 @@ namespace std
}
#include <Nazara/Core/DebugOff.hpp>
#include "Vector2.hpp"

View File

@ -24,105 +24,91 @@ namespace Nz
class Vector3
{
public:
Vector3() = default;
Vector3(T X, T Y, T Z);
Vector3(T X, const Vector2<T>& vec);
explicit Vector3(T scale);
Vector3(const Vector2<T>& vec, T Z = 0.0);
template<typename U> explicit Vector3(const Vector3<U>& vec);
Vector3(const Vector3& vec) = default;
explicit Vector3(const Vector4<T>& vec);
constexpr Vector3() = default;
constexpr Vector3(T X, T Y, T Z);
constexpr Vector3(T X, const Vector2<T>& vec);
constexpr explicit Vector3(T scale);
constexpr Vector3(const Vector2<T>& vec, T Z = 0.0);
template<typename U> constexpr explicit Vector3(const Vector3<U>& vec);
constexpr Vector3(const Vector3&) = default;
constexpr Vector3(Vector3&&) = default;
constexpr explicit Vector3(const Vector4<T>& vec);
~Vector3() = default;
T AbsDotProduct(const Vector3& vec) const;
RadianAngle<T> AngleBetween(const Vector3& vec) const;
constexpr bool ApproxEqual(const Vector3& vec, T maxDifference = std::numeric_limits<T>::epsilon()) const;
Vector3 CrossProduct(const Vector3& vec) const;
constexpr Vector3 CrossProduct(const Vector3& vec) const;
template<typename U = T>
U Distance(const Vector3& vec) const;
T DotProduct(const Vector3& vec) const;
template<typename U = T> U Distance(const Vector3& vec) const;
constexpr T DotProduct(const Vector3& vec) const;
Vector3 GetAbs() const;
T GetLength() const;
float GetLengthf() const;
template<typename U = T> 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<T>& vec);
Vector3& Set(T scale);
Vector3& Set(const T* vec);
Vector3& Set(const Vector2<T>& vec, T Z = 0.0);
template<typename U> Vector3& Set(const Vector3<U>& vec);
Vector3& Set(const Vector4<T>& 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<T>::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<typename U = T> 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<typename T> std::ostream& operator<<(std::ostream& out, const Vector3<T>& vec);
template<typename T> Vector3<T> operator*(T scale, const Vector3<T>& vec);
template<typename T> Vector3<T> operator/(T scale, const Vector3<T>& vec);
template<typename T> constexpr Vector3<T> operator*(T scale, const Vector3<T>& vec);
template<typename T> constexpr Vector3<T> operator/(T scale, const Vector3<T>& vec);
}
namespace std

View File

@ -27,9 +27,11 @@ namespace Nz
* \param Z Z component
*/
template<typename T>
Vector3<T>::Vector3(T X, T Y, T Z)
constexpr Vector3<T>::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<typename T>
Vector3<T>::Vector3(T X, const Vector2<T>& vec)
constexpr Vector3<T>::Vector3(T X, const Vector2<T>& 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<typename T>
Vector3<T>::Vector3(T scale)
constexpr Vector3<T>::Vector3(T scale) :
x(scale),
y(scale),
z(scale)
{
Set(scale);
}
/*!
@ -62,9 +68,11 @@ namespace Nz
* \param Z Z component
*/
template<typename T>
Vector3<T>::Vector3(const Vector2<T>& vec, T Z)
constexpr Vector3<T>::Vector3(const Vector2<T>& vec, T Z) :
x(vec.x),
y(vec.y),
z(Z)
{
Set(vec, Z);
}
/*!
@ -74,9 +82,11 @@ namespace Nz
*/
template<typename T>
template<typename U>
Vector3<T>::Vector3(const Vector3<U>& vec)
constexpr Vector3<T>::Vector3(const Vector3<U>& vec) :
x(static_cast<T>(vec.x)),
y(static_cast<T>(vec.y)),
z(static_cast<T>(vec.z))
{
Set(vec);
}
/*!
@ -85,9 +95,11 @@ namespace Nz
* \param vec Vector4 where only the first three components are taken
*/
template<typename T>
Vector3<T>::Vector3(const Vector4<T>& vec)
constexpr Vector3<T>::Vector3(const Vector4<T>& 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<typename T>
constexpr bool Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::CrossProduct(const Vector3& vec) const
constexpr Vector3<T> Vector3<T>::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<typename U>
U Vector3<T>::Distance(const Vector3& vec) const
{
return static_cast<U>(std::sqrt(SquaredDistance(vec)));
return static_cast<U>(std::sqrt(static_cast<U>(SquaredDistance(vec))));
}
/*!
@ -174,7 +192,7 @@ namespace Nz
* \see AbsDotProduct, DotProduct
*/
template<typename T>
T Vector3<T>::DotProduct(const Vector3& vec) const
constexpr T Vector3<T>::DotProduct(const Vector3& vec) const
{
return x * vec.x + y * vec.y + z * vec.z;
}
@ -196,19 +214,10 @@ namespace Nz
* \see GetSquaredLength
*/
template<typename T>
T Vector3<T>::GetLength() const
template<typename U>
U Vector3<T>::GetLength() const
{
return static_cast<T>(std::sqrt(GetSquaredLength()));
}
/*!
* \brief Calculates the length (magnitude) of the vector
* \return The length in float of the vector
*/
template<typename T>
float Vector3<T>::GetLengthf() const
{
return std::sqrt(static_cast<float>(GetSquaredLength()));
return static_cast<U>(std::sqrt(static_cast<U>(GetSquaredLength())));
}
/*!
@ -237,143 +246,11 @@ namespace Nz
* \see GetLength
*/
template<typename T>
T Vector3<T>::GetSquaredLength() const
constexpr T Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::Maximize(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::Maximize(const Vector3& vec)
{
if (vec.x > x)
x = vec.x;
@ -406,7 +283,7 @@ namespace Nz
* \see Maximize
*/
template<typename T>
Vector3<T>& Vector3<T>::Minimize(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::Set(T X, const Vector2<T>& 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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::Set(const Vector2<T>& 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<typename T>
template<typename U>
Vector3<T>& Vector3<T>::Set(const Vector3<U>& 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<typename T>
Vector3<T>& Vector3<T>::Set(const Vector4<T>& 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<typename T>
T Vector3<T>::SquaredDistance(const Vector3& vec) const
constexpr T Vector3<T>::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<typename T>
T& Vector3<T>::operator[](std::size_t i)
constexpr T& Vector3<T>::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<typename T>
T Vector3<T>::operator[](std::size_t i) const
constexpr const T& Vector3<T>::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<typename T>
const Vector3<T>& Vector3<T>::operator+() const
constexpr const Vector3<T>& Vector3<T>::operator+() const
{
return *this;
}
@ -624,7 +386,7 @@ namespace Nz
* \return A constant reference to this vector with negate components
*/
template<typename T>
Vector3<T> Vector3<T>::operator-() const
constexpr Vector3<T> Vector3<T>::operator-() const
{
return Vector3(-x, -y, -z);
}
@ -636,7 +398,7 @@ namespace Nz
* \param vec The other vector to add components with
*/
template<typename T>
Vector3<T> Vector3<T>::operator+(const Vector3& vec) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::operator-(const Vector3& vec) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::operator*(const Vector3& vec) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::operator*(T scale) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::operator/(const Vector3& vec) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::operator/(T scale) const
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::operator+=(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::operator-=(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::operator*=(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::operator*=(T scale)
constexpr Vector3<T>& Vector3<T>::operator*=(T scale)
{
x *= scale;
y *= scale;
@ -772,7 +534,7 @@ namespace Nz
* \param vec The other vector to multiply components with
*/
template<typename T>
Vector3<T>& Vector3<T>::operator/=(const Vector3& vec)
constexpr Vector3<T>& Vector3<T>::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<typename T>
Vector3<T>& Vector3<T>::operator/=(T scale)
constexpr Vector3<T>& Vector3<T>::operator/=(T scale)
{
x /= scale;
y /= scale;
@ -804,11 +566,9 @@ namespace Nz
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector3<T>::operator==(const Vector3& vec) const
constexpr bool Vector3<T>::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<typename T>
bool Vector3<T>::operator!=(const Vector3& vec) const
constexpr bool Vector3<T>::operator!=(const Vector3& vec) const
{
return !operator==(vec);
}
@ -830,17 +590,15 @@ namespace Nz
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector3<T>::operator<(const Vector3& vec) const
constexpr bool Vector3<T>::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<typename T>
bool Vector3<T>::operator<=(const Vector3& vec) const
constexpr bool Vector3<T>::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<typename T>
bool Vector3<T>::operator>(const Vector3& vec) const
constexpr bool Vector3<T>::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<typename T>
bool Vector3<T>::operator>=(const Vector3& vec) const
constexpr bool Vector3<T>::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<typename T>
constexpr bool Vector3<T>::ApproxEqual(const Vector3& lhs, const Vector3& rhs, T maxDifference)
{
return lhs.ApproxEqual(rhs, maxDifference);
}
/*!
@ -897,7 +671,7 @@ namespace Nz
* \see CrossProduct
*/
template<typename T>
Vector3<T> Vector3<T>::CrossProduct(const Vector3& vec1, const Vector3& vec2)
constexpr Vector3<T> Vector3<T>::CrossProduct(const Vector3& vec1, const Vector3& vec2)
{
return vec1.CrossProduct(vec2);
}
@ -912,7 +686,7 @@ namespace Nz
* \see AbsDotProduct, DotProduct
*/
template<typename T>
T Vector3<T>::DotProduct(const Vector3& vec1, const Vector3& vec2)
constexpr T Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Backward()
constexpr Vector3<T> Vector3<T>::Backward()
{
Vector3 vector;
vector.MakeBackward();
return Vector3(0, 0, 1);
}
return vector;
template<typename T>
constexpr Vector3<T> Vector3<T>::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<typename T>
template<typename U>
@ -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<typename T>
Vector3<T> Vector3<T>::Down()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Forward()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Left()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Lerp(const Vector3& from, const Vector3& to, T interpolation)
constexpr Vector3<T> Vector3<T>::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<typename T>
constexpr Vector3<T> Vector3<T>::Max(const Vector3& lhs, const Vector3& rhs)
{
Vector3 max = lhs;
max.Maximize(rhs);
return max;
}
template<typename T>
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Right()
constexpr Vector3<T> Vector3<T>::Right()
{
Vector3 vector;
vector.MakeRight();
return vector;
return Vector3(1, 0, 0);
}
/*!
@ -1059,7 +830,7 @@ namespace Nz
* \see Distance
*/
template<typename T>
T Vector3<T>::SquaredDistance(const Vector3& vec1, const Vector3& vec2)
constexpr T Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Unit()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::UnitX()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::UnitY()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::UnitZ()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Up()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> Vector3<T>::Zero()
constexpr Vector3<T> Vector3<T>::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<typename T>
Vector3<T> operator*(T scale, const Vector3<T>& vec)
constexpr Vector3<T> operator*(T scale, const Vector3<T>& vec)
{
return Vector3<T>(scale * vec.x, scale * vec.y, scale * vec.z);
}
@ -1230,7 +971,7 @@ namespace Nz
* \param scale The scalar to divide components with
*/
template<typename T>
Vector3<T> operator/(T scale, const Vector3<T>& vec)
constexpr Vector3<T> operator/(T scale, const Vector3<T>& vec)
{
return Vector3<T>(scale / vec.x, scale / vec.y, scale / vec.z);
}

View File

@ -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<T>& vec);
Vector4(T X, const Vector2<T>& vec, T W);
Vector4(T X, const Vector3<T>& vec);
explicit Vector4(T scale);
Vector4(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
Vector4(const Vector3<T>& vec, T W = 1.0);
template<typename U> explicit Vector4(const Vector4<U>& 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<T>& vec);
constexpr Vector4(T X, const Vector2<T>& vec, T W);
constexpr Vector4(T X, const Vector3<T>& vec);
constexpr explicit Vector4(T scale);
constexpr Vector4(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
constexpr Vector4(const Vector3<T>& vec, T W = 1.0);
template<typename U> constexpr explicit Vector4(const Vector4<U>& 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<T>::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<T>& vec);
Vector4& Set(T X, const Vector2<T>& vec, T W);
Vector4& Set(T X, const Vector3<T>& vec);
Vector4& Set(T scale);
Vector4& Set(const T* vec);
Vector4& Set(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
Vector4& Set(const Vector3<T>& vec, T W = 1.0);
template<typename U> Vector4& Set(const Vector4<U>& 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<T>::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<typename T> std::ostream& operator<<(std::ostream& out, const Vector4<T>& vec);
template<typename T> Vector4<T> operator*(T scale, const Vector4<T>& vec);
template<typename T> Vector4<T> operator/(T scale, const Vector4<T>& vec);
template<typename T> constexpr Vector4<T> operator*(T scale, const Vector4<T>& vec);
template<typename T> constexpr Vector4<T> operator/(T scale, const Vector4<T>& vec);
}
namespace std

View File

@ -28,11 +28,13 @@ namespace Nz
* \param Z Z component
* \param W W component
*/
template<typename T>
Vector4<T>::Vector4(T X, T Y, T Z, T W)
constexpr Vector4<T>::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<typename T>
Vector4<T>::Vector4(T X, T Y, const Vector2<T>& vec)
constexpr Vector4<T>::Vector4(T X, T Y, const Vector2<T>& 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<typename T>
Vector4<T>::Vector4(T X, const Vector2<T>& vec, T W)
constexpr Vector4<T>::Vector4(T X, const Vector2<T>& 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<typename T>
Vector4<T>::Vector4(T X, const Vector3<T>& vec)
constexpr Vector4<T>::Vector4(T X, const Vector3<T>& 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<typename T>
Vector4<T>::Vector4(T scale)
constexpr Vector4<T>::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<typename T>
Vector4<T>::Vector4(const Vector2<T>& vec, T Z, T W)
constexpr Vector4<T>::Vector4(const Vector2<T>& 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<typename T>
Vector4<T>::Vector4(const Vector3<T>& vec, T W)
constexpr Vector4<T>::Vector4(const Vector3<T>& vec, T W) :
x(vec.x),
y(vec.y),
z(vec.z),
w(W)
{
Set(vec, W);
}
/*!
@ -123,9 +137,12 @@ namespace Nz
template<typename T>
template<typename U>
Vector4<T>::Vector4(const Vector4<U>& vec)
constexpr Vector4<T>::Vector4(const Vector4<U>& vec) :
x(static_cast<T>(vec.x)),
y(static_cast<T>(vec.y)),
z(static_cast<T>(vec.z)),
w(static_cast<T>(vec.w))
{
Set(vec);
}
/*!
@ -136,13 +153,18 @@ namespace Nz
*
* \see DotProduct
*/
template<typename T>
T Vector4<T>::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<typename T>
constexpr bool Vector4<T>::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<typename T>
T Vector4<T>::DotProduct(const Vector4& vec) const
constexpr T Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::Maximize(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::Maximize(const Vector4& vec)
{
if (vec.x > x)
x = vec.x;
@ -263,9 +230,8 @@ namespace Nz
*
* \see Maximize
*/
template<typename T>
Vector4<T>& Vector4<T>::Minimize(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::Minimize(const Vector4& vec)
{
if (vec.x < x)
x = vec.x;
@ -290,11 +256,10 @@ namespace Nz
*
* \see GetNormal
*/
template<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::Set(T X, T Y, const Vector2<T>& 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<typename T>
Vector4<T>& Vector4<T>::Set(T X, const Vector2<T>& 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<typename T>
Vector4<T>& Vector4<T>::Set(T X, const Vector3<T>& 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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::Set(const Vector2<T>& 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<typename T>
Vector4<T>& Vector4<T>::Set(const Vector3<T>& 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<typename T>
template<typename U>
Vector4<T>& Vector4<T>::Set(const Vector4<U>& 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<typename T>
std::string Vector4<T>::ToString() const
{
@ -497,7 +290,7 @@ namespace Nz
* \return X, Y, Z depending on index (0, 1, 2)
*/
template<typename T>
T& Vector4<T>::operator[](std::size_t i)
constexpr T& Vector4<T>::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<typename T>
T Vector4<T>::operator[](std::size_t i) const
constexpr const T& Vector4<T>::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<typename T>
const Vector4<T>& Vector4<T>::operator+() const
constexpr const Vector4<T>& Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator-() const
constexpr Vector4<T> Vector4<T>::operator-() const
{
return Vector4(-x, -y, -z, -w);
}
@ -542,9 +333,8 @@ namespace Nz
*
* \param vec The other vector to add components with
*/
template<typename T>
Vector4<T> Vector4<T>::operator+(const Vector4& vec) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator-(const Vector4& vec) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator*(const Vector4& vec) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator*(T scale) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator/(const Vector4& vec) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::operator/(T scale) const
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::operator+=(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::operator-=(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::operator*=(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::operator*=(T scale)
constexpr Vector4<T>& Vector4<T>::operator*=(T scale)
{
x *= scale;
y *= scale;
@ -692,9 +473,8 @@ namespace Nz
*
* \param vec The other vector to multiply components with
*/
template<typename T>
Vector4<T>& Vector4<T>::operator/=(const Vector4& vec)
constexpr Vector4<T>& Vector4<T>::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<typename T>
Vector4<T>& Vector4<T>::operator/=(T scale)
constexpr Vector4<T>& Vector4<T>::operator/=(T scale)
{
x /= scale;
y /= scale;
@ -728,14 +507,10 @@ namespace Nz
*
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector4<T>::operator==(const Vector4& vec) const
constexpr bool Vector4<T>::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<typename T>
bool Vector4<T>::operator!=(const Vector4& vec) const
constexpr bool Vector4<T>::operator!=(const Vector4& vec) const
{
return !operator==(vec);
}
@ -757,24 +531,19 @@ namespace Nz
*
* \param vec Other vector to compare with
*/
template<typename T>
bool Vector4<T>::operator<(const Vector4& vec) const
constexpr bool Vector4<T>::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<typename T>
bool Vector4<T>::operator<=(const Vector4& vec) const
constexpr bool Vector4<T>::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<typename T>
bool Vector4<T>::operator>(const Vector4& vec) const
constexpr bool Vector4<T>::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<typename T>
constexpr bool Vector4<T>::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<typename T>
bool Vector4<T>::operator>=(const Vector4& vec) const
constexpr bool Vector4<T>::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<typename T>
T Vector4<T>::DotProduct(const Vector4& vec1, const Vector4& vec2)
constexpr T Vector4<T>::DotProduct(const Vector4& vec1, const Vector4& vec2)
{
return vec1.DotProduct(vec2);
}
@ -857,7 +643,7 @@ namespace Nz
* \see Lerp
*/
template<typename T>
Vector4<T> Vector4<T>::Lerp(const Vector4& from, const Vector4& to, T interpolation)
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::UnitX()
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::UnitY()
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::UnitZ()
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> Vector4<T>::Zero()
constexpr Vector4<T> Vector4<T>::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<typename T>
Vector4<T> operator*(T scale, const Vector4<T>& vec)
constexpr Vector4<T> operator*(T scale, const Vector4<T>& vec)
{
return Nz::Vector4<T>(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<typename T>
Vector4<T> operator/(T scale, const Vector4<T>& vec)
constexpr Vector4<T> operator/(T scale, const Vector4<T>& vec)
{
return Nz::Vector4<T>(scale / vec.x, scale / vec.y, scale / vec.z, scale / vec.w);
}
@ -1061,3 +822,4 @@ namespace std
}
#include <Nazara/Core/DebugOff.hpp>
#include "Vector4.hpp"

View File

@ -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);
}

View File

@ -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()

View File

@ -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]);
}

View File

@ -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

View File

@ -117,7 +117,7 @@ namespace Nz
StackArray<Vector2f> 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<cpFloat>(*vertices++);
}
Vector2f ChipmunkConvexCollider2D::ComputeCenterOfMass() const

View File

@ -45,7 +45,7 @@ namespace Nz
StackArray<Vector2f> 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<cpFloat>(queryInfo.point.x, queryInfo.point.y));
result->closestPoint = Vector2f(Vector2<cpFloat>(queryInfo.point.x, queryInfo.point.y));
result->distance = float(queryInfo.distance);
result->fraction.Set(Vector2<cpFloat>(queryInfo.gradient.x, queryInfo.gradient.y));
result->fraction = Vector2f(Vector2<cpFloat>(queryInfo.gradient.x, queryInfo.gradient.y));
result->nearestBody = static_cast<ChipmunkRigidBody2D*>(cpShapeGetUserData(queryInfo.shape));
return true;
@ -213,8 +213,8 @@ namespace Nz
RaycastHit hitInfo;
hitInfo.fraction = float(alpha);
hitInfo.hitNormal.Set(Vector2<cpFloat>(normal.x, normal.y));
hitInfo.hitPos.Set(Vector2<cpFloat>(point.x, point.y));
hitInfo.hitNormal = Vector2f(Vector2<cpFloat>(normal.x, normal.y));
hitInfo.hitPos = Vector2f(Vector2<cpFloat>(point.x, point.y));
hitInfo.nearestBody = static_cast<ChipmunkRigidBody2D*>(cpShapeGetUserData(shape));
callback(hitInfo);
@ -234,8 +234,8 @@ namespace Nz
RaycastHit hitInfo;
hitInfo.fraction = float(alpha);
hitInfo.hitNormal.Set(Vector2<cpFloat>(normal.x, normal.y));
hitInfo.hitPos.Set(Vector2<cpFloat>(point.x, point.y));
hitInfo.hitNormal = Vector2f(Vector2<cpFloat>(normal.x, normal.y));
hitInfo.hitPos = Vector2f(Vector2<cpFloat>(point.x, point.y));
hitInfo.nearestBody = static_cast<ChipmunkRigidBody2D*>(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<cpFloat>(queryInfo.normal.x, queryInfo.normal.y));
hitInfo->hitPos.Set(Vector2<cpFloat>(queryInfo.point.x, queryInfo.point.y));
hitInfo->hitNormal = Vector2f(Vector2<cpFloat>(queryInfo.normal.x, queryInfo.normal.y));
hitInfo->hitPos = Vector2f(Vector2<cpFloat>(queryInfo.point.x, queryInfo.point.y));
hitInfo->nearestBody = static_cast<ChipmunkRigidBody2D*>(cpShapeGetUserData(queryInfo.shape));
return true;

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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++;
}

View File

@ -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 })
{

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -83,7 +83,7 @@ namespace Nz
sequenceJoint.rotation = rotationQuat * frames[frameIndex].joints[jointIndex].orient;
}
sequenceJoint.scale.Set(1.f);
sequenceJoint.scale = Vector3f::Unit();
}
}

View File

@ -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))

View File

@ -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;
}
}

View File

@ -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<float>(firstBlock.characterSize));
for (const Block& block : m_blocks)
{

View File

@ -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<float>(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);

View File

@ -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);

View File

@ -56,8 +56,8 @@ namespace Nz
textDrawer.Clear();
UpdateTextSprite();
m_cursorPositionBegin.MakeZero();
m_cursorPositionEnd.MakeZero();
m_cursorPositionBegin = Vector2ui::Zero();
m_cursorPositionEnd = Vector2ui::Zero();
RefreshCursor();
}

View File

@ -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<SlicedSprite>(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<SlicedSprite>(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<SlicedSprite>(m_material);
m_sprite->SetCorners(corner, corner);

View File

@ -196,7 +196,7 @@ SCENARIO("Angle", "[MATH][ANGLE]")
{
Nz::RadianAnglef expectedResult(Nz::Pi<float>);
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));
}
}
}

View File

@ -65,8 +65,10 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]")
THEN("There's no problem")
{
Nz::BoundingVolume<int> 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")

View File

@ -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));
}
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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));

View File

@ -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<float>::infinity());

View File

@ -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)));
}
}

View File

@ -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)));
}

View File

@ -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);