Craig Woollett

Computing the side planes of a 3D AABB

Recommended Posts

I have a 3D AABB defined by two sets of points a min/max.

I'd like to define the 6 planes that make up the sides of the AABB, such that any point that is within the AABB will have a positive signed-distance.

My plane definition is comprised of a normal (x,y,z) and a constant D, Corresponding to the Ax + By +Cz + D = 0 form plane equation.

    struct myplane {
       double nx,ny,nz;
       double D;
    };

Note: nx,ny, and nz are normalized.

    The AABB struct is as follows:

    struct myAABB {
       point3d min;
       point3d max;
    };

I'm currently defining instances of the AABB sides like so:

    myplane p0 =  myplane{-1.0f, 0.0f, 0.0f,aabb.max.x);
    myplane p1 =  myplane{ 0.0f,-1.0f, 0.0f,aabb.max.y);
    myplane p2 =  myplane{ 0.0f, 0.0f,-1.0f,aabb.max.z);
    myplane p3 =  myplane{+1.0f, 0.0f, 0.0f,aabb.min.x);
    myplane p4 =  myplane{ 0.0f,+1.0f, 0.0f,aabb.min.y);
    myplane p5 =  myplane{ 0.0f, 0.0f,+1.0f,aabb.min.z);


where aabb is in this case is:  min(-1,-1,-1) max(1,1,1)


The problem is that points in the AABB return a positive distance for the planes p0,p1 and p2, however not so for planes p3,p4 and p5, as they return negative distances which seem to indicate the points are on the other side.

For example the origin point **(0,0,0)** should return a positive distance of 1 for each of the planes however does not for planes p3,p4 and p5.

The signed-distance calculation being used is:

    double distance(myplane& p, const point3d& v)
    {
        // p.normal dot v + D
        return (p.nx * v.x) + (p.ny * v.y)  + (p.nz * v.z)  + p.D;
    }

I think my equations are wrong in some way, but I can't seem to figure it out.

Share this post


Link to post
Share on other sites
55 minutes ago, Craig Woollett said:

myplane p0 =  myplane{-1.0f, 0.0f, 0.0f,aabb.max.x);

you can switch the signs of the unit vector or swap min/max. If it still does not work as expected, negate the value for D.

(It's a question of convention, you can do trial and error until it is how you want it.)

Share this post


Link to post
Share on other sites

signed distance is fairly simple.

vec3 pn = { -1, 0, 0 } // plane normal
vec3 pp = { -2, 0. 0 } // plane point
vec3 pt = { 0, 0, 0 }  // test point
float d = dot(pn, pt - pp) // signed distance

so in your case using min/max and pushing along the normal with an absolute value 

vec3 pn1 = {-1, 0, 0 } // min plane normal
float min = -2
vec3 pn2 = { 1, 0, 0 } // max plane normal
float max = 2
	
vec3 pt = { 0, 0, 0 }  // test point
float dmin = dot(pn1, pt - (pn1*abs(min))) // signed distance
float dmax = dot(pn2, pt - (pn2*abs(max))) // signed distance

the test point is on the negative side of both planes.

Feels a little confusing with this min/max usage because if you don't use an absolute value, you'd be pushing the plane the wrong way. Another way to look at it is, since you're axis aligned, forget the absolute stuff, have your normals always point to positive quadrants and use min/max naturally. Something like this...

vec3 axisX = { 1, 0, 0 } // yz plane
float xMin = -2;
float xMax = +2;

vec3 pt = { 0, 0, 0 } // test point
float dmin = dot(axisX, pt - (axisX * xMin)) // signed distance
float dmax = dot(axisX, pt - (axisX * xMax)) // signed distance

But if min shifts over the origin, that last one and the one before is broken. What we need to do is introduce object origin offset. Something like this

vec3 axisXP = { 1, 0, 0 }
vec3 axisXN = {-1, 0, 0 }
float xMin = -2; // relative to object origin
float xMax = +2; // relative to object origin
vec3 objPos = { 5, 0, 0 } // relative to world origin shifts to xMin = 3 xMax = 7

vec3 pt = { 4, 0, 0 } // test point relative to world origin
float dmin = dot(axisXN, pt - abs(axisXN * abs(objPos.x + xMin)))
float dmax = dot(axisXP, pt - abs(axisXP * abs(objPos.x + xMax)))

Now we're good except when the object moves to the negative side of the origin. Well crumb...looks like there is more work to do...Hope that helps you see the problem more clearly.

Edited by GoliathForge
fixed code formatting and an additional thought.

Share this post


Link to post
Share on other sites

Well thats really trivial question since you own all data needrd to crrate planes yoy ask herr there are plenty of ways to do this but they all involve these teo points, i recommend you draw an axis aligned box on paper then mark your points - you still cant compute other points? Well yhats so obvious that noone will tell you how to do that, when you compute all 8 points you have two options , either compute crossproduct for each side or use normal of side and a point that lies on that side to find D in your Ax+By+Cz+D=0. Aftrr that you need to chceck whenever your planes face right direction you do that by dividing min and max by 2

(Min+max)/2= cp        //center point

 

U assume you know that ABC arr your side plane normal components correspondibgto xyz in vector

Then you just do dot(side nornal, cp) and check whenever they are negative or else and change the sign of a normal

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now