(Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)
Main object: Use arrow keys to move left/right and up/down
Camera: Left/Right (A/D), Up/down (W/S), Zoom in/out (Q/E)
(When moving the camera things in the world will appear to move opposite. Thus when you move camera left, the world will appear to move right.)
About the Project
This week I completed the transformation of the game to 3D. To accomplish this I added a third dimension: depth. Then added three matrix transformations to take 3D objects from their local space (at their origin and facing forward), to world space (where the object is in relation to the origin of the world), to camera space (where the object in the world is in relation to the observer, or camera).
Local space is essentially where a 3D mesh’s vertices are in relation to its origin, and we place the object facing forward as convention so we know automatically how to rotate things and how they should appear without even seeing them initially.
World space is where an object is in the world of the game: if we have a city then we have streets and buildings, and we may use the same mesh to represent all those buildings, at the same local space, but in the world they can be all over the map. World space gives us an object in the map of a game.
Finally we have an observer: world space really doesn’t mean anything until we have an observer. In 2D space what we draw to screen is the world we’ve made, but in 3D what we draw to screen depends entirely upon the perspective we are looking at since we are taking something that has 3 dimensions and moving it to two. Without the observer there’s no way to know how to flatten the world. There must be an observer. In this case we call the observer the camera. Since the camera is looking at the world, when the camera moves the world appears to move in the opposite direction (up:down, left:right, forward:back, clockwise:counterclockwise, etc.). To make the math simple, and since moving the camera is just moving the world inversely to the camera: we take the world to the camera.
The last transform we need then is the one to flatten the world to render on screen.
Here’s how the platform independent transform from local space to world space (localToWorld) in the shader looks:
float4 verPosWorld = MultiplyMV(g_transform_localToWorld, float4(i_position, 1.0));
The last thing I did was implement depth buffering so that instead of the last mesh drawn just covering up the previous one, you can actually have meshes covering up parts of each other. This allows us to render the plane and the cube intersecting (without depth buffering the cube or the plane would be covering the other up):
I chose to make the plane double sided: so I used the same four vertices but sent the index buffer 12 points (instead of six) so that you can see the plane from underneath as well as on top, but the plane is still flat (no sides).
I didn’t have time for any optional challenges this week. I had wanted to do camera rotation, but I ended up spending my extra hours on a Visual Studio bug. I was relieved to discover that the bug wasn’t in my implementation, but still the time was gone. Maybe next time.