Let’s see what you can do about getting this thing onscreen. If you turn to the CObj::Render() function in obj. cpp, you will see what it takes to get everything onscreen. The first thing to do is to activate and bind the texture. Make sure to check if the texture is valid before calling bind to avoid problems.
Then you can start rendering. The first thing that happens is it checks to see which components are included in the model and picks a loop based on the result. There is a separate loop for every possible combination to improve the speed. In pseudo-code, the rendering code would look like the following code. Keep in mind the pseudo-code gives you only a basic layout of how a function should look. It should be obvious that the following code will not compile in a regular C/C++ compiler.
if(normals are present)
SendNormal(); if(texcoords are present)
That would require two if statements for every vertex, which is a waste of processor time when you can do with but a couple for every frame. Instead, the structure is more like this:
if(has normals and tex coords) for(each vertex)
SendVertex() else if(has texcoords but not normals) for(each vertex)
Because the geometry is static, you might want to consider compiling all of your rending code into a display list. A display list creates a precompiled object and will drastically cut down on the processing time needed for each frame. This can be done at load time in OpenGL using the functions glGenList and glNewList. Then, in your rending function, instead of sending every vertex to the renderer, you simply run glCallList with the appropriate display list to display your model.
And so on. Although this approach is longer, it is much more efficient. To get the appropriate values for each of the components, you use the face structure to index into the arrays of normals, tex coords, and vertices. There is one little quirk here, however. For some reason, the creators of the OBJ format decided to make 1 the first index, instead of 0. To counter this, you must subtract 1 from each of the vertex, texture coordinate, and vertex normal indexes that make up a face. This is done at load time in the demo code; see the constructor of SObjFace for more information. Have fun.
Take a quick look at the fully rendered model, shown in Figure 4.1.
The OBJ format actually has much more to offer. It can support multiple kinds of curved surfaces, faces that have more than three sides, and other cool stuff. If you are feeling ambitious, try modifying the loader to work with all of the extra stuff. There are documents of the complete OBJ all over the Internet. Just type OBJ Format into any search engine. A couple of good links that pop up are http://astronomy. swin. edu. au/~pbourke/geomformats/obj/ and http://www. royriggs. com/obj. html. Both contain de — □ scriptions of the OBJ file format; the first URL covers the II
I full format, including lines, points, surfaces, and curves. J
N______ I—I__________________________ L f_____________ /
That wraps up the chapter. Although the basic OBJ format is fairly simple, the concepts from this chapter can be used to load other ASCII-based formats you may come across, such as ASE and ASC.
The next chapter delves into some more advanced information with an introduction to skeletal animation. In the following chapter, you will see how skeletal animation has changed the gaming world and learn about some of the games that already use it. You will also learn how skeletal animation works, and why you might want to use it in your next game.