Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View Matrix from Quaternion

I'm currently building my own quaternion camera. As far as I know, you only need one quaternion to fully specify the camera's orientation (correct me if I'm wrong). So, how would I go about creating the view matrix? I'm using C++ as a programming language by the way.

Any help would be appreciated.

like image 203
l3utterfly Avatar asked Oct 08 '12 08:10

l3utterfly


People also ask

How do you find the view matrix?

A common method to derive the view matrix is to compute a Look-at matrix given the position of the camera in world space (usually referred to as the “eye” position), an “up” vector (which is usually [010]T), and a target point to look at in world space.

What is view matrix in OpenGL?

The view matrix By default, in OpenGL, the viewer is positioned on the z axis, it is like using a camera to take a shot. Imagine that your camera points to the origin of the Cartesian system. The up direction is parallel to the Oy axis and in the positive sense of Oy.

What is the view projection matrix?

The projection matrix is used to convert world space coordinates into clip space coordinates. A commonly used projection matrix, the perspective projection matrix, is used to mimic the effects of a typical camera serving as the stand-in for the viewer in the 3D virtual world.

How does view matrix work?

Like the model matrix, the view matrix can contain translation and rotation components - but instead of transforming an individual object, it transforms everything! It moves your geometry from world space to view space - that is, a coordinate system with your desired viewpoint at the origin.


4 Answers

First some caveats. You'll see lots of apparently conflicting formulae on the 'net and in literature on this subject. Most of the conflicts are apparent only. A few are real conflicts, but that's because somebody got the math wrong. The problem is that there is no single right way to do it. You need to know how you are using quaternions and matrices, how the source is using them, and how to rectify those apparent discrepancies.

Rotation versus transformation
Your camera has a reference frame associated with it, as does the underlying space. Does your matrix represent the physical rotation of the camera from the underlying space to the camera's orientation or the matrix that transforms vectors as represented in the underlying space to the frame of the camera? (Or something else; there are four choices here.) These choices are related; the transformation matrix is the transpose of the rotation matrix. Transformation and rotation are conjugate operations. The same concept applies to quaternions. Are you using transformation quaternions or rotation quaternions? These are once again related concepts; one is the conjugate of the other.

Left versus right quaternions
Given a unit quaternion q to transform or rotate a vector v, some use qvq* to transform/rotate the vector, others use q*vq. Which form is correct? Both are. The two forms differ only in whether the unconjugated quaternion is to the left (qvq*) or to the right (q*vq) of the vector to be transformed/rotated.

Column versus row vectors
Most people use column vectors, but some do use row vectors. Here you run into a left versus right issue with matrices. Column vectors transform/rotate via Mv, with the matrix to the left of the vectors; row vectors via vM, with the matrix on the right.

Impact
You have to be careful in reading the literature. With regard to forming a matrix from a quaternion you need to watch out for sign changes in constructing the off-diagonal elements of the matrix. One formulation's addition/subtraction may change to subtraction/addition in another formulation.

Left transformation quaternions to row vector transformation matrices
I use left transformation quaternions and transformation matrices, and I represent vectors as row vectors. I also represent a quaternion q as comprising a real scalar part qs and a vectorial imaginary part qv. Given these representations, the computations to generate a matrix from a quaternion are (pseudocode):

// Compute the cosine of the rotation angle.
cost = 2.0*qs*qs - 1.0;

// Construct the diagonal of the matrix:
// T_ii = cost + 2qv_i^2
for (i = 0; i < 3; ++i) {
   T[i][i] = cost + 2.0*qv[i]*qv[i];
}

// Construct off-diagonal transformation matrix elements:
//   T_ij = 2 (qv_i qv_j - eps_ijk qs qv_k), where eps is the Levi-Civita symbol
for (k = 0; k < 3; ++k) {
   i = (k+1)%3;
   j = (i+1)%3;
   T[i][j] = 2.0*(qv[i]*qv[j] - qs*qv[k]);
   T[j][i] = 2.0*(qv[i]*qv[j] + qs*qv[k]);
}

You might want to expand those loops out. The first loop expands into three statements, the latter, six. You don't need to compute i and j in the expansion of the latter loop; the expansion of the loop makes them fixed quantities.

Alternate representations
Those caveats above aren't as bad as they seem. You need to make sure my representation is consistent with yours. Odds are 50-50 that it isn't. If it isn't, simply swap the assignments to the off-diagonal elements. Use the computation of T[i][j] for T[j][i], and vice versa. How to tell:

  • Start with s=1.
  • Multiply s by -1 if you use rotation quaternions instead of transformation quaternions.
  • Multiply s by -1 if you use right quaternions instead of left quaternions.
  • Multiply s by -1 if you use rotation matrices instead of transformation matrices.
  • Multiply s by -1 if you use row vectors instead of column vectors.

Use my formulation if the final value of s is 1. If it's -1, simply swap the assignments to T[i][j] and T[j][i]. Or you could change the addition to subtraction, the subtraction to addition.

One last gotcha
The above calculation applies when the scalar part is not close to zero. It would be valid everywhere if we had infinite precision arithmetic. You might want to use a separate calculation for rotations that are very close to zero or 180 degrees.

like image 140
David Hammen Avatar answered Nov 08 '22 11:11

David Hammen


Wikipedia knows it: Quaternions and spatial rotation

like image 43
filmor Avatar answered Nov 08 '22 11:11

filmor


I would recommend using the Eigen C++ library to represent your quaternions and matrices. When you have a quaternion object, you can simply call .toRotationMatrix() on it to get a 3x3 matrix.

Another library that would probably work is glm.

like image 27
David Grayson Avatar answered Nov 08 '22 09:11

David Grayson


The Configurable Math Library ( http://cmldev.net/ ) is a very lightweight lib that could do the computation for you. It is a header library, so integration into your code shouldn't be a problem. This function ( http://cmldev.net/?p=196 ) might help you as well.

like image 1
Dirk Avatar answered Nov 08 '22 10:11

Dirk