1. 핵심 개념
오늘은 어제에 이어서 사원수에 대해 공부해보았다. 사원수의 회전과 사원수와 오일러 각 사이 변환을 알아보겠다.
사원수는 회전 보간 가능!!
- 언리얼 엔진은 행 벡터를 사용해서 행렬을 왼쪽에서부 오른쪽으로 계산함(DirectX 영향)
- 사원수의 회전
- 사원수와 오일러 각 변환
1.1. 삼중곱
오늘 식 전개에 사용 예정
1.1.1. 스칼라 삼중곱

$$a \cdot (b \times c) = \begin{vmatrix} a_1 & a_2 & a_3 \ b_1 & b_2 & b_3 \ c_1 & c_2 & c_3 \end{vmatrix}$$
1.1.2. 벡터 삼중곱
벡터 삼중곱은 bac - cab
$$a \times (b \times c) = b(a \cdot c) - c(a \cdot b)$$
2. 상세 내용
2.1~2.3.1 절은 TIL260504 참고
2.3. 사원수(Quaternion)
2.3.2. 사원수의 회전
두 순허수 사원수 간의 곱은 식 4.9와 같다. 이는 사원수의 곱셈이 기하학적으로 실수부($-\vec{v_1} \cdot \vec{v_2}$)는 두 벡터 사이의 투영(내적)을, 허수부($\vec{v_1} \times \vec{v_2}$)는 원래 벡터와 두 벡터 사이의 수직인 축(외적)을 동시에 계산하는 것을 알 수 있다.

위 이미지와 같이 크기가 1인 순허수 사원수는 허수와 동일한 성질을 만족하므로 오일러 공식에 허수 i를 대치하여 3차원 벡터의 회전을 표현하는데 사용할 수 있다.[^1]
$$e^{\vec{n}\theta}=\cos\theta + \sin\theta \cdot \vec{n}=(\cos\theta, \sin\theta \cdot \vec{n}) \tag{4.10}$$
[!note] 오일러 공식을 이용한 회전
2차원 벡터를 복소 평면상의 하나의 숫자로 간주하면, 회전은 지수의 덧셈으로 처리 가능
v = (a ,b)를 z = a + bi로 변환 후 극형식 표현
- 복소수 변환: $z = r e^{i\phi}$ (여기서 $r$은 거리, $\phi$는 원래 각도)
- 회전 연산자: $q = e^{i\theta}$ (여기서 $\theta$는 회전시킬 각도)
- 회전 결과: $z' = z \cdot q = (r e^{i\phi}) \cdot e^{i\theta} = r e^{i(\phi + \theta)}$

추가적으로 켤레사원수는 식 4.11과 같이 반대방향으로의 회전을 나타낸다.
$$q^* = e^{-\vec{n}\theta} = e^{\vec{n}(-\theta)} \tag{4.11}$$
이제 사원수의 회전식을 유도해보자.
우선, 벡터 $\vec{v}$를 $\theta$만큼 회전시킨 결과 $\vec{v}'$를 회전 사원수 $q = e^{\vec{n}\theta}$와 순허수 사원수 $v = (0, \vec{v})$의 단순 곱으로 표현하면 다음과 같이 전개된다.
$$v' = q \cdot v = e^{\vec{n}\theta} \cdot (0, \vec{v})$$
$$v' = (-\sin \theta (\vec{n} \cdot \vec{v}), \cos \theta \vec{v} + \sin \theta (\vec{n} \times \vec{v})) \tag{4.12}$$
식 4.12와 같이 실수부가 0이 아니게 되어 회전 결과값이 3차원 벡터와 1대1 매핑하기 어려워진다. 이 문제를 해결하기 위해서 실수부가 0이 되도록 사원수의 회전식을 유도해보자.

앞선 문제를 해결하기 위해서 사원수를 임의의 축 $\vec{n}$을 기준으로 회전을 표현하겠다. 이때 회전시킬 벡터는 $\vec{v}$는 회전축에 수직인 성분을 $\vec{n_\perp}$, 수평인 성분을 $\vec{v_|}$로 표현한다. 이때 최종적으로 구할 회전한 벡터 $\vec{v'}$는 수직 성분을 $\theta$만큼 회전한 뒤 수평 성분과 더하면 식 4.13과 같이 나타낼 수 있다.
$$\vec{v'} = \vec{v'_|} + e^{\vec{n} \theta} \cdot \vec{v_\perp} \tag{4.13}$$

회전 사원수와 회전시킬 벡터의 수직성분의 곱 $\vec{e^{\vec{n} \theta}} \cdot \vec{v_\perp}$는 실수부가 0이므로 식 4.12와 달리 3차원 벡터와 일대일로 대응할 수 있다.

식 4.13을 $e^{\vec{n} \theta}=e^{\vec{n} \frac{\theta}{2}} \cdot e^{\vec{n} \frac{\theta}{2}}$임을 이용하면 식 4.14와 같이 사원수의 회전식을 유도할 수 있다.
이때 식 4.14에 사용한 사원수 q의 값은 $q=(\cos \frac{\theta}{2}, \sin \frac{\theta}{2} \vec{n})$임을 주의한다.($\theta$가 반각)
$$v' = q \cdot v \cdot q^* \tag{4.14}$$
식 4.14를 $v' = (w, \vec{r}) \cdot (0, \vec{v}) \cdot (w, -\vec{r}) \tag{4.14}$와 같이 계산하면 실수부는 0이 나옴을 알 수 있다. 그리고 허수부를 정리하면 식 4.15와 같이 사원수를 사용하여 3차원 공간 벡터 $\vec{v}$를 임의의 회전축 $\vec{n}$에 대하여 각 $\theta$만큼 회전시킨 회전식이 완성된다.
$$\vec{v'} = \vec{v} + 2w(\vec{r} \times \vec{v}) + 2(\vec{r} \times (\vec{r} \times \vec{v})) \tag{4.15}$$
2.3.3. 사원수와 오일러 각 변환
오일러각 -> 사원수
식 4.10을 이용해 세 축의 회전($q_{yaw}, q_{pitch}, q_{roll}$)을 결합하여 하나의 사원수를 만드는 공식은 식 4.16과 같다.(roll -> pitch -> yaw 순으로 회전을 적용함)
$$
\begin{aligned}
q_{\text{yaw}} \cdot q_{\text{pitch}} \cdot q_{\text{roll}} =
&\cos \frac{\theta_{\text{roll}}}{2} \cos \frac{\theta_{\text{pitch}}}{2} \cos \frac{\theta_{\text{yaw}}}{2} + \sin \frac{\theta_{\text{roll}}}{2} \sin \frac{\theta_{\text{pitch}}}{2} \sin \frac{\theta_{\text{yaw}}}{2} \\
&+ \left( \cos \frac{\theta_{\text{roll}}}{2} \sin \frac{\theta_{\text{pitch}}}{2} \cos \frac{\theta_{\text{yaw}}}{2} + \sin \frac{\theta_{\text{roll}}}{2} \cos \frac{\theta_{\text{pitch}}}{2} \sin \frac{\theta_{\text{yaw}}}{2} \right) i \\
&+ \left( \cos \frac{\theta_{\text{roll}}}{2} \cos \frac{\theta_{\text{pitch}}}{2} \sin \frac{\theta_{\text{yaw}}}{2} - \sin \frac{\theta_{\text{roll}}}{2} \sin \frac{\theta_{\text{pitch}}}{2} \cos \frac{\theta_{\text{yaw}}}{2} \right) j \\
&+ \left( \sin \frac{\theta_{\text{roll}}}{2} \cos \frac{\theta_{\text{pitch}}}{2} \cos \frac{\theta_{\text{yaw}}}{2} - \cos \frac{\theta_{\text{roll}}}{2} \sin \frac{\theta_{\text{pitch}}}{2} \sin \frac{\theta_{\text{yaw}}}{2} \right) k
\end{aligned} \tag{4.16}
$$
사원수 -> 오일러각
이제 역으로 식 4.16을 이용해 사원수에서 오일러 각의 값으로 변환하는 공식은 식 4.17과 같다. 이때 식 4.16에서 실수부를 w, 허수부 i, j, k를 각각 x, y, z라고 두자.
$$
\begin{aligned}
\theta_{\text{roll}} &= \operatorname{atan2}(2(wz + xy), 1 - 2(z^2 + x^2)) \\
\theta_{\text{pitch}} &= \operatorname{asin}(2(wx - yz)) \\
\theta_{\text{yaw}} &= \operatorname{atan2}(2(wy + xz), 1 - 2(x^2 + y^2))
\end{aligned} \tag{4.17}
$$
[!note] atan2
arctan 함수는 임의의 벡터 $\vec{v} = (x, y)$의 $\frac{y}{x}$를 계산하여 나온 값을 넣는 것으로 해당 벡터와 x 축 사이 사잇각을 구할 수 있다.
arctan의 치역은 $(-\frac{\pi}{2}, \frac{\pi}{2})$로 1, 4분면에 국한되어 있는데, 앞서 구한 임의의 벡터 $\vec{v} = (x, y)$의 $\frac{y}{x}$의 x, y 성분을 y/x으로 계산하지 않고((-1, -1)과 (1, 1)이 구분 불가) 각각을 인자로 받아 부호를 계산한다면 2, 3 사분면에 존재하는 벡터의 사잇각도 구할 수 있게 된다. 가령 x, y가 모두 음수인 경우 벡터는 3사분면에 존재한다.
이렇게 임의의 벡터의 성분 y, x를 받아서 모든 사분면에 대응되는 각을 구하도록 설계한 함수를 atan2(y, x)이다.

3. 질문 및 해결 (Q&A)
- 내일은 언리얼 내부의 Rotator 구현을 보고 사원수가 실제로 어떻게 쓰이는지 확인 + 사원수의 보간 방법에 대해서 알아본다.
- 배운점
- 오일러각 <-> 사원수 변환 시 반각 사용
- 사원수는 각도에 보간(Slerp) 사용 가능
- 언리얼에서 쿼터니언을 래핑한 Rotator 함수 외에 직접 쿼터니언을 다룰 수 있게 됨
4. 참고자료 (Links)
회전축 $\vec{n}$에 대하여 각 $\theta$만큼 회전시키는 회전 사원수 곱](벡터의 외적과 삼중곱)
[아핀 변환 파트 참고](이득우의 게임 수학)
[이득우의 게임수학](이득우의 게임 수학 | 이득우 | 알라딘)
[^1]: 엄밀하지는 않은데 직관적으로 허수 i와 비슷한 성질을 가지면 오일러 공식으로 회전을 표현할 수 있고 순허수의 사원수 벡터는 이것을 i, j, k 세 개 축까지 확장하므로, 직관적으로 3개 축에 대한 회전을 표현하는데 순허수의 사원수 벡터를 사용했다고 받아들임.
'내일배움캠프 > TIL' 카테고리의 다른 글
| TIL260508 - CPP (0) | 2026.05.08 |
|---|---|
| TIL260507 - Quaternion (0) | 2026.05.07 |
| TIL260504 - Quaternion (0) | 2026.05.04 |
| TIL260430 - CPP (0) | 2026.04.30 |
| TIL260429 - CPP (0) | 2026.04.29 |