4
\$\begingroup\$

Given a quaternionic camera such that:

typedef struct
{
    vector3 upReference;
    vector3 rightReference;
    vector3 forwardReference;

    vector3 position;
    quaternion orientation;

    float pov;
} camera_t;

Where:

  • upReference, rightReference, forwardReference are always (0,1,0, 1,0,0, 0,0,-1) respectively
  • pov is the viewing angle

and quaternion is:

typedef struct 
{
    float x, y, z, w;
} quaternion;

Is there some way to create a view matrix directly from all of this and skip gluLookAt?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Since I would first have to mentally parse it in order to write a complete answer, I'll just note that Wikpedia has section for this entitled Quaternion-derived Rotation Matrix, which you could use to create the rotation component of a view matrix. The translation would have to applied separately, because the quaternions rotate vectors around an assumed origin. \$\endgroup\$ Commented Feb 1, 2015 at 6:10

3 Answers 3

1
\$\begingroup\$

The three columns of a 3x3 rotation matrix (or the upper 3x3 block of a 4x4 rotation-and-translation matrix) can be thought of as the images of unit vectors in the x+, y+, and z+ directions, respectively, after rotation.

That means we can find the first column by rotating the vector \$(1, 0, 0)\$ by the quaternion \$q\$:

$$\begin{align} q (1i + 0j + 0k + 0) q^{-1} &= (q_xi + q_yj + q_zk + q_w) (i) (-q_xi - q_yj - q_zk + q_w)\\ & = (q_x^2 - q_y^2 -q_z^2 + q_w^2)i + 2(q_xq_y + 2q_zq_w)j + 2(q_xq_z - 2q_yq_w)k\\ \end{align}$$

And we can repeat this for each of the other columns, and use the fact that \$\|q\| = 1\$ to simplify the terms with the squares into the equivalent \$q_x^2 - q_y^2 -q_z^2 + q_w^2 = 1 - 2(q_y^2 + q_z^2)\$ and similar for the other axes. That gives us this 3x3 rotation matrix \$R\$ that does the same job as the quaternion \$q\$:

$$R = 2 \begin{bmatrix} \frac 1 2 - q_y^2 - q_z^2 & q_xq_y -q_zq_w & q_xq_z + q_yq_w\\ q_xq_y +q_zq_w & \frac 1 2 - q_x^2 - q_z^2 & q_yq_z -q_xq_w\\ q_xq_z -q_yq_w & q_yq_z + q_xq_w & \frac 1 2 - q_x^2 - q_y^2 \end{bmatrix}$$

But of course for a view matrix, we want the inverse of this rotation. But for a pure rotation matrix where all columns are orthogonal unit vectors, that's just the transpose:

$$R^T = 2 \begin{bmatrix} \frac 1 2 - q_y^2 - q_z^2 & q_xq_y +q_zq_w & q_xq_z - q_yq_w\\ q_xq_y - q_zq_w & \frac 1 2 - q_x^2 - q_z^2 & q_yq_z +q_xq_w\\ q_xq_z + q_yq_w & q_yq_z - q_xq_w & \frac 1 2 - q_x^2 - q_y^2 \end{bmatrix}$$

Now to translate this back so that some position vector \$\vec p = (p_x, p_y, p_z)\$ gets mapped to the origin, we can take the image of \$\vec p\$ after rotation by \$R^T\$:

$$\vec p^\prime = R^T \vec p = 2\begin{bmatrix} p_x(\frac 1 2 - q_y^2 - q_z^2) + p_y(q_xq_y + q_zq_w) + p_z(q_xq_z - q_yq_w)\\ p_x(q_xq_y - q_zq_w) + p_y(\frac 1 2 - q_x^2 - q_z^2) + p_z(q_yq_z +q_xq_w)\\ p_x(q_xq_z + q_yq_w) + p_y(q_yq_z - q_xq_w) + p_z(\frac 1 2 - q_x^2 - q_y^2) \end{bmatrix}$$

And subtract it to get the fourth column of our 4x4 view matrix \$V\$:

$$V = \begin{bmatrix}R^T &-\vec p^\prime\\ 0 \, 0 \, 0 & 1\end{bmatrix}$$

\$\endgroup\$
0
\$\begingroup\$

Try this below:

XMMATRIX is transpose of the transform matrix, so you read it as column,row

XMMATRIX viewMatrix = XMMatrixRotationQuaternion(v_quaterion);
XMFLOAT4X4 f_view;
XMStoreFloat4x4(&f_view, viewMatrix);
f_view._41 = mPosition.x * f_view._11 + mPosition.y * f_view._21 + mPosition.x * f_view._31;
f_view._42 = mPosition.x * f_view._12 + mPosition.y * f_view._22 + mPosition.x * f_view._32;
f_view._43 = mPosition.x * f_view._13 + mPosition.y * f_view._23 + mPosition.x * f_view._33;
viewMatrix = XMLoadFloat4x4(&f_view);

You need to multiply the translation vector by the rotation first

\$\endgroup\$
0
\$\begingroup\$

Another way to do it, if you already have the quaternion-rotation of a vector:

x = q.rotate (1,0,0)
y = q.rotate (0,1,0)
z = crossprod(x,y)
matrix = { x,y,z,p };

It's definitely not the fastest way to do it. But it's one that is easy to understand.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .