In my physics engine, objects which are not of approximately the same height/length/width (cubelike) develop inaccurate angular velocities.
At first, I had assumed I had made an error in my numerical method for finding the inertia tensor and continued working within the bounds of cubelike objects, planning to fix it at a later stage. Now, as I add support objects whose inertia tensors can be evaluated symbolically (spheres, cones, cylinders), I observe the same behavior despite my confidence in the calculation.
For testing purposes, I focused on the cylinder case. I calculate the body inertia tensor in the same manner as listed at http://scienceworld.wolfram.com/physics ... inder.html, with a 'minor' difference. As I am developing specifically for the XNA Framework, I am using their Matrix class which is exclusively 4x4. For my implementation, I simply used the 4x4 identity matrix as a base, setting the M11, M22, and M33 fields to the appropriate values (as shown in the link).
The body inertia tensor inverse is then calculated based on that, and each frame's inertia tensor is calculated using:
Code: Select all
myInertiaTensorInverse = rotationMatrix * myBodyInertiaTensorInverse * Matrix.Transpose(rotationMatrix);
(removed)
I filmed a test set up with two cylinders of different sizes and the same mass under two different timescales (1 and .25). In each, the iteration count for the iterative solver is very high (100) so the impulse calculation converges accurately. Additionally, the larger, more cubelike cylinder stabilizes quickly after rolling around a little bit, while the smaller cylinder jitters noticably at timescale = 1 as it bounces and attempts to flip around. In both timescales, significant rotational error can be observed after the cylinder falls off the platform. As an extra note, the larger cylinder and other similarly cube-like objects experience no such noticable behavior upon falling off the platform.
What is the most likely culprit for the wildly accelerating deathspin after falling from the platform, and the related hyperactivity of the small cylinder on the platform? So far, there's a fairly short list of options I'm currently looking at:
* The inertia tensor representation. As I am not 100% sure, I would like to verify that my 4x4 inertia tensor matrix interpretation is valid.
* My current method of moving the simulation forward is a very simple euler integration implementation; as some of the jitter was removed with a lower timestep (more updates per movement), I thought perhaps that changing to an RK4 or other higher level integration method would help alleviate the issue, though I'm not sure it can fully explain the extreme case of spinning after falling off the platform.
* Another option would be that I have misused the inertia tensor somewhere else in the implementation, outside of contact impulse application (given that it spins inappropriately even when not in contact with any object). This narrows it down to essentially a couple of statements:
-As listed above, the inertia tensor inverse update in the forces/velocities update method:
Code: Select all
myInertiaTensorInverse = rotationMatrix * myBodyInertiaTensorInverse * Matrix.Transpose(rotationMatrix);
Code: Select all
angularVelocity = Vector3.Transform(myAngularMomentum, myInertiaTensorInverse);
* I use a quaternion and matrix method for storing rotations, similar to David Baraff's approach on pages 21 and 22 in the paper at http://www.cs.cmu.edu/~baraff/sigcourse/notesd1.pdf, as follows:
First, I take into account forces to generate the new velocities.
Code: Select all
//Angular Momentum:
myAngularMomentum = myAngularMomentum + myTorque * wait;
//Tensor:
myInertiaTensorInverse = Matrix.Transpose(rotationMatrix) * myBodyInertiaTensorInverse * rotationMatrix;
//Angular Velocity:
angularVelocity = Vector3.Transform(myAngularMomentum, myInertiaTensorInverse);
Code: Select all
rotation += ((new Quaternion(angularVelocity * wait, 0)) * .5f) * rotation;
rotation = Quaternion.Normalize(rotation);
rotationMatrix = Matrix.CreateFromQuaternion(rotation);[/list]
*Edit:
Upon creating a more controlled environment for demonstration purposes, I filmed the following video:
(removed)
Left to right, the momentums provided were:
(1,0,0) (0,1,0) (0,0,1)
Having observed the extremely rapid spin of the thin cylinder under the last angular momentum setting and the equal angular velocity between the first two, it would seem likely that I've reversed the inertia tensor calculation's axes. This could be due to XNA/DirectX's interpretation of Y as 'up', and somewhere in my construction of the tensor I could have used an inconsistent reference.
This is very promising and I'll investigate after I wake up. Perhaps my troubles have come to a premature end
