//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "vbsp.h" #include "BoundBox.h" //#include "hammer_mathlib.h" //#include "MapDefs.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #if !defined(_MSC_VER) || _MSC_VER < 1800 // This C99 function exists in VS 2013's math.h but are not currently available elsewhere. float rint(float f) { if (f > 0.0f) { return (float) floor(f + 0.5f); } else if (f < 0.0f) { return (float) ceil(f - 0.5f); } else return 0.0f; } #endif //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- BoundBox::BoundBox(void) { ResetBounds(); } BoundBox::BoundBox(const Vector &mins, const Vector &maxs) { bmins = mins; bmaxs = maxs; } //----------------------------------------------------------------------------- // Purpose: Sets the box to an uninitialized state, so that calls to UpdateBounds // will properly set the mins and maxs. //----------------------------------------------------------------------------- void BoundBox::ResetBounds(void) { bmins[0] = bmins[1] = bmins[2] = COORD_NOTINIT; bmaxs[0] = bmaxs[1] = bmaxs[2] = -COORD_NOTINIT; } //----------------------------------------------------------------------------- // Purpose: // Input : pt - //----------------------------------------------------------------------------- void BoundBox::UpdateBounds(const Vector& pt) { if(pt[0] < bmins[0]) bmins[0] = pt[0]; if(pt[1] < bmins[1]) bmins[1] = pt[1]; if(pt[2] < bmins[2]) bmins[2] = pt[2]; if(pt[0] > bmaxs[0]) bmaxs[0] = pt[0]; if(pt[1] > bmaxs[1]) bmaxs[1] = pt[1]; if(pt[2] > bmaxs[2]) bmaxs[2] = pt[2]; } //----------------------------------------------------------------------------- // Purpose: // Input : bmins - // bmaxs - //----------------------------------------------------------------------------- void BoundBox::UpdateBounds(const Vector& mins, const Vector& maxs) { if(mins[0] < bmins[0]) bmins[0] = mins[0]; if(mins[1] < bmins[1]) bmins[1] = mins[1]; if(mins[2] < bmins[2]) bmins[2] = mins[2]; if(maxs[0] > bmaxs[0]) bmaxs[0] = maxs[0]; if(maxs[1] > bmaxs[1]) bmaxs[1] = maxs[1]; if(maxs[2] > bmaxs[2]) bmaxs[2] = maxs[2]; } //----------------------------------------------------------------------------- // Purpose: // Input : pBox - //----------------------------------------------------------------------------- void BoundBox::UpdateBounds(const BoundBox *pBox) { UpdateBounds(pBox->bmins, pBox->bmaxs); } //----------------------------------------------------------------------------- // Purpose: // Input : ptdest - //----------------------------------------------------------------------------- void BoundBox::GetBoundsCenter(Vector& ptdest) { ptdest = (bmins + bmaxs)/2.0f; } //----------------------------------------------------------------------------- // Purpose: // Input : pt - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool BoundBox::ContainsPoint(const Vector& pt) const { for (int i = 0; i < 3; i++) { if (pt[i] < bmins[i] || pt[i] > bmaxs[i]) { return(false); } } return(true); } //----------------------------------------------------------------------------- // Purpose: // Input : pfMins - // pfMaxs - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool BoundBox::IsIntersectingBox(const Vector& pfMins, const Vector& pfMaxs) const { if ((bmins[0] >= pfMaxs[0]) || (bmaxs[0] <= pfMins[0])) { return(false); } if ((bmins[1] >= pfMaxs[1]) || (bmaxs[1] <= pfMins[1])) { return(false); } if ((bmins[2] >= pfMaxs[2]) || (bmaxs[2] <= pfMins[2])) { return(false); } return(true); } //----------------------------------------------------------------------------- // Purpose: // Input : pfMins - // pfMaxs - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool BoundBox::IsInsideBox(const Vector& pfMins, const Vector& pfMaxs) const { if ((bmins[0] < pfMins[0]) || (bmaxs[0] > pfMaxs[0])) { return(false); } if ((bmins[1] < pfMins[1]) || (bmaxs[1] > pfMaxs[1])) { return(false); } if ((bmins[2] < pfMins[2]) || (bmaxs[2] > pfMaxs[2])) { return(false); } return(true); } //----------------------------------------------------------------------------- // Purpose: Returns whether this bounding box is valid, ie maxs >= mins. //----------------------------------------------------------------------------- bool BoundBox::IsValidBox(void) const { for (int i = 0; i < 3; i++) { if (bmins[i] > bmaxs[i]) { return(false); } } return(true); } //----------------------------------------------------------------------------- // Purpose: // Input : size - //----------------------------------------------------------------------------- void BoundBox::GetBoundsSize(Vector& size) { size[0] = bmaxs[0] - bmins[0]; size[1] = bmaxs[1] - bmins[1]; size[2] = bmaxs[2] - bmins[2]; } //----------------------------------------------------------------------------- // Purpose: // Input : iValue - // iGridSize - // Output : //----------------------------------------------------------------------------- static int Snap(/*int*/ float iValue, int iGridSize) { return (int)(rint(iValue/iGridSize) * iGridSize); } //----------------------------------------------------------------------------- // Purpose: // Input : iGridSize - //----------------------------------------------------------------------------- void BoundBox::SnapToGrid(int iGridSize) { // does not alter the size of the box .. snaps its minimal coordinates // to the grid size specified in iGridSize Vector size; GetBoundsSize(size); for(int i = 0; i < 3; i++) { bmins[i] = (float)Snap(/* YWB (int)*/bmins[i], iGridSize); bmaxs[i] = bmins[i] + size[i]; } } //----------------------------------------------------------------------------- // Purpose: // Input : axis - //----------------------------------------------------------------------------- void BoundBox::Rotate90(int axis) { int e1 = AXIS_X, e2 = AXIS_Y; // get bounds center first Vector center; GetBoundsCenter(center); switch(axis) { case AXIS_Z: e1 = AXIS_X; e2 = AXIS_Y; break; case AXIS_X: e1 = AXIS_Y; e2 = AXIS_Z; break; case AXIS_Y: e1 = AXIS_X; e2 = AXIS_Z; break; } float tmp1, tmp2; tmp1 = bmins[e1] - center[e1] + center[e2]; tmp2 = bmaxs[e1] - center[e1] + center[e2]; bmins[e1] = bmins[e2] - center[e2] + center[e1]; bmaxs[e1] = bmaxs[e2] - center[e2] + center[e1]; bmins[e2] = tmp1; bmaxs[e2] = tmp2; }