카테고리 없음

벡터란 무엇인가? 쿼터니언은 뭐야?

막뇌 2023. 8. 14. 22:35

수학적으로 벡터는 연산이 가능하고, 정해진 개수의 원소가 있다면, 무엇이든 벡터가 될 수 있습니다.

 

게임 개발자에게 벡터는 공간상의 점이나 화살표로 사용됩니다.

( 절대 좌표로 사용 되면 점, 상대 좌표로 사용된다면 화살표 )

 

즉, 벡터는 두가지 상태를 나타낼 수 있다는 것인데

첫번째로 현재 위치 좌표 이며

두번째로 방향과 속도 입니다.

 

벡터의 덧셈

벡터끼리 덧셈을 하게 되면 각 원소끼리 연산이 이루어 집니다.

이를 공간상에서 보면 A만큼 이동한 상태에서 B만큼 더 이동한다는 의미입니다.

 

벡터의 뺄셈

벡터의 뺄셈 역시 각 원소끼리 연산이 이루어 지는데

뺄셈을 완료 한 뒤, 절대 좌표로 0,0 에서 시작하는 선을 그려 보면 이 선이 곧 두 점 사이의 거리가 됩니다.

이를 공간상에서 보자면 두 점을 직선으로 이었을 때, 직선의 길이가 됩니다.

한마디로 벡터의 뺄셈을 수행하면 두 점사이의 거리가 나오게 됩니다.

 

벡터의 곱셈

벡터에 어떤 수를 곱하면 곱하는 수는 각 원소에 각각 곱해지게 되는데 이를 스칼라곱이라고 하며

곱하는 수를 스칼라 라고 부릅니다.

결과적으로 곱셈을 취하게 되면 방향은 변하지 않고, 동일한, 기하학적으로 '닮은꼴' 직선이 생겨나게 되는데 곱하기 전의 상태와 크기만 다를 뿐입니다. 즉, 속도에만 차이가 있을 뿐입니다.

벡터의 곱셈은 속도를 결정합니다.

 

방향 벡터 (정규화된 벡터) Normalized Vector

벡터는 방향과 속도를 나타낸다고 했습니다.

여기서 속도를 제외하고 방향만을 구하고 싶을 때, 직선의 길이를 1로 정규화 시키기로 약속했습니다.

좌표계에서 직선의 길이가 1이므로 √(X² + Y²) = 1 을 항상 만족시키는 X, Y값을 가지고 있을 것입니다.

 

벡터의 내적과 외적

벡터의 내적의 개념을 알기 위해서는 두 방향벡터가 만났을때를 상상해 보아야 합니다.

두 벡터의 관계를 나타내는 것이기 때문에 A와 B의 내적은 A⋅B로 표기합니다. (ㄱ한자, 2번째 페이지의 8)

가운데에 점이 들어가는데 말 그대로 점이기 때문에 영어로 dot operator 라고도 합니다.

 

두 벡터가 만났을때, 이루는 각도가 있을 것입니다. 이 각도가 0인 것은 서로 같은 방향임을 의미 하고

둘이 완전히 겹쳐진 모양을 생각하면 됩니다.

이때 내적은 1입니다.이제 각도가 점점 커지면서 90도에 가까워 집니다. 

이러면 내적은 1에서 점점 줄어들다가 0이 됩니다, 다시 완전히 반대방향을 가리켜, 180도가 되면 내적은 -1이 됩니다.

빛의 방향이 수직 방향일 때 그림자의 크기라고 생각하면 편합니다.

실제 내적을 구하는 공식은 A⋅B = |B|cosθ 이지만 여기서는 깊게 다루지 않겠습니다.

(ㅎ한자에 기호 있음)

 

 

벡터의 외적

외적은 두 백터를 모두 수직으로 통과하는 벡터를 구하는 연산입니다.A, B 벡터가 2개 가 있죠? 이 두가지가 방향 벡터라고 했을 때, 선이 2개 만들어집니다.벡터의 뺄셈에서 공간 벡터(점) 두개로 선을 만들었죠?이제 방향 벡터(선) 두개로 가상의 면을 만든다고 가정 하겠습니다.그리고 그 면의 수직인 방향을 구하면 구것이 외적입니다.

 

A, B의 외적이 C 라고 할 때C는 A, B 모두에게 수직인 방향입니다.

 

유니티C#에서도 벡터를 위와 같은 방법으로 Vector2(2차원만 사용), Vector3(3차원에서 사용) 등으로 사용하게 됩니다.

 

쿼터니언

쿼터니언은 벡터와는 또다른 타입으로 회전하기 전 상태에서, 회전 후 상태가 되려면 x,y,z 축으로 각각 얼만큼 회전하면 되는지 회전을 표현하는 방식입니다.

 

먼저 회전을 표현하는 방법에 오일러와 쿼터니언이 있다는 점을 알고 가도록 합니다.

오일러 방식은 x,y,z 세 축으로 나누어 각각 얼마만큼 회전하면 되는지 계산하여 회전을 표현하는 방식입니다.

위의 쿼터니언을 설명한 것과 같아 보이지만 차이가 있습니다. 오일러각 체계에서는 회전을 한번에 계산하지 않고

한축씩 세번에 걸쳐 순서대로 계산합니다. 

왜냐하면 한 축의 회전이 다른 축의 회전에 영향을 주기 때문입니다.

선풍기를 정면에서 바라보게 되면, 선풍기의 프로펠러는 z축으로 회전 하고 있습니다.

여기서, 선풍기의 고개를 돌리는 회전을 한다고 생각 해봅니다. 이는 y축 회전입니다.

y축 회전을 함으로 인해서 z 축 회전이 영향을 받아서 바람의 방향이 바뀌게 됩니다.

이처럼  한 축의 회전이 다른 축의 회전에 영향을 미치는 현상 때문에 세 축 중에 한 축의 회전을 사용할 수 없는 현상이 발생합니다.

이를 짐벌락 현상이라고 합니다.

 

다시 선풍기를 예로 들어 보겠습니다.

선풍기 고개를 도리도리 돌리는것은 y축의 회전에 해당 하는데 y축을 90도 돌리는 순간 기존 x축(바람 방향 상하 조절 축)이 같이 회전하며,z축(원래 선풍기 프로펠러의 회전 축이었던 축)과 축이 겹치게 됩니다.

이 때부터 3차원 회전을 제대로 표현하지 못하게 됩니다.

 

쿼터니언은 원소 값으로  4개를 가지는 값으로, 사원수라고 부르기도 합니다.

쿼터니언 사이의 연산은 행렬을 사용하며, 더 많은 회전값을 주려면 덧셈이 아니라 곱셈으로 표현합니다.

쿼터니언의 복잡함 때문에 유니티는 쿼터니언 내부 값을 개발자가 직접 제어 할 수 없게 막았습니다.

대신 쿼터니언을 다루는 메서드를 통해 제어 하게 됩니다.

 

Quaternion.Euler(Vector3);

오일러 각을 표현하는 Vector3 좌표상의 값에서 Quaternion 값을 생성할 수 있습니다.

위 메소드의 반환값은 쿼터니언 형식이 되게 됩니다.

 

Quaternion rotation = Quaternion.Euler(new Vector3(0, 60, 0));

위 코드는 Vector3 형식으로 다른 축은 움직이지 않고 y축 60도 회전을 표현하는 쿼터니언 형식의 변수 rotation 생성하기 입니다.

 

Vector3 eulerRotation = rotation.eulerAngles;

쿼터니언 타입을 Vector3 타입의 오일러각으로 변환 하여 가져온 변수 eulerRotation 선언.

[eulerAngles] 맴버함수를 사용해서 가능합니다.