• Advertisement
Sign in to follow this  

Extracting basis vectors from a quaternion

This topic is 800 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

A 3x3 matrix describes orientation and/or rotation with three (basis) vectors placed in the matrix vectors (or columns). Such a matrix can be converted to a quaternion and vice-versa. I'm wondering how to extract the three basis vectors from the quaternio, without converting the quaternion to a matrix. Is that even possible?

Share this post


Link to post
Share on other sites
Advertisement

Yes but is there any other way? I mean, to sort of "read" the basis vectors straight from the quaternion? Or to put it this way. From a quaternion we can easily read the axis of rotation and the angle. I think that axis-angle and quaternion are equivalent beings. If so, then that means that from axis-angle we could also somewhat "read" the basis vectors. But I don't see how.

Share this post


Link to post
Share on other sites

But my point is, you want the basis vectors, and the matrix consists exclusively of the basis vectors. No matter how you read the basis vectors from the quaternion, a matrix can always be created exactly the same way and you get the matrix for free when you have the basis vectors. There's no way to read the basis vectors that doesn't give you the matrix, because the collection of basis vectors is the matrix.

Share this post


Link to post
Share on other sites

Of course Brother Bob is right, but perhaps this explanation might help you. A rotation is a mapping from R^3 to R^3. When a matrix is used to represent a rotation, its columns are the images of (1,0,0), (0,1,0) and (0,0,1). If you have the rotation represented as a quaternion, you can compute those columns the same way you would rotate any other vector (something like q * i * conj(q), q * j * conj(q) and q * k * conj(q)).

Share this post


Link to post
Share on other sites

Okay... I think I get your point but still something bugs me.

Let's put it this way. We have axis-angle representation and want to get the basis-vectors (or matrix if you like). One of the basis vectors is the axis of rotation. How do I compute the other two vectors? The only information I have left is that these two vectors lie on the plane perpendicular to the axis of rotation. And of course I have the angle, which definitely is needed to get the second vector but I'm not sure how.

Share this post


Link to post
Share on other sites

The axis of rotation is not a basis vector. This is only true if you are rotating about one of the principal axes, but not in general.

Share this post


Link to post
Share on other sites

Just take each of the identity basis vectors (1, 0, 0), (0, 1, 0) and (0, 0, 1) and rotate them with the quaternion.  This will give you a new set of basis vectors that should correspond to the columns in a rotation matrix.

Edited by NickW

Share this post


Link to post
Share on other sites
Here the code to compute the forward, right and up vector from a quaternion :
CVector3 CQuaternion::ComputeForwardVector() const
{
  const float x2 = 2.0f * x;
  const float y2 = 2.0f * y;
  const float z2 = 2.0f * z;
  const float x2w = x2 * w;
  const float y2w = y2 * w;
  const float x2x = x2 * x;
  const float z2x = z2 * x;
  const float y2y = y2 * y;
  const float z2y = z2 * y;
  return CVector3( z2x + y2w, z2y - x2w, 1.0f - ( x2x + y2y ) );
}

CVector3 CQuaternion::ComputeRightVector() const
{
  const float y2 = 2.0f * y;
  const float z2 = 2.0f * z;
  const float y2w = y2 * w;
  const float z2w = z2 * w;
  const float y2x = y2 * x;
  const float z2x = z2 * x;
  const float y2y = y2 * y;
  const float z2z = z2 * z;
  return CVector3( 1.0f - ( y2y + z2z ), y2x + z2w, z2x - y2w );
}

CVector3 CQuaternion::ComputeUpVector() const
{
  const float x2 = 2.0f * x;
  const float y2 = 2.0f * y;
  const float z2 = 2.0f * z;
  const float x2w = x2 * w;
  const float z2w = z2 * w;
  const float x2x = x2 * x;
  const float y2x = y2 * x;
  const float z2y = z2 * y;
  const float z2z = z2 * z;
  return CVector3( y2x - z2w, 1.0f - ( x2x + z2z ), z2y + x2w );
}

Share this post


Link to post
Share on other sites

Code snippets like the above should definitely come with a comment disambiguating the used conventions. Inherently a quaternion (nor a matrix) does not have forward, right or up vectors, but it is the semantic conventions that give such meanings. What is 'Up' in one engine can be 'Forward' in the conventions of another engine. Quickly glancing, in the conventions used by the above snippet, the function ComputeRightVector is the image of (1,0,0) or +X vector when transformed (=conjugated) by the quaternion, and ComputeUpVector is the image of (0,1,0)/+Y vector, and ComputeForwardVector is the image of (0,0,1)/+Z vector transformed by the quaternion. The coordinate system is assumed to be left-handed. Were those the assumed conventions?

Share this post


Link to post
Share on other sites


Just take each of the identity basis vectors (1, 0, 0), (0, 1, 0) and (0, 0, 1) and rotate them with the quaternion.

Good luck on doing that without the quaternion's matrix.

Alundra- that is just an expanded routine of the actual quaternion to matrix conversion.

Share this post


Link to post
Share on other sites

Good luck on doing that without the quaternion's matrix.


You don't need luck if you know what you are doing, or if you have the formulas I posted above in this very thread.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement