Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Bit of a complex and lengthy question that, I'll admit, I don't quite understand very well yet so I will try and explain as best as I can.

Short Version: Is there a general c++/physx formula out there to calculate inertia tensors based off an objects shape?

Long Version: For our physics, we need to specify x, y and z inertia tensors. Currently the way we do it is pretty much just a ratio based off of mass. So if an object is long on the X axis and thin on Y and Z, and the mass is 10000, we will set Z and Y to 7000 and X to 3000. (This isn't exact, but just to give an idea)

This works relatively well but our biggest problem is when there is joint instability somewhere, we have to keep guessing at tensors until we figure out what works best. This can become very time consuming if we have a very big physics simulation and one out of 20+ joints is causing all the others to lose stability.

What I am working on is a function that will take the bounding box of an object and hopefully calculate relatively accurate tensors. I have taken some of the math from http://en.wikipedia.org/wiki/List_of_moment_of_inertia_tensors and made a function that basically works like the following for similar rotations below.

Solid cuboid of width w, height h, depth d, and mass m enter image description here

Or if the rotation is on an end, like this:

enter image description here enter image description here

So, this seems to give me results that are similar to the way we have been doing it, but I dont want to switch to this way without making sure that it will work for general use. Below is the code for my function based on the first image with a cube and center pivot.

NxVec3 CalculateInertiaTensor( VisBoundingBox_cl boundingBox, float m )
{
    float width = boundingBox.GetSizeX();
    float height = boundingBox.GetSizeZ();
    float depth = boundingBox.GetSizeY();

    float xTensor = 0.083f * m*(height*height + depth*depth);
    float yTensor = 0.083f * m*(width*width + depth*depth);
    float zTensor = 0.083f * m*(width*width + height*height);

    return NxVec3(xTensor, yTensor, zTensor);
}

I can't guarantee that this is the right way to do it (as the most accurate way is to use the actual shape instead of a bounding box) and i am not very familiar with inertia tensors and the math but it seems to return numbers fairly similar to what we were using. Anyone here happen to know if there is a better way to do this?

share|improve this question
3  
If you can decompose your object into tetrahedra then you ought to be able to use the linearity of the tensor along with the basic formula for the moment of inertia of a tetrahedron (you can find this with Wolfram Alpha, for instance) to compute an exact tensor. My concern with the bounding box method would be that it really depends on how much of your BB the object fills; imagine the difference between a fat ellipsoid and a slender helical spring, for instance. –  Steven Stadnicki Apr 24 '12 at 21:21
    
Thanks for the input. And you are correct, my main issue comes up when there is, say, an 'A' shaped object, the BB will make the tensors come back incorrectly. I'll check your info, thanks! –  Mungoid Apr 24 '12 at 21:23
    
You're welcome - if you'd like me to flesh this out in more detail, I ought to be able to build a proper answer out of it, but that should be enough to get you started. –  Steven Stadnicki Apr 24 '12 at 21:25
    
If you would be willing to, that would be awesome! I have been trying to figure this out for a while but I am still a bit of a fledgling in this area so I end up getting myself more and more confused =-) –  Mungoid Apr 24 '12 at 21:30

3 Answers 3

up vote 7 down vote accepted

I was going to suggest that this is a hard problem because the usual formulations based on using Green's Theorem to convert volume integrals into surface integrals don't apply, and so you actually do have to provide a tetrahedral decomposition of your figure - but it turns out that that's not correct. As long as your shape is of uniform density (which is an approximation you're already making anyway, presumably, and a perfectly reasonable one for most circumstances) then the volume integrals can be simplified to surface integrals, and the latter simplified even further. Better yet, there appears to be a pretty good-looking algorithm and code out there on the net to do this; have a look at http://www.cs.berkeley.edu/~jfc/mirtich/massProps.html , Brian Mirtich's page describing his algorithms for calculating moments and center of mass. It should cover pretty much all your needs on this front. Note that this is something you'll want to do one time, either as a tool on export of the shape or at import time, but not something you'll need to do every frame; just store the inertia tensor about the center of mass along with the rest of the shape info, and if you ever need to find the tensor for moments of inertia about some other axis then you can use the standard theorems to derive it.

Hopefully this should cover what you need - if there's more that I can try to help with, just let me know!

share|improve this answer

I have never done this myself, but if I had to write a quick solution for arbitrary meshes I would probably generate enough mass points inside the object to approximate it and calculate the inertia tensors from those.

The points could be generated uniformly inside the bounding box of the shape and then discarding those that are outside the actual shape. This would reduce the problem to just checking if a point is inside a shape.

share|improve this answer

For most game applications (i.e. "blowing up stuff") just using the equation for a rectangular solid given above is probably good enough. Provided that the object is axis-aligned, not a diagonal across the bounding box, that should work. Some game physics engines, such as ODE, only use the terms on the main diagonal of the inertia tensor. For them, your objects need to be at least roughly axis-aligned to work right.

I used Mirtich's algorithm in Falling Bodies back in 1997. It works well, but you must have clean geometry - a topologically correct closed non-self-intersecting mesh. If there are holes, the inertia computation will produce totally bogus results. I used only convex geometry, so I ran QHull first to get a convex hull for collision purposes, then computed the inertia from that.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.