source-engine/utils/vbsp/boundbox.cpp

286 lines
6.7 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright 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"
float V_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;
}
//-----------------------------------------------------------------------------
// 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)(V_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;
}