3D Objects Introduction Now it's time to really enter the world of 3D. We've drawn, coloured, and rotated flat, 2D objects, now we're going to do the same to real (simple) 3D objects. A pyramid and a cube are our next victims. The pyramid will rotate around the Y-axis. The cube will tumble around the X & Z axes. The only other thing of note is that both objects will be stored in the same Vertex Buffer, but will still be drawn with 2 separate calls. As in previous lessons, the animation is frame-based, so it may run very slowly or very quickly depending on your computer. Feel free to play with the values in the sample code to get a result you like. If you've understood the previous lessons, this one will be really easy. Building a Pyramid Our pyramid has 4 sides with no bottom. Think of it as a basic rule, if no one can see it anyway, don't render it. Because of the organization of the triangles (4 triangles connected by a center point) this could also have been done with a Triangle Fan, but I chose to use the more generally useful Triangle List. Building The Cube Generally when people draw cubes, they treat the faces as separate objects, often with unrelated texture maps. This actually makes a cube one of the worst simple models you can use to explore 3D graphics. But it's used in virtually every other tutorial series on the planet, so one more won't hurt. The most remarkable thing about the cube's geometry is how boring it is to type in. Fortunately for you, I've saved you the effort. Just to make it look different than the pyramid the faces of the cube are flat shaded in a solid colour rather than having colour gradients. To do that you simply set the colour of all the vertices on a given face to the same colour. Shared Vertex Buffer By having all of our data in a single Vertex Buffer we can get a slight performance increase. No extra calls are needed to set the stream in between renders. In fact, since the Vertex Buffer is only set once we could move the call to SetFVF and SetStreamSource completely out of the render loop. In this case it's not a significant performance gain, but if there were a large number of small objects that needed to be rendered the savings could add up. A Vertex Buffer is basically an array of vertices. So when you want to render from a Vertex Buffer you can give an offset for where to start rendering. In the past we've always set it to 0, but to render the cube we need to change that offset. Since the Vertex Buffer stores vertices, it only makes sense that the offset be given as a count of vertices to be skipped. It's a common mistake to give the offset as a triangle count. Culling In the set_device_states function the Cull mode is set to counter clockwise. This is the default so it doesn't need to be set. However it is good practice to explicitly set any states that you depend on. It can save you a lot of hassle. I also included a line (commented out) that turns culling off. If you uncomment that line, you'll notice some very bizarre behaviour. Normally triangles facing away from the camera (CCW vertex winding order) are culled so they are never drawn. By turning culling off, those backwards facing triangles are being rendered. Since we have no depth buffer (covered in a later tutorial), triangles are drawn in the order they are processed. This means that often a triangle that should be in the back, gets drawn on top of a triangle in front. In general you'll want culling left enabled. Lesson Downloads Source and Executable for C++ (127K) Source for C++ (10K) To compile this lesson you will also need the Drunken Hyena Common Code Back