views:

201

answers:

2

Hey guys, this one's been eating up my entire night, and I'm finally throwing up my hands for some assistance. Basically, it's fairly straightforward to calculate the Pitch and Yaw from the View Matrix right after you do a camera update:

D3DXMatrixLookAtLH(&m_View, &sCam.pos, &vLookAt, &sCam.up);
pDev->SetTransform(D3DTS_VIEW, &m_View);

// Set the camera axes from the view matrix
sCam.right.x = m_View._11;
sCam.right.y = m_View._21;
sCam.right.z = m_View._31;
sCam.up.x    = m_View._12;
sCam.up.y    = m_View._22;
sCam.up.z    = m_View._32;
sCam.look.x  = m_View._13;
sCam.look.y  = m_View._23;
sCam.look.z  = m_View._33;

// Calculate yaw and pitch and roll
float lookLengthOnXZ = sqrtf( sCam.look.z^2 + sCam.look.x^2 );
fPitch = atan2f( sCam.look.y, lookLengthOnXZ );
fYaw   = atan2f( sCam.look.x, sCam.look.z );

So my problem is: there must be some way to obtain the Roll in radians similar to how the Pitch and Yaw are being obtained at the end of the code there. I've tried several dozen algorithms that seemed to make sense to me, but none of them gave quite the desired result. I realize that many developers don't track these values, however I am writing some re-centering routines and setting clipping based on the values, and manual tracking breaks down as you apply mixed rotations to the View Matrix. So, does anyone have the formula for getting the Roll in radians (or degrees, I don't care) from the View Matrix? Thanks!

+1  A: 

It seems the Wikipedia article about Euler angles contains the formula you're lookin for at the end.

stacker
Heh in hindsight my explanation was complete crap as I totally forgot that you'd need to tilt the default up vector down dependent on the forward vector.
Goz
A: 

Woohoo, got it! Thank you stacker for the link to the Euler Angles entry on Wikipedia, the gamma formula at the end was indeed the correct solution! So, to calculate Roll in radians from a "vertical plane" I'm using the following line of C++ code:

fRoll  = atan2f( sCam.up.y, sCam.right.y ) - D3DX_PI/2;

As Euler pointed out, you're looking for the arc tangent of the Y (up) matrix's Z value against the X (right) matrix's Z value - though in this case I tried the Z values and they did not yield the desired result so I tried the Y values on a whim and I got a value which was off by +PI/2 radians (right angle to the desired value), which is easily compensated for. Finally I have a gryscopically accurate and stable 3D camera platform with self-correcting balance. =)

tpartee