22. Quaternion - 개념과 사용 방법
- 사원수라고도 부르며, Vector4와 같이 float4개로 이루어진 단위
- 행렬에 비해 빠르고, 메모리를 적게 차지한다
- 그리고 짐벌락 현상을 막을 수 있다.
쿼터니언 q는 xi + yj + zk + w로 이루어져 있으며,
xi + yj + zk를 허수부, w를 실수부로 표현한다.
i, j, k는 서로 다른 공간에 존재하며, 아래와 같은 식을 만족한다.
i² = j² = k² = -1
ij = -ji = k
jk = -kj = i
ki = -ik = j
각 요소의 제곱은 -1이지만 각각 요소에 대한 곱은 다른 차원으로 이동된다.
xi + yj + zk + w 로 이루어진 구성은 Vector4에서 x, y, z, w의 구성과 비슷함을 알 수 있다.
따라서 3차원 벡터 v(x, y, z)를 4차원 벡터 v(x, y, z, 0)로 변경하여 쿼터니언과의 연산을 진행할 수 있다.
선행 지식
쿼터니언의 곱
q₁ = x₁i + y₁j + z₁k + w₁ = (v₁, s₁)
q₂ = x₂i + y₂j + z₂k + w₂ = (v₂, s₂)
q₁*q₂ =
(x₁w₂ + y₁z₂ - z₁y₂ + w₁x₂)i +
(y₁w₂ + z₁x₂ + w₁y₂ - x₁z₂)j +
(z₁w₂ + w₁z₂ + x₁y₂ - y₁x₂)k +
(w₁w₂ - x₁x₂ - y₁y₂ - z₁z₂)
이 식을 정리하면 아래와 같다.
q₁q₂ = (v₁ x v₂ + s₁v₂ + s₂v₁, s₁s₂ - v₁·v₂)
벡터의 삼중곱
a x b x c = b( a · c ) - c( a · b )
변환된 벡터 v'을 구해보자
벡터 v (v, 0)을 변환한 벡터 v'은 다음과 같이 계산된다.
v' = qvq* (q*는 q의 켤례, 허수부에 -를 붙인 수)
이 식은 다음과 같이 전개된다.
v' = qvq* = (u, w)(v, 0)(-u, w)
쿼터니언의 곱으로 (v, 0)(-u, w)부터 연산
v' = (u, w)(-v x u + wv, v·u)
나머지도 이어서 연산하면 아래와 같이 전개된다.
실수부
w · v · u - u · ( -v x u + wv) = u · ( v x u ) = 0
두 벡터의 외적은 각각 벡터에 수직인 벡터가 나오는데,
그 벡터와 외적한 요소인 벡터를 내적하면 당연히 수직이므로 90도가 나와서 내적의 결과는 0이 된다.
허수부
-u x v x u + w · u x v + w ( -v x u + wv ) + ( v · u ) · u
= -v( u · u ) + u( u · v ) + w · u x v - w · v x u + w²v + ( v · u ) · u
= w²v + 2w( u x v ) + 2u( u · v ) - v( u · u )
= (w² - u · u)v + 2u( u · v ) + 2w( u x v )
따라서
v' = ( (w² - u · u)v + 2u( u · v ) + 2w( u x v ), 0 ) 으로 계산된다.
그래서 어떻게 적용하지?
이 좌표는 (r cos𝜽 , r sin𝜽)로 이루어져 있다.
위에서 구한 식을 좌표에 대입할 수 있을까?
좌표의 x 성분을 실수부를 나타내는 w로 두고, y 성분을 허수부를 나타내는 u로 두면 가능하다!
그런데 u는 3차원 요소를 가졌는데 이걸 어떻게 한 축으로 압축하지?
u는 u의 크기에 u를 가리키는 방향으로 분해하여 u를 표현할 수 있다.
u = s * n
(s는 u의 크기이며, n은 u의 방향벡터)
s는 피타고라스의 정리를 통해 구할 수 있다.
이 방식으로 계산된 식에 치환하면
(w² - u · u)v + 2u( u · v ) + 2w( u x v )
= ((c² - s²)v + 2((s)·n·v) (s)n + 2c(s)(n x v)
= (c² - s²)v + 2s²(n·v)·n + 2·c·s(n x v)
이렇게 치환이 가능하다.
이 식에 삼각함수의 합공식을 추가하면?
- cos²𝜽 - sin²𝜽 = cos(2𝜽)- 2cos𝜽sin𝜽 = sin(2𝜽)- cos(2𝜽) = 1 - 2sin²𝜽
= cos(2𝜽)v + (1 - cos(2𝜽))(n · v) · n + sin(2𝜽) · (n x v)
어? 그런데 이 공식 로드리게스 합 공식과 유사하다....
v' = v cos𝜽 + (v · a)a (1 - cos𝜽) + (a x v)sinα
결론적으로, 이 쿼터니언을 사용하는 방법은 아래와 같다
우리가 α축을 기준으로 어떤 벡터 v를 𝜽만큼 이동시키고 싶다면
q = ( sin(𝜽/2)α, cos(𝜽/2) ) 이렇게 쿼터니언을 세팅해준 뒤,
v' = qvq*를 통해 회전시킬 수 있다.