-
DXUT Framework에서 카메라 설치하기정리필요2 2008. 7. 2. 18:59
DXUT Framework에서 카메라 설치하기3D 프로그래밍을 입문하면서 처음에 제일 골아픈 것이 바로 카메라입니다. DXUT는 기본으로 제공하는 카메라가 있으며, 작은 설정으로 그럴듯한 카메라를 이용할 수 있게 해 줍니다. CFirstPersonCamera와 CModelViewerCamera의 두 가지를 제공합니다만, 여기서는 먼저 CModelViewerCamera의 설치법만을 소개합니다. CModelViewerCamera는 마우스 드래그를 통해 해당 위치 주위를 선회하는 카메라를 구현합니다.
-
CModelViewerCamera를 모든 Callback 함수가 접근할 수 있는 위치에 지정합니다.
이 예제에서는 전역에 선언하도록 하겠습니다.
CModelViewerCamera g_Camera;
-
OnCreateDevice에 카메라를 설치합니다.
이 카메라 객체는 단순히 계산만 해주는 객체입니다. 따라서 IDirect3DDevice를 이용하지 않기에 OnCreateDevice에서 초기화합니다.
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { ... D3DXVECTOR3 vEye = D3DXVECTOR3( 0.0f, 0.0f, -5.0f ); D3DXVECTOR3 vLookAt = D3DXVECTOR3( 0.0f, 0.0f, -0.0f ); g_Camera.SetViewParams( &vEye, &vLookAt ); ... }
vEye는 카메라의 위치이고 vLookAt은 물체의 위치입니다. 이 카메라는 마우스 드래그를 통해 카메라의 위치만을 변경하고 항상 현재 설정한 물체의 위치를 바라봅니다.
-
MsgProc에서 입력을 받아 FrameMove에서 카메라의 위치를 계산합니다.
MsgProc에서 입력을 알맞은 카메라 행동으로 바꾸어주고, 실제 계산은 FrameMove에서 하게 됩니다.
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ) { ... g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); ... } void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) { ... g_Camera.FrameMove( fElapsedTime ); ... }
-
FrameRender에서 계산된 행렬을 적용합니다.
카메라는 IDirect3DDevice를 직접 지닌 것이 아니라 사용자가 직접 계산결과를 적용해주는 것이 필요합니다.
내용추가 :
Projection은 OnResetDevice 때마다, World, View는 FrameMove떄마다 호출해도 됩니다. Projection은 Aspect Ratio, 즉 스크린의 가로세로비가 바뀔 때만 그 행렬이 달라지게 되고, World, View는 카메라의 위치 혹은 방향이 바뀌지 않는 한 변경되지 않기 떄문입니다.
참고로 카메라의 정보를 설정하는 내용도 OnResetDevice에 추가하였습니다.
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { ... // Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f ); g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); V( pd3dDevice->SetTransform( D3DTS_PROJECTION, g_Camera.GetProjMatrix() ) ); ... } void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice,
double fTime, float fElapsedTime, void* pUserContext ) { ... V( pd3dDevice->SetTransform( D3DTS_WORLD, g_Camera.GetWorldMatrix() ) ); V( pd3dDevice->SetTransform( D3DTS_VIEW, g_Camera.GetViewMatrix() ) ); ... }각각의 물체에 대해 세계 좌표를 부여하였다면, 카메라의 WorldMatrix에 각 물체의 WorldMatrix를 곱해주어야 합니다. 단 카메라의 WorldMatrix가 먼저 적용되어야 하므로 뒤에 곱해주어야 합니다. 즉, 카메라의 WorldMatrix를 Mw, 물체의 WorldMatrix를 Mo라고 할 때, WorldMatrix = Mo * Mw이 되어야 합니다. 물체를 원점에 배치했다면 위의 예제대로만 하여도 무리없이 나옵니다.
조금 많기는 합니다만 자원 획득 및 파괴를 제외하면 계산 및 적용만 호출해주면 되는 셈입니다. 3D Programming에 입문하면서 제일 어려운 내용이 카메라였는데, 그런 면에서 DXUT로 입문하면 이런 구현된 모듈이 있다는 것이 편한 듯 합니다. ( 문서가 적은게 흠입니다. )
이 글은 DXUT Framework의 이용에 초점을 맞추었으므로, 따로 VertexBuffer나 IndexBuffer의 이용법에 대해서는 적지 않았습니다. 위의 내용은 책에도 많고 문서에도 많으니 잘 찾아서 적용해보세요. 기왕 이렇게 시작한 스터디 잘 따라노셔서 끝까지 갈 수 있었으면 좋겠습니다.
출처 : http://digitz.tistory.com/tag/DirectX -