Vibrating/Rotating/Bouncing object

Started by
15 comments, last by Aressera 5 months, 1 week ago

Hi there

I'm implementing my own game from scratch, and for physics I've been reading the book by Ian Millington “Game Physics Engine Development”

I do my own variation and some things are built differently, but the core of the collision resolution is like Ians. Currently I have implemented collision resolution up until the friction part (meaning no friction yet). And some parts of the engine are not working as intended. I'll show a couple of videos.

Currently I only check for collisions between one OBB (the figure) and the AABBs (static environment). I clip the vertices of the OBB that penetrate through the planes of the AABBs and use them as contactpoints, collect them all in an array alongside their specific penetrations and the overall contact normal for the collision. This gives me 1-4 contact points, 1-4 penetrations, 1 normal for each of my collisions.

I think the penetrationresolution works as in intended. (The white line is min→max point of the OBB)

Just a quick note: On the first video i kinda “push” the object by applying force to it - resulting in the object moving about. I do the same on the second video, but the bouncing/initial rotation and everything else is not coming from me

But when i try to apply correctional velocity, everything starts bouncing and behaving weirdly.

I've walked through the code so many times now and tested a lot of different things out - but can't seem to figure out why this is happening. Any ideas would be highly appreciated!

Advertisement

So I have narrowed it a bit down. It happens during calculation of the needed change in velocity compared to the closing velocity. (at the contact space X is up, Y.Z is the friction plane).

Sometimes the velocity in world space doesn't really point the same way as the contact normal. As a result the delta velocity gets small and the applied impulse gets very big, leading to objects suddenly jumping while they rotate

//cidx = contactindex
VECTOR deltaVelocityWorld = Math::Vector3Cross(contactDataFrame[cidx].relativecontactposition, contactDataFrame[cidx].contactnormal);
deltaVelocityWorld = Math::Vec3MultiplyMatrix(deltaVelocityWorld, worldtransformedinverseInertiaTensors[objectidx]);
deltaVelocityWorld = Math::Vector3Cross(deltaVelocityWorld, contactDataFrame[cidx].relativecontactposition);


float deltaVelocity = Math::Vector3Dot(deltaVelocityWorld, contactDataFrame[cidx].contactnormal).m128_f32[0];

deltaVelocity += mPhysicsOBJData[objectidx].inverseMass;

//desired delta velocity is based on the negative closing velocity in contact coordinates
impulseContact = { contactDataFrame[cidx].desiredDeltaVelocity / deltaVelocity,0.0f,0.0f,0.0f };

Okay, if use the untransformed inverseintertiatensor i suddenly get rid of the jumping up and down and weirdness. It doesn't look great yet, but no sudden rocket launches.

BadProgrammingGuide said:
Okay, if use the untransformed inverseintertiatensor i suddenly get rid of the jumping up and down and weirdness. It doesn't look great yet, but no sudden rocket launches.


That's not really a fix, but maybe it hints you have a math bug with inertia.

However, it's a common trick to use uniform inertia, or make it more uniform than it should be. Uniform inertia makes it easier for the solver, because bodies behave like simple spheres even if they have a complex shape.
I do this for ragdolls. Because the bodies are linked with joints to other bodies, the effect of ‘correct’ inertia is really subtle and rarely matters. With uniform inertia i get better results overall.

To calculate uniform inertia, i generate a sphere with the same volume and mass of the actual body, and then i use the inertia values from that sphere instead. Works pretty well.

@JoeJ Yeah not a fix. Do you know if I'd have to rotate the InverseInertiaTensor between iterations for the solver to work correctly?

The problem is either in the desiredDeltaVelocity or the actualDeltaVelocity calculations, since it's when the difference between them get too high a larger impulse gets applied and then the objects start jumping out of nowhere.

It's definitely related to the actual rotations of the object and thereby the InertiaTensor, since it's mostly when the object is about to stabilize after being turned over or something like that. Then it just starts jumping higher and higher.

BadProgrammingGuide said:
Do you know if I'd have to rotate the InverseInertiaTensor between iterations for the solver to work correctly?

Likely so. If your solver assumes inertia is already given in global space, you need to rotate the tensor each time the orientation of an object changes.
But it also works to keep inertia local all the time, and instead rotate the queried global lookup direction into local space on demand.

If inertia rotates wrongly, e.g. due to a bug of wrong multiplication order, it would explain the bouncing.

I would set up a test case: Make a capsule floating in empty space with out gravity, and apply torques of equal magnitudes along X,Y and Z directions. It should rotate faster on the direction aligned to the capsule axis.
Then you could rotate the entire setup randomly, and see if you still get the same results. If not, there must be a bug.

@JoeJ Thank you for the suggestions. I will toy around with it.

Parts of the simulation does look correctly (like a box that tries to stabilize on either of it's faces), but then the simulation starts adding a lot of momentum to the whole thing.

Do you know the formula for translating the Inverse tensor from object space into worldspace? And it's the same for the actual tensor (not the inverse)? I just want to be sure that the math is correct

@joej I'm a complete idiot. So transforming the matrix of the inverse tensor should ALSO have a multiplication with the transposed 3x3 rotational matrix. My god. Everything looks a bit better. But I don't think the OBB ends up landing in a stable position on the floor.

(The slam into the wall at the end is me applying force in that direction)

So the next problems are:

Objects don't seem to fall over… And once in a while they rotate kinda endlessly. I'm guessing the last part is due to no friction and the velocity perpendicular to the contact normal doesn't get affected?

The Inverted Tensor is like follows:
	{ 	0.30f,0.0f,0.0f,
		0.0f,1.0f,0.0f,
		0.0f,0.0f,0.46f };

BadProgrammingGuide said:
Parts of the simulation does look correctly (like a box that tries to stabilize on either of it's faces), but then the simulation starts adding a lot of momentum to the whole thing.

Reminds me that proofing conversation of momentum was very helpful to me when debugging physics. Though, right now we can see with bare eyes that some things are obviously very wrong.

BadProgrammingGuide said:
Do you know the formula for translating the Inverse tensor from object space into worldspace? And it's the same for the actual tensor (not the inverse)?

Not really, because i never used tensors. I had only used the 3 numbers of its diagonal, representing local inertia.
But i guess you can treat the tensor like a 3x3 matrix and rotate it like that.
And in any case, you can visualize inertia to reduce doubts. I did this some time back and still have the image:

But that's accurate inertia treating the whole character as a single rigid body. So i have to iterate and accumulate all bodies to calculate inertia for a single direction. That's not what the inertia tensor gives us, since it's an approximation.
I also have an image for a simple box, using points instead lines, so the actual directions is not as nicely visible as above:

The green shape is accurate inertia of a box, and the red shape shows the approximation an inertia tensor gives us.

So if you visialize many directions at many angles, you should get an ellipsoid shape. The values are larger for directions there it's harder to rotate the object.
If you rotate the object, the visualization should rotate with it, but the dimensions of the ellipsoid should remain the same. Just like with the box itself. That's probably a good test / proof to verify inertia math.

BadProgrammingGuide said:
So transforming the matrix of the inverse tensor should ALSO have a multiplication with the transposed 3x3 rotational matrix.

Makes some sense. Though, transpose of a 3x3 rotation gives its inverse, so the rotation from global to local space, if your rotational matrix is the worldspace orientation of the body.
So it might rotate the wrong way. What happens if you don't transpose it? Then you would rotate the tensor from local to global space, which is what i assume you want.

Sadly i'm no expert and can't really help. Usually there are some physics experts hanging out here.

This topic is closed to new replies.

Advertisement