Implementing a vector-based camera with FPS style input support
We will begin this chapter by designing a simple class to handle the camera. In a typical OpenGL application, the viewing operations are carried out to place a virtual object on screen. We leave the details of the transformations required in between to a typical graduate text on computer graphics like the one given in the See also section of this recipe. This recipe will focus on designing a simple and efficient camera class. We create a simple inheritance from a base class called CAbstractCamera. We will inherit two classes from this parent class, CFreeCamera and CTargetCamera, as shown in the following figure:
Getting ready
The code for this recipe is in the Chapter2/src directory. The CAbstractCamera class is defined in the AbstractCamera.[h/cpp] files.
We first declare the constructor/destructor pair. Next, the function for setting the projection for the camera is specified. Then some functions for updating the camera matrices based on rotation values are declared. Following these, the accessors and mutators are defined.
The class declaration is concluded with the view frustum culling-specific functions. Finally, the member fields are declared. The inheriting class needs to provide the implementation of one pure virtual function—Update (to recalculate the matrices and orientation vectors). The movement of the camera is based on three orientation vectors, namely, look, up, and right.
How to do it…
In a typical application, we will not use the CAbstractCamera class. Instead, we will use either the CFreeCamera class or the CTargetCamera class, as detailed in the following recipes. In this recipe, we will see how to handle input using the mouse and keyboard.
In order to handle the keyboard events, we perform the following processing in the idle callback function:
Check for the keyboard key press event.
If the W or S key is pressed, move the camera in the look vector direction:
If the rotate state is chosen, calculate the rotation amount (pitch and yaw). If mouse filtering is enabled, use the filtered mouse input, otherwise use the raw rotation amount:
It is always better to use filtered mouse input, which gives smoother movement. In the recipes, we use a simple average filter of the last 10 inputs weighted based on their temporal distance. So the previous input is given more weight and the 5th latest input is given less weight. The filtered result is used as shown in the following code snippet:
When using filtered mouse input, make sure that the history buffer is filled with the appropriate initial value; otherwise you will see a sudden jerk in the first few frames.