### 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

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);
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

$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

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);

// 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$
$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

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);

// 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
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?

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