title: Rotate Camera With Quaternions
body: <p>I am attempting to make a camera that can rotate when arrow keys are pressed, however, when I turn the camera and attempt to rotate it, it does not rotate around the correct axis.</p>
  
  <p>For example, my up vector is ( 0, 1, 0 ). I can rotate my camera left and right perfectly because this vector is constant. Where my camera fails to work is when I attempt to rotate around its right axis. If I turn my camera left or right and rotate around the right axis it often treats the axis in a strange direction that is not correct. This should not be the case as I can still move my camera right perfectly, it just does not rotate correctly.</p>
  
  <p>Below is all the relevant code. I'm not sure why rotation works around the y-axis and not any others.</p>
  
  <pre><code>// m_rotation is a Quaternion and rotation is a 4x4 view matrix
  
  // Rotate around y-axis when left arrow pressed
  // This works perfectly
  if ( Input::IsKeyDown( Input::KEY_LEFT_ARROW ) ) {
      Rotate( Vector3&lt;float&gt;( 0, -1, 0 ), m_sensitivity );
  }
  
  // When down arrow is pressed, rotate around right axis
  // This rotates around strange axis
  if ( Input::IsKeyDown( Input::KEY_DOWN_ARROW ) ) {
      Rotate( m_rotation.GetRight( rotation ), m_sensitivity );
  }
  
  // Rotate methods
  void Camera::Rotate( const Vector3&lt;float&gt; &amp;axis, float angle ) {
      Rotate( Quaternion( axis, angle ) );
  }
  
  void Camera::Rotate( const Quaternion &amp;quaternion ) {
      m_rotation = Quaternion( ( quaternion * m_rotation ).Normalized() );
  }
  
  // Quaternion code
  Quaternion( const Vector3&lt;float&gt; &amp;vect, float angle ) {
      float sinAngle = sinf( angle / 2.0f );
      float cosAngle = cosf( angle / 2.0f );
  
      ( *this )[ 0 ] = vect[ 0 ] * sinAngle;
      ( *this )[ 1 ] = vect[ 1 ] * sinAngle;
      ( *this )[ 2 ] = vect[ 2 ] * sinAngle;
      ( *this )[ 3 ] = cosAngle;
  }
  
  inline Quaternion operator*( const Quaternion &amp;quat ) const {
      Quaternion ret;
  
      ret[ 3 ] = ( ( *this )[ 3 ] * quat[ 3 ] ) - ( ( *this )[ 0 ] * quat[ 0 ] ) - ( ( *this )[ 1 ] * quat[ 1 ] ) - ( ( *this )[ 2 ] * quat[ 2 ] );
      ret[ 0 ] = ( ( *this )[ 3 ] * quat[ 0 ] ) + ( ( *this )[ 0 ] * quat[ 3 ] ) + ( ( *this )[ 1 ] * quat[ 2 ] ) - ( ( *this )[ 2 ] * quat[ 1 ] );
      ret[ 1 ] = ( ( *this )[ 3 ] * quat[ 1 ] ) + ( ( *this )[ 1 ] * quat[ 3 ] ) + ( ( *this )[ 2 ] * quat[ 0 ] ) - ( ( *this )[ 0 ] * quat[ 2 ] );
      ret[ 2 ] = ( ( *this )[ 3 ] * quat[ 2 ] ) + ( ( *this )[ 2 ] * quat[ 3 ] ) + ( ( *this )[ 0 ] * quat[ 1 ] ) - ( ( *this )[ 1 ] * quat[ 0 ] );
  
      return ret;
  }
  
  inline Vector3&lt;float&gt; GetRight( const Matrix4&lt;float&gt; &amp;viewMatrix ) const {
      return Vector3&lt;float&gt;( rotation[ 0 ][ 0 ], rotation[ 1 ][ 0 ], rotation[ 2 ][ 0 ] );
  }
  </code></pre>
  
  <p>Any help or advice is greatly appreciated. Thanks.</p>