Ogre 3D 1.7 Beginner's Guide
上QQ阅读APP看书,第一时间看更新

Time for action — making the camera work again

We have already created our camera; now we are going to use it in combination with user input as follows:

  1. Extend the constructor of the Framelistener to get a pointer to our camera:
    Example30FrameListener(Ogre::SceneNode* node,RenderWindow* win,Ogre::Camera* cam)
    
  2. Also add a member variable for storing the camera pointer:
    Ogre::Camera* _Cam;
    
  3. Then assign the parameter to the member:
    _Cam = cam;
    
  4. Modify the instantiation of the FrameListener to add the camera pointer:
    Ogre::FrameListener* FrameListener = new Example30FrameListener(_SinbadNode,mWindow,mCamera);
    
  5. To move the camera, we need to get mouse input. So create a new member variable for storing the mouse:
    OIS::Mouse* _mouse;
    
  6. In the constructor, init the mouse after the keyboard:
    _mouse = static_cast<OIS::Mouse*>(_man->createInputObject( OIS::OISMouse, false ));
    
  7. Now as we have the mouse, we also need to capture the mouse state as we did with the keyboard. Add this line after the call for capturing the keyboard state:
    _mouse->capture();
    
  8. Remove the line to translate the node:
    _node->translate(translate*evt.timeSinceLastFrame * _movementspeed);
    
  9. After processing the keyboard state in the frameStarted() method, add the following code to process the mouse state:
    float rotX = _mouse->getMouseState().X.rel * evt.timeSinceLastFrame* -1;
    float rotY = _mouse->getMouseState().Y.rel * evt.timeSinceLastFrame * -1;
    
  10. Now apply the rotations and the translation to the camera:
    _Cam->yaw(Ogre::Radian(rotX));
    _Cam->pitch(Ogre::Radian(rotY));
    _Cam->moveRelative(translate*evt.timeSinceLastFrame * _movementspeed);
    
  11. We created a mouse object, so we need to destroy it in the destructor of the FrameListener:
    _man->destroyInputObject(_mouse);
    
  12. Compile and run the application. You should be able to navigate the scene, just like we did previously.
    Time for action — making the camera work again

What just happened?

We used our created camera in combination with user input. To be able to manipulate the camera, we needed to pass it to our FrameListener. This was done in steps 1 and 2 using the constructor. To control our camera, we wanted to use the mouse. So first we had to create a mouse interface to use. This was done in step 6, in the same way we used to create a keyboard. In step 7, we called the capture() function of our new mouse interface to update the mouse state.

Mouse state

Querying the keyboard state was done using the isKeyDown() function. To get the mouse state, we used the getMouseState() function. This function returns a mouse state struct as an instance of the MouseState class, which contains information about the button state, whether they are pressed or not, and how the mouse moved since the last capture call. We want the movement information to calculate how much our camera needs to be rotated. Mouse movement can happen on two axes, namely, the x-axis and the y-axis. Both axes' movements are saved separately in the X and Y variable of the mouse state. We then have the possibility to get the relative or absolute values. Because we are only interested in mouse movement and not the position of the mouse, we are using the relative values. The absolute values contain the position of the mouse on the screen. These are needed when we want to test if the mouse has clicked into a certain area of our application. For camera rotation, we only need the mouse movement, so we use the relative values. The relative value only indicates whether the speed and direction of the mouse has moved, but not the number of pixels.

These values are then multiplied by the time since the last frame and by -1. -1 is used because we get the movement in a different direction to which we want the camera to rotate. So we simply invert the movement direction. After calculating the rotation values, we apply them to the camera with the yaw() and pitch() functions. The last thing to do is to apply the translation vector we created from the keyboard input to the camera. For this, we use the moveRelative() function of the camera. This function translates the camera in the local space without considering the rotation of the camera. This is useful, because we know that in local space (0,0,-1) moves the camera forward. With rotations applied to the camera, this isn't necessarily true. Refer to the chapter about the different spaces in 3D space for a more detailed explanation.

Pop quiz — capturing the input

Why do we call the capture() method for the mouse and keyboard?

Have a go hero — playing with the example

Try removing the -1 from the rotation calculation and see how this changes the camera controls.

Try removing the capture() function calls and see what impact this has.