To get the center of mass and inertial properties of a mesh you can copy/paste code from here:
http://www.melax.com/volint
But to combine a number shapes together into a single rigid body you can combine the mass properties together.
Obviously, The total mass is the sum of all the individual subshape masses. The center of mass for the aggregate object is the weighted average of the individual shapes.
Deriving the inertia tensor is almost, but not quite, as simple. For now lets assume that you have a 3x3 inertia for each shape and that there is no local orientation to worry about. We will deal with that later. Each of these 3x3 inertia tensors is with respect to the corresponding shape's center of mass - not the center of mass of the whole thing (combined aggregate object/rigidbody). Lets start with the pseudocode then discuss the theory later if there is any interest.
First, If you dont yet have an outerproduct function in your math library then add one next to your dot and cross product functions. its simply:
Code: Select all
float3x3 outerproduct(const float3 &a,const float3 &b)
{
return float3x3(a.x*b,a.y*b,a.z*b); // row initialization assumed
}
Now, What you want to do is:
Code: Select all
float3 center_of_mass // of rigidbody weighted sum of subshapes
float3x3 inertia(0,0,...0) // inertia tensor of combined object/rigidbody
float3x3 Identity(1,0,0,0,1,0,0,0,1)
for each shape s
{
r = s.center_of_mass - center_of_mass
inertia += s.inertia + (dot(r,r)*Identity-outerproduct(r,r))*s.mass
}
The rhs of the inertia+= expression becomes what the original inertia summation/integration for that shape would have been had it been done with respect to the new body's center of mass instead of with respect to the subshape's center of mass.
Now you might be combining subshapes that have local orientations - not just offset local positions and centers of mass. In this case you first have to align the 3x3 inertia tensors to the same "global" or rigidbody space. Its not just a matter of multiplying the 3x3 by the orientation matrix the same way you might rotate a vertex or normal. Instead you want:
Code: Select all
inertia_common_alignment = transpose(R) * inertia_local * R
After you have aligned the tensors, you can add them as described above.
Where R is the local orientation of the shape. Note I used d3d-ish convention where
Reverse the order (to R*T*R^T) if you are using opposite conventions.
One way to help understand why we are multiplying on both sides is to think of how you would apply a function or transformation. Imagine you have a process that works in a particular coordinate frame. You would transform your data to that frame, do the process, then transform it back. If, like the transform, the process is also just a matrix multiply, then the 3 steps can be combined by multiplying the 3 matrices.
Erwin, feel free to check the math/code in case I made an error. This tends to be a high quality website and forum - I dont want to ruin that.
If any further explanations are needed feel free to ask.