Download

Custom physics, Bouncing Ball - Angular and linear velocity after bounce

Hello,

I’m trying to create my own physics for a soccer ball and I’m having some issues with calculating the angular and linear velocity after impact/bouncing.
Using only the linear velocity the ball bounces pretty nice and it comes to rest. But, the angular velocity will change after impact and would actually alter the linear velocity as well. This is what I don’t know how to do, how to make use of the angular velocity on impact in order to change ball direction and rotation.

My current physics:

Linear Motion:



if (MagnusEffect > 0.f)
{
	Data.Forces.Add(MagnusEffect * FVector::CrossProduct(Data.AngularVelocity, Data.LinearVelocity));
}

FVector NetForce = -LinearDrag * 0.5f * 1.225e-6f * (Data.LinearVelocity * Data.LinearVelocity) * (3.14f * Radius * Radius);
for (const FVector& Force : Data.Forces)
{
	NetForce += Force;
}

FVector Acceleration = NetForce * Data.InverseMass;
if (!Data.IsOnGround)
{
	Acceleration += FVector(0.f, 0.f, Gravity);
}

Data.LinearVelocity += Acceleration * DeltaTime;

Data.PreviousLocation = Data.CurrentLocation;
Data.CurrentLocation += Data.LinearVelocity * DeltaTime;


Angular motion:



FVector NetAngularForce = FVector::ZeroVector;
for (const FVector& Force : Data.AngularForces)
{
	NetAngularForce += Force;
}

FVector AngularAcceleration = NetAngularForce / InertiaTensor;

Data.AngularVelocity = Data.AngularVelocity * FMath::Pow(AngularDamping, DeltaTime) + AngularAcceleration * DeltaTime;
if (Data.AngularVelocity.Size() > MaxAngularVelocity)
{
	Data.AngularVelocity = Data.AngularVelocity.GetSafeNormal() * MaxAngularVelocity;
}

Data.PreviousRotation = Data.CurrentRotation;
Data.CurrentRotation *= (FRotator(Data.AngularVelocity.Y, Data.AngularVelocity.Z, Data.AngularVelocity.X) * DeltaTime).Quaternion();


Impact handling:



Data.CurrentLocation = HitResult.ImpactNormal * Radius + HitResult.ImpactPoint;
Data.LinearVelocity = Restitution * Data.LinearVelocity.MirrorByVector(HitResult.ImpactNormal);

FPhysicsData FutureData = Data;
CalculatePhysicsLinearMotion(FutureData, DeltaTime);

if (FutureData.LinearVelocity.Z < 0.f)
{
	Data.LinearVelocity.Z = 0.f;
	Data.IsOnGround = true;
}

Data.IsColliding = true;


Any tips in how to handle the angular and linear velocity after impact?

Based on the “Physics for Game Developers” book I got this code to apply friction to a rotating ball to change its direction:



float friction = 0.1f;
FVector vCollisionPoint = HitResult.ImpactPoint - Data.CurrentLocation;
FVector vRelativeVelocity = Data.LinearVelocity + (Data.AngularVelocity ^ vCollisionPoint);
FVector vCollisionTangent = ((HitResult.ImpactNormal ^ vRelativeVelocity) ^ HitResult.ImpactNormal).GetSafeNormal();
		
float j = (-(1 + Restitution) * (vRelativeVelocity | HitResult.ImpactNormal)) /
          (Data.InverseMass + (HitResult.ImpactNormal | (((vCollisionPoint ^ HitResult.ImpactNormal) / InertiaTensor) ^ vCollisionPoint)));

Data.LinearVelocity += ((j * HitResult.ImpactNormal) + ((friction * j) * vCollisionTangent)) * Data.InverseMass;

The result is this:

As you can see my custom physics ball (the white one) changes its direction based on the angular velocity when hitting the ground. The problem is that the forward distance traveled on each bounce gets bigger and bigger, instead of getting smaller as the PhysX ball does (the red one).

Any idea what I’m doing wrong? Was quite cumbersome to translate the code from the book to Unreal, so maybe I missed something or translated bad.

I thought that maybe the forward distance keeps getting bigger because of the continuous spin of the ball, so on first bounce I set the angular velocity to 0. But, while the ball is no longer spinning, the ball still keeps jumping further and further.