1. 3D Direct Application
1.1 Camera
1.1.1 View Space
- 시야 공간은 카메라에 부착된 좌표계, 카메라는 이 좌표계의 원점에 위치해 z축을 바라봄
- 세계 공간에서 시야 공간으로의 좌표 변경 변환을 시야 변환, 해당 변환 행렬을 시야 행렬이라 부름
- 세계 공간에서 시야 공간으로부터 변환 행렬을 수행하려면 역행렬을 통해 변환 행렬을 구함
- 실제 물체를 이동하는것이 아닌 기준계가 세계 공간 좌표계에서 카메라 공간 좌표계로 변경
1.1.2 Cemera System
- 카메라 클래스를 생성하여 중요한 두 종류의 정보를 저장
- 카메라 좌표계를 규정하는 속성, 세계공간에서 시야 공간 좌표계의 해당하는 벡터
- 카메라 렌즈에 비유할 수 있는 시야 절두체를 규정하는 속성, 시야각과 가까운 평면, 먼 평면 거리
class Camera
1.1.2.1 Projection Space Matrix
void Camera::SetLens(float fovY, float aspect, float zn, float zf);
- 시야 절두체는 시야를 제어한다는 점에서 카메라의 렌즈에 해당
- 절두체 속성들을 설정하고 투영 행렬도 생성
XMMATRIX P = ::XMMatrixPerspectiveFovLH(_fovY, _aspect, _nearZ, _farZ);
::XMStoreFloat4x4(&_proj, P);
1.1.2.2 Camera Transform
void Camera::Walk(float d);
- 카메라를 시선 벡터를 따라 앞, 뒤로 움직이는 함수 생성, 카메라의 위치를 시선 벡터에 따라 이동시켜 구현
- 현재 카메라의 앞 벡터, 즉 Look Vector와 움직이는 방향에 대해 곱한 후 카메라의 위치를 더함
- 위에서 곱할 때 Look Vector는 카메라의 앞방향만 알고 있으므로 나머지 요소는 삭제
- 삭제된 이후 카메라의 위치에서 더하게 된다면 앞으로 가거나 뒤로 갈 벡터를 생성함
XMVECTOR s = ::XMVectorReplicate(d);
XMVECTOR l = ::XMLoadFloat3(&_look); XMVECTOR p = ::XMLoadFloat3(&_position);
::XMStoreFloat3(&_position, ::XMVectorMultiplyAdd(s, l, p));
void Camera::Strafe(float d);
- 카메라를 오른쪽 벡터에 따라 좌, 우로 움직이는 함수 생성, 카메라의 위치를 오른쪽 벡터에 따라 이동시켜 구현
- 위와 비슷하게 오른쪽으로 이동하는 벡터, Right Vector를 사용하여 곱하고 카메라의 위치에 더함
XMVECTOR s = ::XMVectorReplicate(d);
XMVECTOR r = ::XMLoadFloat3(&_right); XMVECTOR p = ::XMLoadFloat3(&_position);
::XMStoreFloat3(&_position, XMVectorMultiplyAdd(s, r, p));
void Camera::Pitch(float angle);
- 위, 아래를 훑어볼 수 있도록 카메라를 오른쪽 벡터에 대해 회전
- 카메라의 Look Vector와 Up Vector를 이용하여 카메라 Right Vector 중심으로 회전함으로써 구현
- Right Vector에 대한 축을 통해 Angle만큼 회전하는 행렬 생성
- 회전 행렬을 통해 Up, Look Vector를 곱하여 위, 아래로 훑어볼 수 있도록 설정
XMMATRIX R = ::XMMatrixRotationAxis(::XMLoadFloat3(&_right), angle);
::XMStoreFloat3(&_up, ::XMVector3TransformNormal(XMLoadFloat3(&_up), R));
::XMStoreFloat3(&_look, ::XMVector3TransformNormal(XMLoadFloat3(&_look), R));
void Camera::RotateY(float angle);
- 좌, 우를 훑어볼 수 있도록 카메라를 세계 공간의 Up Vector에 대해 회전
- 세계 공간으로 부터 Angle만큼 회전하는 행렬 생성 후 위와 같이 모든 값으로 부터 곱하여 설정
XMMATRIX R = XMMatrixRotationY(angle);
::XMStoreFloat3(&_right, ::XMVector3TransformNormal(::XMLoadFloat3(&_right), R));
::XMStoreFloat3(&_up, ::XMVector3TransformNormal(::XMLoadFloat3(&_up), R));
::XMStoreFloat3(&_look, ::XMVector3TransformNormal(::XMLoadFloat3(&_look), R));
1.1.2.3 Update View Matrix
void Camera::UpdateViewMatrix();
- 카메라의 Up, Right, Look Vector를 다시 정규 직교화, 모두 서로 직교인 단위벡터들로 생성
- 회전이 여러 번 반복되면 수치 오차가 누적되어 벡터들이 정규직교벡터가 아닐 수 있음
- 정규직교가 아닐 경우 카메라 좌표계는 직교 좌표계가 아닌 특정방향으로 기울어진 좌표계가 되어 문제 발생
- 카메라의 Up, Right, Look, Position Vector를 받아 새 변수로 적용하여 설정
XMVECTOR R = ::XMLoadFloat3(&_right); XMVECTOR U = ::XMLoadFloat3(&_up);
XMVECTOR L = ::XMLoadFloat3(&_look); XMVECTOR P = ::XMLoadFloat3(&_position);
- Look Vector를 단위 벡터, 즉 정규화를 사용하여 Right Vector와 외적을 하면 직교 상태인 Up Vector를 구할 수 있음
L = ::XMVector3Normalize(L); U = ::XMVector3Normalize(::XMVector3Cross(L, R));
- 이 후 Up Vector와 Look Vector를 외적한다면 직교 상태인 Right Vector를 생성할 수 있음\
R = ::XMVector3Cross(U, L);
- 카메라의 위치를 통해 벡터를 생성할 수 있는데 나머지 적용하는 부분은 생략
::XMStoreFloat3(&_right, R); ::XMStoreFloat3(&_up, U); ::XMStoreFloat3(&_look, L);
1.1.3 C++ 응용프로그램
1.1.3.1 Camera
- 응용 프로그램에서 카메라 시스템에 관한 변수를 클래스를 통해 사용하였기에 모든 카메라에 대한 변수 제거
- 이후 카메라의 변수를 생성하여 적용
Camera _camera;
1.1.3.2 Resize
- 응용 프로그램의 창을 변경할 때 투영 행렬을 갱신하는 작업을 카메라의 함수를 통해 적용
_camera.SetLens(0.25f * MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
1.1.3.3 Update Scene & Draw Scene
- 카메라의 위치를 이동할 때 카메라의 함수를 적용하여 이동
if (::GetAsyncKeyState('W') & 0x8000) _camera.Walk(10.0f * dt);
if (::GetAsyncKeyState('S') & 0x8000) _camera.Walk(-10.0f * dt);
if (::GetAsyncKeyState('A') & 0x8000) _camera.Strafe(-10.0f * dt);
if (::GetAsyncKeyState('D') & 0x8000) _camera.Strafe(10.0f * dt);
- 장면을 렌더링할 때 카메라의 변수를 받아 적용하고 사용하고 카메라의 벡터들을 직교 상태로 적용
_camera.UpdateViewMatrix();
XMMATRIX view = _camera.View(); XMMATRIX proj = _camera.Proj();
XMMATRIX viewProj = _camera.ViewProj();
1.1.3.4 Mouse Move
- 마우스가 이동하고 클릭이 입력되었을 때 시선 방향을 변경
if ((btnState & MK_LBUTTON) != 0)
{
float dx = XMConvertToRadians(0.25f * static_cast<float>(x - _lastMousePos.x));
float dy = XMConvertToRadians(0.25f * static_cast<float>(y - _lastMousePos.y));
_camera.Pitch(dy); _camera.RotateY(dx);
}
_lastMousePos.x = x; _lastMousePos.y = y;
'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글
[Direct11] 34. 3D Direct Application - Picking System (0) | 2023.06.27 |
---|---|
[Direct11] 33. 3D Direct Application - Instancing & Culling (0) | 2023.06.26 |
[Direct11] 31. EX App Program - Quad Tesselation (0) | 2023.06.22 |
[Direct11] 30. Direct3D Tesselation (0) | 2023.06.22 |
[Direct11] 29. EX App Program - Blur System (0) | 2023.06.21 |