// Given point p, return point q on (or in) OBB b, closest to p
void ClosestPtInOBB(D3DXVECTOR3 p,
D3DXVECTOR3 bc,
D3DXVECTOR3* bu,
float* be,
D3DXVECTOR3 &q )
{
D3DXVECTOR3 d = p - bc;
// Start result at center of box; make steps from there
q = bc;
// For each OBB axis...
for (int i = 0; i < 3; i++)
{
// ...project d onto that axis to get the distance
// along the axis of d from the box center
float dist = D3DXVec3Dot(&d, &bu[i]);
// If distance farther than the box extents, clamp to the box
if (dist > be[i]) dist = be[i];
if (dist < -be[i]) dist = -be[i];
// Step that distance along the axis to get world coordinate
q += dist * bu[i];
}
}
// Returns true if sphere s intersects OBB b, false otherwise.
// The point p on the OBB closest to the sphere center is also returned
int SimpleSphereOBB_2D( D3DXVECTOR3 sc, float sr,
D3DXVECTOR3 *boxCorners,
D3DXVECTOR3 &p)
{
D3DXVECTOR3 bMin = D3DXVECTOR3(0,0,0);
D3DXVECTOR3 bMax = D3DXVECTOR3(0,0,0);
D3DXVECTOR3 obbCentre;
int i = 0;
bMin.x = boxCorners[i].x;
bMin.y = boxCorners[i].y;
bMin.z = boxCorners[i].z;
bMax.x = boxCorners[i].x;
bMax.y = boxCorners[i].y;
bMax.z = boxCorners[i].z;
for (i=0; i<4; i++)
{
bMin.x = min(bMin.x, boxCorners[i].x);
bMin.y = min(bMin.y, boxCorners[i].y);
bMin.z = min(bMin.z, boxCorners[i].z);
bMax.x = max(bMax.x, boxCorners[i].x);
bMax.y = max(bMax.y, boxCorners[i].y);
bMax.z = max(bMax.z, boxCorners[i].z);
}
obbCentre = (bMax - bMin)/2.0f;
float be[3];
D3DXVECTOR3 bu[3];
bu[0] = boxCorners[0] - boxCorners[1];
be[0] = D3DXVec3Length(&bu[0]);
D3DXVec3Normalize(&bu[0], &bu[0]);
bu[1] = boxCorners[1] - boxCorners[2];
be[1] = D3DXVec3Length(&bu[1]);
D3DXVec3Normalize(&bu[1], &bu[1]);
bu[2] = D3DXVECTOR3(0,0,0);
be[2] = 0.0f;
// Find point p on OBB closest to sphere center
ClosestPtPointOBB(sc,
obbCentre,
bu,
be,
p);
// Sphere and OBB intersect if the (squared) distance from sphere
// center to point p is less than the (squared) sphere radius
D3DXVECTOR3 v = p - sc;
return D3DXVec3Dot(&v, &v) <= sr * sr;
}
|