2013-09-01 06:25:53 -04:00
|
|
|
// BoundingBox.cpp
|
|
|
|
|
|
|
|
// Implements the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords
|
|
|
|
|
|
|
|
#include "Globals.h"
|
|
|
|
#include "BoundingBox.h"
|
2013-09-01 16:38:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-09-01 06:25:53 -04:00
|
|
|
cBoundingBox::cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ) :
|
|
|
|
m_Min(a_MinX, a_MinY, a_MinZ),
|
|
|
|
m_Max(a_MaxX, a_MaxY, a_MaxZ)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
cBoundingBox::cBoundingBox(Vector3d a_Min, Vector3d a_Max) :
|
2013-09-01 06:25:53 -04:00
|
|
|
m_Min(a_Min),
|
|
|
|
m_Max(a_Max)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height) :
|
2013-09-01 06:25:53 -04:00
|
|
|
m_Min(a_Pos.x - a_Radius, a_Pos.y, a_Pos.z - a_Radius),
|
|
|
|
m_Max(a_Pos.x + a_Radius, a_Pos.y + a_Height, a_Pos.z + a_Radius)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-21 04:46:41 -04:00
|
|
|
cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height, double a_VerticalOffset) :
|
|
|
|
m_Min(a_Pos.x - a_Radius, a_Pos.y + a_VerticalOffset, a_Pos.z - a_Radius),
|
|
|
|
m_Max(a_Pos.x + a_Radius, a_Pos.y + a_VerticalOffset + a_Height, a_Pos.z + a_Radius)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_CubeLength) :
|
2016-01-22 13:55:46 -05:00
|
|
|
m_Min(a_Pos.x - a_CubeLength / 2, a_Pos.y - a_CubeLength / 2, a_Pos.z - a_CubeLength / 2),
|
|
|
|
m_Max(a_Pos.x + a_CubeLength / 2, a_Pos.y + a_CubeLength / 2, a_Pos.z + a_CubeLength / 2)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-09-01 06:25:53 -04:00
|
|
|
void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ)
|
|
|
|
{
|
|
|
|
m_Min.x += a_OffX;
|
|
|
|
m_Min.y += a_OffY;
|
|
|
|
m_Min.z += a_OffZ;
|
|
|
|
m_Max.x += a_OffX;
|
|
|
|
m_Max.y += a_OffY;
|
|
|
|
m_Max.z += a_OffZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
void cBoundingBox::Move(Vector3d a_Off)
|
2013-09-01 06:25:53 -04:00
|
|
|
{
|
|
|
|
m_Min.x += a_Off.x;
|
|
|
|
m_Min.y += a_Off.y;
|
|
|
|
m_Min.z += a_Off.z;
|
|
|
|
m_Max.x += a_Off.x;
|
|
|
|
m_Max.y += a_Off.y;
|
|
|
|
m_Max.z += a_Off.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cBoundingBox::Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
|
|
|
|
{
|
|
|
|
m_Min.x -= a_ExpandX;
|
|
|
|
m_Min.y -= a_ExpandY;
|
|
|
|
m_Min.z -= a_ExpandZ;
|
|
|
|
m_Max.x += a_ExpandX;
|
|
|
|
m_Max.y += a_ExpandY;
|
|
|
|
m_Max.z += a_ExpandZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cBoundingBox::DoesIntersect(const cBoundingBox & a_Other)
|
|
|
|
{
|
|
|
|
return (
|
2013-09-01 16:38:09 -04:00
|
|
|
((a_Other.m_Min.x <= m_Max.x) && (a_Other.m_Max.x >= m_Min.x)) && // X coords intersect
|
|
|
|
((a_Other.m_Min.y <= m_Max.y) && (a_Other.m_Max.y >= m_Min.y)) && // Y coords intersect
|
|
|
|
((a_Other.m_Min.z <= m_Max.z) && (a_Other.m_Max.z >= m_Min.z)) // Z coords intersect
|
2013-09-01 06:25:53 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cBoundingBox cBoundingBox::Union(const cBoundingBox & a_Other)
|
|
|
|
{
|
|
|
|
return cBoundingBox(
|
|
|
|
std::min(m_Min.x, a_Other.m_Min.x),
|
|
|
|
std::max(m_Max.x, a_Other.m_Max.x),
|
2017-07-28 12:59:21 -04:00
|
|
|
std::min(m_Min.y, a_Other.m_Min.y),
|
2013-09-01 06:25:53 -04:00
|
|
|
std::max(m_Max.y, a_Other.m_Max.y),
|
2017-07-28 12:59:21 -04:00
|
|
|
std::min(m_Min.z, a_Other.m_Min.z),
|
2013-09-01 06:25:53 -04:00
|
|
|
std::max(m_Max.z, a_Other.m_Max.z)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::IsInside(Vector3d a_Point)
|
2013-09-01 06:25:53 -04:00
|
|
|
{
|
2013-09-01 13:08:51 -04:00
|
|
|
return IsInside(m_Min, m_Max, a_Point);
|
2013-09-01 06:25:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-19 08:53:41 -04:00
|
|
|
bool cBoundingBox::IsInside(double a_X, double a_Y, double a_Z)
|
2013-09-01 06:25:53 -04:00
|
|
|
{
|
2013-09-01 13:08:51 -04:00
|
|
|
return IsInside(m_Min, m_Max, a_X, a_Y, a_Z);
|
2013-09-01 06:25:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cBoundingBox::IsInside(cBoundingBox & a_Other)
|
|
|
|
{
|
|
|
|
// If both a_Other's coords are inside this, then the entire a_Other is inside
|
|
|
|
return (IsInside(a_Other.m_Min) && IsInside(a_Other.m_Max));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max)
|
2013-09-01 06:25:53 -04:00
|
|
|
{
|
|
|
|
// If both coords are inside this, then the entire a_Other is inside
|
|
|
|
return (IsInside(a_Min) && IsInside(a_Max));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max, Vector3d a_Point)
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
return (
|
2013-09-01 16:38:09 -04:00
|
|
|
((a_Point.x >= a_Min.x) && (a_Point.x <= a_Max.x)) &&
|
|
|
|
((a_Point.y >= a_Min.y) && (a_Point.y <= a_Max.y)) &&
|
|
|
|
((a_Point.z >= a_Min.z) && (a_Point.z <= a_Max.z))
|
2013-09-01 13:08:51 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max, double a_X, double a_Y, double a_Z)
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
return (
|
2013-09-01 16:38:09 -04:00
|
|
|
((a_X >= a_Min.x) && (a_X <= a_Max.x)) &&
|
|
|
|
((a_Y >= a_Min.y) && (a_Y <= a_Max.y)) &&
|
|
|
|
((a_Z >= a_Min.z) && (a_Z <= a_Max.z))
|
2013-09-01 13:08:51 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::CalcLineIntersection(Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face) const
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
return CalcLineIntersection(m_Min, m_Max, a_Line1, a_Line2, a_LineCoeff, a_Face);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
bool cBoundingBox::CalcLineIntersection(Vector3d a_Min, Vector3d a_Max, Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face)
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
2013-09-02 13:51:13 -04:00
|
|
|
if (IsInside(a_Min, a_Max, a_Line1))
|
|
|
|
{
|
|
|
|
// The starting point is inside the bounding box.
|
|
|
|
a_LineCoeff = 0;
|
2013-11-12 16:43:20 -05:00
|
|
|
a_Face = BLOCK_FACE_NONE; // No faces hit
|
2013-09-02 13:51:13 -04:00
|
|
|
return true;
|
|
|
|
}
|
2016-01-22 13:55:46 -05:00
|
|
|
|
2014-02-04 13:59:05 -05:00
|
|
|
eBlockFace Face = BLOCK_FACE_NONE;
|
2013-09-01 13:08:51 -04:00
|
|
|
double Coeff = Vector3d::NO_INTERSECTION;
|
2016-01-22 13:55:46 -05:00
|
|
|
|
2013-09-01 13:08:51 -04:00
|
|
|
// Check each individual bbox face for intersection with the line, remember the one with the lowest coeff
|
|
|
|
double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z);
|
2013-09-02 13:51:13 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
|
|
|
c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z);
|
2013-09-02 13:51:13 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
|
|
|
c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y);
|
2013-09-02 13:51:13 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
|
|
|
c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y);
|
2014-04-18 15:09:44 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
|
|
|
c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x);
|
2013-09-02 13:51:13 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
|
|
|
c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x);
|
2013-09-02 13:51:13 -04:00
|
|
|
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
|
2013-09-01 13:08:51 -04:00
|
|
|
{
|
|
|
|
Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
|
|
|
|
Coeff = c;
|
|
|
|
}
|
2016-01-22 13:55:46 -05:00
|
|
|
|
2013-09-01 13:08:51 -04:00
|
|
|
if (Coeff >= Vector3d::NO_INTERSECTION)
|
|
|
|
{
|
|
|
|
// There has been no intersection
|
|
|
|
return false;
|
|
|
|
}
|
2016-01-22 13:55:46 -05:00
|
|
|
|
2013-09-01 13:08:51 -04:00
|
|
|
a_LineCoeff = Coeff;
|
|
|
|
a_Face = Face;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-05 12:23:16 -04:00
|
|
|
bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const
|
2013-09-01 06:25:53 -04:00
|
|
|
{
|
|
|
|
a_Intersection.m_Min.x = std::max(m_Min.x, a_Other.m_Min.x);
|
|
|
|
a_Intersection.m_Max.x = std::min(m_Max.x, a_Other.m_Max.x);
|
|
|
|
if (a_Intersection.m_Min.x >= a_Intersection.m_Max.x)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
a_Intersection.m_Min.y = std::max(m_Min.y, a_Other.m_Min.y);
|
|
|
|
a_Intersection.m_Max.y = std::min(m_Max.y, a_Other.m_Max.y);
|
|
|
|
if (a_Intersection.m_Min.y >= a_Intersection.m_Max.y)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
a_Intersection.m_Min.z = std::max(m_Min.z, a_Other.m_Min.z);
|
|
|
|
a_Intersection.m_Max.z = std::min(m_Max.z, a_Other.m_Max.z);
|
|
|
|
if (a_Intersection.m_Min.z >= a_Intersection.m_Max.z)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|