개발하는 리프터 꽃게맨입니다.

[그래픽스] 모델링 행렬 설계 본문

컴퓨터 그래픽스

[그래픽스] 모델링 행렬 설계

파워꽃게맨 2024. 8. 6. 17:12

변환 행렬

 

대표적인 선형 트랜스폼은 3개 존재합니다.

바로 크기, 회전, 이동 변환이죠.

 

2차원에서 이들의 변환행렬을 한 번 살펴봅시다.

 

크기 변환 행렬

 

크기 변환 행렬에 대해서 살펴봅시다.

크기 변환은 이런 식으로 한 좌표를 일정한 비율로 키워야 합니다.

예를 들어 P(2, 4) 라고 했을 때,

x축으로 2배 y축으로 3배 늘린다고 했을 때,

P'(2 * 2, 3 * 4) 가 됩니다. 

 

이런 식으로 정점을 늘린 후,

정점끼리 선을 그리면 마치 크기가 늘어난 듯한 모습을 보여줍니다.

그러면 이렇게 정리할 수 있겠죠

점 P(x, y) 가 있다고 할 때, x축으로 a배 만큼 y축으로 b배 만큼 늘린다면 그 좌표를 P(ax, by) 라고 할 수 있다.

 

그러면 크기 변환 행렬은 다음과 같이 구할 수 있습니다.

 

회전 변환 행렬

 

어떤 점 P(x, y)는 다음과 같이 행렬로 정의할 수 있습니다.

그렇다면 해당 표준기저벡터를 세타만큼 회전시킨다고 해봅시다.

표준기저벡터는 단위원 위의 점이므로 e1' 와 e2' 역시 쉽게 구할 수 있습니다.

 

 

이 새로운 기저벡터를 이용해서 x, y를 새롭게 정의해봅시다.

 

 

그러면 P를 표준기저벡터로 정의했던 것 처럼 P'도 정의해봅시다.

 

 

회전 변환 행렬도 완성했습니다.

 

이동 변환 행렬

 

이동 변환 행렬은 만들기가 까다롭습니다.

위와같은 이동 변환 행렬은 아래와 같습니다.

 

그런데 해당 식에는 문제점이 있습니다.

선형성이 존재하지 않습니다.

 

선형성을 만족하려면 가산성과 동차성을 만족해야 합니다.

각각 만족하는지 봅시다.

 

 

가산성을 만족하지 않으므로 이동연산은 선형성이 없습니다.

 

그리고 이동 변환은 행렬 곱으로 나타낼 수 없기 때문에, 성능 저하가 나타날 수 있습니다.

 

이동 변환을 행렬곱으로 나타내는 방법은 3차원 전단을 사용하는 방법입니다.

 

이런 식으로 z = 1 을 축으로 하여 전단 변환을 사용해봅시다.

그러면 z = 1인 평면에 대해서 이동하는 듯한 효과를 만들어 냅니다.

 

그렇다면 차원을 하나 높여서 이동변환행렬을 만들 수 있습니다.

 

이제 선형성도 만족하면서 행렬곱으로 표현할 수 있는 이동변환행렬을 만들었습니다.

 

이동변환행렬과 다른 행렬들 끼리 곱셈을 만족시키기 위해서는 다른 변환들도 다 3x3 행렬로 만들어줘야만 합니다.

 

 

모델링 행렬 설계

 

모델링 행렬을 모두 3x3 행렬로 만들어보았습니다.

그런데 행렬곱은 교환법칙이 성립하지 않기 때문에 어떤 식으로 행렬들을 곱할지 생각해야 합니다.

먼저 경우의 수는 다음과 같습니다.

 

우리는 이동 변환을 가장 마지막에 해야 합니다.

왜냐면 이동 후 회전 및 크기 변환을 하면 아마도 원하는 결과가 나오지 않을 것이기 때문입니다.

그러면 경우의 수가 2가지로 줄어들겠죠.

 

 

그러면 회전을 먼저하냐, 크기 변환을 먼저하냐 두 가지가 남았습니다.

 

크기 변환을 한 후 회전을 하면 강체 변환의 특성이 유지가 됩니다.

그러나 회전을 한 후 크기 변환을 하면 강체의 특성이 깨지게 됩니다.

 

그러므로 모델링 행렬은

 

크기 -> 회전 -> 이동 순으로 적용해야 합니다.

그러면 이를 이용해서 모델링 행렬을 만들어보도록합시다.

 

최종적인 모델링 행렬을 완성시켰습니다.

 

이러한 모델링 행렬을 만들어야하는 게임 오브젝트는 아마도 한정되어 있을 겁니다.

UI 나 버튼 같은게 모델링 행렬을 필요로하지는 않을테니 말이죠.

 

그래서 Transfomer 라는 클래스를 만들어줬습니다.

 

 

Transfomer 클래스는 로컬좌표, 로컬각도, 로컬크기, 로컬 기저 벡터를 가지고 있습니다.

 

 

get set 함수를 통해서 Transfomer의 변수들을 수정할 수 있습니다.

 

그리고 GetModelMatrix 함수를 통해서 모델링 함수를 얻어낼 수 있도록 해봅시다.

 

 

와이어프레임에서 버텍스버퍼와 인덱스버퍼를 꺼내오고

정점들에 모델링 행렬을 곱해서 변환해야 합니다.

 

이것을 정점 변환이라고 합니다. 

VertexShader2D가 정점 변환을 수행하는 함수입니다.

 

 

여기서 position은 2차원값이고 modelMatrix는 3x3 행렬입니다. 즉 곱셈이 정의되지 않습니다.

 

 

그러므로 2차원 벡터를 3차원 벡터로 확장해줘야만 합니다.

아핀 공간으로 벡터를 확장시켜야하기에 z = 1인 3차원 벡터로 확장하도록 합시다. 

 

다음은 결과입니다.

키를 눌러서 크기, 회전, 이동 변환을 수행하고 최종적으로 모델링 행렬으로 변환하여 정점을 그립니다.