- 우리가 새롭게 구축할 3D 공간에 대한 설명
- Y-up Right Handed Coordinate(오른손 좌표계)
양의 x와 y 축은 오른쪽과 위를 가리키고, 음의 z 축은 앞으로 가리킨다.
양의 회전은 회전 축에 대해 시계 반대 방향이다.
오른손 좌표계가 시계 반대 방향인 이유는 주먹이 쥐어진 상태로 오른손을 들고 엄지손가락만 펴보면 알 수 있다.
- X axis(Right), Z axis(Forward) 각각의 용도
X axis의 용도 : 왼쪽, 오른쪽 방향을 구분
Z axis의 용도 : 앞, 뒤 방향을 구분
- 3D Rotation에 대한 고찰
- 회전이란 공간 변환의 관점에서 어떤 행동인지 기술
회전이란 물체가 돌아가는 것이 아닌 공간이 돌아가는 것이다.
수학적으로 설명하자면 벡터 공간 입장에서 보았을 때 공간이 돌아간다고 할 수 있다.
예를 들어
한 이미지를 만들어서 월드 공간에 배치를 하게 되면 이것은 물체를 배치하는 것이 아닌
아핀 공간이라고 하는 점들의 집합 즉, 마지막 차원이 1인 공간 자체가 평행 이동을 해서 월드 공간에 덧 씌워진 것이다.
그렇게 덧 씌워진 상태에서 선형 변환을 한다는 것은 그 이미지에 속하는 로컬 공간이 있고,
그 공간 자체에는 두 개의 기둥이 있는데 이것은 x축과 y축이 있는 것이다.
그리고 그 공간의 x축과 y축을 변형 시킨다는 것은 그 공간 자체의 기반을 변형시킨다는 것이다.
따라서 그 공간은 표준 기저 두개의 조합이라고 설명할 수 있다.
그렇다면 이 공간의 회전은 어떤 의미를 하는 것일까?
모습이 변하지 않는 것이라고 할 수 있다.
그렇다면 회전을 하기 위해 이 모습이 변하지 않기 위한 조건은 무엇일까?
첫 번째 조건은 변환된 표준 기저(x, y)의 크기가 1이면 된다.
하지만 크기가 1이라고 다 변하지 않는 것이라고 할 수 없다.
왜냐하면 크기가 1인 상태에서 서로 직교를 해줘야 하기 때문이다.
만약 서로 직교를 해주지 않게 되면
위의 그림과 같은 형태의 모양이 나왔을 때 일그러지게 된다.
따라서 회전을 하기 위한 조건에는 크기가 1인 상태에서 서로 직교를 해야 한다는 특징이 있고,
이것을 Rigid Transform이라고 한다.
3차원도 마찬가지로 x, y, z 축이 서로 직교한 상태에서 그대로 돌아간다고 보면 된다.
3차원의 회전은 x, y 축의 방향이 어떻게 재설정 됐는지 볼 수 있는데,
이것을 "Orientation(방향의 재설정)"이라고 할 수 있다.
x, y, z의 방향이 유지된 상태에서 틀어졌기때문에 회전을 정확하게 표현하는 방법은 딱 한가지가 있다.
그것은 x, y, z 벡터를 꽂아주는 것이다.
x, y, z 벡터를 꽂아주게 되면 가장 정확하게 회전의 상태를 알아낼 수 있게 되는데,
문제는 이것은 데이터가 너무 많고 직관적이지가 않다는 것이다.
이 문제로 인해서 데이터가 적고 직관적인 방식을 보완한 것이 있는데
대표적으로 오일러 각 방식( Yaw(Y), Roll(Z), Pitch(X) )이 있다.
이 방식은 언리얼 엔진에서도 사용을 하고 있는데,
언리얼 엔진 같은 경우는 회전에 벡터를 사용하지 않고 오일러 각 방식을 따로 만들어서 데이터를 관리하고 있다.
오일러 각 방식을 만들어서 사용하는 이유는?
3D Rotation 값을 매트릭스로 저장하면 모든 변환된 인스턴스에 더 많은 메모리를 사용할 수 있기 때문이다.
- 각 축에 대한 회전 행렬을 생성할 때 왜 Y 축은 반대인지 이유
각 축에 대한 회전 행렬은 다음과 같다.
여기서 x, z 축은 일반적인 방법의 회전 행렬을 사용하고 있지만 y 축은 다르게 되어 있다.
먼저 x, z 축을 90도씩 돌려보자
x축
z축
일반적인 방식으로 y 축을 계산해 보면 다음과 같이 나오게된다.
여기서 결과가 [-1, 0, 0]이 나오는데 -1이 나왔다는 것은 반대 방향으로 돌았기 때문이다.
이렇게 되면 x, y, z 축을 회전 시켰을 때 사이클이 돌지 않게 되고 회전이 이상하게 꼬일 수가 있다.
그런데 다음과 같이 한쪽이 틀어진 상태로 계산을 하게 되면
결과가 [1, 0, 0]이 나오게 되고, 이 상태로 x, y, z 축을 회전 시키게 되면 다음과 같이 사이클이 돌게 된다.
따라서 y의 회전 행렬은 부호를 반대 방향으로 뒤집어서 전치가 되어야 원하는 사이클을 돌릴 수가 있다.
- 3D 회전 행렬
이번에는 R(yaw) R(pitch) R(roll)의 순서로 회전 행렬을 곱해서 최종 로컬 Forward, Right, Up의 값을 구해보자
- 카메라 뷰 좌표계
뷰 좌표계는 카메라 뒤쪽으로 향하는 방향이 +z인 좌표계이다.
- 목표 지점 정보가 주어진다면 이를 토대로 카메라의 회전 행렬을 제작하는 전체 과정을 유도
먼저 카메라가 목표 지점의 방향으로 회전을 시키려면 회전한 값에 대한 3x3 행렬이 필요하고,
카메라의 위치랑 바라봐야 하는 게임 오브젝트의 위치가 필요하다.
먼저 벡터의 크기를 1로 만들어 놓고 위치를 지정 해놓고 Z 축으로 정해 놓는다.
그 이후에 벡터를 기준으로 두 개의 직교하는 벡터를 똑같은 순서대로 만들어서 작업을 하면 끝이 난다.
그런데 이 벡터만 가지고 직교를 할 때 하나의 직교를 하는 축의 정보를 구할 수 있을까?
문제는 이것이 두 가지 쌍이 존재할 수도 있는데, 밑으로 가는 쌍이 있고, 위로 가는 쌍이 있을 수도 있다.
그래서 벡터만 있으면 카메라가 반대로 뒤집어져 있는 상태인지 위를 보고 있는지 아래를 보고 있는지
알 수 있는 방법이 없다.
그럼 해결 방법은 무엇인가?
카메라가 위를 바라볼 건지 아래를 바라볼 건지 정해주기만 하면 된다.
위를 바라본다는 것은 월드의 Y 축을 가져와서 외적을 시키면 된다.
외적을 시키게 되면 두 벡터의 직교한 벡터가 나오게 되는데
그렇게 나온 벡터와 Z 축 벡터를 직교해버리면 나머지 한 축을 구할 수가 있고,
그것을 통해서 3x3 행렬을 구할 수가 있다.
3축(Forward, Right, Up)을 구해보자
먼저 카메라의 뒤 쪽 방향(+Z)을 Forward라고 할 수 있고
월드의 Y 축에서 오른쪽으로 돌리게 되면 Right가 나오게 된다.
그리고 Forward 방향에서 Right 방향으로 돌리게 되면 Up이 나오게 된다.
그렇게 최종적으로 3축(Forward, Right, Up) 구한 결과는 다음과 같다.
이때 예외적으로 주의해야 할 사항은 카메라의 뒤 쪽 방향을 구했지만 월드의 Y 축과 겹칠 수가 있는데,
이런 경우에는 카메라가 월드의 위를 보거나 아래를 보는 경우가 발생하게 되면
외적 결과가 나오지 않게 되므로 월드의 X축이 되도록 만들어줘야 한다.
3축(Forward, Right, Up)을 모두 구했으니 이것을 통해 이동과 회전이 고려된 카메라 행렬을 유도해보자
TRS의 역행렬에서 카메라는 크기가 필요 없기 때문에 TR의 역행렬이 되는데
합성 함수의 역행렬은 반대로 되기 때문에 +를 해줘야 하므로
라고 할 수 있다.
그리고 회전 행렬의 성질 중에는 Orthogonal matrix라는 것이 있는데
이것이 항등 행렬로 나오기 위해서는 전치를 해주면 된다.
그 얘기는 즉, 전치행렬은 역행렬이라고 할 수 있다.
따라서 회전 행렬은
가 되는데 이 회전 행렬에서 전치를 해주면 다음과 같이 된다.
- 카메라를 (0, 0, -500)에 두고 원점에 위치한 큐브를 와이어 프레임으로 렌더링 한 이미지
- 회전 행렬을 적용해 입력에 따라 Yaw, Roll, Pitch 회전한 결과
Yaw
Roll
Pitch
- 카메라를 (500, 500, -500)으로 이동하고 원점을 향해 보는 구도를 생성
'Programming > Soft Renderer_2020' 카테고리의 다른 글
GameEngine 3D : Frustum Culling, Euler angle, Rodrigues Rotation (0) | 2020.07.02 |
---|---|
GameEngine 3D : Backface Culling, Perspective Projection (0) | 2020.06.25 |
지수 함수, 맥클로린 급수 (0) | 2020.06.12 |
복소수 (cosθ, sinθ) 가 회전 행렬과 동일함을 증명 (0) | 2020.06.12 |
복소수의 기본 성질 (0) | 2020.06.12 |