1 / 39

Creating a Flexible Camera Class

Creating a Flexible Camera Class. Bryan Duggan. Refresher on Vectors. u.v = (u x v x + u y v y + u z v z ) p = u x v = (u y v z - u z v y , u z v x - u x v z, u x v y - u y v x ). Identity Matrix. Identity Matrix.

pia
Télécharger la présentation

Creating a Flexible Camera Class

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Creating a Flexible Camera Class Bryan Duggan

  2. Refresher on Vectors • u.v = (ux vx + uy vy + uz vz) • p = u x v = (uy vz - uz vy, uz vx - ux vz, ux vy - uy vx)

  3. Identity Matrix • Identity Matrix • The identity matrix has the property that if A is a square matrix, then

  4. Local Space • The co-ordinate system we define the objects triangle list • Build all models around their own co-ordinates • Construct models without regard to position and orientation

  5. World Space • World Transform brings • Objects into the world • Sets up the relationship between objects in the scene • Translations rotations and scaling • May be a different transform for each object in the scene • Use: • IDirect3DDevice::SetTransform(D3DTS_WORLD, &matrix);

  6. View Space • View Space transform: • Translates the camera to the origin, looking down the positive Z-Axis • We don’t need to calculate it!! DirectX has an API to do this: • D3DXMatrixLookAtLH( D3DXMATRIX * pOut , D3DXVECTOR3 * eye , D3DXVECTOR3 * at , D3DXVECTOR3 * up) • Up is usually (0,1,0) • Use: • IDirect3DDevice::SetTransform(D3DTS_VIEW, &matrix);

  7. Backface culling • All polygons have 2 sides. A front (visible) side • And a back (invisible) side • DirectX can cull the backfaces to reduce processing • Triangles with vertices specified in a clockwise winding order are considered front facing • Use: _ device->SetRenderState(D3DRS_CULLMODE, value) Where value is: • D3DCULL_NONE • D3DCULL_CW • D3DCULL-CCW

  8. Projection • Transforming a 3D Scene to a 2D one • Uses perspective projection • Far away objects are smaller • Defines our frustum

  9. The projection matrix • Is complex to derive, but directX has an API to do it: D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.5f, // 90 - degree (float)_width / (float)_height, 1.0f, 1000.0f); _device->SetTransform(D3DTS_PROJECTION, &proj);

  10. The Viewport transform • We can optionally transform to a viewport in the display window: typedef struct _D3DVIEWPORT9  { DWORD X; DWORD Y; DWORD Width; DWORD Height; float MinZ; float MaxZ; } D3DVIEWPORT9; We set the viewport using: _device->SetViewport(&vp)

  11. FPS Camera • In an FPS, the camera may need to: • walk forwards and backwards (W, S keys) • strafe left and right (A, D keys) • fly/jump (space key?) • Look around (the mouse) • Pitch (look up and down) • Yaw (Look left and right) • Roll (tilt left and right)

  12. A static camera can be programmed by… // Position and aim the camera. D3DXVECTOR3 position(-50.0f, 5.0f, -50.0f); D3DXVECTOR3 target(0.0f, 5.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &position, &target, &up); device->SetTransform(D3DTS_VIEW, &V);

  13. This is ok for • A fixed camera position, but not very flexible when we want to have a moving camera as most games

  14. So lets create our own! • To model a camera we require 4 vectors: • _position • _look • _right • _up Must always be mutually orthogonal (perpendicular) to each other _up _look _right _position

  15. Movement • To walk: • Position changes in units of the look vector • Making sure we don’t change the Y value!! (A person can look at the ground, but we don’t want to go in that direction) • To strafe: • Position changes in units of the right vector • To jump: • Position changes in the y direction • To look around: • On the X-Axis, we rotate around the y-axis (Yaw) • Rotate _right and _look • Up and down, we rotate on the _right vector (pitch) • Rotate _up and _look

  16. walk: void MoveableEntity::walk(float units) { D3DXVECTOR3 newPos; newPos = _pos + D3DXVECTOR3(_look.x, 0.0f, _look.z) * units; BoundableEntity * boundableEntity = _world->collidesWith(&newPos); if ((!_collisionDetection) || (boundableEntity == NULL) || (boundableEntity == this)) { _moved = true; _pos = newPos; } }

  17. strafe void MoveableEntity::strafe(float units) { D3DXVECTOR3 newPos; newPos = _pos + D3DXVECTOR3(_right.x, 0.0f, _right.z) * units; BoundableEntity * boundableEntity = _world->collidesWith(&newPos); if ( (!_collisionDetection) || (boundableEntity == NULL) || (boundableEntity == this)) { _moved = true; _pos = newPos; } }

  18. yaw void MoveableEntity::yaw(float angle) { D3DXMATRIX T; D3DXMatrixRotationY(&T, angle); // rotate _right and _look around _up or y-axis D3DXVec3TransformCoord(&_right,&_right, &T); D3DXVec3TransformCoord(&_look,&_look, &T); _moved = true; }

  19. pitch void MoveableEntity::pitch(float angle) { D3DXMATRIX T; D3DXMatrixRotationAxis(&T, &_right, angle); // rotate _up and _look around _right vector D3DXVec3TransformCoord(&_up,&_up, &T); D3DXVec3TransformCoord(&_look,&_look, &T); _moved = true; }

  20. View Matrix • At some point, we need to make a view transform matrix • The view transform does 3 things: • Makes the camera 0, 0, 0. Everything in the world needs to be translated by the same amount • Makes the camera looks down the positive Z axis

  21. So we need to… • Translate • Translate the camera to the origin (and everything else by the same amount) • Rotate • Align the right vector with the x-axis (and everything else by the same amount) • Align the up vector with the y-axis (and everything else by the same amount) • Align the look vector with the z-axis (and everything else by the same amount) • Our new view matrix combines those operations (multiplies the 4 matrices to generate a combined transformation)

  22. Calculate the translation bit • To translate by -px, -py, -pz, we multiply by:

  23. Calculate the rotation matrix Rotate the right vector so that it aligns with the x-axis Rotate the up vector so that it aligns with the y-axis Rotate the look vector so that it aligns with the z-axis

  24. Solve for the matrix A • Since A is the same in all 3 transformations, we can write them together:

  25. Solve for Matrix A • A is the inverse of B because: • BA = BB-1 = I • You get the inverse of a matrix by switching the rows and columns:

  26. Combine the 2 matrices

  27. In code: // Build the view matrix: float x = -D3DXVec3Dot(&_right, &_pos); float y = -D3DXVec3Dot(&_up, &_pos); float z = -D3DXVec3Dot(&_look, &_pos); (_viewMatrix)(0,0) = _right.x; (_viewMatrix)(0, 1) = _up.x; (_viewMatrix)(0, 2) = _look.x; (_viewMatrix)(0, 3) = 0.0f; (_viewMatrix)(1,0) = _right.y; (_viewMatrix)(1, 1) = _up.y; (_viewMatrix)(1, 2) = _look.y; (_viewMatrix)(1, 3) = 0.0f; (_viewMatrix)(2,0) = _right.z; (_viewMatrix)(2, 1) = _up.z; (_viewMatrix)(2, 2) = _look.z; (_viewMatrix)(2, 3) = 0.0f; (_viewMatrix)(3,0) = x; (_viewMatrix)(3, 1) = y; (_viewMatrix)(3, 2) = z; (_viewMatrix)(3, 3) = 1.0f;

  28. Mouse look • The aim • When the player moves the mouse left and right, we yaw • When the player moves the mouse up and down, we pitch • By how much is determined by the delta between the last mouse position and the current mouse position

  29. Mouse look algorithm handleEvent() { If (event == MOUSE_MOVEMENT) { midX = width / 2 midY = height / 2 deltaX = currentX – midX deltaY = currentY – midY yaw(deltaY * modifier_heuristic) roll(deltaX * modifier_heuristic) set_cursor(midX, midY) } }

  30. To trap mouse events • Windows calls the WinProc (the handler we registered to receive notifications of events • The framework calls: • handleEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) • When a mouse movement has occurred, we receive WM_MOUSEMOVE as the msg parameter

  31. Firstly some Win32 API code to turn off the mouse case WM_SETCURSOR: // Turn off window cursor SetCursor(NULL); _device->ShowCursor(TRUE); return TRUE; // prevent Windows from setting cursor to window class cursor break;

  32. Now to capture the mouse: case WM_MOUSEMOVE: midX = _width / 2; midY = _height / 2; POINT p; GetCursorPos(&p); xPos = p.x; yPos = p.y; if ((xPos == midX) && (yPos == midY)) { break; } deltaX = xPos - midX; deltaY = yPos - midY; _camera->yaw(((float)deltaX) / 100.0f); _camera->pitch(((float)deltaY) / 100.0f); SetCursorPos(midX, midY); break;

  33. RTS Camera • Camera position is over the world • Enable the mouse cursor • When the cursor moves to the extremes of the window: • Pan left & right • Move the position in units of the right vector • Without affecting the Y • Forward & backwards • Move the position in units of the look vector • Without affecting the Y

  34. Extra operations • Zoom in and out by using the scroll wheel? • Free Rotate by holding down the ALT key?

  35. Some important Win32 Calls! • _device->ShowCursor(TRUE); • Turns on the cursor • GetWindowRect • To get the window size • ClipCursor • To keep the cursor within certain screen coordinates • GET_X_LPARAM(lParam); • GET_Y_LPARAM(lParam); • To get the X and Y of the cursor

  36. Picking • If we enable the mouse, we need to know when the user clicks something, what it is • We need to translate from a screen position (x, y) to an (x, y, z) in our world

More Related