쿼터니언과 회전 (이론)
3차원 공간에서의 회전
-
2차원 공간에서의 회전은 1 자유도(DOF)
(시계 <-> 반시계 회전이며, 서로 반대됨) -
3차원 공간에서 회전은 3 자유도
YawPitchRoll
이런식으로 3차원 공간에서의 물체의 회전 상태를 표현하는 것을
‘오일러 각도’ 라 표현한다
오일러 각도(Euler Angles)
각각의 ‘축’에 대한 회전 행렬을
‘곱’하여 회전 행렬을 만든다
(그렇기에 곱하는 순서가 정해져 있어
축에 종속적이기도 하다)
(이건 Column Major 이기에 오른쪽에서 왼쪽으로 적용됨
Z -> Y -> X 순으로 회전 적용)
(Roll -> Yaw -> Pitch)
- 또한 ‘축’ 자체가 다른 회전에 영향을 받음
이미 기울어진 Pitch에 대하여 다시 Roll의 회전까지 적용하기도 함
자이로스코프를 통해 보면 이해가 비교적 쉬운편
바깥의 원의 이동에 안쪽의 원이 영향을 받음
그렇기에 아래와 같은 짐벌락 현상이 발생할 수 있음
왼쪽의 원에서 초록색 원이 90도 회전하며
파란색 원과 합쳐진 상태이며
이후, 파란색 원과 초록색 원을 ‘분리할 수 없는’ 현상이 발생
(두 축이 겹쳐버린 현상)
수식으로 보자면
결과적으로 2개의 각도만이 회전 결과에 반영됨을 볼 수 있다
(마지막 줄)
-
UpVector와 ViewVector(현재 정면 관찰)가 각각 존재할때
RightVector는 Cross로 구할 수 있다 -
그런데 ViewVector를 회전시켜 하늘을 바라보게 하였을때
UpVector와 동일해지므로
이 때는 Cross를 통해 RightVector를 정의할 수 없음
(다소 극단적인 예시이긴 하다)
그렇기에 오일러 벡터 외에도 회전을 표현할만한 방식이 필요해짐
-
그래도 오일러 벡터는 ‘직관적’이며 이해하기 쉽다는 장점이 있어
에디터, Tool, UI 등으로 회전을 표현하는 방식으로
여전히 사용된다 -
또한 ‘입력’에 대한 수치로도 사용됨
(Right 로 90도 회전 등)
쿼터니언 (Quaternion, 사원수)의 개념
3차원 공간의 회전을 위하여 1가지 숫자를 추가한
4개의 숫자로 회전을 표현하는 방식
(숫자가 4개이기에 4원수)
-
숫자가 4개라도 3자유도
(마지막 숫자인 w에 대한 제약 조건이 존재하기에) -
- 회전 행렬과 호환
- 회전을 쿼터니언으로 진행 후, 회전 행렬로 변환할 수 있음
- 회전 행렬과 호환
- 회전의 보간(Interpolation)에 유리함
쿼터니언의 사용 방식
벡터 V를 회전축 N에 대하여 T만큼 회전시키고 싶을때
-
- 쿼터니언 p = (v,0)
- 쿼터니언 p = (v,0)
-
- 쿼터니언 q = (n sin(t/2),cos(t/2))
- 쿼터니언 q = (n sin(t/2),cos(t/2))
-
- 켤레 쿼터니언 q* = (-n sin(t/2),cos(t/2))
- 켤레 쿼터니언 q* = (-n sin(t/2),cos(t/2))
-
- 쿼터니언 p’ = (v’,0) = qpq* 로 회전
- 쿼터니언 p’ = (v’,0) = qpq* 로 회전
-
- 켤레?
- 어떤 수에서 ‘특정 성분’의 부호를 바꿔 ‘짝’을 이루는 수
(ex : a + bi -> a - bi)
- 켤레?
-> 직접 구하기 보단 이미 구현된 라이브러리를 사용하는 편
또는 쿼터니언 q로부터 회전 행렬을 만들어 곱함
회전 행렬을 쿼터니언으로 만들어서 사용할 수도 있음
(메모리를 아끼기 위해 행렬이 아닌 쿼터니언으로 저장하는 방식도 존재)
쿼터니언의 구성
4개의 숫자 x,y,z,w
로 이루어짐
(x,y,z 를 u로 표현하여 (u,v)로 표현하기도 함)
여기서 i,j,k는 허수
(허수는 제곱하여 -1 이 되는 실제로는 없는 수)
- i^2 = ijk = -1
- ij = k = -ji
- jk = i = -kj
- ki = j = -ik
그래서 이런 허수와 회전이 무슨 관계?
허수는 곱할때마다
i -> -1 -> -i -> 1
로 순환하는 특성을 가짐
실수와 허수의 좌표를 가지는 좌표계에서
하나의 ‘회전’으로 볼 수 있음
특정한 좌표 p가
실수 부분 2, 허수 부분 i 정도의 값을 가진다면
p를 p = 2 + i 로 표현이 가능
(이런식으로 허수 + 실수
의 표현을 ‘복소수’ 라고 함)
이때, i를 곱하게 되면
그래프에서 90도 정도 회전하게 된
q와 동일해짐!
(q = 2i - 1)
- i를 계속 곱하면 같은 원리로 p -> q -> r -> s -> p가 됨
허수를 곱해줌으로서 ‘복소수’가 회전하는 듯한 효과를 얻을 수 있음
그렇기에 쿼터니언은
3개의 허수를 이용하여 회전을 표현한다
각각의 허수 좌표 및 연산을 통하여
쿼터니언 만의 독자적인 회전 표현이 가능해짐
- i에 j를 곱하면 k, j에서 i를 곱하면 -k 등
쿼터니언의 기본연산 방식
-
4개의 수가 모두 같으면 같은 쿼터니언 판정
-
덧셈, 뺄셈은 각각의 요소에서 진행
식이 많아보이지만 기본적으로는 항을 정렬하게 되면
가장 아래쪽의 식으로 변환된다
(다항식의 전개)
(‘복소수’의 곱셈만 주의하면 충분히 전개할 수 있는 식)
- dot과 Cross를 사용하여 더 깔끔한 요약이 가능
쿼터니언의 절댓값은
4개의 요소를 제곱한후 더하고, 루트를 씌우면 된다
쿼터니언의 역수를 구하는 방식
먼저 켤레(Conjugate)를 구하고
(q = (u,w)라면 q* = (-u,w))
이후
qq* = | q | ^ 2 = | q* | ^ 2 이므로 |
q^-1 = q* / ( | q | ^2) 로 정의 |
|q| = 1 이라면
q^-1 = q*
-
- 역수?
- 곱했을때 1로 만드는 수
(일반적인 숫자는 1 / a 등으로 역수를 만들 수 있다)
- 역수?
쿼터니언의 회전
앞에서 본 것의 식을 푸는 과정
- 이러한 식을 외우기 보다는 ‘쿼터니언’의 개념을 이해하고
일반적인 오일러 각도와 차이점이 있다는 점을 느낀다면 일단 충분!
(엔진 등을 구현하려면 이러한 부분을 구현해야 할지도?)
(Math 라이브러리 등으로 엔진의 일부분을 대체하는건가?)
댓글남기기