Cuberite
A lightweight, fast and extensible game server for Minecraft
BoundingBox.cpp
Go to the documentation of this file.
1 // BoundingBox.cpp
2 
3 // Implements the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords
4 
5 #include "Globals.h"
6 #include "BoundingBox.h"
7 
8 
9 
10 
11 
12 cBoundingBox::cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ) :
13  m_Min(a_MinX, a_MinY, a_MinZ),
14  m_Max(a_MaxX, a_MaxY, a_MaxZ)
15 {
16 }
17 
18 
19 
20 
21 
23  m_Min(a_Min),
24  m_Max(a_Max)
25 {
26 }
27 
28 
29 
30 
31 
32 cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height) :
33  m_Min(a_Pos.x - a_Radius, a_Pos.y, a_Pos.z - a_Radius),
34  m_Max(a_Pos.x + a_Radius, a_Pos.y + a_Height, a_Pos.z + a_Radius)
35 {
36 }
37 
38 
39 
40 
41 
42 cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height, double a_VerticalOffset) :
43  m_Min(a_Pos.x - a_Radius, a_Pos.y + a_VerticalOffset, a_Pos.z - a_Radius),
44  m_Max(a_Pos.x + a_Radius, a_Pos.y + a_VerticalOffset + a_Height, a_Pos.z + a_Radius)
45 {
46 }
47 
48 
49 
50 
51 
52 cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_CubeLength) :
53  m_Min(a_Pos.x - a_CubeLength / 2, a_Pos.y - a_CubeLength / 2, a_Pos.z - a_CubeLength / 2),
54  m_Max(a_Pos.x + a_CubeLength / 2, a_Pos.y + a_CubeLength / 2, a_Pos.z + a_CubeLength / 2)
55 {
56 }
57 
58 
59 
60 
61 
62 void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ)
63 {
64  m_Min.x += a_OffX;
65  m_Min.y += a_OffY;
66  m_Min.z += a_OffZ;
67  m_Max.x += a_OffX;
68  m_Max.y += a_OffY;
69  m_Max.z += a_OffZ;
70 }
71 
72 
73 
74 
75 
77 {
78  m_Min.x += a_Off.x;
79  m_Min.y += a_Off.y;
80  m_Min.z += a_Off.z;
81  m_Max.x += a_Off.x;
82  m_Max.y += a_Off.y;
83  m_Max.z += a_Off.z;
84 }
85 
86 
87 
88 
89 
90 void cBoundingBox::Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
91 {
92  m_Min.x -= a_ExpandX;
93  m_Min.y -= a_ExpandY;
94  m_Min.z -= a_ExpandZ;
95  m_Max.x += a_ExpandX;
96  m_Max.y += a_ExpandY;
97  m_Max.z += a_ExpandZ;
98 }
99 
100 
101 
102 
103 
105 {
106  return (
107  ((a_Other.m_Min.x <= m_Max.x) && (a_Other.m_Max.x >= m_Min.x)) && // X coords intersect
108  ((a_Other.m_Min.y <= m_Max.y) && (a_Other.m_Max.y >= m_Min.y)) && // Y coords intersect
109  ((a_Other.m_Min.z <= m_Max.z) && (a_Other.m_Max.z >= m_Min.z)) // Z coords intersect
110  );
111 }
112 
113 
114 
115 
116 
118 {
119  return cBoundingBox(
120  std::min(m_Min.x, a_Other.m_Min.x),
121  std::max(m_Max.x, a_Other.m_Max.x),
122  std::min(m_Min.y, a_Other.m_Min.y),
123  std::max(m_Max.y, a_Other.m_Max.y),
124  std::min(m_Min.z, a_Other.m_Min.z),
125  std::max(m_Max.z, a_Other.m_Max.z)
126  );
127 }
128 
129 
130 
131 
132 
134 {
135  return IsInside(m_Min, m_Max, a_Point);
136 }
137 
138 
139 
140 
141 
142 bool cBoundingBox::IsInside(double a_X, double a_Y, double a_Z)
143 {
144  return IsInside(m_Min, m_Max, a_X, a_Y, a_Z);
145 }
146 
147 
148 
149 
150 
152 {
153  // If both a_Other's coords are inside this, then the entire a_Other is inside
154  return (IsInside(a_Other.m_Min) && IsInside(a_Other.m_Max));
155 }
156 
157 
158 
159 
160 
162 {
163  // If both coords are inside this, then the entire a_Other is inside
164  return (IsInside(a_Min) && IsInside(a_Max));
165 }
166 
167 
168 
169 
170 
172 {
173  return (
174  ((a_Point.x >= a_Min.x) && (a_Point.x <= a_Max.x)) &&
175  ((a_Point.y >= a_Min.y) && (a_Point.y <= a_Max.y)) &&
176  ((a_Point.z >= a_Min.z) && (a_Point.z <= a_Max.z))
177  );
178 }
179 
180 
181 
182 
183 
184 bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max, double a_X, double a_Y, double a_Z)
185 {
186  return (
187  ((a_X >= a_Min.x) && (a_X <= a_Max.x)) &&
188  ((a_Y >= a_Min.y) && (a_Y <= a_Max.y)) &&
189  ((a_Z >= a_Min.z) && (a_Z <= a_Max.z))
190  );
191 }
192 
193 
194 
195 
196 
197 bool cBoundingBox::CalcLineIntersection(Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face) const
198 {
199  return CalcLineIntersection(m_Min, m_Max, a_Line1, a_Line2, a_LineCoeff, a_Face);
200 }
201 
202 
203 
204 
205 
206 bool cBoundingBox::CalcLineIntersection(Vector3d a_Min, Vector3d a_Max, Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face)
207 {
208  if (IsInside(a_Min, a_Max, a_Line1))
209  {
210  // The starting point is inside the bounding box.
211  a_LineCoeff = 0;
212  a_Face = BLOCK_FACE_NONE; // No faces hit
213  return true;
214  }
215 
217  double Coeff = Vector3d::NO_INTERSECTION;
218 
219  // Check each individual bbox face for intersection with the line, remember the one with the lowest coeff
220  double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z);
221  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
222  {
223  Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
224  Coeff = c;
225  }
226  c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z);
227  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
228  {
229  Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
230  Coeff = c;
231  }
232  c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y);
233  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
234  {
235  Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
236  Coeff = c;
237  }
238  c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y);
239  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
240  {
241  Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
242  Coeff = c;
243  }
244  c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x);
245  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
246  {
247  Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
248  Coeff = c;
249  }
250  c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x);
251  if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
252  {
253  Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
254  Coeff = c;
255  }
256 
257  if (Coeff >= Vector3d::NO_INTERSECTION)
258  {
259  // There has been no intersection
260  return false;
261  }
262 
263  a_LineCoeff = Coeff;
264  a_Face = Face;
265  return true;
266 }
267 
268 
269 
270 
271 
272 bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const
273 {
274  a_Intersection.m_Min.x = std::max(m_Min.x, a_Other.m_Min.x);
275  a_Intersection.m_Max.x = std::min(m_Max.x, a_Other.m_Max.x);
276  if (a_Intersection.m_Min.x >= a_Intersection.m_Max.x)
277  {
278  return false;
279  }
280  a_Intersection.m_Min.y = std::max(m_Min.y, a_Other.m_Min.y);
281  a_Intersection.m_Max.y = std::min(m_Max.y, a_Other.m_Max.y);
282  if (a_Intersection.m_Min.y >= a_Intersection.m_Max.y)
283  {
284  return false;
285  }
286  a_Intersection.m_Min.z = std::max(m_Min.z, a_Other.m_Min.z);
287  a_Intersection.m_Max.z = std::min(m_Max.z, a_Other.m_Max.z);
288  return (a_Intersection.m_Min.z < a_Intersection.m_Max.z);
289 }
290 
291 
292 
293 
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
@ BLOCK_FACE_XP
Definition: Defines.h:41
@ BLOCK_FACE_YP
Definition: Defines.h:43
@ BLOCK_FACE_YM
Definition: Defines.h:42
@ BLOCK_FACE_ZM
Definition: Defines.h:44
@ BLOCK_FACE_ZP
Definition: Defines.h:45
@ BLOCK_FACE_XM
Definition: Defines.h:40
@ BLOCK_FACE_NONE
Definition: Defines.h:39
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Vector3d m_Max
Definition: BoundingBox.h:107
bool IsInside(Vector3d a_Point)
Returns true if the point is inside the bounding box.
void Move(double a_OffX, double a_OffY, double a_OffZ)
Moves the entire boundingbox by the specified offset.
Definition: BoundingBox.cpp:62
bool DoesIntersect(const cBoundingBox &a_Other)
Returns true if the two bounding boxes intersect.
cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ)
Definition: BoundingBox.cpp:12
bool Intersect(const cBoundingBox &a_Other, cBoundingBox &a_Intersection) const
Calculates the intersection of the two bounding boxes; returns true if nonempty.
bool CalcLineIntersection(Vector3d a_LinePoint1, Vector3d a_LinePoint2, double &a_LineCoeff, eBlockFace &a_Face) const
Returns true if this bounding box is intersected by the line specified by its two points Also calcula...
Vector3d m_Min
Definition: BoundingBox.h:106
void Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
Expands the bounding box by the specified amount in each direction (so the box becomes larger by 2 * ...
Definition: BoundingBox.cpp:90
cBoundingBox Union(const cBoundingBox &a_Other)
Returns the union of the two bounding boxes.
T x
Definition: Vector3.h:17
double LineCoeffToXZPlane(const Vector3< T > &a_OtherEnd, T a_Y) const
Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Y coord.
Definition: Vector3.h:351
static const double NO_INTERSECTION
Return value of LineCoeffToPlane() if the line is parallel to the plane.
Definition: Vector3.h:396
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
double LineCoeffToYZPlane(const Vector3< T > &a_OtherEnd, T a_X) const
Returns the coefficient for the (a_OtherEnd - this) line to reach the specified X coord.
Definition: Vector3.h:366
double LineCoeffToXYPlane(const Vector3< T > &a_OtherEnd, T a_Z) const
Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Z coord.
Definition: Vector3.h:336