Fastgraph 3D Tutorial

Chapter 3: Keeping Objects in Order

Object Space and World Space Revisited

In the last chapter, we talked about defining objects in object space and world space. That implies there is some difference in the objects. In fact, object space and world space objects are the same thing, the only difference is the transformations that are applied to them. To illustrate this, let's look at another example.


//----------------------------------------------------------------------
void DrawCube()
{
   int i;
   static int Colors[] = {19,20,21,22,23,24};
   double tempxy[40];
   int xy[40];

   // use the default render state (filled polygons with backface removal)
   fg_3Drenderstate(0);

   // set the point of view: at the origin looking down the z axis
   fg_3Dpov(5.0, 5.0, -20.0, 0, 0, 0);

   // put the cube at Z=10.0 and rotate it slightly
   fg_3Dsetobject(0.0, 0.0, 20.0, -300, 300, 300);

   // draw the axes
   fg_setcolor(0);
   fg_3Dline(0,0,0,10,0,0);
   fg_3Dline(0,0,0,0,10,0);
   fg_3Dline(0,0,-50.0,0,0,500.0);

   // draw all the faces
   for (i = 0; i < 6; i++)
   {
      // set the color
      fg_setcolor(Colors[i]);

      // draw the face as a solid colored polygon
      fg_3Dpolygon(CubeData[i],4);
      fg_3Dpolygonobject(CubeData[i],4);
   }
}

This example uses exactly the same code as the one in the last chapter, except the title is changed and the DrawCube() function has been modified. The first thing we do is set our point of view a little back, above and to the side of the coordinate axes, so we can see them. Then we draw the coordinate axes so we will have a frame of reference. Then we draw the cube as before, but we draw it twice. The first time, we draw each face using fg_3Dpolygon(). This draws the cube right at the origin, where it was defined. The second time we draw each face using fg_3Dpolygonobject(). This moves the cube down the Z axis and rotates it by 30 degrees. The results can be seen in Figure 3.1.


Fig. 3.1 Object Space and World Space.

Notice the way I drew the axes with calls to fg_3Dline(). This is an extremely useful function. If you ever find yourself lost in 3D space, draw some lines so you know where you are. Fastgraph's 3D lines are z clipped and z buffered, and have a constant 1-pixel width no matter where you put them.

Backface Removal

In the above example, we allowed Fastgraph to use a technique called backface removal. That means that only polygons that are facing the viewer are drawn. The faces of the cube on the back are facing away from the viewer, so they are not drawn. The trick to doing backface removal is to define the vertices in clockwise order. That is exactly what we did when we defined the data for the faces of the cube:


double CubeData[6][12]=
{
   {-1.0, 1.0,-1.0,  1.0, 1.0,-1.0,  1.0,-1.0,-1.0, -1.0,-1.0,-1.0}, // front
   {-1.0, 1.0, 1.0, -1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0,-1.0, 1.0}, // left
   { 1.0, 1.0,-1.0,  1.0, 1.0, 1.0,  1.0,-1.0, 1.0,  1.0,-1.0,-1.0}, // right
   {-1.0, 1.0, 1.0,  1.0, 1.0, 1.0,  1.0, 1.0,-1.0, -1.0, 1.0,-1.0}, // top
   {-1.0,-1.0,-1.0,  1.0,-1.0,-1.0,  1.0,-1.0, 1.0, -1.0,-1.0, 1.0}, // bottom
   { 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0,-1.0, 1.0,  1.0,-1.0, 1.0}  // back
};

It's not easy to type in coordinates in clockwise order. It quickly gets confusing. The way I did it was with a CD-R box and a magic marker. Whatever works for you is fine.

Usually, we don't bother with backface removal. A better technique is z buffering which is more versatile and powerful.

Z Buffering

When you display objects in a 3D world, it is important to pay attention to the relative location of objects. Objects that are behind other objects are not seen. This phenomenon is called z buffering. When you z buffer objects, you will not see the parts that are covered by other objects, as shown in Figure 3.2.


Figure 3.2 Z Buffering.

Fastgraph will handle z buffering for you. There are just a few things you need to do.

Somewhere in your initialization procedures, you need to create a z buffer. This should be the same size as your virtual buffer. The code looks like this:

   ZBuffer = fg_zballoc(640,480);
   fg_zbopen(ZBuffer);
ZBuffer is an integer handle. You can have more than one z buffer, for example if you have more than one viewport.

You will also want to set FG_ZBUFFER as one of the flags you pass to fg_3Drenderstate().

   fg_3Drenderstate(FG_ZBUFFER);
You need to clear the z buffer every frame. It's very easy. Just call
   fg_zbframe();
That prepares the z buffer for the next frame.

Z buffering is a bit processor intensitive, as you can imagine. For every object, Fastgraph needs to examine the points in the z buffer and determine if there is something already there, and if it is closer or farther away than what you want to put there now. There are ways to optimize the z buffer, including those suggested by John De Goes. One optimization is to sort your objects in Z order after they are transformed but before they are projected. Another optimization involves having a z clipping limit at no less than 1.0, as described below.

Don't worry to much about z buffering efficiency. Fastgraph does it very well (in assembler!) and you should get good performance.

Z Clipping

Z clipping means part of the picture gets cut off directly in front of your view. That is, objects that are behind you or right on top of you are not drawn. Also, objects that are very, very close to you are not drawn. The things you see on the screen are considered to be in front


Figure 3.3 Z Clipping.

In Figure 3.3, you can see a top down view of your range of vision (sometimes called the frustum). Remember, an object that is 10 feet wide and 10 feet away will fill the whole screen (as we saw in Chapter 1). The front part of the frustum is clipped off. This is the near z clipping limit. There is also a far z clipping limit, which is not pictured.


   fg_setzclip(1.0,1000.0);
Notice that we set our near z clipping limit at 1.0. This is the absolute minimum z clipping limit. This is for reasons of speed and efficiency. The far clipping limit is set sufficiently large to include anything I happen to draw.


Figure 3.4 Z Clipping.

In Figure 3.4, it looks like a 1.0 z clipping limit is too much. That is, it clips off too much information. If your object is small, and drawn very close to you, it will indeed suffer from clipping off too much.


Figure 3.5 Z Clipping.

The easiest solution is to change the units, as in Figure 3.5. That is, if you are drawing a chair that is 1 meter high, make it 100 centimeters high. Then only one centimeter is clipped off.

Review

Backface removal, z clipping, and z buffering keep objects in your 3D space in order. Fastgraph handles these techniques very efficiently. The function calls at the high level are quite simple. You only need to keep a few issues in mind when designing your program:

  • z buffering is more versatile and provides better results than backface removal
  • the minimum near z clipping limit is 1.0
  • choose smaller units rather than larger ones

 

Introduction
Chapter 1 | Chapter 2 | Chapter 3
Chapter 4 | Chapter 5 | Chapter 6 | Chapter 7
Appendix 1 | Appendix 2 | Appendix 3
Benchmarks
Fastgraph Home Page

 

become a computer game developer

copyright © 2007 Ted Gruber Software inc. all rights reserved.
This page written by Diana Gruber.