[ODE] trimesh inertia

gero.mueller@cloo.de gero.mueller at cloo.de
Sun Oct 29 10:15:31 MST 2006


Hi!

I successfully integrated the dMassSetTrimesh function. Just add it to  
the mass.cpp file. You need to add the declaration in the mass.h,  
aswell as the trimesh_internal include in the mass.cpp.

It works very well so far.

Gero
-------------- next part --------------
/*
 * Based on Brian Mirtich, "Fast and Accurate Computation of
 * Polyhedral Mass Properties," journal of graphics tools, volume 1,
 * number 2, 1996.
 */
void dMassSetTrimesh( dMass *m, dReal density, dGeomID g )
{
  dAASSERT (m);
  dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
  
  dMassSetZero (m);

  unsigned int triangles = dGeomTriMeshGetTriangleCount( g );
  
  dReal nx, ny, nz;
  unsigned int i, A, B, C;
  // face integrals
  dReal Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
  
  // projection integrals
  dReal P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;

  dReal T0 = 0;
  dReal T1[3] = {0., 0., 0.};
  dReal T2[3] = {0., 0., 0.};
  dReal TP[3] = {0., 0., 0.};

  for( i = 0; i < triangles; i++ )	 	
  {
  	dVector3 v0, v1, v2;	 	  
    dGeomTriMeshGetTriangle( g, i, &v0, &v1, &v2);
    
	dVector3 n, a, b;
	dOP( a, -, v1, v0 ); 
	dOP( b, -, v2, v0 ); 
	dCROSS( n, =, b, a );
	nx = fabs(n[0]);
	ny = fabs(n[1]);
	nz = fabs(n[2]);
		
	if( nx > ny && nx > nz )
		C = 0;
	else
		C = (ny > nz) ? 1 : 2;
	
	A = (C + 1) % 3;
	B = (A + 1) % 3;

	// calculate face integrals
	{
		dReal w;
		dReal k1, k2, k3, k4;
		
		//compProjectionIntegrals(f);
		{
			dReal a0, a1, da;
			dReal b0, b1, db;
			dReal a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
			dReal a1_2, a1_3, b1_2, b1_3;
			dReal C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
			dReal Cab, Kab, Caab, Kaab, Cabb, Kabb;
	
			P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
	
			for( int j = 0; j < 3; j++)
			{
				switch(j)
				{
				case 0:
					a0 = v0[A];
					b0 = v0[B];
					a1 = v1[A];
					b1 = v1[B];
					break;
				case 1:
					a0 = v1[A];
					b0 = v1[B];
					a1 = v2[A];
					b1 = v2[B];
					break;
				case 2:
					a0 = v2[A];
					b0 = v2[B];
					a1 = v0[A];
					b1 = v0[B];
					break;
				}
				da = a1 - a0;
				db = b1 - b0;
				a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
				b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
				a1_2 = a1 * a1; a1_3 = a1_2 * a1; 
				b1_2 = b1 * b1; b1_3 = b1_2 * b1;
	
	 			C1 = a1 + a0;
				Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
				Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
				Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
				Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
				Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
				Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
	
				P1 += db*C1;
				Pa += db*Ca;
				Paa += db*Caa;
				Paaa += db*Caaa;
				Pb += da*Cb;
				Pbb += da*Cbb;
				Pbbb += da*Cbbb;
				Pab += db*(b1*Cab + b0*Kab);
				Paab += db*(b1*Caab + b0*Kaab);
				Pabb += da*(a1*Cabb + a0*Kabb);
			}
	
			P1 /= 2.0;
			Pa /= 6.0;
			Paa /= 12.0;
			Paaa /= 20.0;
			Pb /= -6.0;
			Pbb /= -12.0;
			Pbbb /= -20.0;
			Pab /= 24.0;
			Paab /= 60.0;
			Pabb /= -60.0;
		}			
		
		w = - dDOT(n, v0);

		k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1;
	
		Fa = k1 * Pa;
		Fb = k1 * Pb;
		Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
	
		Faa = k1 * Paa;
		Fbb = k1 * Pbb;
		Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb +
			w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
	
		Faaa = k1 * Paaa;
		Fbbb = k1 * Pbbb;
		Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab 
			+ 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb
			+ 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb)
			+ w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
	
		Faab = k1 * Paab;
		Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
		Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb
			+ w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
	}


	T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));

	T1[A] += n[A] * Faa;
	T1[B] += n[B] * Fbb;
	T1[C] += n[C] * Fcc;
	T2[A] += n[A] * Faaa;
	T2[B] += n[B] * Fbbb;
	T2[C] += n[C] * Fccc;
	TP[A] += n[A] * Faab;
	TP[B] += n[B] * Fbbc;
	TP[C] += n[C] * Fcca;
  }

  T1[0] /= 2; T1[1] /= 2; T1[2] /= 2;
  T2[0] /= 3; T2[1] /= 3; T2[2] /= 3;
  TP[0] /= 2; TP[1] /= 2; TP[2] /= 2;

  m->mass = density * T0;
  m->_I(0,0) = density * (T2[1] + T2[2]);
  m->_I(1,1) = density * (T2[2] + T2[0]);
  m->_I(2,2) = density * (T2[0] + T2[1]);
  m->_I(0,1) = - density * TP[0];
  m->_I(1,0) = - density * TP[0];
  m->_I(2,1) = - density * TP[1];
  m->_I(1,2) = - density * TP[1];
  m->_I(2,0) = - density * TP[2];
  m->_I(0,2) = - density * TP[2];

  # ifndef dNODEBUG
  dMassCheck (m);
  # endif
}


More information about the ODE mailing list