Adding a camera to my terrain came pretty quickly after I generated my terrain, but it took me a while to iron out all the bugs. I also feel like I went at the problem in kind of a strange way, but I’ll get to that later. My cameras controls use WASD for advancing and strafing and the arrow keys for looking around (left-right for Yaw and up-down for Pitch). The only one of these that gave me trouble was Pitch. I figured out how to rotate the to vector in order to get the pitch effect pretty quickly, but after implementing it originally there was an issue where the view would spin (kind of a roll effect) if you yawed after pitching. I eventually realized I needed to rotate the up vector as well, and the rest of the camera’s control followed from there.
After I had the camera’s basic controls working I started adding height changes to my camera’s movement. The way I decided to do this was to create a 2D grid (like with feature 2 I used a vector of vectors for this) with the heights at each vertex. I read these heights in from the obj file that is generating the terrain, so for any terrain obj that is entered the heights will be correct. The algorithm assumes the height is the y coordinate of the terrain, and uses the x and z coordinates to find the spot in the grid at which to add the height.
The grid of heights is then passed to the camera, which stores it as an instance variable. I added 3 new methods–2 for strafing and advancing with height and another called GetNewHeight(). The movement functions both call GetNewHeight, which finds the height at the current position. The current position used is the x and z coordinates of from. The movement functions then set the y value of from to the new height.
I also had to decide what to do if the camera moved off of the terrain. I decided to keep the height constant at whatever it was at when the camera was last over the terrain. Then when the camera moves back over the terrain it will “jump” up or down to the correct height for the location on the terrain. This allows for some funky movement if someone pitches while off the terrain, but once they are back over the terrain their height will be readjusted accordingly. I decided this wasn’t a big deal since the camera should never leave the terrain anyway.
Applying this technique worked to move around, but the movement was very rough. Also, if the camera was at a spot where the height was changing very quickly, the camera would look into the terrain. The reason for this was that I was rounding the current x and z positions to integers and then searching for the height. This means that To fix this I decided to use linear interpolation. I applied the following algorithm, which I found on the wikipedia page for bilinear interpolation.
The algorithm looks complicated, but it really isn’t. The first 8 lines simply find the x, y, and z values that will be used in the algorithm. When using interpolation I ran into issues at my borders, so the min/max calls make sure the x and z are inside of the grid and don’t cause an out of bounds exception.
There is an issue with the way I set up my camera class, which is that the camera class does a lot of things typically not associated with a camera. I probably should have made a separate “Terrain” class that would store the array of heights, but I didn’t think this was too necessary. If I want to use my camera without the heights of the grid, I can still do so.
Lastly, here is a video of me walking around on my terrain: