This time, I gave my camera the ability to walk around the map with its height varying with the height of the land. The first thing I did was create a class called Heightmap, which held a width, a height, and a 2D array of floats (heights). Then, I made a couple of new methods called StrafeOnGround and ForwardOnGround in the camera class that did all of the same stuff, but replaced the heights of the to and from vectors with new heights generated by a QueryHeight method in the Heightmap class. I did keep my original methods for strafing and moving around, in case I decided to allow the player to switch between a free-movement view and a grounded view, and because of this, some of my code was structured a bit differently.
In order to smooth out my movements, I used bi linear interpolation (idea courtesy of Corey Schulz, equation courtesy of Wikipedia). However, I had to be careful as to how large I made the box around my current position, because sometimes the interpolation would place me inside of a bump or hill if it was steep enough. That was a pretty simple issue to work out. I’ll also note that I had to change my pitch and yaw functions to rotate my up vector as well as my to vector. Otherwise, my camera’s rotation would do all sorts of crazy things. Once again, Corey Schulz gets credit for the idea.
Next, I had to decide how to handle a player who decides it is a good idea to step off the map. I wanted to have some fun with this, so what I did was to set a Boolean variable in my ProjectRenderer.cpp class that, when true, would disable all manual movement of the camera by the player and initiate an animation, handled by the OnDraw method. The variable would be set to true whenever the camera comes within a few pixels of the edge of the map. The animation basically moves the camera back to the center of the map, rotating the camera wildly all the while. It has to save its current rotated state, look towards the center, move forward, and then revert to the saved state and continue to rotate. The reason that it has to be this complicated is that we want the camera to stay above the ground, even as it is being tossed, so we would like to move it towards the center using the ForwardOnGround method. However, in order to get a continuous rotation, you have to save your rotated to and up directions, so that they aren’t lost when you look at the center and advance. It’s supposed to look as if you have been tossed back by some invisible force. Here is the function that I used to do the tossing, and remember that it gets called over and over again from OnDraw to get the full effect.
The last thing that I did was to allow multiple key presses at once, which I did by passing an array of key states from glut_utilities back to the renderer each time OnDraw was called. The renderer would then read the array and apply the functions assigned to every key with a value of true simultaneously. None of the other key functions actually passed anything to the Project Renderer, but instead changed the states of individual keys in the array that was stored in glut_utilities. I had to use glutSpecialUpFunc() and glutKeyboardUpFunc() in conjunction with the ones we were already using to change the states back to false after the keys were released, and I had to use glutIgnoreKeyRepeat(1) to prevent the program from registering constant key_up and key_down functions when the user holds down a key.
Here is a link to the youtube video that I posted: