본문 바로가기
Unity

[Unity] 유니티 오일러 각과 쿼터니언 Euler, Quaternion 개념 정리

by ifhead 2022. 8. 19.
반응형

오일러 각 Euler Angle

강체가 놓인 방향을 3차원 공간에 표시하기 위해 레온하르트 오일러가 도입한 세 개의 각도로
3개의 서로 수직인 X,Y,Z축 각도로 표현하는 일반적이고 직관적인 방법 중 하나입니다.

오일러 각도는 회전한 축을 기준으로 삼아 순차적으로 회전합니다.

오일러 각
ZYX 표현

같은 각도라도 축을 회전시키는 순서에 따라 모양이 달라집니다.
오일러 각도는 3차원 상의 물체 방향을 직관적으로 표현할 수 있지만 두 가지 한계점이 있습니다.

 

1. 짐벌락 Gimbal Lock

 

같은 방향으로 두 회전 축이 겹친 다음부터, 겹친 축이 서로 구분되지 않는 고정 상태가 됩니다.
오일러 각은 세 개의 축을 동시에 계산하지 않다보니 겹쳐버리는 현상이 발생합니다.

 

 

짐벌락 현상

 

2. 보간 문제 Interpolation

 

오일러 각으로 방향을 표현할 때는 문제가 되지 않지만
회전을 표현할 때 문제가 됩니다.
어느 방향으로 돌아갈지 중간 값을 결정할 수 없습니다.

2D 게임은 오일러 각만을 이용해도 구현에 문제가 없습니다.
하지만 3D 게임은 쿼터니언으로 반드시 변환해야 합니다.

 

쿼터니언 Quarternion

쿼터니언은 x, y, z, w 4개의 성분으로 구성됩니다.
각 성분은 x, y, z 벡터와 스칼라입니다.

쿼터니언은 모든 축을 한 번에 계산하기 때문에 짐벌락 문제가 생기지 않으며
방향과 회전을 모두 표현할 수 있습니다.

쿼터니언의 회전은 A 방향에서 B 방향으로 측정하기 때문에 180도 이상은 환원됩니다.
그래서 180도 이상의 큰 값을 표현할 수 없게 됩니다.

쿼터니언을 다루기 위해서 유니티는 여러 가지 메소드를 제공합니다.

// 1. Vector3로 표현된 오일러각을 쿼터니언으로 변환합니다.
transform.roation = Quaternion.Euler(new Vector3(100,50,60)); 

// 2. 특정 지점을 향해 회전시킵니다.
Vector3 direction = (traget.position - this.transform.position).normalized;
Quaternion lookRotation = Quaternion.LookRotation(direction);
this.transform.rotation = lookRotation;

// 3. 구면 선형 보간. 두 방향 사이에 그려진 최단거리 호를 따라갑니다.
Quaternion.Slerp( "쿼터니언 A" , "쿼터니언 B" , "0 ~ 1 사이의 값" );

// 4. 강체의 축을 골라서, 특정 월드축을 따라 회전시킨 방향을 얻습니다.
Quaternion.FromToRotation( "변환하고 싶은 강체의 축" , "따르게 만들 방향(월드 축 기준)");

// 5. Quaternion.eulerAngles 오일러 각을 쿼터니언으로 변환해서 myAngle에 저장합니다.
Quaternion myAngle = Quaternion.identity; 
myRotation.eulerAngles = new Vector3(150, 35, 45); 
// eulerAngles를 출력해보면 인풋과 같은 각도이긴 하지만 다른 값을 반환합니다.
Debug.Log(myRotation.eulerAngles);
// output is: (30.0, 215.0, 225.0)

// 6. 두 방향의 사잇각을 얻습니다.
float angle = Quaternion.Angle(transform.rotation, target.rotation);

// 7. 월드축을 기준으로 n도 회전시킨 방향을 얻습니다.
transform.rotation = Quaternion.AngleAxis(30, Vector3.up);

// 8. target 방향의 반대 방향을 얻습니다.
Quaternion.Inverse(target.rotation);

// 9. 두 지점이 가리키는 방향을 얻습니다.
// GameObject의 위치에서 다음 GameObject 의 위치로 Quaternion 회전을 설정합니다.
m_MyQuaternion.SetFromToRotation(transform.position, m_NextPoint.position);
// GameObject를 두 번째 GameObject 쪽으로 이동합니다. 
transform.position = Vector3.Lerp( transform.position , m_NextPoint.position, m_Speed * Time.deltaTime );
// GameObject를 두 번째 GameObject 쪽으로 회전 합니다 .
transform.rotation = m_MyQuaternion * transform.rotation;

선형 보간은 직선거리, 구면 선형 보간은 짧은 호

  • 선형 보간은 불균등하게 회전하는 반면
  • 구면 선형 보간은 균등하게 회전합니다
반응형

댓글