185 lines
4.4 KiB
C++
185 lines
4.4 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
------------------------------------------------------------------------------*/
|
|
|
|
|
|
#ifndef __NBOUNDINGBOX__
|
|
#define __NBOUNDINGBOX__
|
|
|
|
|
|
#include "math/matrix3.h"
|
|
|
|
|
|
namespace GS {
|
|
|
|
/*!
|
|
@short AABB.
|
|
@author Emmanuel Julien (ejulien@nworks.fr)
|
|
*/
|
|
class MinMax
|
|
{
|
|
protected:
|
|
|
|
enum
|
|
{
|
|
ClipNone = 0,
|
|
ClipRight = 1,
|
|
ClipLeft = 2,
|
|
ClipTop = 4,
|
|
ClipBottom = 8,
|
|
ClipFront = 16,
|
|
ClipBack = 32
|
|
};
|
|
|
|
/// Internal use.
|
|
uint cc_oc(const Vector4 &min, const Vector4 &max, const Vector4 &p) const
|
|
{
|
|
uint oc = ClipNone;
|
|
if (p.x > max.x) oc |= ClipRight;
|
|
else if (p.x < min.x) oc |= ClipLeft;
|
|
if (p.y > max.y) oc |= ClipTop;
|
|
else if (p.y < min.y) oc |= ClipBottom;
|
|
if (p.z > max.z) oc |= ClipBack;
|
|
else if (p.z < min.z) oc |= ClipFront;
|
|
return oc;
|
|
}
|
|
|
|
/// Internal use.
|
|
uint ss_oc(const Vector4 &p) const
|
|
{
|
|
uint oc = ClipNone;
|
|
oc |= p.x > 0 ? ClipRight : ClipLeft;
|
|
oc |= p.y > 0 ? ClipTop : ClipBottom;
|
|
oc |= p.z > 0 ? ClipBack : ClipFront;
|
|
return oc;
|
|
}
|
|
|
|
public:
|
|
|
|
Vector4 mn, mx;
|
|
|
|
/// Return the start of the interval on a given axis.
|
|
float GetMin(uint axis) const
|
|
{ return mn[axis]; }
|
|
/// Return the end of the interval on a given axis.
|
|
float GetMax(uint axis) const
|
|
{ return mx[axis]; }
|
|
/// Return whether the MinMax object overlap with another one.
|
|
bool TestAxisOverlap(const MinMax &b, uint axis) const
|
|
{ return (b.mn[axis] > mx[axis]) || (b.mx[axis] < mn[axis]) ? false : true; }
|
|
|
|
/// Intersect ray with this minmax.
|
|
bool IntersectRay(const Vector4 &o, const Vector4 &d, float &tmin, float &tmax);
|
|
|
|
/// Returns whether a line intersect with the MinMax.
|
|
bool ClassifyLine(const Vector4 &p, const Vector4 &d, Vector4 &i, Vector4 *n = 0) const;
|
|
/// Returns whether a segment intersect with the MinMax.
|
|
bool ClassifySegment(const Vector4 &p0, const Vector4 &p1, Vector4 &i, Vector4 *n = 0) const;
|
|
|
|
/// Return whether two MinMax overlap at a given time.
|
|
bool TestOverlap(const MinMax &b) const
|
|
{
|
|
if (mx.x < b.mn.x) return false;
|
|
if (mx.y < b.mn.y) return false;
|
|
if (mx.z < b.mn.z) return false;
|
|
if (b.mx.x < mn.x) return false;
|
|
if (b.mx.y < mn.y) return false;
|
|
if (b.mx.z < mn.z) return false;
|
|
return true;
|
|
}
|
|
|
|
/// Test position.
|
|
inline bool IsInside(const Vector4 &p) const
|
|
{ return (p.x < mn.x) || (p.y < mn.y) || (p.z < mn.z) || (p.x > mx.x) || (p.y > mx.y) || (p.z > mx.z) ? false : true; }
|
|
|
|
/// Grow the min~max boundaries to include another min~max structure.
|
|
void Grow(const MinMax &b)
|
|
{
|
|
mn = Vector4::Minimum(b.mn, mn);
|
|
mx = Vector4::Maximum(b.mx, mx);
|
|
}
|
|
|
|
/// Grow the min~max boundaries to include a vector.
|
|
void Grow(const Vector4 &p)
|
|
{
|
|
mn = Vector4::Minimum(p, mn);
|
|
mx = Vector4::Maximum(p, mx);
|
|
}
|
|
|
|
/// Get the min-max area.
|
|
float GetArea() const
|
|
{ return (mx.x - mn.x) * (mx.y - mn.y) * (mx.z - mn.z); }
|
|
/// Get the min-max center.
|
|
Vector4 GetCenter() const
|
|
{ return (mn + mx) * 0.5f; }
|
|
|
|
/// Set min-max.
|
|
void Set(const Vector4 &min, const Vector4 &max)
|
|
{ mn = min; mx = max; }
|
|
/// Set from position and size.
|
|
void SetFromPositionSize(const Vector4 &p, const Vector4 &s)
|
|
{
|
|
mn = p - s * 0.5f;
|
|
mx = p + s * 0.5f;
|
|
}
|
|
|
|
void Reset()
|
|
{ mn.Set(); mx.Set(); }
|
|
|
|
/*!
|
|
@name Serialization
|
|
@{
|
|
*/
|
|
bool FromMetaTag(NML::Tag &tag);
|
|
NML::Tag *AsMetaTag();
|
|
/// @}
|
|
|
|
MinMax() : mn(0, 0, 0), mx(0, 0, 0) {}
|
|
MinMax(const Vector4 &min, const Vector4 &max) : mn(min), mx(max) {}
|
|
};
|
|
|
|
/*!
|
|
@short Oriented bounding box.
|
|
@author Emmanuel Julien (ejulien@nworks.fr)
|
|
*/
|
|
struct OBB
|
|
{
|
|
Vector4 bb_position;
|
|
Vector4 bb_scale;
|
|
Matrix3 bb_rotation;
|
|
|
|
/// Compute the min/max of the OBB.
|
|
void ComputeMinMax(MinMax &minmax);
|
|
|
|
/*!
|
|
@short Transform OBB.
|
|
@warning Scaling is not supported.
|
|
*/
|
|
void Transform(const Matrix4 &mtx);
|
|
|
|
/// OBB from min~max.
|
|
static OBB FromMinMax(const MinMax &minmax)
|
|
{ return OBB((minmax.mn + minmax.mx) * 0.5f, minmax.mx - minmax.mn); }
|
|
|
|
bool FromMetaTag(NML::Tag &tag);
|
|
NML::Tag *AsMetaTag();
|
|
|
|
OBB(const MinMax &minmax)
|
|
{ *this = FromMinMax(minmax); }
|
|
OBB(const Vector4 &p, const Vector4 &s, const Matrix3 *m = 0)
|
|
{
|
|
bb_position = p;
|
|
bb_scale = s;
|
|
if (m)
|
|
bb_rotation = *m;
|
|
}
|
|
OBB() {}
|
|
};
|
|
|
|
} // GS
|
|
|
|
|
|
#endif // __NBOUNDINGBOX__
|
|
|