// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Math module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include ///DOC: Pour que les coins soient valides, la méthode Update doit être appelée namespace Nz { /*! * \ingroup math * \class Nz::OrientedBox * \brief Math class that represents an oriented three dimensional box * * \remark You need to call Update not to have undefined behaviour */ /*! * \brief Constructs a OrientedBox object from a box * * \param box Box object */ template constexpr OrientedBox::OrientedBox(const Box& box) : localBox(box) { } /*! * \brief Constructs a OrientedBox object from another type of OrientedBox * * \param orientedBox OrientedBox of type U to convert to type T */ template template constexpr OrientedBox::OrientedBox(const OrientedBox& orientedBox) : localBox(orientedBox.localBox) { for (auto&& [cornerEnum, corner] : m_corners.iter_kv()) corner = Vector3(orientedBox.GetCorner(cornerEnum)); } template constexpr bool OrientedBox::ApproxEqual(const OrientedBox& obb, T maxDifference) const { if (!localBox.ApproxEqual(obb.localBox, maxDifference)) return false; for (auto&& [cornerEnum, corner] : m_corners.iter_kv()) { if (!corner.ApproxEqual(obb.GetCorner(cornerEnum), maxDifference)) return false; } return true; } /*! * \brief Gets the Vector3 for the corner * \return The position of the corner of the oriented box according to enum BoxCorner * * \param corner Enumeration of type BoxCorner * * \remark If enumeration is not defined in BoxCorner, a NazaraError is thrown and a Vector3 uninitialised is returned */ template constexpr const Vector3& OrientedBox::GetCorner(BoxCorner corner) const { NazaraAssert(corner <= BoxCorner::Max, "invalid corner"); return m_corners[corner]; } template constexpr const Vector3* OrientedBox::GetCorners() const { return &m_corners.front(); } /*! * \brief Checks whether this oriented box is valid * \return true if the oriented box has a strictly positive width, height and depth */ template constexpr bool OrientedBox::IsValid() const { return localBox.IsValid(); } /*! * \brief Gives a string representation * \return A string representation of the object: "OrientedBox(...)" */ template std::string OrientedBox::ToString() const { std::ostringstream ss; ss << *this; return ss.str(); } /*! * \brief Updates the corners of the box * * \param transformMatrix Matrix4 which represents the transformation to apply on the local box */ template constexpr void OrientedBox::Update(const Matrix4& transformMatrix) { for (auto&& [corner, pos] : m_corners.iter_kv()) pos = transformMatrix.Transform(localBox.GetCorner(corner)); } /*! * \brief Updates the corners of the box * * \param translation Vector3 which represents the translation to apply on the local box */ template constexpr void OrientedBox::Update(const Vector3& translation) { for (auto&& [corner, pos] : m_corners.iter_kv()) pos = localBox.GetCorner(corner) + translation; } /*! * \brief Gets the ith corner of the oriented box * \return A reference to this corner * * \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 constexpr Vector3& OrientedBox::operator()(unsigned int i) { NazaraAssert(i < m_corners.size(), "corner out of range"); return m_corners[static_cast(i)]; } /*! * \brief Gets the ith corner of the oriented box * \return A reference to this corner * * \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 constexpr const Vector3& OrientedBox::operator()(unsigned int i) const { NazaraAssert(i < m_corners.size(), "corner out of range"); return m_corners[static_cast(i)]; } /*! * \brief Compares the oriented box to other one * \return true if the two oriented boxes are the same * * \param box Other oriented box to compare with */ template constexpr bool OrientedBox::operator==(const OrientedBox& box) const { return localBox == box.localBox && m_corners == box.m_corners; } /*! * \brief Compares the oriented box to other one * \return false if the two oriented boxes are the same * * \param box Other oriented box to compare with */ template constexpr bool OrientedBox::operator!=(const OrientedBox& box) const { return !operator==(box); } /*! * \brief Interpolates the oriented box to other one with a factor of interpolation * \return A new oriented box which is the interpolation of two oriented boxes * * \param from Initial oriented box * \param to Target oriented box * \param interpolation Factor of interpolation * * \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 Zero() is returned * * \see Lerp */ template constexpr bool OrientedBox::ApproxEqual(const OrientedBox& lhs, const OrientedBox& rhs, T maxDifference) { return lhs.ApproxEqual(rhs, maxDifference); } template constexpr OrientedBox OrientedBox::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation) { return OrientedBox{ Box::Lerp(from.localBox, to.localBox, interpolation) }; } /*! * \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) */ template constexpr OrientedBox OrientedBox::Zero() { return OrientedBox{ Box::Zero() }; } /*! * \brief Serializes a OrientedBox * \return true if successfully serialized * * \param context Serialization context * \param obb Input oriented box */ template bool Serialize(SerializationContext& context, const OrientedBox& obb, TypeTag>) { if (!Serialize(context, obb.localBox)) return false; for (auto&& corner : obb.m_corners) { if (!Serialize(context, corner)) return false; } return true; } /*! * \brief Unserializes a Matrix4 * \return true if successfully unserialized * * \param context Serialization context * \param obb Output oriented box */ template bool Unserialize(SerializationContext& context, OrientedBox* obb, TypeTag>) { if (!Unserialize(context, &obb->localBox)) return false; for (auto&& corner : obb->m_corners) { if (!Unserialize(context, &corner)) return false; } return true; } /*! * \brief Output operator * \return The stream * * \param out The stream * \param orientedBox The orientedBox to output */ template std::ostream& operator<<(std::ostream& out, const OrientedBox& orientedBox) { return out << "OrientedBox(FLB: " << orientedBox.GetCorner(BoxCorner::FarLeftBottom) << ",\n" << " FLT: " << orientedBox.GetCorner(BoxCorner::FarLeftTop) << ",\n" << " FRB: " << orientedBox.GetCorner(BoxCorner::FarRightBottom) << ",\n" << " FRT: " << orientedBox.GetCorner(BoxCorner::FarRightTop) << ",\n" << " NLB: " << orientedBox.GetCorner(BoxCorner::NearLeftBottom) << ",\n" << " NLT: " << orientedBox.GetCorner(BoxCorner::NearLeftTop) << ",\n" << " NRB: " << orientedBox.GetCorner(BoxCorner::NearRightBottom) << ",\n" << " NRT: " << orientedBox.GetCorner(BoxCorner::NearRightTop) << ")\n"; } } #include