Example #1
0
void testRtoQandQtoR()
{
  HEADER;
  dMatrix3 R,I,R2;
  dQuaternion q;
  int i;

  // test makeRandomRotation()
  makeRandomRotation (R);
  dMultiply2 (I,R,R,3,3,3);
  printf ("\tmakeRandomRotation() - %s (1)\n",
	  cmpIdentityMat3(I) ? "passed" : "FAILED");

  // test QtoR() on random normalized quaternions
  int ok = 1;
  for (i=0; i<100; i++) {
    dMakeRandomVector (q,4,1.0);
    dNormalize4 (q);
    dQtoR (q,R);
    dMultiply2 (I,R,R,3,3,3);
    if (cmpIdentityMat3(I)==0) ok = 0;
  }
  printf ("\tQtoR() orthonormality %s (2)\n", ok ? "passed" : "FAILED");

  // test R -> Q -> R works
  dReal maxdiff=0;
  for (i=0; i<100; i++) {
    makeRandomRotation (R);
    dRtoQ (R,q);
    dQtoR (q,R2);
    dReal diff = dMaxDifference (R,R2,3,3);
    if (diff > maxdiff) maxdiff = diff;
  }
  printf ("\tmaximum difference = %e - %s (3)\n",maxdiff,
	  (maxdiff > tol) ? "FAILED" : "passed");
}
Example #2
0
void dxStepBody (dxBody *b, dReal h)
{
    // cap the angular velocity
    if (b->flags & dxBodyMaxAngularSpeed) {
        const dReal max_ang_speed = b->max_angular_speed;
        const dReal aspeed = dCalcVectorDot3( b->avel, b->avel );
        if (aspeed > max_ang_speed*max_ang_speed) {
            const dReal coef = max_ang_speed/dSqrt(aspeed);
            dScaleVector3(b->avel, coef);
        }
    }
    // end of angular velocity cap


    // handle linear velocity
    for (unsigned int j=0; j<3; j++) b->posr.pos[j] += h * b->lvel[j];

    if (b->flags & dxBodyFlagFiniteRotation) {
        dVector3 irv;	// infitesimal rotation vector
        dQuaternion q;	// quaternion for finite rotation

        if (b->flags & dxBodyFlagFiniteRotationAxis) {
            // split the angular velocity vector into a component along the finite
            // rotation axis, and a component orthogonal to it.
            dVector3 frv;		// finite rotation vector
            dReal k = dCalcVectorDot3 (b->finite_rot_axis,b->avel);
            frv[0] = b->finite_rot_axis[0] * k;
            frv[1] = b->finite_rot_axis[1] * k;
            frv[2] = b->finite_rot_axis[2] * k;
            irv[0] = b->avel[0] - frv[0];
            irv[1] = b->avel[1] - frv[1];
            irv[2] = b->avel[2] - frv[2];

            // make a rotation quaternion q that corresponds to frv * h.
            // compare this with the full-finite-rotation case below.
            h *= REAL(0.5);
            dReal theta = k * h;
            q[0] = dCos(theta);
            dReal s = sinc(theta) * h;
            q[1] = frv[0] * s;
            q[2] = frv[1] * s;
            q[3] = frv[2] * s;
        }
        else {
            // make a rotation quaternion q that corresponds to w * h
            dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
                b->avel[2]*b->avel[2]);
            h *= REAL(0.5);
            dReal theta = wlen * h;
            q[0] = dCos(theta);
            dReal s = sinc(theta) * h;
            q[1] = b->avel[0] * s;
            q[2] = b->avel[1] * s;
            q[3] = b->avel[2] * s;
        }

        // do the finite rotation
        dQuaternion q2;
        dQMultiply0 (q2,q,b->q);
        for (unsigned int j=0; j<4; j++) b->q[j] = q2[j];

        // do the infitesimal rotation if required
        if (b->flags & dxBodyFlagFiniteRotationAxis) {
            dReal dq[4];
            dWtoDQ (irv,b->q,dq);
            for (unsigned int j=0; j<4; j++) b->q[j] += h * dq[j];
        }
    }
    else {
        // the normal way - do an infitesimal rotation
        dReal dq[4];
        dWtoDQ (b->avel,b->q,dq);
        for (unsigned int j=0; j<4; j++) b->q[j] += h * dq[j];
    }

    // normalize the quaternion and convert it to a rotation matrix
    dNormalize4 (b->q);
    dQtoR (b->q,b->posr.R);

    // notify all attached geoms that this body has moved
    dxWorldProcessContext *world_process_context = b->world->UnsafeGetWorldProcessingContext(); 
    for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) {
        world_process_context->LockForStepbodySerialization();
        dGeomMoved (geom);
        world_process_context->UnlockForStepbodySerialization();
    }

    // notify the user
    if (b->moved_callback != NULL) {
        b->moved_callback(b);
    }

    // damping
    if (b->flags & dxBodyLinearDamping) {
        const dReal lin_threshold = b->dampingp.linear_threshold;
        const dReal lin_speed = dCalcVectorDot3( b->lvel, b->lvel );
        if ( lin_speed > lin_threshold) {
            const dReal k = 1 - b->dampingp.linear_scale;
            dScaleVector3(b->lvel, k);
        }
    }
    if (b->flags & dxBodyAngularDamping) {
        const dReal ang_threshold = b->dampingp.angular_threshold;
        const dReal ang_speed = dCalcVectorDot3( b->avel, b->avel );
        if ( ang_speed > ang_threshold) {
            const dReal k = 1 - b->dampingp.angular_scale;
            dScaleVector3(b->avel, k);
        }
    }
}
Example #3
0
void dxStepBody (dxBody *b, dReal h)
{
  int j;
#ifdef DEBUG_VALID
dIASSERT(dValid(b->avel[0])&&dValid(b->avel[1])&&dValid(b->avel[2]));
#endif
  // handle linear velocity
  for (j=0; j<3; j++) b->pos[j] += h * b->lvel[j];

  if (b->flags & dxBodyFlagFiniteRotation) {
    dVector3 irv;	// infitesimal rotation vector
    dQuaternion q;	// quaternion for finite rotation

    if (b->flags & dxBodyFlagFiniteRotationAxis) {
      // split the angular velocity vector into a component along the finite
      // rotation axis, and a component orthogonal to it.
      dVector3 frv;		// finite rotation vector
      dReal k = dDOT (b->finite_rot_axis,b->avel);
      frv[0] = b->finite_rot_axis[0] * k;
      frv[1] = b->finite_rot_axis[1] * k;
      frv[2] = b->finite_rot_axis[2] * k;
      irv[0] = b->avel[0] - frv[0];
      irv[1] = b->avel[1] - frv[1];
      irv[2] = b->avel[2] - frv[2];

      // make a rotation quaternion q that corresponds to frv * h.
      // compare this with the full-finite-rotation case below.
      h *= REAL(0.5);
      dReal theta = k * h;
      q[0] = dCos(theta);
      dReal s = sinc(theta) * h;
      q[1] = frv[0] * s;
      q[2] = frv[1] * s;
      q[3] = frv[2] * s;
    }
    else {
      // make a rotation quaternion q that corresponds to w * h
      dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
			  b->avel[2]*b->avel[2]);
      h *= REAL(0.5);
      dReal theta = wlen * h;
      q[0] = dCos(theta);
      dReal s = sinc(theta) * h;
      q[1] = b->avel[0] * s;
      q[2] = b->avel[1] * s;
      q[3] = b->avel[2] * s;
    }

    // do the finite rotation
    dQuaternion q2;
    dQMultiply0 (q2,q,b->q);
    for (j=0; j<4; j++) b->q[j] = q2[j];

    // do the infitesimal rotation if required
    if (b->flags & dxBodyFlagFiniteRotationAxis) {
      dReal dq[4];
      dWtoDQ (irv,b->q,dq);
      for (j=0; j<4; j++) b->q[j] += h * dq[j];
    }
  }
  else {
    // the normal way - do an infitesimal rotation
    dReal dq[4];
    dWtoDQ (b->avel,b->q,dq);
    for (j=0; j<4; j++) b->q[j] += h * dq[j];
  }

  // normalize the quaternion and convert it to a rotation matrix
  dNormalize4 (b->q);
  dQtoR (b->q,b->R);

  // notify all attached geoms that this body has moved
  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
    dGeomMoved (geom);

#ifdef DEBUG_VALID
dIASSERT(dValid(b->avel[0])&&dValid(b->avel[1])&&dValid(b->avel[2]));
#endif






}
Example #4
0
static inline void
moveAndRotateBody (dxBody * b, dReal h)
{
	int j;

	// handle linear velocity
	for (j = 0; j < 3; j++)
		b->posr.pos[j] += dMUL(h,b->lvel[j]);

	if (b->flags & dxBodyFlagFiniteRotation)
	{
		dVector3 irv;			// infitesimal rotation vector
		dQuaternion q;			// quaternion for finite rotation

		if (b->flags & dxBodyFlagFiniteRotationAxis)
		{
			// split the angular velocity vector into a component along the finite
			// rotation axis, and a component orthogonal to it.
			dVector3 frv;	// finite rotation vector
			dReal k = dDOT (b->finite_rot_axis, b->avel);
			frv[0] = dMUL(b->finite_rot_axis[0],k);
			frv[1] = dMUL(b->finite_rot_axis[1],k);
			frv[2] = dMUL(b->finite_rot_axis[2],k);
			irv[0] = b->avel[0] - frv[0];
			irv[1] = b->avel[1] - frv[1];
			irv[2] = b->avel[2] - frv[2];

			// make a rotation quaternion q that corresponds to frv * h.
			// compare this with the full-finite-rotation case below.
			h = dMUL(h,REAL (0.5));
			dReal theta = dMUL(k,h);
			q[0] = dCos (theta);
			dReal s = dMUL(sinc (theta),h);
			q[1] = dMUL(frv[0],s);
			q[2] = dMUL(frv[1],s);
			q[3] = dMUL(frv[2],s);
		}
		else
		{
			// make a rotation quaternion q that corresponds to w * h
			dReal wlen = dSqrt (dMUL(b->avel[0],b->avel[0]) + dMUL(b->avel[1],b->avel[1]) + dMUL(b->avel[2],b->avel[2]));
			h = dMUL(h,REAL (0.5));
			dReal theta = dMUL(wlen,h);
			q[0] = dCos (theta);
			dReal s = dMUL(sinc (theta),h);
			q[1] = dMUL(b->avel[0],s);
			q[2] = dMUL(b->avel[1],s);
			q[3] = dMUL(b->avel[2],s);
		}

		// do the finite rotation
		dQuaternion q2;
		dQMultiply0 (q2, q, b->q);
		for (j = 0; j < 4; j++)
			b->q[j] = q2[j];

		// do the infitesimal rotation if required
		if (b->flags & dxBodyFlagFiniteRotationAxis)
		{
			dReal dq[4];
			dWtoDQ (irv, b->q, dq);
			for (j = 0; j < 4; j++)
				b->q[j] += dMUL(h,dq[j]);
		}
	}
	else
	{
		// the normal way - do an infitesimal rotation
		dReal dq[4];
		dWtoDQ (b->avel, b->q, dq);
		for (j = 0; j < 4; j++)
			b->q[j] += dMUL(h,dq[j]);
	}

	// normalize the quaternion and convert it to a rotation matrix
	dNormalize4 (b->q);
	dQtoR (b->q, b->posr.R);

	// notify all attached geoms that this body has moved
	for (dxGeom * geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
		dGeomMoved (geom);
}
Example #5
0
void reset_test()
{
  int i;
  dMass m,anchor_m;
  dReal q[NUM][3], pm[NUM];	// particle positions and masses
  dReal pos1[3] = {1,0,1};	// point of reference (POR)
  dReal pos2[3] = {-1,0,1};	// point of reference (POR)

  // make random particle positions (relative to POR) and masses
  for (i=0; i<NUM; i++) {
    pm[i] = dRandReal()+0.1;
    q[i][0] = dRandReal()-0.5;
    q[i][1] = dRandReal()-0.5;
    q[i][2] = dRandReal()-0.5;
  }

  // adjust particle positions so centor of mass = POR
  computeMassParams (&m,q,pm);
  for (i=0; i<NUM; i++) {
    q[i][0] -= m.c[0];
    q[i][1] -= m.c[1];
    q[i][2] -= m.c[2];
  }

  if (world) dWorldDestroy (world);
  world = dWorldCreate();

  anchor_body = dBodyCreate (world);
  dBodySetPosition (anchor_body,pos1[0],pos1[1],pos1[2]);
  dMassSetBox (&anchor_m,1,SIDE,SIDE,SIDE);
  dMassAdjust (&anchor_m,0.1);
  dBodySetMass (anchor_body,&anchor_m);

  for (i=0; i<NUM; i++) {
    particle[i] = dBodyCreate (world);
    dBodySetPosition (particle[i],
		      pos1[0]+q[i][0],pos1[1]+q[i][1],pos1[2]+q[i][2]);
    dMassSetBox (&m,1,SIDE,SIDE,SIDE);
    dMassAdjust (&m,pm[i]);
    dBodySetMass (particle[i],&m);
  }

  for (i=0; i < NUM; i++) {
    particle_joint[i] = dJointCreateBall (world,0);
    dJointAttach (particle_joint[i],anchor_body,particle[i]);
    const dReal *p = dBodyGetPosition (particle[i]);
    dJointSetBallAnchor (particle_joint[i],p[0],p[1],p[2]);
  }

  // make test_body with the same mass and inertia of the anchor_body plus
  // all the particles

  test_body = dBodyCreate (world);
  dBodySetPosition (test_body,pos2[0],pos2[1],pos2[2]);
  computeMassParams (&m,q,pm);
  m.mass += anchor_m.mass;
  for (i=0; i<12; i++) m.I[i] = m.I[i] + anchor_m.I[i];
  dBodySetMass (test_body,&m);

  // rotate the test and anchor bodies by a random amount
  dQuaternion qrot;
  for (i=0; i<4; i++) qrot[i] = dRandReal()-0.5;
  dNormalize4 (qrot);
  dBodySetQuaternion (anchor_body,qrot);
  dBodySetQuaternion (test_body,qrot);
  dMatrix3 R;
  dQtoR (qrot,R);
  for (i=0; i<NUM; i++) {
    dVector3 v;
    dMultiply0 (v,R,&q[i][0],3,3,1);
    dBodySetPosition (particle[i],pos1[0]+v[0],pos1[1]+v[1],pos1[2]+v[2]);
  }

  // set random torque
  for (i=0; i<3; i++) torque[i] = (dRandReal()-0.5) * 0.1;


  iteration=0;
}
// Ripped from Opcode 1.1.
static bool GetContactData(const dVector3& Center, dReal Radius, const dVector3 Origin, const dVector3 Edge0, const dVector3 Edge1, dReal& Dist, float& u, float& v){
	//calculate plane of triangle
	dVector4 Plane;
	dCROSS(Plane, =, Edge0, Edge1);
	Plane[3] = dDOT(Plane, Origin);
 
	//normalize
        dNormalize4(Plane);
  
	/* If the center of the sphere is within the positive halfspace of the
         * triangle's plane, allow a contact to be generated.
         * If the center of the sphere made it into the positive halfspace of a
         * back-facing triangle, then the physics update and/or velocity needs
         * to be adjusted (penetration has occured anyway).
         */
  
	float side = dDOT(Plane,Center) - Plane[3];
  
	if(side < 0.0f) {
		return false;
        }
  
        // now onto the bulk of the collision...

	dVector3 Diff;
	Diff[0] = Origin[0] - Center[0];
	Diff[1] = Origin[1] - Center[1];
	Diff[2] = Origin[2] - Center[2];
	Diff[3] = Origin[3] - Center[3];

	float A00 = dDOT(Edge0, Edge0);
	float A01 = dDOT(Edge0, Edge1);
	float A11 = dDOT(Edge1, Edge1);

	float B0 = dDOT(Diff, Edge0);
	float B1 = dDOT(Diff, Edge1);

	float C = dDOT(Diff, Diff);

	float Det = dFabs(A00 * A11 - A01 * A01);
	u = A01 * B1 - A11 * B0;
	v = A01 * B0 - A00 * B1;

	float DistSq;

	if (u + v <= Det){
		if(u < REAL(0.0)){
			if(v < REAL(0.0)){  // region 4
				if(B0 < REAL(0.0)){
					v = REAL(0.0);
					if (-B0 >= A00){
						u = REAL(1.0);
						DistSq = A00 + REAL(2.0) * B0 + C;
					}
					else{
						u = -B0 / A00;
						DistSq = B0 * u + C;
					}
				}
				else{
					u = REAL(0.0);
					if(B1 >= REAL(0.0)){
						v = REAL(0.0);
						DistSq = C;
					}
					else if(-B1 >= A11){
						v = REAL(1.0);
						DistSq = A11 + REAL(2.0) * B1 + C;
					}
					else{
						v = -B1 / A11;
						DistSq = B1 * v + C;
					}
				}
			}
			else{  // region 3
				u = REAL(0.0);
				if(B1 >= REAL(0.0)){
					v = REAL(0.0);
					DistSq = C;
				}
				else if(-B1 >= A11){
					v = REAL(1.0);
					DistSq = A11 + REAL(2.0) * B1 + C;
				}
				else{
					v = -B1 / A11;
					DistSq = B1 * v + C;
				}
			}
		}
		else if(v < REAL(0.0)){  // region 5
			v = REAL(0.0);
			if (B0 >= REAL(0.0)){
				u = REAL(0.0);
				DistSq = C;
			}
			else if (-B0 >= A00){
				u = REAL(1.0);
				DistSq = A00 + REAL(2.0) * B0 + C;
			}
			else{
				u = -B0 / A00;
				DistSq = B0 * u + C;
			}
		}
		else{  // region 0
			// minimum at interior point
			if (Det == REAL(0.0)){
				u = REAL(0.0);
				v = REAL(0.0);
				DistSq = FLT_MAX;
			}
			else{
				float InvDet = REAL(1.0) / Det;
				u *= InvDet;
				v *= InvDet;
				DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
			}
		}
	}
	else{
		float Tmp0, Tmp1, Numer, Denom;

		if(u < REAL(0.0)){  // region 2
			Tmp0 = A01 + B0;
			Tmp1 = A11 + B1;
			if (Tmp1 > Tmp0){
				Numer = Tmp1 - Tmp0;
				Denom = A00 - REAL(2.0) * A01 + A11;
				if (Numer >= Denom){
					u = REAL(1.0);
					v = REAL(0.0);
					DistSq = A00 + REAL(2.0) * B0 + C;
				}
				else{
					u = Numer / Denom;
					v = REAL(1.0) - u;
					DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
				}
			}
			else{
				u = REAL(0.0);
				if(Tmp1 <= REAL(0.0)){
					v = REAL(1.0);
					DistSq = A11 + REAL(2.0) * B1 + C;
				}
				else if(B1 >= REAL(0.0)){
					v = REAL(0.0);
					DistSq = C;
				}
				else{
					v = -B1 / A11;
					DistSq = B1 * v + C;
				}
			}
		}
		else if(v < REAL(0.0)){  // region 6
			Tmp0 = A01 + B1;
			Tmp1 = A00 + B0;
			if (Tmp1 > Tmp0){
				Numer = Tmp1 - Tmp0;
				Denom = A00 - REAL(2.0) * A01 + A11;
				if (Numer >= Denom){
					v = REAL(1.0);
					u = REAL(0.0);
					DistSq = A11 + REAL(2.0) * B1 + C;
				}
				else{
					v = Numer / Denom;
					u = REAL(1.0) - v;
					DistSq =  u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
				}
			}
			else{
				v = REAL(0.0);
				if (Tmp1 <= REAL(0.0)){
					u = REAL(1.0);
					DistSq = A00 + REAL(2.0) * B0 + C;
				}
				else if(B0 >= REAL(0.0)){
					u = REAL(0.0);
					DistSq = C;
				}
				else{
					u = -B0 / A00;
					DistSq = B0 * u + C;
				}
			}
		}
		else{  // region 1
			Numer = A11 + B1 - A01 - B0;
			if (Numer <= REAL(0.0)){
				u = REAL(0.0);
				v = REAL(1.0);
				DistSq = A11 + REAL(2.0) * B1 + C;
			}
			else{
				Denom = A00 - REAL(2.0) * A01 + A11;
				if (Numer >= Denom){
					u = REAL(1.0);
					v = REAL(0.0);
					DistSq = A00 + REAL(2.0) * B0 + C;
				}
				else{
					u = Numer / Denom;
					v = REAL(1.0) - u;
					DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
				}
			}
		}
	}

	Dist = dSqrt(dFabs(DistSq));

	if (Dist <= Radius){
		Dist = Radius - Dist;
		return true;
	}
	else return false;
}