이득우의 게임 수학
2차원 카메라를 구현할 때는 이동 기능만 부여했지만, 3차원 카메라에는 회전 기능도 함께 부여해본다.
3차원의 카메라는 고려할 요소가 더 많다.
원점에 카메라가 있고, 카메라가 바라보는 Z축 앞 방향 (0, 20, 500)에 게임 오브젝트가 위치했다고 해보자.
- xy평면으로 최종 화면을 생성한다고 할 때, CK소프트렌더러의 좌표계 상 카메라의 화면에서 x축은 익숙한 오른쪽이 아닌 왼쪽을 향하게 된다.
따라서 보편적으로 인지하는 데카르트 좌표계와 맞춰주기 위해 y축을 180° 회전시켜 x축을 오른쪽을 향하도록 해주면, 게임 오브젝트의 좌표는 (0, -20, -500)이 된다.
카메라에는 크기의 개념이 없기 때문에, 카메라의 위치를 t, 오일러 각을 통해 구한 로컬 축을 x, y, z라고 할 때, 이동 행렬 T와 회전 행렬 R은 다음과 같다.
2차원과 마찬가지로, 뷰 행렬은 이동과 회전 변환의 역행렬을 통해 구한다.
- 카메라가 t에 있고 게임 오브젝트가 p에 있다면, 카메라를 기준으로 한 게임 오브젝트의 상대 좌표는 p - t가 된다.
- 물체가 가만히 있는데 카메라가 30° 회전한 상황이라면, 물체가 -30° 회전한 것과 동일하게 느낄 것이다.
역행렬을 적용하는 순서는 이동 역변환이 먼저 적용되어야 한다.
- 카메라 회전을 적용할 시점에, 모든 좌표는 카메라를 중심으로 위치가 변환되어 있어야 하기 때문이다.
두 역행렬을 곱한 결과는 다음과 같다.
- 4열은 내적으로 표현했다.
현재 좌표계에서는 x축을 왼쪽에서 오른쪽을 향하도록 하기 위해 y축을 180° 회전해야 한다고 했다.
- x축, z축 기저를 반전시킨다.
최종 뷰 행렬 V는 다음과 같다.
책의 예제인 CK소프트렌더러에서 카메라 트랜스폼 정보로 뷰 행렬을 생성하는 부분이다.
// 책의 예제인 CK소프트렌더러에서 카메라 트랜스폼 정보로 뷰 행렬을 생성하는 부분
class CameraObject
{
public:
FORCEINLINE void GetViewAxes(Vector3& OutViewX, Vector3& OutViewY, Vector3& OutViewZ) const;
{
// 로컬 Z축 값의 반대 방향을 뷰 공간의 Z축으로 설정
OutViewZ = -_Transform.GetLocalZ();
OutViewY = _Transform.GetLocalY();
OutViewX = -_Transform.GetLocalX();
}
FORCEINLINE Matrix4x4 GetViewMatrix() const;
{
Vector3 viewX, viewY, viewZ;
GetViewAxes(viewX, viewY, viewZ);
Vector3 pos = _Transform.GetPosition();
return Matrix4x4(
Vector4(Vector3(viewX.X, viewY.X, viewZ.X), false),
Vector4(Vector3(viewX.Y, viewY.Y, viewZ.Y), false),
Vector4(Vector3(viewX.Z, viewY.Z, viewZ.Z), false),
Vector4(-viewX.Dot(pos), -viewY.Dot(pos), -viewZ.Dot(pos), 1.f)
);
}
}
'게임 수학 > 이득우의 게임 수학' 카테고리의 다른 글
오일러 각에서의 회전 보간 (0) | 2023.05.08 |
---|---|
짐벌 락(Gimbal Lock) (0) | 2023.05.07 |
오일러 각(Euler's angle) (0) | 2023.05.05 |
3차원 공간의 설계 (0) | 2023.05.04 |
카메라 시스템 (0) | 2023.05.03 |