1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6#include "Math/BsVector3.h"
7#include "Math/BsMatrix4.h"
8
9namespace bs
10{
11 /** @addtogroup Math
12 * @{
13 */
14
15 /** Axis aligned box represented by minimum and maximum point. */
16 class BS_UTILITY_EXPORT AABox
17 {
18 public:
19 /** Different corners of a box. */
20 /*
21 1-----2
22 /| /|
23 / | / |
24 5-----4 |
25 | 0--|--3
26 | / | /
27 |/ |/
28 6-----7
29 */
30 enum Corner
31 {
32 FAR_LEFT_BOTTOM = 0,
33 FAR_LEFT_TOP = 1,
34 FAR_RIGHT_TOP = 2,
35 FAR_RIGHT_BOTTOM = 3,
36 NEAR_RIGHT_BOTTOM = 7,
37 NEAR_LEFT_BOTTOM = 6,
38 NEAR_LEFT_TOP = 5,
39 NEAR_RIGHT_TOP = 4
40 };
41
42 AABox();
43 AABox(const AABox& copy) = default;
44 AABox(const Vector3& min, const Vector3& max);
45
46 ~AABox() = default;
47
48 /** Gets the corner of the box with minimum values (opposite to maximum corner). */
49 const Vector3& getMin() const { return mMinimum; }
50
51 /** Gets the corner of the box with maximum values (opposite to minimum corner). */
52 const Vector3& getMax() const { return mMaximum; }
53
54 /** Sets the corner of the box with minimum values (opposite to maximum corner). */
55 void setMin(const Vector3& vec) { mMinimum = vec; }
56
57 /** Sets the corner of the box with maximum values (opposite to minimum corner). */
58 void setMax(const Vector3& vec) { mMaximum = vec; }
59
60 /** Sets the minimum and maximum corners. */
61 void setExtents(const Vector3& min, const Vector3& max);
62
63 /** Scales the box around the center by multiplying its extents with the provided scale. */
64 void scale(const Vector3& s);
65
66 /** Returns the coordinates of a specific corner. */
67 Vector3 getCorner(Corner cornerToGet) const;
68
69 /** Merges the two boxes, creating a new bounding box that encapsulates them both. */
70 void merge(const AABox& rhs);
71
72 /** Expands the bounding box so it includes the provided point. */
73 void merge(const Vector3& point);
74
75 /**
76 * Transforms the bounding box by the given matrix.
77 *
78 * @note
79 * As the resulting box will no longer be axis aligned, an axis align box
80 * is instead created by encompassing the transformed oriented bounding box.
81 * Retrieving the value as an actual OBB would provide a tighter fit.
82 */
83 void transform(const Matrix4& matrix);
84
85 /**
86 * Transforms the bounding box by the given matrix.
87 *
88 * @note
89 * As the resulting box will no longer be axis aligned, an axis align box
90 * is instead created by encompassing the transformed oriented bounding box.
91 * Retrieving the value as an actual OBB would provide a tighter fit.
92 *
93 * @note
94 * Provided matrix must be affine.
95 */
96 void transformAffine(const Matrix4& matrix);
97
98 /** Returns true if this and the provided box intersect. */
99 bool intersects(const AABox& b2) const;
100
101 /** Returns true if the sphere intersects the bounding box. */
102 bool intersects(const Sphere& s) const;
103
104 /** Returns true if the plane intersects the bounding box. */
105 bool intersects(const Plane& p) const;
106
107 /** Ray / box intersection, returns a boolean result and nearest distance to intersection. */
108 std::pair<bool, float> intersects(const Ray& ray) const;
109
110 /** Ray / box intersection, returns boolean result and near and far intersection distance. */
111 bool intersects(const Ray& ray, float& d1, float& d2) const;
112
113 /** Center of the box. */
114 Vector3 getCenter() const;
115
116 /** Size of the box (difference between minimum and maximum corners) */
117 Vector3 getSize() const;
118
119 /** Extents of the box (distance from center to one of the corners) */
120 Vector3 getHalfSize() const;
121
122 /** Radius of a sphere that fully encompasses the box. */
123 float getRadius() const;
124
125 /** Size of the volume in the box. */
126 float getVolume() const;
127
128 /** Returns true if the provided point is inside the bounding box. */
129 bool contains(const Vector3& v) const;
130
131 /**
132 * Returns true if the provided point is inside the bounding box while expanding the bounds by @p extra in every
133 * direction.
134 */
135 bool contains(const Vector3& v, float extra) const;
136
137 /** Returns true if the provided bounding box is completely inside the bounding box. */
138 bool contains(const AABox& other) const;
139
140 bool operator== (const AABox& rhs) const;
141 bool operator!= (const AABox& rhs) const;
142
143 static const AABox BOX_EMPTY;
144 static const AABox UNIT_BOX;
145 static const AABox INF_BOX;
146
147 /**
148 * Indices that can be used for rendering a box constructed from 8 corner vertices, using AABox::Corner for
149 * mapping.
150 */
151 static const UINT32 CUBE_INDICES[36];
152
153 protected:
154 Vector3 mMinimum{Vector3::ZERO};
155 Vector3 mMaximum{Vector3::ONE};
156 };
157
158 /** @} */
159
160 /** @cond SPECIALIZATIONS */
161 BS_ALLOW_MEMCPY_SERIALIZATION(AABox);
162 /** @endcond */
163}
164