# Sphere and rectangle collision, adjusting for intersection

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

## Recommended Posts

I am currently doing a sphere to rectangle collision in which case I can find if it has collision, no collision or resting contact. While finding the resting contact I have to get the intersection depth. However, if how can I adjust the spheres position so that way it is no longer intersecting? I tried to scurry the internet, however, I just do not see much on the topic. Here is my currently implementation.
	D3DXMATRIX mTransform = *pCollisionRectangle->GetTransform();
D3DXMATRIX mInverseTransform;
D3DXMatrixInverse(&mInverseTransform, NULL, &mTransform);

D3DXVECTOR4 vLocalPoint4;
D3DXVECTOR3 vLocalPoint;
D3DXVec3Transform(&vLocalPoint4, &pCollisionSphere->GetOrigin(), &mInverseTransform);
vLocalPoint = D3DXVECTOR3(vLocalPoint4.x, vLocalPoint4.y, vLocalPoint4.z);
clamp(vLocalPoint.x, -pCollisionRectangle->GetExtents().x, pCollisionRectangle->GetExtents().x);
clamp(vLocalPoint.y, -pCollisionRectangle->GetExtents().y, pCollisionRectangle->GetExtents().y);
vLocalPoint.z = 0;

D3DXVECTOR4 vClosest4;
D3DXVec3Transform(&vClosest4, &vLocalPoint, &mTransform);
D3DXVECTOR3 vClosest(vClosest4.x, vClosest4.y, vClosest4.z);

D3DXVECTOR3 vDelta = pCollisionSphere->GetOrigin() - vClosest;

float dist = D3DXVec3Dot(&vDelta, &vDelta);

return NO_COLLISION;

float d = sqrt(dist);

D3DXVECTOR3 vCollisionNormal = vDelta / d;
float fIntersectionDepth = (pCollisionSphere->GetRadius() - d);

if(fIntersectionDepth == 0.0f)
return RESTING_CONTACT;

return HAS_COLLISION;


##### Share on other sites
"is no longer intersecting" is not a detailed description of what you want.

The simplest correction would be to shift the sphere's origin along what you've called the collision normal, because the intersection depth is given for that direction:
pCollisionSphere->GetOrigin() += vCollisionNormal * fIntersectionDepth

However, that makes the correction without taking any history into account. What I mean is that if the collision occured due to a motion of the (e.g.) sphere, then repelling the sphere in an arbitrary direction and amount (here arbitrary w.r.t. the motion) may look unnaturally. In this case the sphere seems to suddenly stick with the plane as soon as the collision occurs. This may or may not what you want. So you have to do the collision correction w.r.t. the "physical" effect that you've in mind, but we don't know what that is ...

##### Share on other sites
Quote:
 Original post by haegarrHowever, that makes the correction without taking any history into account. What I mean is that if the collision occured due to a motion of the (e.g.) sphere, then repelling the sphere in an arbitrary direction and amount (here arbitrary w.r.t. the motion) may look unnaturally. In this case the sphere seems to suddenly stick with the plane as soon as the collision occurs. This may or may not what you want. So you have to do the collision correction w.r.t. the "physical" effect that you've in mind, but we don't know what that is ...

The sphere would be in motion, so I am not sure if my initial collision detection would have to change also. I know that the collision detection being a sphere/plane and a in motion sphere/plane is a little bit different. What would be the most natural looking way to adjust for intersection?

##### Share on other sites
1) find point on box surface closest to the sphere centre.
2) if point outside sphere, no collision.
3) else reflect against normal (point - sphere.centre); That's your collision plane.

##### Share on other sites
I've recently composed a little tutorial on how to sweep a sphere against a polygon.

##### Share on other sites
Quote:
 Original post by oliii1) find point on box surface closest to the sphere centre.2) if point outside sphere, no collision.3) else reflect against normal (point - sphere.centre); That's your collision plane.

Maybe I worded my question wrong.

I know how to detect collision with a sphere and rectangle, but if the sphere and rectangle are colliding and the sphere is inside the rectangle, I am not sure what is the proper way to adjust the sphere so it is no longer intersecting it.

##### Share on other sites
Quote:
 I know how to detect collision with a sphere and rectangle, but if the sphere and rectangle are colliding and the sphere is inside the rectangle, I am not sure what is the proper way to adjust the sphere so it is no longer intersecting it.
Quote:
 Original post by haegarrThe simplest correction would be to shift the sphere's origin along what you've called the collision normal, because the intersection depth is given for that direction:pCollisionSphere->GetOrigin() += vCollisionNormal * fIntersectionDepth
Like haegarr said, this may not always give the desired results (depending on the circumstances), but geometrically speaking, it will resolve the intersection in the most direct way possible, if that's what you're looking for.

##### Share on other sites
Not entirely, just in case for the strange reason that it is not actually in resting contact but the intersection depth is zero (very rare, but it could happen). Plus if the sphere is approaching the rectangle on the x axis (rectangle is 90 x rotated), it would pop above the rectangle rather then move back on the x.

I am trying to put together a solution that is a mix between mine and Eric_Brown's. However, I am not sure if that is more of a hack

##### Share on other sites
Well I just tested implementing browns tutorial with my code, and I must have messed something up to say the least. In fact, I am not even sure if hacking his code into mine is suppose to be the correct formular. Here is what I came up with, P4 will be (-1.#, -1.#, -1.#) the first time there is collision (and the sphere is intersecting the rectangle).

// If there is no collision, will in intersect?	D3DXVECTOR3 P1 = pRigidBodySphere->GetOrigin() - (vCollisionNormal * pRigidBodySphere->GetRadius());	float s = d - (D3DXVec3Dot(&P1, &vCollisionNormal));	D3DXVECTOR3 P2 = P1 + (pRigidBodySphere->GetVelocity() * s);	D3DXVECTOR3 P3;	// Calculate the nearest point	{		float t = (D3DXVec3Dot(&vCollisionNormal, &P2) - d) / D3DXVec3Dot(&vCollisionNormal, &vCollisionNormal);		P3 = P2 - (t * vCollisionNormal);	}		float sweep = D3DXVec3Dot(&(P3 - pRigidBodySphere->GetOrigin()), &pRigidBodySphere->GetVelocity())*2 -	4 * (D3DXVec3Dot(&pRigidBodySphere->GetVelocity(), &pRigidBodySphere->GetVelocity())) *	D3DXVec3Dot(&(P3 + pRigidBodySphere->GetOrigin()), &(P3 - pRigidBodySphere->GetOrigin())) - (pRigidBodySphere->GetRadius()*2);	float t = (sqrt(sweep) - D3DXVec3Dot(&(2 * (P3-pRigidBodySphere->GetOrigin())), &pRigidBodySphere->GetVelocity())) / D3DXVec3Dot(&(2*pRigidBodySphere->GetVelocity()), &pRigidBodySphere->GetVelocity());	D3DXVECTOR3 P4 = P3 - (pRigidBodySphere->GetVelocity() *t);

##### Share on other sites
Quote:
 Well I just tested implementing browns tutorial with my code, and I must have messed something up to say the least.
We were just discussing in another thread that the method described in that tutorial is not actually correct (see the thread here for further details).

• 18
• 11
• 20
• 9
• 52
• ### Forum Statistics

• Total Topics
631397
• Total Posts
2999812
×