Have a look at this code. It specifies the axis of rotation but not as you would expect.
Code:
void X3DCamera::Pitch(float angle)
{
D3DXQUATERNION quat = m_qRot;
D3DXQuaternionRotationAxis(&quat,TransformVector(&m_qRot,&D3DXVECTOR3(1.0f, 0.0f, 0.0f)),angle);
m_qRot *= quat;
D3DXQuaternionNormalize(&m_qRot,&m_qRot);
m_inTransition = true;
}
void X3DCamera::Yaw(float angle)
{
m_yaw += angle;
D3DXMATRIX matRot;
D3DXQUATERNION quat;
D3DXMatrixRotationY(&matRot,m_yaw);
D3DXQuaternionRotationMatrix(&quat,&matRot);
D3DXQuaternionRotationAxis(&quat,TransformVector(&quat,&D3DXVECTOR3(0.0f, 1.0f, 0.0f)),angle);
m_qRot *= quat;
D3DXQuaternionNormalize(&m_qRot,&m_qRot);
m_inTransition = true;
}
void X3DCamera::Roll(float angle)
{
D3DXQUATERNION quat = m_qRot;
D3DXQuaternionRotationAxis(&quat,TransformVector(&m_qRot,&D3DXVECTOR3(0.0f, 0.0f, 1.0f)),angle);
m_qRot *= quat;
D3DXQuaternionNormalize(&m_qRot , &m_qRot);
m_inTransition = true;
}
void X3DCamera::GetViewMatrix(D3DXMATRIX *outMatrix)
{
D3DXMATRIX matRot;
D3DXQuaternionNormalize(&m_qRot,&m_qRot);
D3DXMatrixRotationQuaternion(&matRot,&D3DXQUATERNION(-m_qRot.x,-m_qRot.y,-m_qRot.z,m_qRot.w));
D3DXVECTOR3 vecLook(matRot._13,matRot._23,matRot._33);
D3DXVECTOR3 vecOrbitPos = m_vecTargetPos + vecLook * -m_fCamDist;
D3DXMATRIX matOrbit;
D3DXMatrixTranslation(&matOrbit,-vecOrbitPos.x,-vecOrbitPos.y,-vecOrbitPos.z);
D3DXMATRIX matTrans;
D3DXMatrixTranslation(&matTrans,-Pos.x,-Pos.y,-Pos.z);
m_matView = matOrbit * matRot * matTrans;
*outMatrix = m_matView;
}
D3DXVECTOR3* X3DCamera::TransformVector(D3DXQUATERNION *pOrientation, D3DXVECTOR3 *pAxis)
{
D3DVECTOR vNewAxis;
D3DXMATRIX matRotation;
// Build a matrix from the quaternion.
D3DXMatrixRotationQuaternion(&matRotation, pOrientation);
// Transform the queried axis vector by the matrix.
vNewAxis.x = pAxis->x * matRotation._11 + pAxis->y * matRotation._21 + pAxis->z * matRotation._31 + matRotation._41;
vNewAxis.y = pAxis->x * matRotation._12 + pAxis->y * matRotation._22 + pAxis->z * matRotation._32 + matRotation._42;
vNewAxis.z = pAxis->x * matRotation._13 + pAxis->y * matRotation._23 + pAxis->z * matRotation._33 + matRotation._43;
memcpy(pAxis, &vNewAxis, sizeof(vNewAxis)); // Copy axis.
return(pAxis);
}
In essence this code is doing exactly the same thing as the axis-angle version. The axis angle version transforms the orientation vectors according to yaw, pitch and roll and the resulting matrix formed by these vectors is the final view matrix. Note that the orientation vectors always start at their original values IE: right: 1 0 0, up 0 1 0 0 and look 0 0 1. This is because if you transform the vectors and then transform them from there that would be the same as transforming an object from local to world space and then from world space to another world space. Camera orientation vectors always start at the original vectors and are transformed from there. Note that the approach shown is only one way to create a quaternion based camera. There are other ways to do this.
Also note that if you take this code and create the transpose of the final view matrix it creates you can use this as a quaternion-based frame class for orienting all of your 3D objects.