Thursday, October 28, 2010

Project 1 - Moving the camera

So, I have a working terrain, but the camera is fixed. I want to change that. Being able to see it from different angles without having to change the code and recompile would be handy.

I've mentioned a few times that OpenGL is kind of strange about how moving around the world works. Since I'm going to be talking about the camera now, it seems a good moment to delve into that. The first thing that should be explained I guess is that OpenGL doesn't have a camera. It has a viewport. The viewport never moves, in the sense that the absolute origin of OpenGL's coordinate system is always the middle of the viewport.

Instead, in order to have different views, we have to move the rest of the world. Why do I talk about a camera then? Because it is easier for me to think that way. A camera moving around a world is easier to think about than a world moving around a fixed point in space. Moving the world 5 units to the left is functionally the same as moving the 'camera' 5 units to the right, but the latter is easier to picture.

So, how do we move everything around then? OpenGL has this thing called the ModelView matrix. While working with this matrix, we can change the origin of the coordinate system. There are a couple of functions that do this, glTranslatef and glRotatef. glTranslatef moves the origin by the number of units you tell it to. glRotate changes its orientation. After modifing the matrix with these functions, the points we pass to the program are modified by these operations and placed in the proper place.

So, as soon as the program starts, if you draw something at 0,0,0 it will appear at the center of the screen. But if you then call glTranslatef( 5 , 0 , 0 ), and draw something at 0 , 0 , 0, the resulting image appears at 5,0,0, or to the right of the screen. If you then call glRotatef( 180 , 0 , 0 , 1 ) and draw at 1 , 0 , 0 the drawing will appear at 4 , 0 , 0 . We basically draw on a relative coordinate system centered where we want with the translate and rotate functions, and then it is drawn on the absolute coordinate system centered on the screen.

How does this relate to the camera then? As I said, to move the 'camera' around, what we do instead is move the world around. If before we start drawing we translate 5 units to the right, when we then start drawing everything will end up 5 units to the right. Because everything maintains its position relative to everything except the viewport, it ends up looking as though the camera had moved 5 units to the left.

This covers the OpenGL side of things. If we want to move inside the world in a given direction, we have to move everything else in the opposite direction. How do we get our commands to the system, though? The SDL will handle recognizing when an 'event' happens. An event is any keystroke, mouse movement or whatever other input method we use to give commands to the computer.

I've decided to go with a fairly standard set of commands to start with. 'W' and 'S' move the camera forwards and backwards. 'A' and 'D' move it sideways. Horizontal mouse movements will rotate it around the vertical axis, letting us look around. Vertical mouse movement will rotate it around the horizontal axis, letting us look up and down. This should be enough to enable us to move everywhere in the world.

Next up, how to get the SDL to catch our commands.

No comments:

Post a Comment