// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2010-2014 SharpDX - Alexandre Mutel #pragma once #include "Transform.h" enum class ContainmentType; /// /// Oriented Bounding Box (OBB) is a rectangular block, much like an AABB (Bounding Box) but with an arbitrary orientation in 3D space. /// API_STRUCT() struct FLAXENGINE_API OrientedBoundingBox { DECLARE_SCRIPTING_TYPE_MINIMAL(OrientedBoundingBox); /// /// Half lengths of the box along each axis. /// API_FIELD() Vector3 Extents; /// /// The transformation which aligns and scales the box, and its translation vector represents the center of the box. /// API_FIELD() Transform Transformation; public: /// /// Empty constructor. /// OrientedBoundingBox() { } OrientedBoundingBox(const Vector3& extents, const Transform& transformation) { Extents = extents; Transformation = transformation; } OrientedBoundingBox(const BoundingBox& bb); OrientedBoundingBox(const Vector3& extents, const Matrix& transformation); OrientedBoundingBox(const Vector3& extents, const Matrix3x3& rotationScale, const Vector3& translation); OrientedBoundingBox(const Vector3& minimum, const Vector3& maximum); OrientedBoundingBox(Vector3 points[], int32 pointCount); public: String ToString() const; public: // Gets the eight corners of the bounding box. void GetCorners(Float3 corners[8]) const; void GetCorners(Double3 corners[8]) const; // The size of the OBB if no scaling is applied to the transformation matrix. Vector3 GetSizeUnscaled() const { return Extents * 2.0f; } // Returns the size of the OBB taking into consideration the scaling applied to the transformation matrix. Vector3 GetSize() const; // Returns the square size of the OBB taking into consideration the scaling applied to the transformation matrix. // @returns The size of the consideration. Vector3 GetSizeSquared() const; // Gets the center of the OBB. FORCE_INLINE Vector3 GetCenter() const { return Transformation.Translation; } /// /// Gets the AABB which contains all OBB corners. /// /// The result BoundingBox GetBoundingBox() const; /// /// Gets the AABB which contains all OBB corners. /// /// The result. void GetBoundingBox(BoundingBox& result) const; public: // Transforms this box using a transformation matrix. // @param mat The transformation matrix. void Transform(const Matrix& matrix); void Transform(const ::Transform& transform); // Scales the OBB by scaling its Extents without affecting the Transformation matrix. // By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. // @param scaling Scale to apply to the box. void Scale(const Vector3& scaling) { Extents *= scaling; } // Scales the OBB by scaling its Extents without affecting the Transformation matrix. // By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. // @param scaling Scale to apply to the box. void Scale(Real scaling) { Extents *= scaling; } // Translates the OBB to a new position using a translation vector. // @param translation the translation vector. void Translate(const Vector3& translation) { Transformation.Translation += translation; } public: FORCE_INLINE bool operator==(const OrientedBoundingBox& other) const { return Extents == other.Extents && Transformation == other.Transformation; } FORCE_INLINE bool operator!=(const OrientedBoundingBox& other) const { return Extents != other.Extents || Transformation != other.Transformation; } FORCE_INLINE OrientedBoundingBox operator*(const Matrix& matrix) const { OrientedBoundingBox result = *this; result.Transform(matrix); return result; } FORCE_INLINE OrientedBoundingBox operator*(const ::Transform& matrix) const { OrientedBoundingBox result = *this; result.Transform(matrix); return result; } public: /// /// Creates the centered box (axis aligned). /// /// The center. /// The size. /// The result. static void CreateCentered(const Vector3& center, const Vector3& size, OrientedBoundingBox& result) { result.Extents = size * 0.5f; result.Transformation = ::Transform(center); } /// /// Creates the centered box (axis-aligned). /// /// The center. /// The size. /// The result. static OrientedBoundingBox CreateCentered(const Vector3& center, const Vector3& size) { OrientedBoundingBox result; CreateCentered(center, size, result); return result; } public: // Determines whether a OBB contains a point. // @param point The point to test. // @returns The type of containment the two objects have. ContainmentType Contains(const Vector3& point, Real* distance = nullptr) const; // Determines whether a OBB contains a BoundingSphere. // @param sphere The sphere to test. // @param ignoreScale Optimize the check operation by assuming that OBB has no scaling applied. // @returns The type of containment the two objects have. ContainmentType Contains(const BoundingSphere& sphere, bool ignoreScale = false) const; // Determines whether there is an intersection between a Ray and a OBB. // @param ray The ray to test. // @param point When the method completes, contains the point of intersection, or Vector3.Zero if there was no intersection. // @returns Whether the two objects intersected. bool Intersects(const Ray& ray, Vector3& point) const; // Determines if there is an intersection between the current object and a Ray. // @param ray The ray to test. // @param distance When the method completes, contains the distance of the intersection, or 0 if there was no intersection. // @returns Whether the two objects intersected. bool Intersects(const Ray& ray, Real& distance) const; // Determines if there is an intersection between the current object and a Ray. // @param ray The ray to test. // @param distance When the method completes, contains the distance of the intersection, or 0 if there was no intersection. // @param normal When the method completes, contains the intersection surface normal vector, or Vector3::Up if there was no intersection. // @returns Whether the two objects intersected. bool Intersects(const Ray& ray, Real& distance, Vector3& normal) const; // Determines whether there is an intersection between a Ray and a OBB. // @param ray The ray to test. // @returns Whether the two objects intersected. bool Intersects(const Ray& ray) const { Vector3 point; return Intersects(ray, point); } }; template<> struct TIsPODType { enum { Value = true }; }; DEFINE_DEFAULT_FORMATTING(OrientedBoundingBox, "Center: {0}, Size: {1}", v.GetCenter(), v.GetSize());