Jump to content
  • Advertisement
Sign in to follow this  
Medo Mex

Box vs Plane Collision Detection

This topic is 1822 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

This topic is 1822 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
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!