Control Keys

move to next slide (also Enter or Spacebar).
move to previous slide.
 d  enable/disable drawing on slides
 p  toggles between print and presentation view
CTRL  +  zoom in
CTRL  -  zoom out
CTRL  0  reset zoom

Slides can also be advanced by clicking on the left or right border of the slide.

Notation

Type Font Examples
Variables (scalars) italics $a, b, x, y$
Functions upright $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$
Vectors bold, elements row-wise $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$
Matrices Typewriter $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$
Sets calligraphic $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$
Number systems, Coordinate spaces double-struck $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$

3D Transformations

3D Object Transformations

  • To perform 3D object transformations, we can apply the same approach as in the 2D case, namely, linear maps and homogeneous coordinates
  • In principle, the coordinates must "only" be extended by a z-coordinate
  • However, transformations in the 3D space are more complicated than in 2D because they have more parameters
  • In particular, the description of a rotation is more difficult because there are now three instead of only one axis around which can be rotated

Right- and Left-handed Coordinate System

coordinates
x
y
z
x
y
z
Left-handed coordinate system
Right-handed coordinate system
  • Left-handed coordinate systems are used relatively rarely. In this course, only right-handed coordinate systems are used.
  • OpenGL also uses a right-handed coordinate system:
    $x$ is to the right, $y$ upwards, and $z$ points out of the screen

3D Translation

  • Changing the position of an object can be achieved by a translation
  • A 2D translation in matrix notation
    $\underline{\tilde{\mathbf{p}}} = \begin{pmatrix} \tilde{x} \\ \tilde{y} \\ 1 \end{pmatrix} = \begin{bmatrix}1 & 0& t_x\\ 0 & 1 & t_y \\ 0 & 0 &1\end{bmatrix} \begin{pmatrix} x \\ y \\ 1 \end{pmatrix} $
    can be easily extended to include the $z$ coordinate to enable a translation in all spatial 3D directions $t_x, t_y, t_z$:
    $\underline{\tilde{\mathbf{P}}} = \begin{pmatrix} \tilde{x} \\ \tilde{y} \\ \tilde{z} \\ 1 \end{pmatrix} = \begin{bmatrix}1 & 0& 0 & t_x\\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 &1\end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \mathtt{T}_t \, \underline{\mathbf{P}}$
  • The homogeneous points $\underline{\mathbf{P}}=(p_1, p_2, p_3, p_4)^\top \in \mathbb{H}^3$ have now 4 coordinates and $\mathtt{T}$ is a $4 \times 4$ matrix
  • As before, the Cartesian coordinates of a point $\mathbf{P}$ can be calculated by dividing by the last coordinate $\mathbf{P}=(\frac{p_1}{p_4}, \frac{p_2}{p_4}, \frac{p_3}{p_4}) \in \mathbb{R}^3$

3D Scaling

  • Changing the size of an object can be achieved by scaling
  • Non-uniform scaling in all three spatial directions $s_x, s_y, s_z$ is achieved by:
    $\underline{\tilde{\mathbf{P}}} = \begin{pmatrix} \tilde{x} \\ \tilde{y} \\ \tilde{z} \\ 1 \end{pmatrix} = \begin{bmatrix}s_x & 0& 0 & 0\\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 &1\end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \mathtt{T}_s \, \underline{\mathbf{P}}$

3D Rotation

  • In the 2D case, rotation was always performed around the origin. In 3D space, we have the $x$-, $y$- and $z$-axis around which can be rotated
  • The rotation around the $z$-axis corresponds exactly to a 2D rotation, since only the $x$- and $y$-coordinates of a point are changed
  • Rotation around the $z$-axis by the angle $\alpha$:
    $\underline{\tilde{\mathbf{P}}} = \begin{bmatrix}\cos \alpha & -\sin \alpha& 0 & 0\\ \sin \alpha & \cos \alpha & 0 & 0\\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 &1\end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \mathtt{T}_{r_z} \, \underline{\mathbf{P}}$

3D Rotation

  • Rotation around the $x$-axis by the angle $\alpha$:
    $\underline{\tilde{\mathbf{P}}} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0& \cos \alpha & -\sin \alpha& 0 \\ 0 & \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 0 &1 \\ \end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \mathtt{T}_{r_x} \, \underline{\mathbf{P}}$
  • Rotation around the $y$-axis by the angle $\alpha$:
    $\underline{\tilde{\mathbf{P}}} = \begin{bmatrix} \cos \alpha & 0& \sin \alpha& 0 \\ 0 & 1 & 0 & 0 \\ -\sin \alpha & 0 &\cos \alpha & 0 \\ 0 & 0 & 0 &1 \\ \end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} = \mathtt{T}_{r_y} \, \underline{\mathbf{P}}$

Transformation Matrices in OpenGL

  • The $4 \times 4$ transformation matrices for homogeneous points are represented as a float-array in OpenGL
    GLfloat T[16];
  • The matrix elements are stored in column-major order:
    $\mathtt{T} = \begin{bmatrix} t_0 & t_4 & t_8 & t_{12} \\ t_1 & t_5 & t_9 & t_{13} \\ t_2 & t_6 & t_{10} & t_{14} \\ t_3 & t_7 & t_{11} & t_{15} \end{bmatrix}$
    Attention: Common practice is usually row-major order!

Transformation Matrices in OpenGL

  • In OpenGL, the GL_MODELVIEW matrix is responsible for the transformation of objects.
  • The manipulation of this matrix is activated by
    glMatrixMode(GL_MODELVIEW);
  • All functions for matrix manipulation, such as glLoadIdentity, glLoadMatrix, glMultMatrix glRotate, glScale, glTranslate, glPushMatrix, glPopMatrix are then executed on the GL_MODELVIEW matrix.
  • The current state of the GL_MODELVIEW matrix influences the transformation of objects only if they are drawn (OpenGL as a state machine)

Transformation Matrices in OpenGL

  • The glLoadIdentity function sets the current GL_MODELVIEW matrix to a $4 \times 4$ identity matrix:
    $\mathtt{T}_{\mathrm{\small modelview}}= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 &0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} = \mathtt{I}_{4 \times 4}$
  • Functions for transformation, such as glMultMatrix, glRotate, glScale, glTranslate, create internally a $4 \times 4$ matrix that is multiplied from the right to the current GL_MODELVIEW matrix

    Example:

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(...);
    glRotatef(...);
    glScalef(..);    
    


    $\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}$
    $\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t$
    $\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t\,\mathtt{T}_r$
    $\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_t\,\mathtt{T}_r\,\mathtt{T}_s $

    $\underline{\tilde{\mathbf{P}}} = \mathtt{T}_{\mathrm{\small modelview}} \, \underline{\mathbf{P}}$

Rotations in 3D: Euler angles

  • To perform an arbitrary rotation, rotations around different axes can be performed one after the other
  • Here, in principle, arbitrary sequences are possible, for example, first around the $x$-axis, then around the static $y$-axis, and lastly around the static $z$-axis
    $\underline{\tilde{\mathbf{P}}} = \mathtt{T}_{r_z} \mathtt{T}_{r_y} \mathtt{T}_{r_x} \, \underline{\mathbf{P}}$
  • Note, that the order in OpenGL code is exactly the opposite because of the matrix multiplication from the right:
    // rotate around z
    glRotatef(rot1, 0.0, 0.0, 1.0);
    // rotate around y
    glRotatef(rot2, 0.0, 1.0, 0.0);
    // rotate around x
    glRotatef(rot3, 1.0, 0.0, 0.0);  
    

Rotations in 3D: Euler Angles

airplane
$x$
$y$
$z$
  • The transformation $\underline{\tilde{\mathbf{P}}} = \mathtt{T}_{r_z} \mathtt{T}_{r_y} \mathtt{T}_{r_x} \, \underline{\mathbf{P}}$ can also be interpreted differently when the rotation axes are no longer static but are rotated in the same way as the points
  • For a co-rotated frame, the formula can be interpreted from left to right: First rotation around the $z$-axis, then around the co-rotated $y$-axis and lastly around the co-rotated $x$-axis
  • For example, this order and way of thinking is used in the aviation industry. The reference frame is the aircraft that always co-rotates: 1. yaw (around $z$), 2. pitch (around co-rotated  $y$), 3. roll (around co-rotated  $x$)

Rotations in 3D: Euler Angles

  • Since the axes are co-rotating, it may also make sense to rotate again round the same (co-rotated) axis.
  • A popular combination is the so-called "$x$-convention" (also called "313 Euler angles"):
    $\underline{\tilde{\mathbf{P}}} = \mathtt{T}_{r_z} \mathtt{T}_{r_x} \mathtt{T}_{r_z} \, \underline{\mathbf{P}}$
  • Attention: In this example, if the rotation angle for $\mathtt{T}_{r_x}$ is $\alpha = 0$ or $180$ degrees, the first and last rotation axes are parallel and thus one degree of freedom is lost
  • This is called "Gimbal Lock" and is a common problem of Euler angles (not only for 313 Euler angles). For example, a Gimbal Lock led to problems during the Apollo 11 mission.

Euler Angle / Gimbal Lock Demonstration

opengl_gimballock

Euler Angle / Gimbal Lock Demonstration

class Renderer {

public:
  float rot1;
  float rot2;
  float rot3;

public:
  Renderer() : rot1(0.0),  rot2(0.0),  rot3(0.0) {}

public:
  void display() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    // view scene from the side
    glTranslatef(0.0,0.0,-3.0);
    glRotatef( -45.0f, 0.0, 0.0, 1.0);
    glRotatef( -45.0f, 0.0, 1.0, 0.0);
    glRotatef( 135.0f, 1.0, 0.0, 0.0);

    // rotate around z
    glRotatef(rot1, 0.0, 0.0, 1.0);
    glColor3f(0.0f, 0.0f, 1.0f);
    drawCoordinateAxisZ();

    // rotate around local y
    glRotatef(rot2, 0.0, 1.0, 0.0);
    glColor3f(0.0f, 1.0f, 0.0f);
    drawCoordinateAxisY();

    // rotate around local x
    glRotatef(rot3, 1.0, 0.0, 0.0);
    glColor3f(1.0f, 0.0f, 0.0f);
    drawCoordinateAxisX();

    // draw the plane in the local coordinate system
    drawToyPlane();
  }

private:
  void drawCoordinateAxisZ() {
    glBegin(GL_LINE_LOOP); // circle in x-y plane
    for(int a=0; a<360; a+=10) {
      float angle = M_PI / 180.0f * a;
      glVertex3f(cos(angle), sin(angle), 0.0);
    }
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(0.9f, 0.0f, 0.0f); // x-axis
    glVertex3f(1.0f, 0.0f, 0.0f);
    glVertex3f(0.0f, 0.9f, 0.0f); // y-axis
    glVertex3f(0.0f, 1.0f, 0.0f);
    glVertex3f(0.0f, 0.0f,-1.0f); // z-axis
    glVertex3f(0.0f, 0.0f, 1.0f);
    glEnd();

    glBegin(GL_TRIANGLES); // z-axis tip
    glVertex3f(0.0f,-0.1f, 0.9f);
    glVertex3f(0.0f, 0.0f, 1.0f);
    glVertex3f(0.0f, 0.1f, 0.9f);
    glEnd();
  }

  void drawCoordinateAxisX() {
    glPushMatrix();
    glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    drawCoordinateAxisZ();
    glPopMatrix();
  }

  void drawCoordinateAxisY() {
    glPushMatrix();
    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
    drawCoordinateAxisZ();
    glPopMatrix();
  }
  ...
};

Rotation Matrices

  • The transformation around the individual axes can also be combined into a single rotation matrix, e.g.,
    $\underline{\tilde{\mathbf{P}}} = \underbrace{\mathtt{T}_{r_z} \mathtt{T}_{r_y} \mathtt{T}_{r_x}}_{\mathtt{T_r}} \, \underline{\mathbf{P}}$
  • The rotation matrix $\mathtt{T_r}$ has the general form
    $\mathtt{T_r} = \begin{bmatrix} r_{11} & r_{12}& r_{13} & 0 \\ r_{21} & r_{22}& r_{23} & 0 \\ r_{31} & r_{32}& r_{33} & 0 \\ 0 & 0 & 0 &1 \\ \end{bmatrix} = \begin{bmatrix} \mathtt{R} & 0 \\ \mathbf{0} & 1 \end{bmatrix} $
  • The $3 \times 3$ matrix $\mathtt{R}$ describes a rotation matrix if
    • lengths and angles are preserved, that is, for the scalar product we have
      $\langle \mathbf{a} \cdot \mathbf{b}\rangle = \langle \mathtt{R}\,\mathbf{a} \cdot \mathtt{R}\,\mathbf{b}\rangle \quad \forall \, \mathbf{a}, \mathbf{b} \in \mathbb{R}^3$
    • the orientations of the basis vectors $\tilde{\mathbf{b}}_x, \tilde{\mathbf{b}}_y, \tilde{\mathbf{b}}_z$ are preserved
      $\det \mathtt{R} = \det \begin{bmatrix}\tilde{\mathbf{b}}_x & \tilde{\mathbf{b}}_y & \tilde{\mathbf{b}}_z \end{bmatrix} = 1$

Properties of Rotation Matrices

  • The basis vectors $\tilde{\mathbf{b}}_x, \tilde{\mathbf{b}}_y, \tilde{\mathbf{b}}_z$ are orthonormal
  • Rotation matrices are easily invertible by transposing the matrix
    $\mathtt{R}^{-1} = \mathtt{R}^\top$
  • Therefore, it holds:
    $\mathtt{R}^{-1} \mathtt{R}= \mathtt{R}^\top \mathtt{R} = \mathtt{I}_{3 \times 3}$
  • Rotations are not commutative, that is, in general
    $\mathtt{R}_a \mathtt{R}_b \ne \mathtt{R}_b \mathtt{R}_a$

Quaternions

Quaternions

  • Euler angles are easy to implement and understand
  • However, there are discontinuities and a gimbal lock can occur
  • A further disadvantage is that it is relatively difficult to calculate the generating Euler angles from a given rotation matrix (typically not unique)
  • Quaternions can be used as a remedy

Rotation around an arbitrary axis

  • A step towards understanding quaternions is the description of a rotation around an arbitrary given axis $\mathbf{n}$ (with $|\mathbf{n}|=1$) by an angle $\alpha$
rot_around_n
$x$
$y$
$z$
$\mathbf{n}$
$\alpha$
$\mathbf{v}$
$\mathbf{v}_n$
$\mathbf{n} \times \mathbf{v}$
$\mathbf{v} - \mathbf{v}_n$

with $\mathbf{v}_n = (\mathbf{v}^\top \mathbf{n})\, \mathbf{n}$ it holds $\tilde{\mathbf{v}} = \mathbf{v}_n + (\mathbf{v} - \mathbf{v}_n) \cos \alpha + (\mathbf{n} \times \mathbf{v}) \sin \alpha$

Rotation around an arbitrary axis

with $\mathbf{v}_n = (\mathbf{v}^\top \mathbf{n})\, \mathbf{n} = (\mathbf{n}^\top \mathbf{v} )\, \mathbf{n} = (\mathbf{n} \mathbf{n}^\top) \mathbf{v}$ we have:

$\begin{align} \tilde{\mathbf{v}} &= \mathbf{v}_n + (\mathbf{v} - \mathbf{v}_n) \cos \alpha + (\mathbf{n} \times \mathbf{v}) \sin \alpha\\ \tilde{\mathbf{v}} &= (\mathbf{n} \mathbf{n}^\top) \mathbf{v} + (\mathbf{v} - (\mathbf{n}\mathbf{n}^\top ) \mathbf{v}) \cos \alpha + ([\mathbf{n}]_\times \mathbf{v}) \sin \alpha\\ \tilde{\mathbf{v}} &= \mathtt{R} \mathbf{v} \end{align}$

the resulting $3 \times 3$ rotation matrix is a function of $\mathbf{n}$ and $\alpha$, which can be calculated by
$ \mathtt{R} = (\mathbf{n} \mathbf{n}^\top) + (\cos \alpha) (\mathbf{I}_{3\times 3} - (\mathbf{n} \mathbf{n}^\top)) + (\sin \alpha) [\mathbf{n}]_\times$

Thus, the rotation matrix has 4 degrees of freedom $\mathbf{n}=(n_x, n_y, n_z)$ and $\alpha$. Or more exactly, because $|\mathbf{n}|=1$, there are really only 3 degrees of freedom (equivalent to the representation using Euler angles)

Quaternions

  • Important founder of the theory: William Rowan Hamilton (since 1843)
  • A quaternion $\mathbf{q}$ consists of 4 components
  • The components are usually split into the scalor $s$ and a vector $\mathbf{v}=(v_x, v_y, v_y)^\top$:

    $\mathbf{q} = \begin{pmatrix}q_1\\q_2\\ q_3\\ q_4\end{pmatrix} = \begin{pmatrix}s \\v_x \\ v_y \\ v_z\end{pmatrix} = (s, \mathbf{v}^\top)^\top$

  • In the following, always normalized quaternions are used, which means $|\mathbf{q}| = 1$ (again 3 degrees of freedom)

Quaternions

  • Quaternions can be used to represent rotations
  • To represent a rotation around an arbitrary given axis $\mathbf{n}$ (with $|\mathbf{n}|=1$) by an angle $\alpha$:
    $\mathbf{q} = \begin{pmatrix}s\\v_x\\ v_y\\ v_z\end{pmatrix} = \begin{pmatrix}\cos \frac{\alpha}{2} \\n_x \sin \frac{\alpha}{2} \\ n_y \sin \frac{\alpha}{2} \\ n_z \sin \frac{\alpha}{2} \end{pmatrix} = (\cos \frac{\alpha}{2}, (\sin \frac{\alpha}{2}) \mathbf{n}^\top)^\top$

Quaternion Multiplication

  • The multiplication of quaternions is given by:
    $\begin{align}\mathbf{q} \mathbf{q}' &= \begin{pmatrix} s\, s'- v_x v'_x - v_y v'_y-v_z v'_z \\ s v'_x + v_x s' + v_y v'_z - v_z v'_y\\ s v'_y + v_y s' + v_z v'_x - v_x v'_z\\ s v'_z + v_z s' + v_x v'_y - v_y v'_x\end{pmatrix}\\ &=(s \, s'- \mathbf{v}^\top \mathbf{v}' , (s \mathbf{v}' + s'\mathbf{v}+ \mathbf{v} \times \mathbf{v}')^\top )^\top \end{align}$
  • Just like the multiplication of matrices, the quaternion multiplication is not commutative
  • The quaternion multiplication can be used to concatenate rotations (corresponding to the matrix multiplication in rotation matrices)

Quaternion Multiplication

  • By further reformulation and pre-computation of expressions that are required multiple times, the quaternion multiplication can be implemented very efficiently:
Quaternion fastmul(Quaternion ql, Quaternion qr) {
double s[9], t;
s[0] = (ql.vz-ql.vy)*(qr.vy-qr.vz); s[1] = (ql.s +ql.vx)*(qr.s +qr.vx);
s[2] = (ql.s -ql.vx)*(qr.vy+qr.vz); s[3] = (ql.vz+ql.vy)*(qr.s -qr.vx);
s[4] = (ql.vz-ql.vx)*(qr.vx-qr.vy); s[5] = (ql.vz+ql.vx)*(qr.vx+qr.vy);
s[6] = (ql.s +ql.vy)*(qr.s -qr.vz); s[7] = (ql.s -ql.vy)*(qr.s +qr.vz);
s[8] = s[5]+s[6]+s[7];
t = (s[4]+s[8])*0.5;
return Quaternion(s[0]+t-s[5], s[1]+t-s[8], s[2]+t-s[7], s[3]+t-s[6]);
} 

Quaternion Multiplication

  • An inversion can be generated by the conjugation of the quaternion:
    $\mathbf{q}^{-1} = (s, -\mathbf{v}^\top)^\top$
  • The neutral element with respect to the quaternion multiplication is:
    $\mathbf{1} = (1, \mathbf{0}^\top)^\top$

Quaternions

  • A point $\mathbf{p}$ that should be rotated with a quaternion must first be also represented as a quaternion:
    $\mathbf{p} = \begin{pmatrix}x \\ y \\ z \end{pmatrix} \rightarrow \mathbf{p}_q = \begin{pmatrix}0 \\ x \\ y \\ z \end{pmatrix}$
  • Then the transformed point $\tilde{\mathbf{p}}_q$ can be computed by:
    $\tilde{\mathbf{p}}_q = \mathbf{q}\, \mathbf{p}_q \,\mathbf{q}^{-1} $

Quaternions

  • A quaternion $\mathbf{q}= (s, x, y, z)^\top$ can be converted to a rotation matrix $\mathtt{R}$ by:
    $\begin{bmatrix} 1-2y^2-2z^2 & 2xy-2sz& 2xz+2ys \\ 2xy+2sz & 1-2x^2-2z^2& 2yz-2sx \\ 2xz-2sy & 2yz+2sx& 1-2x^2-2y^2 \\ \end{bmatrix} $

Quaternions: Example 1

  • Wanted: Rotation, which rotates the unit vector $\mathbf{b}$ on the unit vector $\tilde{\mathbf{b}}$
  • Solution:
    • Determine the rotation axis using the cross product: $\mathbf{n}= \mathbf{b} \times \tilde{\mathbf{b}}$
    • Determine the rotation angle $\alpha$ with the scalar product: $\mathbf{b}^\top \tilde{\mathbf{b}}=\cos \alpha$
    • The quaternion $\mathbf{q} = (\cos \frac{\alpha}{2}, (\sin \frac{\alpha}{2}) \mathbf{n}^\top)^\top$ describes the desired rotation

Quaternions: Example 2

  • Wanted: Position of the point $\mathbf{p}=(x,y,z)^\top$ after a rotation around the axis $\mathbf{n}$ by the angle $\alpha$
  • Solution:
    • Determine rotation quaternion: $\mathbf{q} = (\cos \frac{\alpha}{2}, (\sin \frac{\alpha}{2}) \mathbf{n}^\top)^\top$
    • Apply quaternion multiplication:
      $\tilde{\mathbf{p}}_q = \mathbf{q}\, \mathbf{p}_q \,\mathbf{q}^{-1} = \mathbf{q}\, (0, x, y, z)^\top \,\mathbf{q}^{-1} $
    • Writing the resulting quaternion $\tilde{\mathbf{p}}_q$ again as Cartesian point $\tilde{\mathbf{p}}$ by extracting the last three components.

Interpolation of Rotation Matrices

  • Given: Two rotation matrices: $\mathtt{R}_{0}$ at time $t=0$ and $\mathtt{R}_{1}$ at time $t=1$
  • Can a temporal linear interpolation of the rotation be achieved by?
    $\mathtt{R}(t) = (1-t) \, \mathtt{R}_0 + t \, \mathtt{R}_1$ with $t \in [0, 1]$
  • No!
  • Apply linear interpolation of the rotation angle instead
    $\alpha(t) = (1-t)\, \alpha_0 + t\, \alpha_1$
    and use $\alpha(t)$ in combination with quaternions (or Euler angles)

Incorrect Interpolation of Rotation Matrices

rotation_interpolation

Incorrect Interpolation of Rotation Matrices

class Renderer {
public:
  Renderer() : t(0.0) {}

public:
  void display() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // view scene from the side
    glTranslatef(0.0,0.0,-3.0);
    glRotatef( -45.0f, 0.0, 0.0, 1.0);
    glRotatef( -45.0f, 0.0, 1.0, 0.0);
    glRotatef( 135.0f, 1.0, 0.0, 0.0);

    if(true) {
      // interpolate rotation matrices, which is wrong
      float r0[16];
      float r1[16];
      float rt[16];
      glPushMatrix(); // save for later use
      glLoadIdentity();
      glGetFloatv(GL_MODELVIEW_MATRIX, r0);
      glRotatef(180.0f, 0.0, 0.0, 1.0); // rotate around z
      glGetFloatv(GL_MODELVIEW_MATRIX, r1);
      glPopMatrix(); // restore
      for(unsigned i=0; i < 16; i++) {
        rt[i] = (1-t) * r0[i] + t * r1[i]; //interpolate
      }
      glMultMatrixf(rt); // apply matrix
    }else{
      // interpolate rotation angle, which is correct
      glRotatef(t*180.0f, 0.0, 0.0, 1.0); // rotate around z
    }
    glColor3f(0.0f, 0.0f, 1.0f);
    drawCoordinateAxisZ();
    glColor3f(0.0f, 1.0f, 0.0f);
    drawCoordinateAxisY();
    glColor3f(1.0f, 0.0f, 0.0f);
    drawCoordinateAxisX();
  }
  ...
 };

Are there any questions?

questions

Please notify me by e-mail if you have questions, suggestions for improvement, or found typos: Contact

More lecture slides

Slides in German (Folien auf Deutsch)