# Shouldn't the spheres rotate?

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

## Recommended Posts

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 on other sites
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 on other sites
Quote:
 Original post by SriLumpaYou 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.

• 11
• 20
• 12
• 10
• 38
• ### Forum Statistics

• Total Topics
631400
• Total Posts
2999862
×