You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
11 KiB
419 lines
11 KiB
//////////////////////////////////////////////////////////////////// |
|
// AABB.inl |
|
// |
|
// Copyright 2007 cDc@seacave |
|
// Distributed under the Boost Software License, Version 1.0 |
|
// (See http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
|
|
// D E F I N E S /////////////////////////////////////////////////// |
|
|
|
|
|
// S T R U C T S /////////////////////////////////////////////////// |
|
|
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>::TAABB(bool) |
|
: |
|
ptMin(POINT::Constant(std::numeric_limits<TYPE>::max())), |
|
ptMax(POINT::Constant(std::numeric_limits<TYPE>::lowest())) |
|
{ |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>::TAABB(const POINT& _pt) |
|
: |
|
ptMin(_pt), ptMax(_pt) |
|
{ |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>::TAABB(const POINT& _ptMin, const POINT& _ptMax) |
|
: |
|
ptMin(_ptMin), ptMax(_ptMax) |
|
{ |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>::TAABB(const POINT& center, const TYPE& radius) |
|
: |
|
ptMin(center-POINT::Constant(radius)), ptMax(center+POINT::Constant(radius)) |
|
{ |
|
} |
|
template <typename TYPE, int DIMS> |
|
template <typename TPoint> |
|
inline TAABB<TYPE,DIMS>::TAABB(const TPoint* pts, size_t n) |
|
{ |
|
Set(pts, n); |
|
} // constructor |
|
template <typename TYPE, int DIMS> |
|
template <typename CTYPE> |
|
inline TAABB<TYPE,DIMS>::TAABB(const TAABB<CTYPE,DIMS>& rhs) |
|
: |
|
ptMin(rhs.ptMin.template cast<TYPE>()), ptMax(rhs.ptMax.template cast<TYPE>()) |
|
{ |
|
} // copy constructor |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Reset() |
|
{ |
|
ptMin = POINT::Constant(std::numeric_limits<TYPE>::max()); |
|
ptMax = POINT::Constant(std::numeric_limits<TYPE>::lowest()); |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Set(const POINT& _pt) |
|
{ |
|
ptMin = ptMax = _pt; |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Set(const POINT& _ptMin, const POINT& _ptMax) |
|
{ |
|
ptMin = _ptMin; |
|
ptMax = _ptMax; |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Set(const POINT& center, const TYPE& radius) |
|
{ |
|
ptMin = center-POINT::Constant(radius); |
|
ptMax = center+POINT::Constant(radius); |
|
} |
|
template <typename TYPE, int DIMS> |
|
template <typename TPoint> |
|
inline void TAABB<TYPE,DIMS>::Set(const TPoint* pts, size_t n) |
|
{ |
|
ASSERT(n > 0); |
|
ptMin = ptMax = pts[0]; |
|
for (size_t i=1; i<n; ++i) |
|
Insert(pts[i]); |
|
} // Set |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline bool TAABB<TYPE,DIMS>::IsEmpty() const |
|
{ |
|
for (int i=0; i<DIMS; ++i) |
|
if (ptMin[i] >= ptMax[i]) |
|
return true; |
|
return false; |
|
} // IsEmpty |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>& TAABB<TYPE,DIMS>::Enlarge(TYPE x) |
|
{ |
|
ptMin.array() -= x; |
|
ptMax.array() += x; |
|
return *this; |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline TAABB<TYPE,DIMS>& TAABB<TYPE,DIMS>::EnlargePercent(TYPE x) |
|
{ |
|
const POINT ptSizeDelta(GetSize() * (x - TYPE(1)) / TYPE(2)); |
|
ptMin -= ptSizeDelta; |
|
ptMax += ptSizeDelta; |
|
return *this; |
|
} // Enlarge |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline typename TAABB<TYPE,DIMS>::POINT TAABB<TYPE,DIMS>::GetCenter() const |
|
{ |
|
return (ptMax + ptMin) * TYPE(0.5); |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::GetCenter(POINT& ptCenter) const |
|
{ |
|
ptCenter = (ptMax + ptMin) * TYPE(0.5); |
|
} // GetCenter |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline typename TAABB<TYPE,DIMS>::POINT TAABB<TYPE,DIMS>::GetSize() const |
|
{ |
|
return ptMax - ptMin; |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::GetSize(POINT& ptSize) const |
|
{ |
|
ptSize = ptMax - ptMin; |
|
} // GetSize |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::GetCorner(BYTE i, POINT& ptCorner) const |
|
{ |
|
ASSERT(i<numCorners); |
|
if (DIMS == 1) { |
|
ptCorner(0) = operator[](i); |
|
} |
|
if (DIMS == 2) { |
|
ptCorner(0) = operator[]((i/2)*2 + 0); |
|
ptCorner(1) = operator[]((i%2)*2 + 1); |
|
} |
|
if (DIMS == 3) { |
|
ptCorner(0) = operator[]((i/4)*3 + 0); |
|
ptCorner(1) = operator[](((i/2)%2)*3 + 1); |
|
ptCorner(2) = operator[]((i%2)*3 + 2); |
|
} |
|
} |
|
template <typename TYPE, int DIMS> |
|
inline typename TAABB<TYPE,DIMS>::POINT TAABB<TYPE,DIMS>::GetCorner(BYTE i) const |
|
{ |
|
POINT ptCorner; |
|
GetCorner(i, ptCorner); |
|
return ptCorner; |
|
} // GetCorner |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::GetCorners(POINT pts[numCorners]) const |
|
{ |
|
for (BYTE i=0; i<numCorners; ++i) |
|
GetCorner(i, pts[i]); |
|
} // GetCorners |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// Update the box by the given pos delta. |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Translate(const POINT& d) |
|
{ |
|
ptMin += d; |
|
ptMax += d; |
|
} |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// Update the box by the given transform. |
|
template <typename TYPE, int DIMS> |
|
inline void TAABB<TYPE,DIMS>::Transform(const MATRIX& m) |
|
{ |
|
ptMin = m * ptMin; |
|
ptMax = m * ptMax; |
|
} |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// Update the box such that it contains the given point. |
|
template <typename TYPE, int DIMS> |
|
void TAABB<TYPE,DIMS>::InsertFull(const POINT& pt) |
|
{ |
|
if (ptMin[0] > pt[0]) |
|
ptMin[0] = pt[0]; |
|
if (ptMax[0] < pt[0]) |
|
ptMax[0] = pt[0]; |
|
|
|
if (DIMS > 1) { |
|
if (ptMin[1] > pt[1]) |
|
ptMin[1] = pt[1]; |
|
if (ptMax[1] < pt[1]) |
|
ptMax[1] = pt[1]; |
|
} |
|
|
|
if (DIMS > 2) { |
|
if (ptMin[2] > pt[2]) |
|
ptMin[2] = pt[2]; |
|
if (ptMax[2] < pt[2]) |
|
ptMax[2] = pt[2]; |
|
} |
|
} |
|
// same as above, but for the initialized case |
|
template <typename TYPE, int DIMS> |
|
void TAABB<TYPE,DIMS>::Insert(const POINT& pt) |
|
{ |
|
if (ptMin[0] > pt[0]) |
|
ptMin[0] = pt[0]; |
|
else if (ptMax[0] < pt[0]) |
|
ptMax[0] = pt[0]; |
|
|
|
if (DIMS > 1) { |
|
if (ptMin[1] > pt[1]) |
|
ptMin[1] = pt[1]; |
|
else if (ptMax[1] < pt[1]) |
|
ptMax[1] = pt[1]; |
|
} |
|
|
|
if (DIMS > 2) { |
|
if (ptMin[2] > pt[2]) |
|
ptMin[2] = pt[2]; |
|
else if (ptMax[2] < pt[2]) |
|
ptMax[2] = pt[2]; |
|
} |
|
} |
|
/*----------------------------------------------------------------*/ |
|
|
|
// Update the box such that it contains the given bounding box. |
|
template <typename TYPE, int DIMS> |
|
void TAABB<TYPE,DIMS>::Insert(const TAABB& aabb) |
|
{ |
|
if (ptMin[0] > aabb.ptMin[0]) |
|
ptMin[0] = aabb.ptMin[0]; |
|
if (ptMax[0] < aabb.ptMax[0]) |
|
ptMax[0] = aabb.ptMax[0]; |
|
|
|
if (DIMS > 1) { |
|
if (ptMin[1] > aabb.ptMin[1]) |
|
ptMin[1] = aabb.ptMin[1]; |
|
if (ptMax[1] < aabb.ptMax[1]) |
|
ptMax[1] = aabb.ptMax[1]; |
|
} |
|
|
|
if (DIMS > 2) { |
|
if (ptMin[2] > aabb.ptMin[2]) |
|
ptMin[2] = aabb.ptMin[2]; |
|
if (ptMax[2] < aabb.ptMax[2]) |
|
ptMax[2] = aabb.ptMax[2]; |
|
} |
|
} |
|
/*----------------------------------------------------------------*/ |
|
|
|
// Update the box such that it does not exceed the given bounding box. |
|
template <typename TYPE, int DIMS> |
|
void TAABB<TYPE,DIMS>::BoundBy(const TAABB& aabb) |
|
{ |
|
if (ptMin[0] < aabb.ptMin[0]) |
|
ptMin[0] = aabb.ptMin[0]; |
|
if (ptMax[0] > aabb.ptMax[0]) |
|
ptMax[0] = aabb.ptMax[0]; |
|
|
|
if (DIMS > 1) { |
|
if (ptMin[1] < aabb.ptMin[1]) |
|
ptMin[1] = aabb.ptMin[1]; |
|
if (ptMax[1] > aabb.ptMax[1]) |
|
ptMax[1] = aabb.ptMax[1]; |
|
} |
|
|
|
if (DIMS > 2) { |
|
if (ptMin[2] < aabb.ptMin[2]) |
|
ptMin[2] = aabb.ptMin[2]; |
|
if (ptMax[2] > aabb.ptMax[2]) |
|
ptMax[2] = aabb.ptMax[2]; |
|
} |
|
} |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// intersection between two AABBs |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::Intersects(const TAABB& aabb) const |
|
{ |
|
if (aabb.ptMax[0] < ptMin[0]) return false; |
|
if (aabb.ptMin[0] >= ptMax[0]) return false; |
|
if (DIMS > 1) { |
|
if (aabb.ptMax[1] < ptMin[1]) return false; |
|
if (aabb.ptMin[1] >= ptMax[1]) return false; |
|
} |
|
if (DIMS > 2) { |
|
if (aabb.ptMax[2] < ptMin[2]) return false; |
|
if (aabb.ptMin[2] >= ptMax[2]) return false; |
|
} |
|
return true; |
|
} |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::IntersectsComplete(const TAABB& aabb, TYPE tolerance) const |
|
{ |
|
if (aabb.ptMax[0]+tolerance < ptMin[0]) return false; |
|
if (aabb.ptMin[0] > ptMax[0]+tolerance) return false; |
|
if (DIMS > 1) { |
|
if (aabb.ptMax[1]+tolerance < ptMin[1]) return false; |
|
if (aabb.ptMin[1] > ptMax[1]+tolerance) return false; |
|
} |
|
if (DIMS > 2) { |
|
if (aabb.ptMax[2]+tolerance < ptMin[2]) return false; |
|
if (aabb.ptMin[2] > ptMax[2]+tolerance) return false; |
|
} |
|
return true; |
|
} |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::IntersectsComplete(const TAABB& aabb) const |
|
{ |
|
return IntersectsComplete(aabb, ZEROTOLERANCE<TYPE>()); |
|
} // Intersects(TAABB) |
|
/*----------------------------------------------------------------*/ |
|
|
|
// does TAABB contain the given point |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::Intersects(const POINT& pt) const |
|
{ |
|
if (pt[0] < ptMin[0]) return false; |
|
if (pt[0] >= ptMax[0]) return false; |
|
if (DIMS > 1) { |
|
if (pt[1] < ptMin[1]) return false; |
|
if (pt[1] >= ptMax[1]) return false; |
|
} |
|
if (DIMS > 2) { |
|
if (pt[2] < ptMin[2]) return false; |
|
if (pt[2] >= ptMax[2]) return false; |
|
} |
|
return true; |
|
} |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::IntersectsComplete(const POINT& pt, TYPE tolerance) const |
|
{ |
|
if (pt[0]+tolerance < ptMin[0]) return false; |
|
if (pt[0] > ptMax[0]+tolerance) return false; |
|
if (DIMS > 1) { |
|
if (pt[1]+tolerance < ptMin[1]) return false; |
|
if (pt[1] > ptMax[1]+tolerance) return false; |
|
} |
|
if (DIMS > 2) { |
|
if (pt[2]+tolerance < ptMin[2]) return false; |
|
if (pt[2] > ptMax[2]+tolerance) return false; |
|
} |
|
return true; |
|
} |
|
template <typename TYPE, int DIMS> |
|
bool TAABB<TYPE,DIMS>::IntersectsComplete(const POINT& pt) const |
|
{ |
|
return IntersectsComplete(pt, ZEROTOLERANCE<TYPE>()); |
|
} // Intersects(point) |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
// split this TAABB by the given axis |
|
// returns number of children (0 or 2) |
|
template <typename TYPE, int DIMS> |
|
unsigned TAABB<TYPE,DIMS>::SplitBy(TYPE d, int a, TAABB child[2]) const |
|
{ |
|
ASSERT(a < DIMS); |
|
if (d >= ptMin[a] && d < ptMax[a]) { |
|
TAABB& child0 = child[0]; |
|
child0.Set(ptMin, ptMax); |
|
TAABB& child1 = child[1]; |
|
child1.Set(ptMin, ptMax); |
|
child0.ptMax[a] = child1.ptMin[a] = d; |
|
return 2; |
|
} |
|
return 0; |
|
} // SplitBy(axis) |
|
/*----------------------------------------------------------------*/ |
|
|
|
// split this TAABB by the given point |
|
// returns number of children (0 - numScalar) |
|
// idxFirst returns the index of the first aabb |
|
template <typename TYPE, int DIMS> |
|
unsigned TAABB<TYPE,DIMS>::SplitBy(const POINT& pt, TAABB child[numChildren], unsigned& idxFirst) const |
|
{ |
|
idxFirst = 0; |
|
unsigned size; |
|
int a = 0; |
|
do { |
|
size = SplitBy(pt[a], a, child); |
|
if (++a == DIMS) |
|
return size; |
|
} while (size == 0); |
|
do { |
|
unsigned n = 0; |
|
for (unsigned b=0; b<size; ++b) { |
|
n += child[(idxFirst+b)%numChildren].SplitBy(pt[a], a, child+((idxFirst+size+n)%numChildren)); |
|
if (n == 0) |
|
goto MAIN_LOOP_END; |
|
} |
|
idxFirst += size; |
|
size = n; |
|
MAIN_LOOP_END:; |
|
} while (++a < DIMS); |
|
return size; |
|
} // SplitBy(point) |
|
/*----------------------------------------------------------------*/
|
|
|