• Advertisement
Sign in to follow this  

Box vs Plane Collision Detection

This topic is 1651 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Lets say that I have a plane and box and their position in the 3D world.

 

What is the mathematics behind detecting collision between box and plane?

 

Share this post


Link to post
Share on other sites
Advertisement

Here's the way to do it for an axis aligned box. For an oriented box, first rotate both box and plane by the inverse of the box's orientation to make the box axis aligned and proceed as if it were axis aligned.

 

The box is represented by a min vector and a max vector. The plane is represented by a normal and a distance.

Vector3 vec1, vec2;
 
if(normal.X >= 0)
{
  vec1.X = min.X;
  vec2.X = max.X;
}
else
{
  vec1.X = max.X;
  vec2.X = min.X;
}
if(normal.Y >= 0)
{
  vec1.Y = min.Y;
  vec2.Y = max.Y;
}
else
{
  vec1.Y = max.Y;
  vec2.Y = min.Y;
}
if(normal.Z >= 0)
{
  vec1.Z = min.Z;
  vec2.Z = max.Z;
}
else
{
  vec1.Z = max.Z;
  vec2.Z = min.Z;
}
float posSide = (normal.X * vec2.X)+(normal.Y * vec2.Y)+(normal.Y * vec2.Y)+planeDistance;
if(posSide > 0)
{
  //box is completely on positive side of plane
  return;
}
float negSide = (normal.X * vec1.X)+(normal.Y * vec1.Y)+(normal.Y * vec1.Y)+planeDistance;
if(negSide < 0)
{
  //box is completely on negative side of plane
  return;
}
//if you get this far, box is currently intersecting the plane.
Edited by shazen

Share this post


Link to post
Share on other sites

if it's an Axis Aligned box, things are easy, you can actually treat the center as a radius

struct Sphere { float m_Radius; Vector3 m_Center; };
struct AABB { Vector3 min,max; };
struct Plane { Vector3 normal; float offset; };
 
int SphereToPlaneCollision(const Plane& plane, const Sphere& sphere)
{
    float dot = dot_product(plane.normal,sphere.m_Center) - plane.offset;
 
    if(dot > sphere.m_Radius)
        return 1; // The sphere is in front of the plane
    else if(dot < -sphere.m_Radius)
        return 2; // The sphere is behind the plane
 
    return 3; // The sphere collides/straddles with the plane
}
int AabbToPlaneCollision(const Plane& plane, const AABB& aabb)
{
    // Get the Extense vector
    Vector3 E = (aabb.max - aabb.min)/2.0f;
    
    // Get the center of the Box
    Vector3 center = aabb.min + E;
 
    Vector3 N = plane.normal;
 
    // Dot Product between the plane normal and the center of the Axis Aligned Box
    // using absolute values
    float fRadius = abs(N.x*E.x) + abs(N.y*E.y) + abs(N.z*E.z);
 
    Sphere sphere;
    sphere.m_Center = center;
    sphere.m_Radius = fRadius;
 
    return SphereToPlaneCollision( plane,sphere );
}
Edited by Muzzy A

Share this post


Link to post
Share on other sites

take 3 points of the plane, any 3.

 

Vector3 vecAB = v1 - v0;
Vector3 vecAC = v2 - v0;
 
// Cross vecAB and vecAC
Vector3 normal = Cross_Product( vecAB,vecAC );
normal.normalize();

Share this post


Link to post
Share on other sites

@shazen: Okay, I can get the plane normal, but what is planeDistance?

 

@Muzzy A: How do I get plane.offset?

Edited by Medo3337

Share this post


Link to post
Share on other sites

dot product the normal of the plane with any point on the plane.

 

The plane offset just tells how far away from the origin the plane is in the direction of the normal.

Edited by Muzzy A

Share this post


Link to post
Share on other sites

@Muzzy A: It's not working with me, I tried the following code:

 

NOTICE: The box has it's position in the 3D world, I think I need to transform the box min/max according to the box transformation?

AABB aabb = GetBox(); // Get box AABB
D3DXVECTOR3 boxPosition = GetBoxPosition(); // Position in 3D world (XYZ)
D3DXVECTOR3 q1, q2, q3, q4; // Plane final vertices in 3D worldPlane plane;

D3DXVECTOR3 planeNormal = GetTriangleNormal(q1, q2, q3);
plane.normal = planeNormal;
plane.offset = D3DXVec3Dot(&plane.normal, &q1);

if (AabbToPlaneCollision(plane, aabb))
{
    // Box/Collision detected
} else {
    // Collision not detected
}
Edited by Medo3337

Share this post


Link to post
Share on other sites

The min and max should be in world space, and this is only for Axis Aligned Boxes. Axis Aligned Bounding Boxes don't have any rotation, They are aligned with all 3 axis (x,y,z) perfectly.

Share this post


Link to post
Share on other sites
@Muzzy A: I tried transforming the AABB min and max to the world space as the following:
AABB aabb = GetBox();
D3DXVECTOR3 boxPosition = GetBoxPosition();
D3DXMATRIX matBox;
D3DXMatrixTranslation(&matBox, boxPosition->x, boxPosition->y, boxPosition->z);

D3DXVec3TransformCoord(&aabb.Min, &aabb.Min, &matBox);
D3DXVec3TransformCoord(&aabb.Max, &aabb.Max, &matBox);

But AabbToPlaneCollision() is returning true all the time if the planes are not intersecting.

Edited by Medo3337

Share this post


Link to post
Share on other sites

if you implemented the bit of code i gave you, then returning 3 means there's a collision

Share this post


Link to post
Share on other sites
@Muzzy A: It's saying that there is collision even when there is no collision, take a look at my code so you could spot something wrong:
// ** I get AABB by using D3DXComputeBoundingBox() on LPD3DXMESH ***
// 'boxPosition' is the position of the LPD3DXMESH
// q1, q2, q3, q4 are the plane 4 vertices in the 3D world
AABB aabb = GetBox();
D3DXVECTOR3 boxPosition = GetBoxPosition();
D3DXMATRIX matBox;
D3DXMatrixTranslation(&matBox, boxPosition.x, boxPosition.y, boxPosition.z);

D3DXVec3TransformCoord(&aabb.Min, &aabb.Min, &matBox);
D3DXVec3TransformCoord(&aabb.Max, &aabb.Max, &matBox);

Plane plane;
plane.normal = GetTriangleNormal(q1, q2, q3);
plane.offset  = D3DXVec3Dot(&planeNormal, &q1);

if (AabbToPlaneCollision(plane, aabb) == 3)
{
    // Collision detected
} else {
    // Collision NOT detected
}

 

Share this post


Link to post
Share on other sites

I think the reason is that D3DXComputeBoundingBox() returns axis oriented bounding box, if so, any code example on how to convert it to axis aligned?

 

I have been trying to convert it to axis aligned but couldn't get it work.

Edited by Medo3337

Share this post


Link to post
Share on other sites

This topic is 1651 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Advertisement