Volume Integration

Jack
Posts: 59
Joined: Thu Aug 31, 2006 11:51 am

Volume Integration

Post by Jack »

It would be great to calculate true inertia tensor, center of mass and body volume.
Look here: http://www.melax.com/volint/

or


Pseudocode
The pseudocode for computing the integrals is quite simple. The polyhedron vertices are passes as the array
p[]. The number of triangles is tmax. The array index[] has tmax triples of integers that are indices into
the vertex array. The return values are the mass, the center of mass, and the inertia tensor relative to the
center of mass.
MACRO Subexpressions(w0,w1,w2,f1,f2,f3,g0,g1,g2)
{
temp0 = w0+w1; f1 = temp0+w2; temp1 = w0*w0; temp2 = temp1+w1*temp0;
f2 = temp2+w2*f1; f3 = w0*temp1+w1*temp2+w2*f2;
g0 = f2+w0*(f1+w0); g1 = f2+w1*(f1+w1); g2 = f2+w2*(f1+w2);
}
void Compute (Point p[], int tmax, int index[], Real& mass, Point& cm, Matrix& inertia)
{
constant Real mult[10] = {1/6,1/24,1/24,1/24,1/60,1/60,1/60,1/120,1/120,1/120};
Real intg[10] = {0,0,0,0,0,0,0,0,0,0}; // order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
for (t = 0; t < tmax; t++)
{
// get vertices of triangle t
i0 = index[3*t]; i1 = index[3*t+1]; i2 = index[3*t+2];
x0 = p[i0].x; y0 = p[i0].y; z0 = p[i0].z;
x1 = p[i1].x; y1 = p[i1].y; z1 = p[i1].z;
x2 = p[i2].x; y2 = p[i2].y; z2 = p[i2].z;
// get edges and cross product of edges
a1 = x1-x0; b1 = y1-y0; c1 = z1-z0; a2 = x2-x0; b2 = y2-y0; c2 = z2-z0;
d0 = b1*c2-b2*c1; d1 = a2*c1-a1*c2; d2 = a1*b2-a2*b1;
// compute integral terms
Subexpressions(x0,x1,x2,f1x,f2x,f3x,g0x,g1x,g2x);
Subexpressions(y0,y1,y2,f1y,f2y,f3y,g0y,g1y,g2y);
Subexpressions(z0,z1,z2,f1z,f2z,f3z,g0z,g1z,g2z);
// update integrals
intg[0] += d0*f1x;
intg[1] += d0*f2x; intg[2] += d1*f2y; intg[3] += d2*f2z;
intg[4] += d0*f3x; intg[5] += d1*f3y; intg[6] += d2*f3z;
intg[7] += d0*(y0*g0x+y1*g1x+y2*g2x);
intg[8] += d1*(z0*g0y+z1*g1y+z2*g2y);
intg[9] += d2*(x0*g0z+x1*g1z+x2*g2z);
}
for (i = 0; i < 10; i++)
intg *= mult;
mass = intg[0];
// center of mass
cm.x = intg[1]/mass;
cm.y = intg[2]/mass;
5
cm.z = intg[3]/mass;
// inertia tensor relative to center of mass
inertia.xx = intg[5]+intg[6]-mass*(cm.y*cm.y+cm.z*cm.z);
inertia.yy = intg[4]+intg[6]-mass*(cm.z*cm.z+cm.x*cm.x);
inertia.zz = intg[4]+intg[5]-mass*(cm.x*cm.x+cm.y*cm.y);
inertia.xy = -(intg[7]-mass*cm.x*cm.y);
inertia.yz = -(intg[8]-mass*cm.y*cm.z);
inertia.xz = -(intg[9]-mass*cm.z*cm.x);
}
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Volume Integration

Post by Erwin Coumans »

Jack wrote:It would be great to calculate true inertia tensor, center of mass and body volume.
It would be nice, but for a lot of applications, apploximate inertia tensors work fine, some developers even intentionally modify the inertia to improve stability...

I'm too busy to add it myself, my short-term focus is on memory management, performance, doing a Fork-lift demo, character control using the convex linear sweep, and integrating FAST concave continuous collision detection.

It would be great to get this as a contribution, preferably one that combines the inertia tensors for multiple objects so we can use it in the CompoundShape class. Typically there are 2 versions, one that distributes the mass uniform over the entire volume, and another that distributes mass at the outer boundary. As long as it is under the zlib license. Brian Mirtich also provides an implementation. Do you volunteer Jack?
Jack
Posts: 59
Joined: Thu Aug 31, 2006 11:51 am

Re: Volume Integration

Post by Jack »

Erwin Coumans wrote:
Jack wrote:It would be great to calculate true inertia tensor, center of mass and body volume.
It would be nice, but for a lot of applications, apploximate inertia tensors work fine, some developers even intentionally modify the inertia to improve stability...

I'm too busy to add it myself, my short-term focus is on memory management, performance, doing a Fork-lift demo, character control using the convex linear sweep, and integrating FAST concave continuous collision detection.

It would be great to get this as a contribution, preferably one that combines the inertia tensors for multiple objects so we can use it in the CompoundShape class. Typically there are 2 versions, one that distributes the mass uniform over the entire volume, and another that distributes mass at the outer boundary. As long as it is under the zlib license. Brian Mirtich also provides an implementation. Do you volunteer Jack?
I have some routines based on Brian Mirtich. They work OK. Ageia also uses full inertia tensor and it looks like they have no stability problems.
Probably I could adopt it to Bullet, but first you need to adjust your solver to use Matrix tensor instead of Vector.

Maybe I am wrong, but I see you do not find COM (Center Of Mass) in local model coords. You assume that it is always at (0,0,0). Right?
If so, then you are to adjust solver to apply rotation around COM....
User avatar
SteveBaker
Posts: 127
Joined: Sun Aug 13, 2006 4:41 pm
Location: Cedar Hill, Texas

Re: Volume Integration

Post by SteveBaker »

Jack wrote: Maybe I am wrong, but I see you do not find COM (Center Of Mass) in local model coords. You assume that it is always at (0,0,0). Right?
I believe that's true - it is the problem I've been having with some of my vehicle models which always come out top-heavy and hence roll over too easily. Being able to adjust the center of mass to be lower to the ground and closer to the front (for most cars for example) would help a lot.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

You can adjust the center of mass by using compound shapes: just translate the collision shape. I will make some demo to demonstrate this.
Bullet uses a full inertial tensor, but it assumes that the main axis of inertia is aligned along the coordinate axis. In that case you can store the inertia as main diagonal (vector3).
The solver uses a 3x3 matrix, the inverse inertia tensor.

I might add an explicit COM shift routine, but right now the is a workaround by shifting the collision model around the 'center of mass'. It gives the same effect.
Jack
Posts: 59
Joined: Thu Aug 31, 2006 11:51 am

Post by Jack »

Erwin Coumans wrote:You can adjust the center of mass by using compound shapes: just translate the collision shape. I will make some demo to demonstrate this.
Bullet uses a full inertial tensor, but it assumes that the main axis of inertia is aligned along the coordinate axis. In that case you can store the inertia as main diagonal (vector3).
The solver uses a 3x3 matrix, the inverse inertia tensor.

I might add an explicit COM shift routine, but right now the is a workaround by shifting the collision model around the 'center of mass'. It gives the same effect.
But many classes hold and accept Vector as inertia. It should be converted to Matrix. It should be Matrix from calculateLocalInertia and btCcdConstructionInfo::m_localInertiaTensor to deep inside the core (among all methods). No?
My routine (assumed it should be called inside calculateLocalInertia) want to fill Matrix....
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

Jack wrote:
Erwin Coumans wrote:You can adjust the center of mass by using compound shapes: just translate the collision shape. I will make some demo to demonstrate this.
Bullet uses a full inertial tensor, but it assumes that the main axis of inertia is aligned along the coordinate axis. In that case you can store the inertia as main diagonal (vector3).
The solver uses a 3x3 matrix, the inverse inertia tensor.

I might add an explicit COM shift routine, but right now the is a workaround by shifting the collision model around the 'center of mass'. It gives the same effect.
But many classes hold and accept Vector as inertia. It should be converted to Matrix. It should be Matrix from calculateLocalInertia and btCcdConstructionInfo::m_localInertiaTensor to deep inside the core (among all methods). No?
My routine (assumed it should be called inside calculateLocalInertia) want to fill Matrix....
As long as the rigidbody center of mass is aligned with the inertia frame, you can store the inertia matrix as a vector3. However, aligning this either requires an additional transform (center of mass shift) or applying the reverse-transform to the collision geometry (using a compound).

If you provide the full local inertia matrix for the model, I can make a utility method that makes the right conversions.