Sign in to follow this  
Narf the Mouse

Shouldn't the spheres rotate?

Recommended Posts

Narf the Mouse    322
I've got a 3D sphere-sphere collision physics setup. One sphere, coming from the left hits the other; it then bounces off and imparts some momentum to the other sphere. This is all as expected.

Except - The collision produces no rotation. The point of collision looks like this:


So...One apparent problem. With an offset like that, I'd think they'd start rotating. However, with the normal calculation I keep seeing on the internet ("Vector3 collisionNormal = Vector3.Normalize(collisionPoint - collisionPositionA);"), they don't rotate. I've tried the following fix, but I'm not sure how correct it is: "Vector3 collisionNormal = Vector3.Normalize(relativeVelocity + (collisionPoint - collisionPositionA))". This is because, when the force offset of "collisionPoint - collisionPositionA" is crossed with that collisionNormal, it naturally results in a (0, 0, 0) vector.

So - Shouldn't they rotate? And, if so, what am I doing wrong? Or am I missing something?

Sphere-Sphere intersection:

internal static bool Intersection(
float radiusA, Vector3 previousPositionA, Vector3 currentPositionA,
float radiusB, Vector3 previousPositionB, Vector3 currentPositionB,
out CollisionData collisionData,
float maxTime
)
{
Vector3 velocityA = currentPositionA - previousPositionA;
Vector3 velocityB = currentPositionB - previousPositionB;
Vector3 lastToLast = previousPositionB - previousPositionA;
// Vector3 lastToLast = currentPositionB - currentPositionA;
Vector3 relativeVelocity = velocityB - velocityA;
float totalRadius = radiusA + radiusB;
float a = Vector3.Dot(relativeVelocity, relativeVelocity);
float b = 2 * Vector3.Dot(relativeVelocity, lastToLast);
float ca = Vector3.Dot(lastToLast, lastToLast);
float cb = totalRadius * totalRadius;
if (ca <= cb)
{
float t1 = 0, t2 = 0;
collisionData = GenerateCollisonData(
radiusA, ref previousPositionA,
radiusB, ref previousPositionB,
ref velocityA, ref velocityB,
ref relativeVelocity,
t1, t2
);
return true;
}
{
float c = ca - cb;
float t1, t2;
if (SGLMath.Quadratic(a, b, c, out t1, out t2))
{
if (t1 > t2)
Main.Swap<float>(ref t1, ref t2);

if (t1 > maxTime ||
t1 < 0)
{
collisionData = new CollisionData(false);
return false;
}

collisionData = GenerateCollisonData(
radiusA, ref previousPositionA,
radiusB, ref previousPositionB,
ref velocityA, ref velocityB,
ref relativeVelocity,
t1, t2
);
return true;
}
}
collisionData = new CollisionData(false);
return false;
}


Collision data generation:

private static CollisionData GenerateCollisonData(
float radiusA, ref Vector3 previousPositionA,
float radiusB, ref Vector3 previousPositionB,
ref Vector3 velocityA, ref Vector3 velocityB,
ref Vector3 relativeVelocity,
float t1, float t2
)
{
CollisionData collisionData;
Vector3 collisionPositionA = previousPositionA + (velocityA * t1);
Vector3 collisionPositionB = previousPositionB + (velocityB * t1);
Vector3 collisionPoint = Vector3.Lerp(collisionPositionA, collisionPositionB, radiusA / (radiusA + radiusB));
Vector3 collisionNormal = Vector3.Normalize(collisionPoint - collisionPositionA);
// Vector3 collisionNormal = Vector3.Normalize(Vector3.Lerp(relativeVelocity, collisionPoint - collisionPositionA, 0.5F));
// Vector3 collisionNormal = Vector3.Normalize(relativeVelocity + (collisionPoint - collisionPositionA));
// Vector3 collisionNormal = Vector3.Normalize(collisionPositionB - collisionPoint);
collisionData = new CollisionData(
true,
t1, t2,
collisionPositionA, collisionPositionB,
collisionPoint, collisionNormal
);
return collisionData;
}


Collision handling:

internal static void HandleCollision(RigidBody rigidBodyOne, RigidBody rigidBodyTwo, CollisionData collisionData)
{
float inverseMass = rigidBodyOne.physic.InverseMass + rigidBodyTwo.physic.InverseMass;
if (inverseMass <= 0.0000001F)
inverseMass = 1.0F;

Vector3 impactVelocity = rigidBodyOne.physic.Velocity - rigidBodyTwo.physic.Velocity;
float impactVelocityDotNormal = Vector3.Dot(impactVelocity, collisionData.Normal);

if (impactVelocityDotNormal < 0F)
return;

float bounce = 1.0F;
float j = -(1.0F + bounce) * impactVelocityDotNormal / inverseMass;

rigidBodyOne.physic.ApplyForce(
new Force(collisionData.Normal * (j * rigidBodyOne.physic.InverseMass),
collisionData.Point - collisionData.PositionA));
rigidBodyTwo.physic.ApplyForce(
new Force(-collisionData.Normal * (j * rigidBodyOne.physic.InverseMass),
collisionData.Point - collisionData.PositionB));
}


ApplyForce function:

public void ApplyForce(Force force)
{
velocity += force.Vector * InverseMass;
Vector3 crossVector = Vector3.Cross(force.Vector, force.Offset);
crossVector = new Vector3(crossVector.X * InverseInertia.X, crossVector.Y * InverseInertia.Y, crossVector.Z * InverseInertia.Z);
angularVelocity += crossVector;
}


Thanks.

Share this post


Link to post
Share on other sites
SriLumpa    198
You need some friction in order to get rotations for spheres.


Probably unrelated, but this:

if (inverseMass <= 0.0000001F)
inverseMass = 1.0F;

looks suspicious.

Share this post


Link to post
Share on other sites
Narf the Mouse    322
Quote:
Original post by SriLumpa
You need some friction in order to get rotations for spheres.


Probably unrelated, but this:

if (inverseMass <= 0.0000001F)
inverseMass = 1.0F;

looks suspicious.

Thanks.


It's only used for calculating the base j-value.

float bounce = 1.0F;
float j = -(1.0F + bounce) * impactVelocityDotNormal / inverseMass;

The actual collision vector is multiplied by the respective inverse mass of the objects.

rigidBodyOne.physic.ApplyForce(
new Force(collisionData.Normal * (j * rigidBodyOne.physic.InverseMass),
collisionData.Point - collisionData.PositionA));
rigidBodyTwo.physic.ApplyForce(
new Force(-collisionData.Normal * (j * rigidBodyOne.physic.InverseMass),
collisionData.Point - collisionData.PositionB));

It is double-take worthy.

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

Sign in to follow this