ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [DirectX] 2-1. 벡터
    Game Development/DirectX 2024. 6. 5. 16:01

    이번 글에서는 다음 글에서 제작할 Vector 클래스에 들어갈 기능 및 연산들을 한번 정리해 보겠습니다.

     

    먼저 벡터가 뭔지부터 알아봅시다.

    벡터는 크기와 방향을 가지는 물리적인 양이며, 기호는 \(\vec {A}\)입니다. (이 글에서는 기호를 생략하도록 하겠습니다)

    벡터는 여러 요소들로 구성되며, 해당 요소들은 각 축들의 방향에 대한 크기입니다.

    예를 들어 3차원 벡터 \(A = (a, b, c)\)는 x축 방향으로 \(a\)만큼, y축 방향으로 \(b\)만큼, z축 방향으로 \(c\)만큼 향한다는 입니다.

    벡터 A

    자 이렇게 벡터가 무엇인지 간단하게 알아보았으니 이번엔 Vector 클래스에 들어갈 기능 및 연산들에 대해 알아봅시다.

     

    1. 크기(Length)

    벡터의 크기는 벡터의 길이라고 생각하시면 됩니다.

    벡터의 A의 길이는 \(\Vert A\Vert\)로 나타내며, 벡터의 길이는 피타고라스 정리를 이용하면 간단하게 구할 수 있습니다.

    3차원 벡터 \(A = (a, b, c)\)의 길이는 다음과 같이 나타낼 수 있습니다.

    $$ \Vert A\Vert = \sqrt{a^2 + b^2 + c^2}$$

    Length

     

    추가로 크기가 1인 벡터를 단위 벡터라고 하며, 기호로는 \(\hat{A}\)로 나타냅니다.

     

    2. 정규화(Normalize)

    Normalize는 벡터의 크기를 1로 만드는 연산입니다. 

    벡터의 크기를 1로 만들려면 벡터의 각 요소들을 벡터의 크기로 나누어주면 됩니다.

    A를 Normalize하는 것은 다음과 같이 계산할 수 있습니다.

    $$\hat{A} = {A\over{\Vert A\Vert}} = ({A_x\over{\Vert A\Vert}}, {A_y\over{\Vert A\Vert}}, {A_z\over{\Vert A\Vert}}) = $$

    $$ ({{A_x}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}}, {{A_y}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}}, {{A_z}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}}) $$

     

    또한 \(\Vert\hat{A}\Vert\)는 아래 식으로 보았을 때, 1이라는 것을 알 수 있습니다.

    $$ \Vert\hat{A}\Vert = \sqrt{({{A_x}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}})^2 + ({{A_y}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}})^2 + ({{A_z}\over{\sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2}}}})^2 = $$

    $$ \sqrt{{{A_x}^2 + {A_y}^2 + {A_z}^2}\over{ {A_x}^2 + {A_y}^2 + {A_z}^2 }} = 1 $$

     

    3. 사칙연산 (스칼라)

    스칼라는 방향을 가지지 않고 크기만 가지고 있는 물리량입니다.

    스칼라에는 정수, 분수, 소수 등등 다양한 것들이 있습니다.

    이러한 스칼라와 벡터끼리는 덧셈과 뺄셈은 불가능하지만 곱셈과 나눗셈은 가능합니다.

    곱셈과 나눗셈을 하는 것은 간단하게도 벡터에 모든 요소에 스칼라를 곱하거나 나누면 됩니다.

    예를 들어 \(A = (a, b, c)\)가 있고, \(A * 5\)를 한다고 하면 다음과 같이 나타낼 수 있습니다.

    $$ A * 5 = (A_x * 5, A_y * 5, A_z * 5) $$

    다른 연산들도 이와 같이 하시면됩니다.

     

    4. 사칙연산 (벡터)

    벡터끼리의 사칙연산은 스칼라와는 반대로 덧셈과 뺄셈은 가능하지만 곱셈(벡터의 곱셈은 따로 있으나 여기서 말하는 사칙연산의 곱셈과는 다른 것이기 때문에 후술 하도록 하겠습니다)과 나눗셈은 불가능합니다.

    벡터끼리의 덧셈과 뺄셈도 간단하게 할 수 있는데, 바로 벡터의 같은 축에 위치하는 요소끼리 더하거나 빼면 됩니다.

    예를 들어 \(A = (a, b, c), B = (d, e, f)\)라고 할 때, 덧셈은 \((a + d, b + e, c + f)\), 뺄셈은 \((a - d, b - e. c - f)\) 이런 식으로 하면 됩니다.

     

    5. 벡터의 곱셈

    벡터의 곱셈은 내적과 외적으로 두 종류가 있습니다.

     

    내적(inner product, dot product, sclar product)

    내적은 벡터의 방향을 고려하여 수처럼 곱하는 방식으로 '\(\cdot\)'를 기호로 사용합니다.

    아래 식을 통해서 계산할 수 있습니다. (\(\theta\)는 두 벡터가 이루는 각도입니다.)

    $$ A \cdot B = \Vert A\Vert \Vert B\Vert cos\theta $$

    내적

    위의 식과 그림처럼 내적은 두 벡터가 있을 때,

    한 벡터의 크기와 해당 벡터의 방향으로 다른 벡터를 투영시켜 나온 벡터의 크기의 곱을 구하는 것이라고도 할 수 있을 것 같습니다.

    하지만 위의 식으로 계산하면 계산이 많이 복잡해지기 때문에 이 식을 바꿔주어야 합니다.

    이는 단위 벡터를 이용해서 해결할 수 있는데, 

    먼저 각 축의 방향을 향하는 단위 벡터 \(i = (1, 0, 0), j = (0, 1, 0), k = (0, 0, 1)\)를 정의합니다.

    그리고 \(A, B\)를 단위 벡터를 이용해 다음과 같이 정의합니다.

    $$ A = A_xi + A_yj + A_zk $$

    $$ B = B_xi + B_yj + B_zk $$

    이렇게 정의된 \(A\)와 \(B\)를 내적을 합니다.

    내적은 분배 법칙이 성립하고, 상수값을 곱한 것을 빼고 해서 나중에 곱해도 되기 때문에 다음과 같이 나타낼 수 있습니다.

    $$ (A_xi + A_yj + A_zk) \cdot (B_xi + B_yj + B_zk) = $$

    $$ A_xB_x(i \cdot i) + A_xB_y(i \cdot j) + A_xB_z(i \cdot k) + $$

    $$ A_yB_x(j \cdot i) + A_yB_y(j \cdot j) + A_yB_z(j \cdot k) + $$

    $$ A_zB_x(k \cdot i) + A_zB_y(k \cdot j) + A_zB_z(k \cdot k) $$

    여기서 \(i, j, k\)는 서로 90도 이고, 단위 벡터여서 길이가 1이기 때문에 자기 자신과 내적 하면 1이 나오고, 그게 아니라면 0이 나옵니다.

    따라서 위의 식은 다음과 같이 고칠 수 있습니다.

    $$ A \cdot B = A_xB_x + A_yB_y + A_zB_z $$

    이렇게 식이 간단해졌기 때문에 계산도 더 빠르고 간단하게 할 수 있습니다.

     

    외적(outer product, cross product, vector product)

    외적은 3차원에서 2개의 벡터와 직교하는 벡터를 구하는 연산으로 '\(\times\)'를 기호로 사용합니다.

    아래의 식을 통해서 계산할 수 있습니다.

    $$ A \times B = (A_yB_z - A_zB_y, A_zB_x - A_xB_z, A_xB_y - A_yB_x) $$

    이 식은 단위 벡터와 행렬식을 통해서 유도할 수 있습니다.

    내적 때와 같이 각 축의 방향을 향하는 단위 벡터 \(i, j, k\)를 정의합니다.

    \(A \times B\)를 아래와 같이 행렬식으로 정의합니다.

    $$ A \times B = \begin {vmatrix} i & j & k \\ A_x & A_y & A_z \\ B_x & B_y & B_z \end{vmatrix} = $$

    $$ \begin {vmatrix} A_y & A_z \\ B_y & B_z \end{vmatrix}i - \begin{vmatrix} A_x & A_z \\ B_x & B_z \end{vmatrix}j + \begin{vmatrix} A_x & A_y \\ B_x & B_y \end {vmatrix} k = (A_yB_z - A_zB_y, -(A_xB_z - A_zB_x), A_xB_y - A_yB_x) = $$

    $$ (A_yB_z - A_zB_y, A_zB_x - A_xB_z, A_xB_y - A_yB_x) $$

    이런 과정을 통해서 처음 식과 같은 식이 나오게 됩니다.

     

    추가적으로 외적을 통해서 나온 벡터의 크기는 \(\Vert A\Vert\Vert B \Vert sin\theta\)이며,

    방향은 오른손 좌표계 기준으로 오른나사 법칙을 따르고,

    왼손 좌표계에서는 오른 나사 법칙을 통해 나온 방향을 \(xy\)평면으로 대칭한 방향입니다. 

    이는 왼손 좌표계와, 오른손 좌표계의  z축이 서로 반대여서 그렇습니다.

     

    내적과 외적은 활용할 수 있는 방법이 여러 가지가 있는데 이건 다음에 기회가 된다면 써보도록 하겠습니다.

    다음 글에서는 3차원 벡터 클래스인 Vector3 클래스와 2차원 벡터 클래스인 Vector2 클래스를 제작해 보도록 하겠습니다.

    읽어주셔서 감사합니다.

Designed by Tistory.