• Home
  • Textbooks
  • Mathematics for Game Programming and Computer Graphics: Explore the essential mathematics for creating, rendering, and manipulating 3D virtual environments
  • Rotating with Quaternions

Mathematics for Game Programming and Computer Graphics: Explore the essential mathematics for creating, rendering, and manipulating 3D virtual environments

Penny de Byl

Chapter 16

Rotating with Quaternions - all with Video Answers

Educators


Section 1

Introducing quaternions

Problem 1

Make a copy of the Chapter_15 folder and name it Chapter_16.

Check back soon!

Problem 2

Make a new Python script file and call it Quaternion. py. Add the following code to the newly created file:
from _ future_ import annotations
import pygame
import math
import numpy as np
class Quaternion:
def_init_(self, vector=None,
axis: pygame.Vector3 = None,
angle: float $=$ None) :
if vector is not None:
self. $w$ = vector $[0]$
self. $x$ = vector [1]
self. $y=$ vector [2]
self. $z$ = vector [3]
else:
axis = axis.normalize()
sin_angle =
math.sin(math.radians (angle/2.0))
cos_angle =
math.cos(math.radians(angle/2.0))
self.w = cos_angle
self.x = axis.x * sin_angle
self.y = axis.y * sin_angle
self.z = axis.z * sin_angle

Check back soon!

Problem 3

Next, we overload the multiplication operation in the class to define how multiplication between quaternions occurs:
def_mul_(self, other: Quaternion) :
$\mathrm{v} 1=$ pygame.Vector3(self.x, self.y, self.z)
$\mathrm{v} 2$ = pygame.Vector3 (other.x, other.y, other.z)
$\operatorname{cross}=\mathrm{v} 1 \cdot \operatorname{cross}(\mathrm{v} 2)$
$\operatorname{dot}=\mathrm{v} 1 \cdot \operatorname{dot}(\mathrm{v} 2)$
$\mathrm{v} 3=$ cross $+($ self.w * $\mathrm{v} 2)+($ other.w * v1)
result $=$ Quaternion (vector $=($ self $\cdot w$ *
other.w - dot,
v3.x, v3.y, v3.z))
return result

Check back soon!
View

Problem 4

Last but not least, we can use the quaternion to $4 \times 4$ matrix conversion to return a matrix we can use to multiply with so it can be integrated with our project's other operations:
$$
\begin{aligned}
& \text { def get_matrix(self) : } \\
& \text { x2 }=\operatorname{self} \cdot x+\operatorname{self} \cdot x \\
& y^2=\operatorname{self} \cdot y+\operatorname{self} \cdot y \\
& z 2=\operatorname{self} \cdot z+\operatorname{self} \cdot z
\end{aligned}
$$
xx2 = self.x * x2
xy2 = self.x * y2
xz2 = self.x * z2
yy2 = self.y * y2
yz2 = self.y * z2
zz2 = self.z * z2
wx2 = self.w * x2
wy2 = self.w * y2
wz2 = self.w * z2
return np.matrix([
[1 - (yy2 + zz2), xy2 + wz2, xz2 - wy2,
0],
[ xy2 - wz2, 1 - (xx2 + zz2), yz2 + wx2,
0],
[xz2 + wy2, yz2 - wx2, 1 - (xx2 + yy2),
0],
[0, 0, 0, 1]
])

Victor Salazar
Victor Salazar
Numerade Educator

Problem 5

To use the new quaternion-based rotation matrix, we must add a new method into the Transform . py class like this:
from Quaternion import *
.
def rotate_axis(self, axis: pygame.Vector3, angle,
local=True) :
$\mathrm{q}=$ Quaternion (axis=axis, angle=angle)
$r$ _mat $=q \cdot$ get_matrix ()
if local:
self.MVM $=$ self.MVM@ $r_{\text {_mat }}$
else:
self.MVM $=r$ mat @ self.MVM

Check back soon!

Problem 6

Make a copy of the recent main file called FlyCamera . py and rename it QuaternionTeapot. py.

Check back soon!

Problem 7

Edit QuaternionTeapot . py to use a quaternion as a rotation in place of our method that used Euler angles like this:
teapot $=$ object ("Teapot")
teapot.add_component (Transform())
teapot.add_component (LoadMesh (GL_LINE_LOOP,
"models/teapotSM.obj"))
trans: Transform = teapot.get_component (Transform)
trans.rotate_axis (pygame.Vector3 $(0,1,0), 90$ )
trans. update_position (pygame. $\operatorname{Vector} 3(0,-2,-3))$

Check back soon!
00:09

Problem 8

You can now run QuaternionTeapot. py and see the teapot rotated 90 degrees around the $y$ axis. The result will be the same as the previous code, as illustrated in Figure 16.7, in which I used the $S$ key to move the camera away from the teapot to fit it in the window:
(Figure can't copy)

Ian Shi
Ian Shi
Numerade Educator