멈추지 않고 끈질기게

[기타][메모용] 행렬의 변환 본문

기타

[기타][메모용] 행렬의 변환

sam0308 2023. 10. 23. 15:44

※ 해당 포스팅은 개인의 공부 정리용 글입니다. 틀린 내용이 있다면 추후 수정될 수 있습니다.

※ 해당 포스팅은 하기 출처들을 참조하였습니다.

- 프랭크 D.루나, DirectX 12를 이용한 3D 게임 프로그래밍 입문(류광 옮김), 한빛미디어, 2021

 

 

1. 선형 변환, 행렬의 표현

 - 3차원 벡터를 입력받아 3차원 벡터를 출력하는 함수가 다음 조건을 만족할 경우,

   3차원 벡터에 대한 선형 변환(linear transformation)이라고 함

 - uv는 임의의 3차원 벡터, k는 스칼라 값

 

그림 1. 3차원 벡터의 선형 변환

 

 - 함수가 상기 두 조건을 모두 만족한다면(선형 변환이라면), 다음 성질이 성립함

 

그림 2. 선형 변환의 성질

 

 - 모든 3차원 벡터는 단위 벡터 i(1, 0, 0), j(0, 1, 0), k(0, 0, 1)로 다음과 같이 표현할 수 있음

 

그림 3. 3차원 벡터의 표현

 

 - 선형변환 함수는 그림 2에서 살펴본 성질과 그림 3의 벡터 표현을 통해 스칼라값과 단위 벡터에 대한 선형 변환으로

    표현할 수 있음

 - 이 형태는 곧 벡터와 행렬의 곱셈이므로, 선형변환을 행렬의 형태로 표현할 수 있음

   => 선형변환의 행렬 표현(matrix representation)

 

그림 4. 선형변환의 행렬 표현

 

 

2. 비례 변환, 회전 변환

 - 비례 변환(scaling transformation): x축, y축, z축 값에 각각 스칼라 값을 곱하는 선형 변환

 - 비례 변환 식은 다음과 같이 정의됨

 

그림5. 비례 변환

 

 - 비례 변환은 선형 변환이므로 행렬로 표현 가능

 - 물체를 표현하는 좌표값에 각각 비례 행렬을 곱할 경우, 물체의 크기를 바꾸는 효과가 있음

 - 그림 7은 최솟점(-2, -2, 0), 최댓점(2, 2, 0)으로 정의되는 정사각형에 비례 행렬을 곱하여 크기를 변경한 예시 

 

그림 6. 비례 변환의 행렬 표현
그림 7. 비례 변환을 통한 도형 크기 변경

 

 - 회전 변환(rotation transformation): 벡터 n을 축으로 θ만큼 회전하는 회전 공식은 벡터의 내적과 외적을 통해 정의됨

 - 회전 변환 또한 선형변환의 일종이므로 벡터로 표현 가능 => 회전 행렬(R)

 - 회전축 n이 x축, y축, z축일 경우 회전 행렬이 아주 간단해짐

 

그림 8. n을 축으로 θ만큼 회전하는 행렬
그림 9. x축, y축, z축 회전 행렬

 

3. 동차좌표와 아핀변환

 - 벡터는 본래 방향과 크기만을 표현한 것이므로, 이동 변환의 영향을 받으면 안됨

 - 동차 좌표(homogeneous coordinate):3차원 벡터에 w라는 값을 추가하여 점과 벡터를 구분하도록 만든 것

     (x, y, z, 0) => 벡터, (x, y, z, 1) => 점

 - 3차원 좌표계를 4x4 배열의 형태로 표현하는 이유

 

 

 - 아핀변환: 선형변환에 이동벡터를 더한 것

 - 벡터 u의 좌표와 선형 변환의 행렬 표현의 곱에 이동벡터를 더하는 식으로 표현 가능

 - w = 1인 동차좌표를 도입하면 아핀변환을 4x4 행렬로 간단하게 표현할 수 있음

   (w = 0일 경우, 이동벡터 b값은 모두 무시되는 부분에 주목)

 

그림 10. 아핀변환의 행렬 표현

 

 - 이동변환은 상기 아핀변환의 행렬 표현에서 행렬 A에 해당하는 부분을 단위행렬로 치환하여 표현 가능

 - 회전변환 또한 행렬 A에 해당하는 부분에 넣어 동차좌표에 적용할 수 있음

 

그림 11. 이동 변환(T) 및 x,y,z축 기준 회전 변환(R)의 행렬 표현(동차좌표)

 

 - 유니티의 Transform 또한 데이터를 동차좌표를 적용한 4x4 배열 형태로 저장(Matrix4x4)

 - 이동변환 및 회전변환의 행렬 표현을 곱하여 변환을 적용할 수 있음

 - ex) 회전 행렬을 통한 오브젝트 회전 예시

// 3차원 큐브에 적용
public class TransformTest : MonoBehaviour
{
    void Start()
    {
        // 30도를 라디안 단위로 변환
        float radian_30 = 30 * Mathf.Deg2Rad;
        // y축 기준 30도 회전변환의 행렬 표현
        Matrix4x4 rotMatrix = new Matrix4x4() { 
            m00 = Mathf.Cos(radian_30), m01 = 0, m02 = -Mathf.Sin(radian_30), m03 = 0,
            m10 = 0, m11 = 1, m12 = 0, m13 = 0,
            m20 = Mathf.Sin(radian_30), m21 = 0, m22 = Mathf.Cos(radian_30), m23 = 0,
            m30 = 0, m31 = 0, m32 = 0, m33 = 1
        };
        // 현재 오브젝트의 월드좌표계 행렬
        Matrix4x4 curMatrix = transform.localToWorldMatrix;
        // y축 기준 30도 회전
        curMatrix *= rotMatrix;
        // 회전값 적용
        transform.SetPositionAndRotation(curMatrix.GetPosition(), curMatrix.rotation);
    }
}

사진 1. (좌) 실행 전, (우) 실행 후

 

4. 강체 변환, 변환의 합성

 - 강체(rigid body) 변환: 물체의 형태에 영향을 미치지 않는 변환(회전, 이동 등)

 - 강체 변환은 회전 변환과 이동 벡터의 합으로 표현할 수 있음 => 아핀 변환

 

그림 12. 강체(rigid body) 변환의 아핀 변환 표현

 

 - 비례 변환, 회전 변환, 이동 변환 등 선형 변환들은 행렬의 형태로 표현 가능함

 - 변환의 적용 => 정점(w=1인 벡터)과 변환 행렬의 곱셈

 - 행렬의 곱셈은 결합법칙 적용 가능 => 연속된 변환을 하나의 행렬로 합성할 수 있음

 - ex) 비례변환, 회전변환, 이동 변환을 순차적으로 적용할 경우,

          회전행렬 S와 회전행렬 R과 이동행렬 T를 순차적으로 곱한 하나의 변환행렬로 합성 가능(SRT)

 

그림 13. 변환의 합성

 

 - 유니티에서도 Matrix4x4 구조체에서 이동행렬 및 회전행렬을 쉽게 구할 수 있는 기능 제공

 - 이동행렬과 회전행렬을 곱하여 합성한 뒤 현재 트랜스폼의 행렬에 곱하고, 이를 토대로 포지션 및 회전을 갱신하면

    한꺼번에 적용됨을 확인 가능

// 3차원 큐브에 적용
public class TransformTest : MonoBehaviour
{
    void Start()
    {
        Matrix4x4 curMatrix = transform.localToWorldMatrix;
        // x축으로 2만큼, y축으로 4만큼, z축으로 5만큼 이동
        Matrix4x4 moveMatrix = Matrix4x4.Translate(new Vector3(2, 4, 5)); 
        // x축, y축, z축 기준 30도 회전
        Matrix4x4 rotMatrix = Matrix4x4.Rotate(Quaternion.Euler(Vector3.one * 30));
        // 변환 합성
        Matrix4x4 combMatrix = moveMatrix * rotMatrix;
        curMatrix *= combMatrix;
        transform.SetPositionAndRotation(curMatrix.GetPosition(), curMatrix.rotation);
    }
}

사진 2. (좌) 실행 전, (우) 실행 후