Sign in to follow this  
Chirieac

Custom ball physics - velocities after bounce

Recommended Posts

Chirieac    147

Hi,

I'm trying to write my own physics for a soccer ball in Unreal Engine 4. I can't use PhysX because I need to predict the ball future location taking drag and other factors into account, and UE doesn't use a fixed timestep which would make the physics more deterministic. Having my own simulation for it I can advance it easily in the future.

Without angular velocity, I have the ball bouncing correctly using a restitution coefficient and coming to a rest properly. What gives me issues is the angular velocity. The ball should rotate after impact collision and the spin of the ball should modify the bounce direction if it was rotating really fast. For example, if you put a back spin to the ball and through it in front of you, the ball should come back to you.

I've searched around and tried different solutions but nothing worked properly. My latest try was to implement Coulomb friction based on Glenn Fiedler's article: http://gafferongames.com/virtual-go/collision-response-and-coulomb-friction/

Using those formulas I actually made the ball change direction after impact based on its angular velocity. The problem is that the angular velocity is not changed properly after impact, so with each bounce the ball jumps further and further way, adding more energy to the linear velocity. If I set angular velocity to 0 after first bounce, the ball seems to bounce as expected.

This is my code:

FTransform T = FTransform(InertiaTensor);
FVector InertiaTensorWorld = (T * Root->GetComponentTransform()).GetLocation();

FVector vCollisionPoint = HitResult.ImpactPoint - Data.CurrentLocation;
FVector r = vCollisionPoint;
FVector velocityAtPoint = Data.LinearVelocity + (-Data.AngularVelocity ^ vCollisionPoint);

const float vn = FMath::Min(0.0f, velocityAtPoint | HitResult.ImpactNormal);
const float k = Data.InverseMass + ((r ^ HitResult.ImpactNormal) | ((r ^ HitResult.ImpactNormal) / InertiaTensorWorld));
const float j = -(1 + Restitution) * vn / k;

Data.LinearVelocity += (j * HitResult.ImpactNormal) * Data.InverseMass;
Data.AngularVelocity += (j * (r ^ HitResult.ImpactNormal)) / InertiaTensorWorld;

// friction
velocityAtPoint = Data.LinearVelocity + (-Data.AngularVelocity ^ vCollisionPoint);
FVector tangentVelocity = velocityAtPoint - HitResult.ImpactNormal * (velocityAtPoint | HitResult.ImpactNormal);
FVector tangent = tangentVelocity.GetSafeNormal();

float u = 0.2f;
const float vt = (velocityAtPoint | tangent);
const float kt = Data.InverseMass + ((r ^ tangent) | ((r ^ tangent) / InertiaTensorWorld));
const float jt = FMath::Clamp(-vt / kt, -u * j, u * j);

Data.LinearVelocity += (jt * tangent) * Data.InverseMass;
Data.AngularVelocity += (jt * (r ^ tangent)) / InertiaTensorWorld;
//Data.AngularVelocity = FVector::ZeroVector;

Sorry it's kinda messy, but I've just copied as is from the examples I could find to make it easier to convert to unreal.

Is there a better way to handle the bouncing of a ball knowing that it just need to collide with the ground and walls?

Edited by Chirieac

Share this post


Link to post
Share on other sites
WiredCat    1451

no matter what you'll end up writing: once per frame, (ball is in motion even when vel is 0) you iterate with drag equation and motion till you hit something this is your hit pos/

 

basically: each frame you find new hitposition, then you do your stuff

Edited by WiredCat

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