CS/게임 수학

오일러(Euler) 쿼터니언(Quaternion) 짐벌락(Gimbal Lock)

tae-woong 2025. 10. 13. 17:01

영상/사진 출처 : https://www.youtube.com/watch?v=vHr77Dre25Q

영상/사진 출처 : https://www.youtube.com/watch?v=owdRmhIq6vk

 

오일러

오일러 각은 우리가 일상에서 흔히 사용하는 각도계처럼, x, y, z 세 개의 축을 기준으로 오브젝트를 회전시키는 방식입니다. 각 축에 대한 회전량을 개별적인 각도로 표현합니다.

 

회전 방식 : X, Y, Z와 같은 특정 순서대로 각 축에 대해 순차적으로 회전을 적용합니다.

(Unity에서는 기본적으로 X, Y, Z 순서로 오일러 각을 계산합니다.)

 

축의 부모-자식 관계 : 오일러 회전은 각 회전축을 마치 부모-자식 관계로 구성하는 특징이 있습니다. 예를 들어 XYZ 회전에서 Z는 할아버지, Y는 아버지, X는 아들 쯤으로 비유할 수 있습니다. 이 관계 때문에 부모 회전이 자식 회전축의 방향을 변경할 수 있습니다.

(Z가 회전하면, YX 영향. Y가 회전하면, X 영향)

 

짐벌락(Gimbal Lock)

정의 : 짐벌락은 오브젝트의 두 회전축이 같은 방향으로 겹쳐버리는 현상을 의미합니다. 이로 인해 한 축에 대한 회전 계산이 불가능해지며, 3차원 공간에서 모든 각도 변환을 표현하는 데 한계가 생깁니다.

 

발생 원인:

  • 순차적인 회전 계산 : 오일러 각은 세 축을 동시에 계산하는 것이 아니라, 자체적으로 설정된 순서(예: X, Y, Z)로 각 축을 독립적으로 회전시킵니다.
  • 중간 회전축의 정렬 : 세 개의 축 중, 두 번째로 회전하는 축이 90도 또는 -90도로 회전할 때 발생합니다.
  • 축의 평행화 : 부모-자식 관계에 있는 회전축 중, 두 번째 회전축이 90도 또는 -90도로 회전하여 자식 축과 할아버지 축(가장 바깥쪽 축)을 평행하게 만들어 버릴 때 짐벌락이 발생합니다.

 

예시 회전(X 빨간축 회전 -> Y 초록축 회전 -> Z 파란축 회전):

 

1. 기본 형태.

 

2. X 빨간축 회전. Y Z 영향.

 

3. Y 초록축 회전. Z 영향.

※ 이 때, X축과 Z축이 겹치면서, 짐벌락 발생.

 

Unity로 2D 게임을 제작할 때는 오일러 각으로도 각도 구현에 문제가 없지만, 모든 각도를 통제해줘야 하는 3D 게임 같은 경우에는 오일러 앵글만으로는 구현에 한계가 있다. 

 

쿼터니언

쿼터니언은 오일러 각의 짐벌락 문제를 해결하기 위해 고안된 회전 표현 방식입니다.

 

  • 탄생 배경 : 오일러 각의 짐벌락 문제를 보완하기 위해 생겨났습니다.
  • 구성 : 쿼터니언은 4개의 성분 (x, y, z, w)으로 이루어져 있으며, 이는 벡터 (x, y, z)와 스칼라 (w)를 의미합니다.
  • 장점:
    • 짐벌락 문제 없음 : 각 축을 한꺼번에 계산하기 때문에 짐벌락 현상이 발생하지 않습니다.
    • 부드러운 보간 : 두 회전 사이를 부드럽게 보간하는 데 용이합니다 (Slerp).
  • 단점:
    • 직관성 부족 : 내부 수학적 구현이 복잡하여 오일러 각처럼 직관적으로 이해하고 다루기 어렵습니다.
    • 180도 이상 표현의 어려움 : 한 방향(orientation)에서 다른 방향(orientation)으로 회전을 측정하기 때문에, 180도보다 큰 회전 값을 직접적으로 표현하기 어렵다는 단점이 있습니다.

 

Unity에서 쿼터니언 활용

Unity는 쿼터니언을 쉽게 사용할 수 있도록 다양한 함수들을 제공합니다. Unity 공식 문서에서도 개발자들이 직접 쿼터니언을 조작하기보다는 제공되는 함수들을 사용하도록 권장합니다.

 

1. Quaternion.Euler

  • 설명 : 오일러 각을 쿼터니언으로 변환하여 사용하고자 할 때 사용합니다. 인자에 오일러 각(x, y, z)을 넣으면 해당 오일러 각에 해당하는 쿼터니언 값을 반환합니다.
  • 사용 예시:
    transform.rotation = Quaternion.Euler(new Vector3(120, 60, 100));
    

 

2. Quaternion.LookRotation

  • 설명 : 오브젝트가 특정 방향을 바라보도록 회전시키는 쿼터니언을 생성합니다. 첫 번째 인자에 바라볼 방향 벡터를 입력하면, 해당 방향을 바라보는 회전을 반환합니다. 두 번째 인자인 upwards는 기본적으로 Vector3.up으로 설정되어 있습니다.
  • 사용 예시 (타겟 바라보기):
    Vector3 direction = (target.position - this.transform.position).normalized;
    Quaternion lookRotation = Quaternion.LookRotation(direction);
    this.transform.rotation = lookRotation;
    

 

3. Quaternion.Slerp

  • 설명 : 두 쿼터니언 a와 b 사이를 t 값에 따라 구면 선형 보간(Spherical Linear Interpolation)합니다. t는 0과 1 사이의 값으로, 0에 가까울수록 a 쿼터니언에, 1에 가까울수록 b 쿼터니언에 가까운 회전을 반환합니다.
  • Lerp vs Slerp:
    • Lerp (선형 보간) : 두 점 사이를 직선으로 보간합니다.
    • Slerp (구면 선형 보간) : 두 점 사이를 구면상의 곡선으로 보간합니다. 회전에서는 Slerp가 더 자연스러운 중간 회전을 제공합니다.
  • 사용 예시
transform.rotation = Quaternion.Slerp(A.transform.rotation, B.transform.rotation, Time.deltaTime);

 

4. Quaternion.FromToRotation

  • 설명 : fromDirection 벡터에서 toDirection 벡터로 회전하는 쿼터니언을 생성합니다. 오브젝트의 특정 축(예: Vector3.up)을 다른 방향(Vector3.right)으로 정렬하고 싶을 때 유용합니다.
  • 사용 예시 : 이 코드를 적용하면 큐브의 위쪽(초록색 화살표)이 오른쪽으로 90도 회전한 모습을 볼 수 있습니다.
    transform.rotation = Quaternion.FromToRotation(Vector3.up, Vector3.right);
    

'CS > 게임 수학' 카테고리의 다른 글

삼각비(SIN, COS, TAN)  (0) 2025.10.09
내적을 활용한 몬스터 시야각 판정  (0) 2025.10.09
백터의 내적 외적  (0) 2025.10.09