Using Newton in the Quake3 engine

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Re: Using Newton in the Quake3 engine

Postby Xycaleth » Fri Jul 03, 2009 4:58 pm

Okay, thanks :)

Hopefully the last problem. I tried extracting the angles myself from the matrix given to the SetTransform callback and most of it seems alright but sometimes there are some weird glitches. Here's some screenshots:
Image
Image
As you can see 2 of the boxes are tilted into the ground, but the rest are resting on the ground just fine.

Here's the code I use to get the angles:
Code: Select all
static void PhysicsEntitySetTransform ( const NewtonBody* body, const dFloat* matrix, int threadIndex )
{
    gentity_t *ent = (gentity_t*)NewtonBodyGetUserData (body);
    vec3_t newPosition;
    vec3_t oldPosition;
    vec3_t angles, velocity;
 
    VectorCopy (ent->r.currentOrigin, oldPosition);
   
    newPosition[0] = matrix[12];
    newPosition[1] = matrix[13];
    newPosition[2] = matrix[14];
   
    angles[ROLL] = RAD2DEG (atan2 (-matrix[6], matrix[5]));
    angles[YAW] = RAD2DEG (-asin (matrix[4]));
    angles[PITCH] = RAD2DEG (atan2 (-matrix[8], matrix[0]));
   
    trap_UnlinkEntity (ent);

    // Set position code is here - removed it in this example to make code easier to read.
   
    // Set the orientation here using the angles calculated
    ent->s.apos.trType = TR_STATIONARY;
    VectorCopy (angles, ent->s.apos.trBase);
    VectorCopy (angles, ent->r.currentAngles);
    VectorCopy (angles, ent->s.angles);
   
    trap_LinkEntity (ent);
}

Am I extracting the angles correctly? Or is it Newton glitching and not me (unlikely I'd say :P)?
Xycaleth
 
Posts: 13
Joined: Mon Jun 29, 2009 6:41 am

Re: Using Newton in the Quake3 engine

Postby JernejL » Fri Jul 03, 2009 5:35 pm

Well obviously you have yaw & roll messed up in this case, tried swapping them?

in worst case, the angles might not be adequate enough to reprisent full body rotations, this is why quarternions and matrixes are normally used, if angles dont work you will have to rework the entity rendering routines to handle matrixes (shouldn't be hard at all to do this, just change the way entity is transformed in graphics engine to use matrix instead of glrotatef or whatever it uses now)
Help improving the Newton Game Dynamics WIKI
User avatar
JernejL
 
Posts: 1587
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Using Newton in the Quake3 engine

Postby Julio Jerez » Fri Jul 03, 2009 6:08 pm

I think you mist teh case whe teh Gibal Lock happens.
If you matrin ix like this
m = = rot(Y) * rot(z) * rot (x)

the Gimbal lock will happens when teh rot(z) is a multiple of +- 90 dress
when this si thr case you must derive the comversion for +90 and for -90
that is

m = rot(Y) * rot(90) * rot (x)
m = rot(Y) * rot(-90) * rot (x)

I adde the modification to your code, but you must check it out as I did not tested
Code: Select all
static void PhysicsEntitySetTransform ( const NewtonBody* body, const dFloat* matrix, int threadIndex )
{
   gentity_t *ent = (gentity_t*)NewtonBodyGetUserData (body);
   vec3_t newPosition;
   vec3_t oldPosition;
   vec3_t angles, velocity;

   VectorCopy (ent->r.currentOrigin, oldPosition);

   newPosition[0] = matrix[12];
   newPosition[1] = matrix[13];
   newPosition[2] = matrix[14];

   if (absf (matrix[4]) > 0.9999f) {
      angles[ROLL] = RAD2DEG (atan2 (-matrix[6], matrix[5]));
      angles[YAW] = RAD2DEG (-asin (matrix[4]));
      angles[PITCH] = RAD2DEG (atan2 (-matrix[8], matrix[0]));
   } else if (matrix[4] > 0)
      angles[ROLL] = 0.0f;
      angles[YAW] = RAD2DEG (-3.1416 * 0.5f));
      angles[PITCH] = RAD2DEG (atan2 (matrix[1], matrix[2]));
   } else {
      angles[ROLL] = 0.0f;
      angles[YAW] = RAD2DEG (3.1416 * 0.5f));
      angles[PITCH] = -RAD2DEG (atan2 (matrix[1], matrix[2]));
   }

   trap_UnlinkEntity (ent);

   // Set position code is here - removed it in this example to make code easier to read.

   // Set the orientation here using the angles calculated
   ent->s.apos.trType = TR_STATIONARY;
   VectorCopy (angles, ent->s.apos.trBase);
   VectorCopy (angles, ent->r.currentAngles);
   VectorCopy (angles, ent->s.angles);

   trap_LinkEntity (ent);
}



a thing that can help you is to add the debug display, they are lines in global space, you can just render then to check that the collision shape is correct.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Using Newton in the Quake3 engine

Postby Xycaleth » Sat Jul 04, 2009 10:26 am

I found a function which does Euler angles to rotation matrix in the mod SDK:
Code: Select all
void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
   vec3_t   right;

   // angle vectors returns "right" instead of "y axis"
   AngleVectors( angles, axis[0], right, axis[2] );
   VectorSubtract( vec3_origin, right, axis[1] );
}

void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
   float      angle;
   static float      sr, sp, sy, cr, cp, cy;
   // static to help MS compiler fp bugs

   angle = angles[YAW] * (M_PI*2 / 360);
   sy = sin(angle);
   cy = cos(angle);
   angle = angles[PITCH] * (M_PI*2 / 360);
   sp = sin(angle);
   cp = cos(angle);
   angle = angles[ROLL] * (M_PI*2 / 360);
   sr = sin(angle);
   cr = cos(angle);

   if (forward)
   {
      forward[0] = cp*cy;
      forward[1] = cp*sy;
      forward[2] = -sp;
   }
   if (right)
   {
      right[0] = (-1*sr*sp*cy+-1*cr*-sy);
      right[1] = (-1*sr*sp*sy+-1*cr*cy);
      right[2] = -1*sr*cp;
   }
   if (up)
   {
      up[0] = (cr*sp*cy+-sr*-sy);
      up[1] = (cr*sp*sy+-sr*cy);
      up[2] = cr*cp;
   }
}

And I've basically written a function which does the reverse of the above functions:
Code: Select all
void AxisToAngles ( const vec3_t axis[3], vec3_t angles )
{
    vec3_t right;
   
    // vec3_origin is the origin (0, 0, 0).
    VectorSubtract (vec3_origin, axis[1], right);
   
    if ( axis[0][2] > 0.999f )
    {
        angles[PITCH] = -90.0f;
        angles[YAW] = RAD2DEG (atan2f (-right[0], right[1]));
        angles[ROLL] = 0.0f;
    }
    else if ( axis[0][2] < -0.999f )
    {
        angles[PITCH] = 90.0f;
        angles[YAW] = RAD2DEG (atan2f (-right[0], right[1]));
        angles[ROLL] = 0.0f;
    }
    else
    {
        angles[PITCH] = RAD2DEG (asinf (-axis[0][2]));
        angles[YAW] = RAD2DEG (atan2f (axis[0][1], axis[0][0]));
        angles[ROLL] = RAD2DEG (atan2f (-right[2], axis[2][2]));
    }
}

The axis parameter is the rotation matrix. Here's the code to copy the rotation matrix out of the 4x4 matrix:
Code: Select all
    vec3_t axis[3];

axis[0][0] = matrix[0];
    axis[0][1] = matrix[1];
    axis[0][2] = matrix[2];
    axis[1][0] = matrix[4];
    axis[1][1] = matrix[5];
    axis[1][2] = matrix[6];
    axis[2][0] = matrix[8];
    axis[2][1] = matrix[9];
    axis[2][2] = matrix[10];

Nothing too complicated as you can see :P I'm not sure if I've done the Gimbal lock correction correctly but it looks okay in-game - I just wanted to double-check I'd done it right :)

EDIT: I've found I've not done the gimbal lock correction properly :( Looks like I'll have to do more thinking...
Xycaleth
 
Posts: 13
Joined: Mon Jun 29, 2009 6:41 am

Previous

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron