Drawing Objects in the Scene
Because you already have z-buffering to draw 3D objects, it would be easy to just continue to use z-buffering when you draw 3D objects in the 3D scene. However, you need to ensure that polygons are drawn correctly in the scene. For example, polygons that are partly behind walls should show only the visible part of the polygon. But-gasp-you want to avoid z-buffering, right? Well, sort of. The easiest way to solve this problem is to just use z-buffering, but not the same z-buffering you used before. When you draw the polygons in the BSP tree, you draw each pixel in the view only once. So, for each pixel, you never have to check the z-buffer; you only have to set it. In other words, setting the z-buffer only once for every pixel won't have the performance impact of plain z-buffering. Here's the basic flow:
- Draw polygons in the BSP tree, setting the z-buffer.
- Draw polygons in the 3D objects, checking and setting the z-buffer.
On machines I've tested, setting the z-buffer for polygons in a BSP tree takes about 3-10% of the processor, depending on the machine. In spite of the performance impact, it gives perfect merging of 3D objects in the scene. Also, it's a common way to do 3D rendering, ever since this technique was used in the original Quake. One thing to note is that you can set the z-buffer separately from texture mapping. To do this, create a polygon renderer class called BSPRenderer that sets the z-buffer for every polygon scan that is drawn, as shown here:
/** Sets the z-depth for the current polygon scan. */ private void setScanDepth(int offset, int width) { float z = c.getDotProduct(viewPos); float dz = c.x; int depth = (int)(w*z); int dDepth = (int)(w*dz); int endOffset = offset + width; // depth will be constant for many floors and ceilings if (dDepth == 0) { short d = (short)(depth >> SCALE_BITS); while (offset < endOffset) { zBuffer.setDepth(offset++, d); } } else { while (offset < endOffset) { zBuffer.setDepth(offset++, (short)(depth >> SCALE_BITS)); depth += dDepth; } } }
This BSPRenderer also draws 3D objects using plain check-and-set z-buffering. Okay, now you can draw 3D objects. One last step: loading maps from a file.