개발일지

241008(화) [쿼터니언(Quaternion), 삼각함수와 역삼각함수]

게임 프로그래머 2024. 10. 8. 21:17

유니티 인스펙터 창에서 나오는 회전은 Vector3(x, y,z)로 표현되며

이것을 오일러각(Euler Angle)이라고 한다.

그러나, 많은 3D 소프트웨어는 짐벌락 문제로 인하여

쿼터니언(Quaternion)사용하고 있다.

 

왜 쿼터니언을 사용하는가?

 : 극단적인 각도로 회전할 경우 한 축으로 회전을 잃어버리는 짐벌락(Gimbal Lock) 문제를 예방할 수 있기 때문이다.

 

쿼터니언(Quaternion)

1) 4가지 복소수를 이용한 회전 표현 방법으로 (x, y, z, w) 형태로 표현한다.

2) 직접 값을 변경하는건 추천하지 않으며 대신 Unity의 내장 함수를 사용한다.

(Quaternion.Euler, Quaternion.LookRotation, Quaternion.Slerp)

3) 쿼터니언은 직관적인 수체계를 사용하지 않으므로, 값을 직접 변경하려면

Quaternion.Identity (회전이 없는 상태를 나타내는 쿼터니언)만 사용한다.

 

유니티에서 제공하는 쿼터니언(Quaternion) 함수

Quaternion.Euler : 오일러각을 쿼터니언으로 변경한다. Quaternion.Euler(0f, 0f, 90f)

여기서 0f, 0f, 90f는 degree 값으로 이 값이 쿼터니언으로 변경된다.

Quaternion.LookRotation : 머리를 회전하여 앞과 위를 볼때처럼, 앞과 위를 특정한 방향으로 회전한다.

Quaternion.Slerp : 쿼터니언과 다른 쿼터니언 사이에 내분점을 알 수 있다.


삼각함수 기초와 아크탄젠트(ArcTangent)

삼각함수 : 각도를 통해 각 변의 비율을 알아낼 수 있는 함수(각도 → 비율)

여기서 비율은 좌표라고도 할 수 있는데 그 이유는 아래와 같다.

삼각비 정의

 

탄젠트를 예로 들면 탄젠트는 위 정의에 따라 높이/밑변의 길이 이므로

이런 식으로 표현할 수 있으며 그래프에 대입하면 밑변(b)은 X좌표, 높이(a)는 Y좌표가 된다. 

이로 인해 비율은 좌표라고도 표현할 수 있다.

즉, 삼각함수는 각도를 통해 비율(좌표)을 얻을 수 있다.

 

아크탄젠트 : 삼각함수의 역함수인 역삼각함수를 말한다.

삼각함수가 각도를 통해 비율을 얻었다면

역삼각함수는 비율(좌표)을 통해 각도를 얻을 수 있다.

 

또한, 비율말고도 x, y가 음수인지, 양수인지를 통해 360도를 다 구분할 수 있는데

이러한 구현을 Atan2라고 하며 비율 적용이 아닌, 높이/밑변인 탄젠트의 개념을 적용하여

y, x순으로 인수를 넣는다.

 

이를 통해 좌표(x, y)에서 Math.Atan(y, x) 함수를 사용하면

벡터가 x축과 이루는 각도를 [- 𝝅 , 𝝅]까지 값을 얻을 수 있다.

여기서 각도는 육십분법인 180°를 호도법인 𝝅 표현한것으로 단위는 라디안(radian)이다.

 

radian 결과값을 degree로 변환해줘야 한다.

이유는 앞서 적은 내용처럼 Quaternion.Euler() 함수가 degree 값을 사용하기 때문이다.

이때 변환과정은 180°를 3.14 … 나누는것이 아니라 Mathf.Rad2Deg 함수를 사용하여 곱해준다.

( Mathf.Rad2Deg 함수에 180°를 3.14로 나눈값이 내장되어 있음)

 

코드예시

private void RotateArm(Vector2 direction)
{
    float rotZ = MathF.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; // ArcTangent를 통하여 세타를 구한것이 라디안 값이고 이것을 각도로 변환해야 한다.

    characterRenderer.flipX = Mathf.Abs(rotZ) > 90f; // absoulute value of rotation z가 90도보다 크면 뒤집을 것

    armPivot.rotation = Quaternion.Euler(0, 0, rotZ);
}

 

아크탄젠트를 통하여 세타값을 구한것이 라디안 값이고 이것을 각도로 변환한 것을

Quaternion.Euler를 통해 각도를 지정해준다.


정리

짐벌락 문제를 예방하기 위해 쿼터니언을 사용하며

Unity에서는 여러가지 쿼터니언에 대한 내장 함수를 사용할 수 있다.

(Quaternion.Euler, Quaternion.LookRotation, Quaternion.Slerp)

 

우리가 알고자 하는건 좌표(비율)를 통해 각도를 계산하는 것이므로

역삼각함수를 이용하여 계산한다.

y와 x의 비율을 통해 각도를 알아내는 Mathf.Atan2 함수에 인수 y와 x를 사용하여

radian 값을 구하고 이 값을 degree로 변환하기 위하여 Mathf.Rad2Deg를 곱한다.

 

왜 쿼터니언을 왜 사용하는지 알게 되었고 삼각함수와 역삼각함수에 대해 오랜만에

수학시간때 들은 내용을 다시 돌이켜보는 시간이 되었다.

내용이 어렵지만 반복 학습으로 이해했는데 다양한 방면으로 응용할 수 있으면 좋을 것 같다.