12장 유연한 카메라 클래스 만들기 한성대학교 멀티미디어공학과 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
목 표 비행 시뮬레이션이나 1인칭 시점의 게임에 적합한 유연한 Camera 클래스를 구현한다. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
[그림 12.2] 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
고정된 위치에서 뷰 스페이스 변환 행렬 D3DXMATRIX *D3DXMATRIXLookAtLH( D3DXMATRIX *pOut, //결과행렬을 받을 포인터 CONST D3DXVECTOR3 *pEye,//카메라 위치 CONST D3DXVECTOR3 *pAt,//카메라가 보는 지점 CONST D3DXVECTOR3 *pUp//up벡터-(0,1,0) }; *pEye<->위치벡터 p *pAt-*pEye <-> 전방벡터 d *pUp <->상향벡터 u 우향벡터 r은 d와 u로부터 유일하게 결정된다.(정규직교) 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
예) D3DXVECTOR3 position(5.0f,3.0f,10.0f); D3DXVECTOR3 targetPoint(0.0f,0.0f,0.0f); D3DXVECTOR3 worldUp(0.0f,1.0f,0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH (&V,&position,&targetPoint,&worldUp); Device->SetTransform(D3DTS_VIEW, &V); 원하는 일: 사용자가 키를 입력함에 따라 위의 data를 바꾼다->이에 따라 V도 바뀐다. ->불편하고 계산이 많음->이를 보완하기 위해 그림 12.1과 같은 데이터를 주고 이를 키에 따라 수정한다.->직관적으로 다양하게 데이터를 바꾸어 줄 수 있다.->바뀐 뷰행렬 V를 계산하기 쉽다. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.1 카메라 디자인 우향 벡터, 상향 벡터, 전방 벡터, 위치 벡터의 네 가지 카메라 벡터를 이용하여 월드 좌표 시스템에서의 카메라 위치와 방향을 정의.[그림 12.1] 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.1 카메라 디자인 Camera 클래스 선언 class Camera { public: enum CameraType { LANDOBJECT, AIRCRAFT }; Camera(); Camera(CameraType cameraType); ~Camera(); void strafe(float units); // left/right void fly(float units); // up/down void walk(float units); // forward/backward void pitch(float angle); // rotate on right vector void yaw(float angle); // rotate on up vector void roll(float angle); // rotate on look vector 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.1 카메라 디자인 //과제로 만들 함수 void mouse_motion(); //rotate up to mouse motion void getViewMatrix(D3DXMATRIX* V); void setCameraType(CameraType cameraType); void getPosition(D3DXVECTOR3* pos); void setPosition(D3DXVECTOR3* pos); void getRight(D3DXVECTOR3* right); void getUp(D3DXVECTOR3* up); void getLook(D3DXVECTOR3* look); private: CameraType _cameraType; D3DXVECTOR3 _right; D3DXVECTOR3 _up; D3DXVECTOR3 _look; D3DXVECTOR3 _pos; }; 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2 구현 방법 뷰 행렬 계산하기 위치 벡터 p = (px, py, pz) 우향 벡터 r = (rx, ry, rz) 상향 벡터 u = (ux, uy, uz) 전방 벡터 d = (dx, dy, dz) 계산을 쉽게 하기 위해 r,u,d는 서로 직교하는 단위벡터로 준다.(정규직교 기저) 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
따라서 변환 행렬 V로 다음과 같은 작업이 수행 됨. ▣ pV=(0, 0, 0) - 행렬 V는 카메라를 원점 이동. ▣ rV=(1, 0, 0) - 행렬 V는 우향 벡터를 월드 x-축과 정렬. ▣ uV=(0, 1, 0) - 행렬 V는 상향 벡터를 월드 y-축과 정렬. ▣ dV=(0, 0, 1) - 행렬 V는 전향 벡터를 월드 z-축과 정렬. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.1 파트 1: 이동 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.2 파트 2: 회전 우향, 상향, 전방 벡터를 각각 월드의 x-, y-, z-축과 정렬하는 3ⅹ3 행렬인 A가 필요. 행렬은 다음과 같은 세 개의 방정식 시스템을 만족. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.2 파트 2: 회전 BA=BB =I이므로 A는 B의 역 B는 직교 행렬이므로(행렬의 행 벡터가 정직교성 기저 벡터 이다) 역행렬이 또한 전치 행렬임. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.3 두 개의 파트를 조합하기 A를 4ⅹ4 행렬로 변환하고 이동 파트와 회전 파트를 결합하면 뷰 변환 행렬 V를 얻을 수 있다. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.3 두 개의 파트를 조합하기 void Camera::getViewMatrix(D3DXMATRIX* V) { // Keep camera's axes orthogonal to each other D3DXVec3Normalize(&_look, &_look); D3DXVec3Cross(&_up, &_look, &_right); D3DXVec3Normalize(&_up, &_up); D3DXVec3Cross(&_right, &_up, &_look); D3DXVec3Normalize(&_right, &_right); // Build the view matrix: float x = -D3DXVec3Dot(&_right, &_pos); float y = -D3DXVec3Dot(&_up, &_pos); float z = -D3DXVec3Dot(&_look, &_pos); 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.1.3 두 개의 파트를 조합하기 (*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f; (*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f; (*v)(2,0) =_right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f; (*V)(3,0) = x; (*V)(3, 1) = y; (*V)(3, 2) = z; (*V)(3, 3) = 1.0f; } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.2 임의의 축으로 회전하기 D3DXMATRIX *D3DXMatrixRotationAxis ( D3DXMATRIX *pOut, // 회전 행렬을 리턴한다. CONST D3DXVECTOR3 *pv, // 회전의 기준 축 FLOAT AngleArc // 라디안 단위의 회전할 각도 ) ; [그림 12.3] 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.2 임의의 축으로 회전하기 예를 들어, 벡터(0.707, 0.707, 0)로 정의 된 축을 기준으로 /2 라디안만큼 회전 시키고자 한다면.. D3DXMATRIX R; D3DXVECTOR3 axis(0.707f, 0.707f, 0.0f); D3DXMatrixRotationAxis(&R, &axis, D3DX_PI / 2.0f); 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.3- Pitch, Yaw, Roll 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.3-(1) Pitch void Camera::pitch(float angle) { D3DXMATRIX T; D3DXMatrixRotationAxis(&T, &_right, angle); // rotate _up and _look around _right vector D3DXVec3TransformCoord(&_up,&_up, &T); D3DXVec3TransformCoord(&_look,&_look, &T); } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.3-(2) Yaw void Camera::yaw(float angle) { D3DXMATRIX T; // rotate around world y (0, 1, 0) always for land object if( _cameraType == LANDOBJECT ) D3DXMatrixRotationY(&T, angle); // rotate around own up vector for aircraft if( _cameraType == AIRCRAFT ) D3DXMatrixRotationAxis(&T, &_up, angle); // rotate _right and _look around _up or y-axis D3DXVec3TransformCoord(&_right,&_right, &T); D3DXVec3TransformCoord(&_look,&_look, &T); } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.3-(3) Roll void Camera::roll(float angle) { // only roll for aircraft type if( _cameraType == AIRCRAFT ) D3DXMATRIX T; D3DXMatrixRotationAxis(&T, &_look, angle); // rotate _up and _right around _look vector D3DXVec3TransformCoord(&_right,&_right, &T); D3DXVec3TransformCoord(&_up,&_up, &T); } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.4 걷기, 옆걸음질, 날기 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.4(1) 걷기 void Camera::walk(float units) { // move only on xz plane for land object if( _cameraType == LANDOBJECT ) _pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units; if( _cameraType == AIRCRAFT ) _pos += _look * units; } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.4(2) 옆걸음질 void Camera::strafe(float units) { // move only on xz plane for land object if( _cameraType == LANDOBJECT ) _pos += D3DXVECTOR3(_right.x, 0.0f, _right.z) * units; if( _cameraType == AIRCRAFT ) _pos += _right * units; } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.2.4(3) 날기 void Camera::fly(float units) { // move only on y-axis for land object if( _cameraType == LANDOBJECT ) _pos.y += units; if( _cameraType == AIRCRAFT ) _pos += _up * units; } 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.3 예제 애플리케이션: 카메라 ▣ W/S – 전진/후진 ▣ A/D – 왼쪽/오른쪽 옆걸음질 ▣ R/F – 위/아래 날기 ▣ 위/아래 화살표 키 – Pitch ▣ 왼쪽/오른쪽 화살표 키 – Yew ▣ N/M - Roll 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.3 예제 애플리케이션: 카메라 bool Display(float timeDelta) { if( Device ) // Update: Update the camera. if( ::GetAsyncKeyState('W') & 0x8000f ) TheCamera.walk(4.0f * timeDelta); if( ::GetAsyncKeyState('S') & 0x8000f ) TheCamera.walk(-4.0f * timeDelta); if( ::GetAsyncKeyState('A') & 0x8000f ) TheCamera.strafe(-4.0f * timeDelta); if( ::GetAsyncKeyState('D') & 0x8000f ) TheCamera.strafe(4.0f * timeDelta); 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.3 예제 애플리케이션: 카메라 if( ::GetAsyncKeyState('R') & 0x8000f ) TheCamera.fly(4.0f * timeDelta); if( ::GetAsyncKeyState('F') & 0x8000f ) TheCamera.fly(-4.0f * timeDelta); if( ::GetAsyncKeyState(VK_UP) & 0x8000f ) TheCamera.pitch(1.0f * timeDelta); if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f ) TheCamera.pitch(-1.0f * timeDelta); if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f ) TheCamera.yaw(-1.0f * timeDelta); if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f ) TheCamera.yaw(1.0f * timeDelta); 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.3 예제 애플리케이션: 카메라 if( ::GetAsyncKeyState('N') & 0x8000f ) TheCamera.roll(1.0f * timeDelta); if( ::GetAsyncKeyState('M') & 0x8000f ) TheCamera.roll(-1.0f * timeDelta); // Update the view matrix representing the cameras // new position/orientation. D3DXMATRIX V; TheCamera.getViewMatrix(&V); Device->SetTransform(D3DTS_VIEW, &V); 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
12.3 예제 애플리케이션: 카메라 // Render Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); Device->BeginScene(); d3d::DrawBasicScene(Device, 1.0f); Device->EndScene(); Device->Present(0, 0, 0, 0); } return true; 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
과제 (1)마우스를 움직임에 따라 적절하게 화면을 움직이게 하시오. 즉 화면의 중앙에서 마우스가 가로로 움직인 만큼 비례하여 가로로 회전하고 세로로 움직인 만큼 비례하여 세로 방향으로 회전하는 함수 mouse_motion을 구현하시오. 다음을 참고하시오. POINT mousePos; GetCursorPos(&mousePos); SetCursorPos(화면의 가운데를 주도록); 화면의 가운데와 mousePos의 차를 적당한 상수로 나누어 준 후 (약 500에서 1000정도)…. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과
(2) 총의 표적이 총을 움직임에 따라 움직이듯이 키의 입력에 따라 카메라에 대한 데이터가 바뀜에 따라 카메라 앞에 일정한 거리에 작은 공이 그려지도록 하라. 게임 프로그래밍-I 강의노트 © 2006 한성대학교 멀티미디어공학과