OpenGTA/math/obb.cpp

127 lines
3.6 KiB
C++
Raw Normal View History

2015-12-03 00:37:02 +00:00
#ifndef GOMEZ_OBB_H
#define GOMEZ_OBB_H
/**
* Taken from:
* http://www.gamasutra.com/features/19990702/data_structures_01.htm
* http://www.gamasutra.com/features/19991018/Gomez_1.htm
*
* Both by Miguel Gomez
*/
#include "obb.hpp"
#include "vector.hpp"
namespace GomezMath {
//check if two oriented bounding boxes overlap
const bool OBBOverlap (
//A
Vector & a, //extents
Vector & Pa, //position
Vector * A, //orthonormal basis
//B
Vector & b, //extents
Vector & Pb, //position
Vector * B //orthonormal basis
)
{
//translation, in parent frame
Vector v = Pb - Pa;
//translation, in A's frame
Vector T (v.dot (A[0]), v.dot (A[1]), v.dot (A[2]));
//B's basis with respect to A's local frame
Scalar R[3][3];
float ra, rb, t;
long i, k;
//calculate rotation matrix
for (i = 0; i < 3; i++)
for (k = 0; k < 3; k++)
R[i][k] = A[i].dot (B[k]);
/*ALGORITHM: Use the separating axis test for all 15 potential
separating axes. If a separating axis could not be found, the two
boxes overlap. */
//A's basis vectors
for (i = 0; i < 3; i++)
{
ra = a[i];
rb =
b[0] * fabs (R[i][0]) + b[1] * fabs (R[i][1]) + b[2] * fabs (R[i][2]);
t = fabs (T[i]);
if (t > ra + rb)
return false;
}
//B's basis vectors
for (k = 0; k < 3; k++)
{
ra =
a[0] * fabs (R[0][k]) + a[1] * fabs (R[1][k]) + a[2] * fabs (R[2][k]);
rb = b[k];
t = fabs (T[0] * R[0][k] + T[1] * R[1][k] + T[2] * R[2][k]);
if (t > ra + rb)
return false;
}
//9 cross products
//L = A0 x B0
ra = a[1] * fabs (R[2][0]) + a[2] * fabs (R[1][0]);
rb = b[1] * fabs (R[0][2]) + b[2] * fabs (R[0][1]);
t = fabs (T[2] * R[1][0] - T[1] * R[2][0]);
if (t > ra + rb)
return false;
//L = A0 x B1
ra = a[1] * fabs (R[2][1]) + a[2] * fabs (R[1][1]);
rb = b[0] * fabs (R[0][2]) + b[2] * fabs (R[0][0]);
t = fabs (T[2] * R[1][1] - T[1] * R[2][1]);
if (t > ra + rb)
return false;
//L = A0 x B2
ra = a[1] * fabs (R[2][2]) + a[2] * fabs (R[1][2]);
rb = b[0] * fabs (R[0][1]) + b[1] * fabs (R[0][0]);
t = fabs (T[2] * R[1][2] - T[1] * R[2][2]);
if (t > ra + rb)
return false;
//L = A1 x B0
ra = a[0] * fabs (R[2][0]) + a[2] * fabs (R[0][0]);
rb = b[1] * fabs (R[1][2]) + b[2] * fabs (R[1][1]);
t = fabs (T[0] * R[2][0] - T[2] * R[0][0]);
if (t > ra + rb)
return false;
//L = A1 x B1
ra = a[0] * fabs (R[2][1]) + a[2] * fabs (R[0][1]);
rb = b[0] * fabs (R[1][2]) + b[2] * fabs (R[1][0]);
t = fabs (T[0] * R[2][1] - T[2] * R[0][1]);
if (t > ra + rb)
return false;
//L = A1 x B2
ra = a[0] * fabs (R[2][2]) + a[2] * fabs (R[0][2]);
rb = b[0] * fabs (R[1][1]) + b[1] * fabs (R[1][0]);
t = fabs (T[0] * R[2][2] - T[2] * R[0][2]);
if (t > ra + rb)
return false;
//L = A2 x B0
ra = a[0] * fabs (R[1][0]) + a[1] * fabs (R[0][0]);
rb = b[1] * fabs (R[2][2]) + b[2] * fabs (R[2][1]);
t = fabs (T[1] * R[0][0] - T[0] * R[1][0]);
if (t > ra + rb)
return false;
//L = A2 x B1
ra = a[0] * fabs (R[1][1]) + a[1] * fabs (R[0][1]);
rb = b[0] * fabs (R[2][2]) + b[2] * fabs (R[2][0]);
t = fabs (T[1] * R[0][1] - T[0] * R[1][1]);
if (t > ra + rb)
return false;
//L = A2 x B2
ra = a[0] * fabs (R[1][2]) + a[1] * fabs (R[0][2]);
rb = b[0] * fabs (R[2][1]) + b[1] * fabs (R[2][0]);
t = fabs (T[1] * R[0][2] - T[0] * R[1][2]);
if (t > ra + rb)
return false;
/*no separating axis found,
the two boxes overlap */
return true;
}
}
#endif