This text file contains a short discussion of the Binary Space Partition 
algorithm, which allows the correct representation of solid objects in a 
3D environment.  This algorithm is the basis for many modeling and 
rendering systems.  In this discussion we will review the canonical form 
of the BSP as applied to back-to-front drawing of polygons in a multi-
frame animation environment, and then explore some important performance 
optimizations. We will not explore performance issues in the utility 
algorithms used by the BSP (such as normal calculations of surface to 
surface intersections)

The BSP determines the z-order of objects in a 3D scene, allowing back 
to front drawing without error and calculation of ray-object 
intersections.  Improper determination of z-order results in 
applications that display assorted hidden surfaces in front of occulting 
surfaces when the viewpoint is moved in the scene.  The "flashing" 
effect is quite distracting and severely impacts the appearance of the 
displayed scene.  The BSP takes as input all the objects in a 3D scene;  
splits any objects that are only partially hidden or pierced by other 
objects, into new objects; produces as output a sorted list of all these 
objects in z-order ready for back-to-front processing.  The BSP takes 
each object in the scene and compares it against every other object to 
determine whether one is in front of the other.   

The BSP algorithm is really 3 different algorithms rolled under one 
cover:
1-  The binary space partition determines which object is in front, 
which is in back.
2-  The binary object partition determines where to split an object that 
has penetrated another object, or that is mutually occluding another 
object.
3-  The binary tree manages all the objects and sub objects that you are 
dealing with.

Pseudo code:

Before drawing a frame.

For each object ( the partitioning object) in the scene do  
  {
      For each other object (the test object) in the scene do 
      {
         1- take each vertex of the test object and compare against the 
partitioning object by determining the normal from the vertex to the 
surface defined by the partitioning object.  The partitioning object is 
used to split the scene into 2 sides, therefore the name binary space 
partition...(we want to know if the test object is on one side of the 
partitioning plane or the other).
         2- if all vertices of the test object are on the far side of 
the partition(from the view point), the test object goes on the left 
node of the binary tree whose root starts at the partitioning object.
         3- if all vertices of the test object are on the near side of 
the partition (from the view point), the test object goes on the right 
node of the binary tree whose root starts at the partitioning object.
         4- if some vertices of the test object are on the near side of 
the partition and some are on the far side, then the test object gets 
split into 2 sub objects: one sub object goes on the left node, and the 
other goes on the right (this is the binary object partition).  The 
split is made where the partitioning plane intersects the test object.
      }
  }
(The binary tree now contains all the objects in the scene in z-order.)

5- Draw all objects in the tree from leftmost leaf to right most leaf.  

( end of pseudo code)

As it stands, the above algorithm is impressively correct, but horribly 
slow.  There are several optimizations that improve it dramatically. 

Optimizations:

The following optimizations have a greater impact with larger numbers of 
objects in the scene.  A couple dozen objects won't show much 
improvement and may not be worth the trouble.

1- The viewpoint translate optimization: You can place the viewpoint in 
the tree(as a pseudo object), so when the viewpoint translates (but does 
not rotate) you do not process all the objects (they have not moved 
relative to each other). You process only the viewpoint pseudo object by 
sliding it left or right in the tree, and then drawing from the farthest 
leaf to the viewpoint object.  This optimization helps prevent having to 
balance the tree all the time. You have placed the viewpoint in the tree 
as a virtual root, if you will.  Stopping the draw process at the 
viewpoint leaf saves a lot of time if you have objects in the scene 
behind the viewpoint.

2-  The join optimization.  Notice that the BSP leaves a bunch of sub-
objects floating around.  Given enough transformations, you will 
eventually end up with a btree where every object is 1 pixel in size!   
After you have drawn the frame, go back through the tree and rejoin all 
the split objects.  For small numbers of splits you may wish to build a 
list of split objects when doing the splits, and then go through this 
list to do the joins.

3-  The backface optimization.  Backfaces are non displaying, do not 
split backfaces, simply toss them arbitrarily on left or right leaves.  
Do not use backfaces as partitioning objects. 

4- The bounding box optimization:  Before you test if an object is split 
by the space partition (normals and normals to surfaces take a long 
time) test if the entire test object is further in z (from the 
viewpoint) from the partitioning object.  If the test object is entirely 
further, then you really don't care if it is split or not, it needs to 
be drawn first regardless.  Likewise if the test object is entirely 
closer.  This one saves tons of time.

5-  The nearest neighbor optimization:  Once you have built the BSP for 
the first frame, you need not discard it...simply re-use it for all 
subsequent frames.  If you are using the bounding box optimization you 
can add this one.  Since all the objects in the tree are in z-order 
before you draw the scene, you only have to process the objects that 
have moved in the z axis since the last frame.  Not only do you limit 
the number of test objects to process, you also limit the number of 
partitioning objects.  You do not have to compare  against all the other 
objects in the tree, only against those objects immediately next to the 
test object in the tree.  Continue comparing the test object that moved 
against its partitioning neighbors until you reach the portion of the 
tree where the test object that moved is fully further in z than the 
partitioning object you are comparing against.  At that point you can 
stop comparing.  Repeat in the other direction in the tree.  This 
optimization only works if you are also doing bounding box and if you 
keep the BSP between frames.  

6-  The non-penetrating optimization.  For certain applications you do 
not have to split the test object.  In a doom style game you may never 
have a polygon penetrate another.  Likewise you will rarely get a case 
where 3 or more polygons will produce a configuration where you would 
need to split them.  For doom style applications you may be able to 
dispense with splitting all together.  CAD and modelers have no choice--
they have to split.

7-  The linked list optimization.  For certain applications a given 
object moves only a small distance in the world space.  In a doom style 
game the objects mostly translate in small increments.  You will get 
improvements in the nearest neighbor optimization if you use a linear 
linked list instead of a binary tree.  If objects get beamed around a 
great deal, then the binary tree remains more useful.  Note that binary 
trees tend to become unbalanced over time, leading to deep recursions 
that can impact your stack space, not to mention performance.  Under 
such circumstances you may also benefit from a linked list.  Use this 
optimization with care. Benchmarking is recommended .


Mike. (71530,1337)


"Windows Graphics Programming with Borland C++", Loren Heiny, John Wiley 
& Sons, ISBN 0-471-54891-X,  pp 422-428.

"Computer Graphics, Principles and Practice", Foley et al, Addison-
Wesley, ISBN 0-201-12110-7, pp 555-557, 675-680.

"VGA Palette Mapping using BSP Trees", Mark Betz, Dr. Dobb's Journal, 
7/93.

"Partitioning a 3D convex polygon with an arbitrary plane", Norman Chin, 
Graphics Gems III, ISBN 0-12-409670-0, pp 219-222.

"Ray tracing with the BSP tree", Kelvin Sung and Peter Shirley, Graphics 
Gems III, ISBN 0-12-409670-0, pp 271-274.

"Front-to-back Display of BSP trees", Dan Gordon and Shuhong Chen, IEEE 
Computer Graphics and Applications, Sept. 1991, pp 79-85.

"On visible surface generation by a priori tree structures", Fuchs et 
al, Computer Graphics (SIGGRAPH '80 Proceedings), 14(3), 124-133.

"Near real time shaded display of rigid objects", Fuchs et al, SIGGRAPH 
'83, pp 65-72.

"Study for Applying Computer Generated Images to Visual Simulations", 
Schumaker et al, Technical report AFHRL-TR-69-14, NTIS AD700375, USAF 
Human Resources Lab, Air Force Systems Command, Brooks AFB, TX, Sept 
1969.

"Linear Time Voxel Walking for Octrees", James Arvo, Ray Tracing News 
1(2).  E-mail edition, available under anonymous ftp from 
weedeater.math.yale.edu.

"Fast ray tracing using K-D trees", Fussel and Subramanian, Technical 
report TR-88-07, Dept. of computer science, The University of Texas at 
Austin, 1988.

"Heuristics for ray tracing using space subdivision", MacDonald and 
Booth, Proceedings of Graphics Interface '89, pp 152-163.

"Automatic termination criteria for ray tracing hierarchies", 
Subramanian and Fussel, Proceedings of Graphics Interface '91, pp 93-
100.
