# Bounding Box - Push away objects

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

## Recommended Posts

Hi, I have an Bounding box collision test and I whanna know how to push away objects that are inside it, does anyone knows how to do this? thx.

##### Share on other sites
A quick way is to take the minimum overlap between the boxes, and use that to push the objects around. Not very accurate, but it's a start.

bool Collide(Box A, Box B, Vector& PushVector){    Vector ABpush(A.Max - B.Min);    Vector BApush(B.Max - A.Min);    if (ABpush.x < 0.0f || ABpush.y < 0.0f || ABpush.z < 0.0f ||        BApush.x < 0.0f || BApush.y < 0.0f || BApush.z < 0.0f)        return false;    PushVector = Vector((ABpush.x < BApush.x)? -ABpush.x : BApush.x,                        (ABpush.y < BApush.y)? -ABpush.y : BApush.y,                        (ABpush.z < BApush.z)? -ABpush.z : BApush.z);    float min;    if (fabs(PushVector.y) < fabs(PushVector.x))    {        PushVector.x = 0.0f;        min = PushVector.y;    }    else    {        PushVector.y = 0.0f;        min = PushVector.x;    }        if (fabs(PushVector.z) < min)    {        PushVector.x = PushVector.y = 0.0f;    }    else    {        PushVector.z = 0.0f;    }    return true;  }// if boxA intersects boxB, push boxA awayVector PushVector;if (Collide(BoxA, BoxB, PushVector)){    BoxA.Min += PushVector;    BoxA.Max += PushVector;}

##### Share on other sites
Thanks it works well using the box->box, but if I use this I need to have an box around my character, cant I just use and sphere -> box collision in this case? and whant changes do I need to do for this?

##### Share on other sites
Sure, circle to box is a little more difficult than bounding box. Linear algebra is a plus. This in fact requires 8 tests. The first four are against the lines, and the other four are against the points. Of course, some of these can be eliminated with some clever coding. I'm feeling generous, so I'll post how I do sphere against box:

		public static bool ballAgainstRectangleMove(Sprite ball, Sprite rectangle)		{			Point ballPoint = new Point(ball.x, ball.y);			Segment topEdge = new Segment(new Point(-rectangle.sclX, rectangle.sclY), new Point(rectangle.sclX, rectangle.sclY));			CommonFunctions.RotateLineAroundPoint(new Point(0, 0), ref topEdge, rectangle.rotZ);			topEdge.MoveBy(rectangle.x, rectangle.y);			float smallestDistance;			string edgeClosestTo;			Math2D.Segment collisionPointToBall = new Segment();			smallestDistance = ballPoint.DistanceTo(topEdge,ref collisionPointToBall);			edgeClosestTo = "top";			Segment bottomEdge = new Segment(new Point(-rectangle.sclX, -rectangle.sclY), new Point(rectangle.sclX, -rectangle.sclY));			CommonFunctions.RotateLineAroundPoint(new Point(0, 0), ref bottomEdge, rectangle.rotZ);			bottomEdge.MoveBy(rectangle.x, rectangle.y);			if(ballPoint.DistanceTo(bottomEdge) < smallestDistance)			{				smallestDistance = ballPoint.DistanceTo(bottomEdge,ref collisionPointToBall);				edgeClosestTo = "bottom";			}			Segment leftEdge = new Segment(new Point(-rectangle.sclX, rectangle.sclY), new Point(-rectangle.sclX, -rectangle.sclY));			CommonFunctions.RotateLineAroundPoint(new Point(0, 0), ref leftEdge, rectangle.rotZ);			leftEdge.MoveBy(rectangle.x, rectangle.y);			if(ballPoint.DistanceTo(leftEdge) < smallestDistance)			{				smallestDistance = ballPoint.DistanceTo(leftEdge,ref collisionPointToBall);				edgeClosestTo = "left";			}			Segment rightEdge = new Segment(new Point(rectangle.sclX, rectangle.sclY), new Point(rectangle.sclX, -rectangle.sclY));			CommonFunctions.RotateLineAroundPoint(new Point(0, 0), ref rightEdge, rectangle.rotZ);			rightEdge.MoveBy(rectangle.x, rectangle.y);			if(ballPoint.DistanceTo(rightEdge) < smallestDistance)			{				smallestDistance = ballPoint.DistanceTo(rightEdge,ref collisionPointToBall);				edgeClosestTo = "right";			}			if(smallestDistance < ball.sclX)			{				float remainingDistance = ball.sclX - smallestDistance;				Vector2 amountToMove = new Vector2(ballPoint.x - collisionPointToBall.p1.x, ballPoint.y - collisionPointToBall.p1.y);				amountToMove.Normalize();				amountToMove = amountToMove * remainingDistance;				ball.x += amountToMove.X;				ball.y += amountToMove.Y;				return true;			}			else				return false;}

Wow, that's a lot of code. But it's a start. If you're interested in discussing it, you can send me a message on AOL Instant Messenger: ArmySarj.

Good luck.

--vic--

##### Share on other sites
for sphere box, it's actually quite similar. You need to find the closest point on the box to the sphere centre, which is similar to the code I posted, but even simpler in the case of the centre being outside the box. Then it's a matter of testing if that point is inside the sphere, if it is, calculate the point on the sphere that is the closest to that point (again, take the opposite point of the sphere centre is inside the box), and push the sphere so that the two contact points meet.

// returns if point is inside the box alreadybool ClosestPointOnBox(Vector P, Box B, Vectop& Q){    Vector D = (P - Box.Centre);    // Vector::Abs() takes abosilute values of x, y, z, store it     // in vector form    Vector F = Box.Extent - D.Abs();    if (inx && iny && inz)    {        float min;        if (F.x < F.y)        {             D.y = 0.0f;             min = F.x;        }        else        {             D.x = 0.0f;             min = F.y;        }        if (F.z < min)        {            D.x = D.y = 0.0f;        }        else        {             D.z = 0.0f;        }        // Vector::Sign() calcualtes the sign of x, y , z and         // store it as vector         D = D.Sign();        D.ScaleBy(Box.Extent);                Q = B.Centre + D;     }     else     {         if (inxx) D.x = sgn(D.x) * Box.Extent.x;         if (inxy) D.y = sgn(D.y) * Box.Extent.y;         if (inxz) D.z = sgn(D.z) * Box.Extent.z;             Pbox = Box.Centre + D;         return false;     }}bool PointInsideSphere(SphereS, Vector P){    Vector D = P - S.Centre;    float d2 = D.LengthSquared();    return (d2 < Sphere.Radius2);}Vector ClosestPointOnSphere(Vector P, Sphere S){    Vector D = P - S.Centre;    D /= D.Length();    return S.Centre + D * Sphere.Radius;}Vector FurthestPointOnSphere(Vector P, Sphere S){    Vector D = P - S.Centre;    D /= D.Length();    return S.Centre - D * Sphere.Radius;}bool ContactPoints(Sphere S, Box B, Vector& Pbox, Vector& Psphere){     bool inside = ClosestPointOnBox(S.Centre, B, Pbox);     if (!PointInsideSphere(S, Pbox))         return false;     if (inside)     {         FurthestPointOnSphere(Pbox, S, Psphere);     }     else     {         ClosestPointOnSphere(Pbox, S, Psphere);     }     return true;}bool Collide(Sphere S, Box B, Vector& Push){    Vector Psphere;    Vector Pbox;        if (!ContactPoints(S, B, Psphere, Pbox))        return false;    Push = Pbox - Psphere;    return true;}

that's what I use. And the method can be generalised to any kind of convex shapes, like triangles, segments and polygons.

##### Share on other sites
Thanks for your replys guys, got an picture on how all this works now, thx.

1. 1
2. 2
3. 3
4. 4
5. 5

• 14
• 9
• 10
• 12
• 17
• ### Forum Statistics

• Total Topics
632909
• Total Posts
3009171
• ### Who's Online (See full list)

There are no registered users currently online

×