Building a 3D Portal Engine - Issue 05 - Coding A Wireframe Cube
by (29 January 1999)
|Return to The Archives|
Welcome to the fifth episode of Phantom's Guide! This week we'll discuss the real basics of 3D: The famous wireframe cube. If you're an expert that just came here for scientific discussions of the latest 3D topics, you can leave the room now. Check back next week, the fancy stuff will follow.|
The purpose of this article is to get you going if you really don't know where to start. I can rant about PTC and windows programming, data structures and so on, but in the end there's nothing like a good example. Well, I've just coded a very small program (54 lines of code, in fact) that just shows a wireframe cube, and that might be just what you need. Here's the code:
Please take a moment to get this stuff running. Using VC5 or 6, create a new Win32 application with no files in it. Add the PTC lib file to the project (using add files) and the ptc.h header file, and of course the source that I just showed. Next you have to disable the inclusion of two default libraries (under the 'linker input settings'), LIBC and LIBCD. Now the program should compile just fine. You might try to make it slightly more readible by splitting lines that do multiple variable initializations on a single line. :)
So what does this program do? Let's start with the program entry, which is in this case the WinMain function. The first thing that happens here is the definition of a cube. A cube has eight vertices, which could be initialized as follows:
The weird construction with the modulo operators does just that (only shorter:). If you take a moment to visualize this data, you'll see that these are 8 vertices centered around (0, 0, 0), wich is handy, because rotations are easy around the origin of 3D space.
After that, we need to set up PTC. I used a 16 bit display in this case, at a resolution of 640x480 pixels. This video mode should work on most computers.
In the main loop the function 'render' is called, with a pointer to the PTC buffer and the rotation around the three axi as input. Note that the rotations are passed in degrees.
The 'render' function is slightly more interesting. Let's see what it needs to do: Ultimately it should draw lines between the rotated vertices, and those lines should be somewhere near the center of the screen. Rotations are done using a matrix. If you forgot how that worked, browse back to the article that discusses them. As you know, a rotation around three axi can be performed by calculating the matrix for the rotation around each axis, and them concatenating them. In this case, I have done the concatenation for you: The matrix 'mat' is filled with sins and cosines at once. I encourage you to alter the code so that the final matrix is calculated by concatenating the separate matrices, so that you can also rotate around the axi in a different order.
The rotated vertices are still centered at the origin. Since perspective calculations do a nice divide by the z coordinate, we need to move the object away from the camera. This is done by adding 300 to the rotated z. Note that you could also add something to x and y: This is how you rotate an object around something else than the origin. In this case, the object is effectively rotated around (0, 0, 300).
Finally, the perspective is calculated. Note that the object is also centered on screen, by adding 320 to the screen-x coordinate, and 240 to the screen-y coordinate.
Now the lines can be drawn to the screen. The line function that I included is very short, and that's the only thing that is good about it. If you need fast code, ditch this function, and include your own assembler bresenham code. Some comments about this code:
If you want to play a bit around with this code, then here are some suggestions:
* Editor's Note: Feel free to submit any modified versions of this program that you make, and I'll probably post it here with your name.
Note that the code I just presented is really ugly. It isn't object oriented, doesn't use good structures (not even a polygon structure), and does really nasty matrix math without concatenations. I realize that this sucks, but I think some of you will appreciate a 'single-A4' working example.
This should get you going for the moment. Please check back next week, I'll discuss 'hidden surface removal' then. That will get rid of the ugly wires on the back of the cube... And some more, too.