The previous implementation of this engine was based on a static, zero-based camera. In other words, the camera was assumed to be located at <0,0,0> with a static view frustum heading forward, along the positive z-axis.
Whenever movement was required, all of the vertices within the scene had to be translated or rotated, relative to <0,0,0>. Since I planned to start exploring the use of scenes with a high polygon count this approach would quickly become impractical from a performance standpoint.
I knew this was going to be a constraint when I put together the first iteration, but at the time having all of the vertices in 'camera space' ready to be rendered simplified the mathematics somewhat.
There are two fundamental changes with the new version, they are:-
Dynamic camera - The camera class now describes a location, orientation and viewing direction. The advantage is that movement around the world simply requires the re-positioning or rotation of the camera.
The render pipeline requires an additional step to transform all of the required vertices to camera space, but only once we have dropped all of the vertices that don't need to be drawn via clipping.
This is far cheaper (in terms of processing required) than transforming every scene vertex each time a movement is requested.
Quaternion rotation - All rotations, for camera and world, are performed using quaternions. A quaternion class provides constructors based on vector/deg, Euler angles (yaw,pitch,roll) or an existing quaternion.
This class also includes a method to extract a 3x3 rotation matrix for the quaternion. The camera object utilises this, storing the rotation matrix for the inverse of its own viewing direction quaternion, which can later be used for the 'world to camera' transformation.
Let's finish of with a demo just to check that everything is as it should be! Use the cursor keys to move, 'a'/'z' to tilt the camera and 'q' to jump.