ashen-aetna-ko

Ashen Aetna

— 재 덮인 화산 위에서 서툴게 비틀거리기

(3D 그래픽, Rust, Vulkan, ash에 대한/속의/관한/함께하는 튜토리얼)

각도, 직교성, 회전

지난 장에서 우리는 위치를 조작하기 위해 몇 가지 회전을 사용했습니다. 좌표 변환과 벡터 수학을 파고드는 것은 이번이 마지막이 아닐 것이므로, 3D 수학의 몇 가지 기본 개념을 더 살펴보겠습니다. 어떤 경우에는 nalgebra가 제공하는 함수를 계속 사용하겠지만, 그렇다고 해서 그 배경을 살펴보는 것을 막지는 못할 것입니다.

벡터의 길이, 각도, 사인과 코사인, 스칼라 곱(내적), 직교성, (한 벡터를 다른 벡터에 투영하는) 투영, (그람-슈미트 과정과 외적을 포함한) 직교화, 그리고 회전 행렬에 이미 익숙하다면 이 장을 건너뛰셔도 안전합니다. 우리는 프로그램 코드를 변경하지 않을 것입니다.

비록 3D 그래픽을 위해 사용하는 벡터를 4개의 성분을 가진 벡터로 확장했지만, 여기서는 3개(또는 때때로 2개)의 성분을 가진 벡터에 집중하겠습니다. (이 벡터들과 4성분 벡터의 관계는 15장16장을 참조하세요.)

이러한 개념 대부분은 “화면에 어떻게 표시할까”를 생각하기 전의 연산에 필요합니다.

벡터의 길이

‘길이’가 무엇인지에 대한 생각은 누구나 가지고 있으며, 우리는 단지 그것을 측정하는 방법을 찾으면 됩니다.

다음과 같은 벡터의 경우: 또는 , 길이를 구하는 것은 쉽습니다. 길이 는 0이 아닌 성분의 값일 뿐입니다:

, .

에… 알겠습니다, 0이 아닌 성분의 절댓값(즉, 음수일 경우 부호를 뒤집은 값)입니다: .

벡터가 0이 아닌 두 개의 성분을 가질 때, 예를 들어 의 경우 상황은 이렇습니다:

그리고 직각삼각형을 찾아 피타고라스의 정리를 사용합니다: 녹색 선의 길이의 제곱은 파란색 선들의 길이의 제곱의 합과 같습니다: 또는 .

실제 3차원 설정은 어떨까요? 예를 들어, ?

이것은 다음과 같이 보입니다:

그리고 여기에도 직각삼각형이 있습니다. 그 변 중 하나는 우리가 이전에 계산했던 길이입니다. 그리고

.

같은 방식으로, 우리는 모든 벡터를 직각삼각형으로 분해할 수 있으며, 의 길이에 대한 일반 공식은 다음과 같습니다.

어떤 에 대해서도, 임을 알 수 있습니다. 따라서 벡터를 정규화하는(그리고 이를 통해 “단위 벡터”를 얻는) 방법은 간단합니다: 대신 를 사용합니다. 이 벡터는 여전히 같은 방향을 가리키지만, 길이는 입니다. 이 방법(이 공식뿐만 아니라 일반적으로 정규화)은 에 대해서는 작동하지 않습니다.

벡터 사이의 각도

다음으로, 두 벡터 사이의 각도를 고려해 봅시다. 어떤 벡터 쌍이든 두 벡터를 모두 포함하는 평면이 존재하므로, 모든 그림을 2D로 제한할 수 있습니다.

각도 — 두 벡터 “사이에 있는 것”. “얼마나”를 어떻게 측정할까요?

첫 번째 관찰: 다음 각도들은 모두 같습니다.

우리는 단위 벡터 사이의 각도에 대해서만 생각하면 됩니다.

또한, (두 벡터를 같은 양만큼) 회전해도 각도는 변하지 않으므로, 와 두 번째 벡터 사이의 각도를 측정하려고 시도할 수 있습니다. 이것은 이전과 여전히 같은 각도입니다:

이제, 그 크기는 얼마일까요? 각도의 측정값으로, 한 벡터(의 끝)에서 다른 벡터까지 원을 따라가는 곡선의 길이를 사용합니다. (기억하세요: 우리는 길이가 1인 벡터에 대해 이야기하고 있으므로, 벡터들을 원점에서 시작하게 하면 두 벡터의 끝은 모두 반지름이 1인 원 위에 놓입니다.)

따라서 전체 원은 2π의 각도에 해당합니다. (그리고 °(“도”)를 숫자 π/180으로 정의하면, 원한다면 이 전체 원의 각도를 360°라고 부를 수 있습니다.)

9/2 * π 각도는 어떨까요? 글쎄요:

π/2와 구별할 수 있는 차이가 없습니다.

음수 각도는 어떨까요? 글쎄요, 그건 그냥 “다른 방향으로”라고 합시다:

(이것은 예를 들어, x축에서 다른 벡터까지 -π/4의 각도가 될 것입니다)

부호, 즉 방향을 도입한다는 것은 우리가 사이의 각도보다는 …에서 …까지의 각도에 대해 더 많이 이야기하고 있다는 것을 의미합니다.

다음 두 각도 중 어느 것이 +π/4이고 어느 것이 -π/4인지 어떻게 알 수 있을까요?

그것은 관례의 문제입니다. 우리는 이렇게 결정합니다: 에서 까지의 각도는 양수입니다.

그래서, 이 각도는 +π/4입니다:

그리고 이 각도는 +π/4입니다.

둘이 같지 않나요? 아닙니다. 매우 중요하지만 매우 미묘한 차이입니다: 축의 방향에 주의하세요! (그리고 제발, 축의 양쪽 끝에 화살표를 그리지 마세요. 화살표는 “이 방향으로 더 있다”는 의미가 아니라 “이 방향으로 숫자가 증가한다”는 의미입니다.)

제 그림 중 일부는 Vulkan의 좌표계의 방향과 일치하지 않습니다. 신경 쓰지 않습니다. 그것은 “어느 방향에서 보고 있는가”의 문제입니다. 하지만 축에 표시된 방향을 보는 것이 더욱 중요해집니다.

이 각도는 실제로 -π/4입니다 (이전에 언급했듯이, 이제 축의 방향을 이해할 수 있을 것입니다…):

이것은 x-y 평면의 각도에는 잘 작동하는 좋은 정의이지만, 그 밖에서는 별로 도움이 되지 않으며, 우리는 결국 3D를 희망하고 있습니다. 거기서 양수와 음수 각도를 어떻게 구별할까요?

이것을 다루는 두 가지 방법이 있습니다 (둘 다 나타날 것입니다):

  1. 우리는 구별하지 않습니다. 어떤 경우에는 …에서 …까지의 각도가 아니라 사이의 각도에만 관심이 있으며, 이 경우 부호는 중요하지 않으므로 정의하는 데 신경 쓰지 않습니다.
  2. 우리가 어느 축을 중심으로 회전하는지 명시하고(각도를 첫 번째 벡터를 두 번째 벡터 위로 회전시키는 것으로 생각하세요) 어느 회전 방향이 양수 회전에 해당하는지 정의합니다. “x-y 평면에서의” 회전에 대해, 우리는 그것들을 “ 주변의 회전”으로 간주할 것입니다. 어느 방향으로요? 벡터 주위로 회전한다는 것은 무엇을 의미할까요? 오른손을 들어 엄지손가락을 펴세요. 이것이 회전축 벡터입니다. 어느 방향으로요? 나머지 (펴지 않은) 손가락들이 약간의 상상력을 더하면 나선 방향을 나타내는 호를 형성합니다. (엄지손가락이 코를 향하면 반시계 방향으로 인식될 것입니다.) 그것이 양의 방향입니다. 주위로 +π/2만큼 회전하면 실제로 가 되는지 확인해보세요.

마지막으로, 공식에서 “ 사이의 각도”라고 쓰고 싶지 않을 경우를 위한 기호: .

사인과 코사인

위에서는 두 벡터가 주어졌을 때 각도가 무엇인지에 대해 다뤘습니다. 이제 그 반대를 살펴보겠습니다: 각도(예: φ)가 주어졌을 때, 그 각도를 이루는 두 벡터를 찾을 수 있을까요? 다시 한 번, 첫 번째 벡터를 로 고정합시다.

우리는 각도, 즉 그림에 표시된 호의 길이를 알고 있으므로, 벡터를 그래픽으로 찾는 것은 쉽습니다:

그 좌표는 무엇일까요? 꼼수를 써봅시다. 이 좌표들은 위 절차(단위 원의 일부를 (1,0)에서 시작하여 호 길이가 φ와 같게 그리고, 끝점의 좌표를 취함)에 의해 명백히 유일하게 정의됩니다. 우리는 이 결과에 “이 점의 x좌표”(txcotp), “이 점의 y좌표”(tycotp)라는 이름을 붙이고, 필요할 때마다 모든 계산에서 txcotp(φ)와 tycotp(φ)를 참조할 수 있습니다. 만약 이것들이 충분히 유용하다면, 많은 사람들이 그것들을 사용할 것이고, 결국 우리는 φ 값을 넘겨주면 즉시 이 값들을 주는 Rust와 GLSL 함수를 갖게 될 것입니다.

글쎄요, 전통적으로 사용되어 온 이름은 다르지만, 아이디어는 그리 멀지 않습니다: txcotp는 cos라고 불리고 tycotp는 sin이라고 불립니다. 따라서 원점에서 시작하여 x축과 φ 각도를 이루는 단위 벡터의 끝에 있는 점은 다음과 같습니다.

(그리고 cos φ 또는 cos(φ)라고 쓰는 것은 단지 취향과 가독성의 문제입니다.)

참고로: 우리가 사인과 코사인을 단위 원 위의 점을 통해 정의했으므로, 본질적으로 정의에 의해 입니다. (다시 한 번 표기법에 대한 참고: 이것은 종종 로 축약되지만, 와 혼동될 수 있습니다 — 하지만 후자는 너무 드물어서 실제적인 우려는 없습니다.)

코사인 값을 이미 알고 있지만 해당하는 각도를 알고 싶다면: 그 질문에 대한 답은 arccos라고 불리며, 따라서 입니다 — 적어도 0과 π 사이의 각도 φ에 대해서는 그렇습니다. 더 큰 각도를 허용하면 동일한 코사인 값을 갖는 다른 가능성들이 있습니다.

마찬가지로, arcsin은 “주어진 값을 사인으로 갖는 각도는 무엇인가?”라는 질문에 대한 답입니다.

그리고 삼각함수를 소개하는 김에: 탄젠트는 사인과 코사인의 몫입니다: .

2D에서의 회전

이제 x축 위의 점을 주변으로 특정 각도만큼 회전시킨 후의 좌표에 대한 이름을 가졌으니, (평면 내의) 임의의 점을 주어진 각도 φ만큼 회전시키는 것을 설명해 봅시다.

회전은 선형이므로(생각해보세요; 필요하다면 14장의 선형성 소개를 다시 보세요), 행렬로 표현될 수 있습니다.

각도 φ만큼 회전하고 싶다고 가정하고, 이 회전을 라고 부릅시다. 그러면

”?”의 값을 어떻게 찾을까요? 첫 번째 열은 회전을 에 적용한 결과였습니다. 글쎄요, 그건 그리 어렵지 않습니다. 우리는 방금 그 성분들에 이름을 붙였습니다:

두 번째 열은 에 일어나는 일입니다. 그리고 로 회전됩니다.

너무 빨랐거나 그림을 선호한다면:

따라서 최종 행렬은 다음과 같습니다.

만약 먼저 각도 만큼 회전하고 그 다음 각도 만큼 회전하면 어떻게 될까요? 글쎄요, 총 만큼 회전합니다. 행렬에서도 그것을 볼 수 있을까요? 네: .

아, 이전에 두 행렬을 곱하는 방법을 다루지 않았군요. 그럼 지금 살펴보겠습니다. 다음은 무엇일까요?

우리는 행렬과 벡터를 곱하는 방법을 압니다. 한번 보죠:

그래서:

결과의 (1,2) 위치(즉, 첫 번째 행, 두 번째 열)에는 첫 번째 행렬의 첫 번째 행과 두 번째 행렬의 두 번째 열의 곱이 들어갑니다. (그리고 첫 번째 행과 두 번째 열의 곱은 “행렬 곱하기 벡터”의 관점에서 해석할 수 있습니다: .)

좋습니다, 이 문제는 해결되었으니 다시 회전으로 돌아갑시다:

그 짧은 계산에서 첫 번째와 마지막 행렬의 성분을 비교하여 다음을 알게 됩니다:

그리고

(이것들은 매우 유용한 항등식입니다.)

두 벡터 사이의 각도 계산하기

만약 한 벡터 v가 주어지고 와 이 벡터 사이의 각도를 계산하고 싶다면, 그리 어렵지 않습니다: v를 정규화하고(위의 모든 것은 단위 벡터에 대한 것이었습니다), 그 첫 번째 성분을 취합니다: 그것이 각도의 코사인 값입니다.

하지만 다른 벡터가 가 아니라면, 두 (단위) 벡터 가 있다면 어떨까요?

글쎄요, 이들은 단위 벡터이므로, , 로 쓸 수 있습니다. 그리고 두 벡터를 모두 회전시켜도 각도는 변하지 않으므로, 사이의 각도는 모든 회전 R에 대해 우리가 찾고자 하는 각도와 같습니다. 로 바꾸는 만큼의 회전을 선택합시다. 그러면 이전 설정으로 돌아가게 됩니다.

그래서: . (마지막 단계에서 부호 변경이 혼란스럽다면, 사인과 코사인 및 음수 각도의 정의 “그림”을 따라가며 확인해보세요.)

는 무엇일까요? 계산해봅시다:

좋습니다, 이것이 우리가 원했던 것입니다. 왜냐하면 이제 우리는 와 (회전된) 두 번째 벡터 사이의 각도만 필요하기 때문입니다.

그리고 각도의 코사인은 첫 번째 성분입니다:

(우리는 또한 를 계산하여 이 항을 얻을 수도 있습니다. 놀랍네요.)

그래서, 두 벡터 , 에서 시작하여 로 끝났습니다. 더 일반적으로는:

이것은 계산하기 쉽습니다. 그리고 각도와 관련하여 유용합니다. 이름을 붙여야겠습니다: 스칼라 곱. 내적. 점곱.

기억해야 할 공식:

(우리가 계속 단위 벡터를 사용했다는 사실을 고려하여 벡터의 길이를 포함시켰습니다.)

좋은 점은 이 공식이 3D에서도 여전히 작동한다는 것입니다. 여기서, (예상했듯이), 그리고 “기억해야 할 공식”은 동일합니다.

직교성

각도가 가질 수 있는 가장 중요한 크기 중 하나는 π/2, 즉 직각입니다. 두 벡터 사이의 각도가 직각이라는 것(읽기: “벡터들이 서로 직교한다”)은 그 코사인 값이 0이라는 것, 즉 스칼라 곱이 0이라는 것을 의미합니다. 매우 간단하게 확인할 수 있어서 매우 좋습니다.

인지 알아내는 것은 사인과 코사인을 포함하지도 않습니다.

그리고 3D에서도: 일 때만 직교합니다.

두 벡터()가 주어졌고, 그 중 하나(예: )를 두 부분으로 분해하고 싶다고 가정해 봅시다: 한 부분은 다른 주어진 벡터와 같은 방향을 가지며(이 부분을 라고 부릅시다), 두 번째 부분은 그것에 직교하는 부분()입니다.

만약 의 길이가 1이었다면, 는 cosφ의 길이를 가졌을 것입니다. 또한 와 같은 방향을 가리킵니다.

명백하게도,

그리고 우리는 cosφ를 (정규화된 벡터 e와 v 사이의) 내적으로 훨씬 쉽게 계산할 수 있습니다:

(의 길이가 1이라면, , 훨씬 더 멋지고 짧습니다.)

마지막으로, 로 설정할 수 있습니다.

방법: 만약 두 벡터(예: 3D)가 있고 같은 평면에 놓인 두 개의 직교 벡터를 원한다면, 벡터 중 첫 번째 것을 취하고(e라고 부릅시다), 두 번째 벡터 v의 직교 부분 를 취합니다. (는 표기법이 이 의존성을 나타내지 않더라도 의 선택에 의존한다는 점에 유의하세요.) 종종 이것들을 정규화하고 싶을 것입니다.

만약 두 벡터 가 있고 둘 다에 직교하는 세 번째 벡터를 찾고 싶다면, 먼저 에 직교하도록 보장할 수 있습니다(로 교체함으로써). 그런 다음 임의의 벡터 를 선택하고(의 평면에 놓이면 문제가 생길 것입니다. 하지만 그럴 확률은 낮고, 그냥 다른 벡터로 시작하면 됩니다), 에 대한 를 계산합니다. 그런 다음 를 취하고 에 대한 를 계산합니다. 최종적인 에 직교합니다.

하지만 우리는 지름길을 사용하여 두 주어진 벡터에 직교하는 벡터를 산출하는 기성 개념과 공식인 외적(cross-product)을 도입할 수도 있습니다.

사실, 이 문장에서 “ 벡터”의 “그”는 지나치게 낙관적입니다: 그러한 벡터는 많습니다; 적어도 그들은 모두 하나의 선에 속합니다. 만약 우리가 벡터의 길이와 방향(이 선 위의 두 가능한 방향 중 하나)을 결정한다면, 우리는 그것을 유일하게 결정한 것입니다. 두 벡터 가 주어지면, 우리는 이 새로운 직교 벡터를 “외적”이라고 부를 것입니다.

아마도 미래에 다시 다룰 수도 있겠지만, 지금은 그냥 정의를 쓰겠습니다:

(한 줄에서 다음 줄로 갈 때마다, 각 인덱스는 1씩 증가하며, 4 대신 1부터 다시 시작합니다.)

이 벡터는 실제로 에 직교합니다:

또한 에도 직교합니다 (계산은 여러분이 해보세요).

게다가, (이 순서대로)는 오른손 좌표계를 형성합니다.

정의를 확인하거나 이 마지막 속성을 사용하여 임을 볼 수 있습니다.

회전 행렬 (3D)

회전을 어떻게 인식할 수 있을까요?

각도에 대한 위의 아이디어와 연결하여: 만약 우리가 몇몇 벡터를 가지고 있고 그들에게 같은 회전을 적용한다면, 그들 사이의 각도는 변하지 않습니다. 또한 그들의 길이도 동일하게 유지됩니다.

이 두 아이디어를 하나의 조건으로 넣고 싶다면, 스칼라 곱이 변하지 않는다고 말할 수 있습니다: 모든 회전 R과 모든 벡터 u, v에 대해, 우리는 를 가집니다. (이것이 길이와 무슨 관련이 있을까요? 글쎄요, 입니다.)

우리는 R을 나타내는 행렬의 열이 , 그리고 에 의해 주어진다는 것을 압니다. 그리고 우리는 , 그리고 가 길이가 1이고 서로 직교한다는 것을 압니다.

만약 우리가 길이가 1이고 서로 직교하는 세 벡터 , , 를 안다면, 다음과 같이 설정하여 회전 행렬을 형성할 수 있습니다.

(좋아요, 더 정확히 말하면, 그것은 완전히 사실이 아닙니다: 우리는 회전뿐만 아니라 반사도 얻을 수 있습니다. 하지만 거의 비슷합니다.)

이것은 , 그리고 를 각각 , 그리고 로 바꾸는 회전입니다.

, 그리고 , 그리고 로 바꾸는 회전(예: )을 어떻게 찾을까요?

의 성분들에 이름을 붙여봅시다:

이것은 이상해 보입니다 — 지금까지는 행렬의 열이 어떤 의미를 가졌기 때문에 주로 사용되었는데, 왜 지금은 행을 사용하는 걸까요? 왜 다른 것을 하는 걸까요? 왜냐하면 결국에는 이런 방식으로 이름을 붙이는 것이 열 a, b, c를 갖는 것보다 더 유용하다는 것이 밝혀질 것이기 때문입니다. (보게 될 것입니다.)

그리고, 참고로, 또 다른 임의의 표기법(어딘가에 소개해야겠습니다): 만약 라면, 의 전치(transpose)라고 불리며 로 표기됩니다. 그래서, 원한다면: .

다시 우리의 질문으로 돌아가서: 등으로 회전시키기를 원한다면 , , 는 무엇일까요?

글쎄요:

즉:

또는, 별도로: , , . 스칼라 곱을 선호한다면, 이것은 , , 와 같습니다. (정의로 확인해보세요.)

를 같은 방식으로 처리하면, , , 그리고 , 그리고 도 찾을 수 있습니다.

에 대해 우리가 아는 것을 반복해 보겠습니다: 그것은 길이가 1인 벡터여야 하고(회전 행렬의 열이기 때문에), , , , 즉 에 직교하고(가 모두 단위 벡터이기 때문에) 와 이루는 각의 코사인이 1과 같습니다. 하지만 그렇다면… 입니다.

마찬가지로, 이고 입니다.

따라서 , , , 그리고 로 회전시키는 행렬은

분명히, 이 회전 의 효과를 되돌립니다(먼저 , , , , 로 회전시킨 다음 다시 , 그리고 로 회전시키는 것은 모든 것이 시작된 곳으로 돌아갔음을 의미합니다).

의 소위 “역행렬”입니다: .

요약하자면, 회전 에 대해:

(일반적인 행렬 의 경우, 역행렬 는 보통 계산하기 더 어렵고, 많은 행렬의 경우 존재하지조차 않습니다.)

행렬과 역행렬에 대해 더 할 말이 많습니다; 그리고 회전에 대해서도 그렇습니다(예를 들어, 주어진 축 주위의 회전을 설명하는 행렬에 대해서는 이야기하지 않았습니다). 하지만 지금은 이 정도의 “수학 강의”로 충분하다고 생각합니다(그리고 주어진 축 주위의 회전 예제에 대해서는, 우리를 도와줄 특정 nalgebra 함수를 사용할 수 있습니다).

계속