An Explanation of how our BSP Tree System Operates
Molnar \ Kucalaba Production
http://members.aol.com/mkwebsite
June 2001

INTRODUCTION
 This was written in order to provide a general overview of how the entire
BSP tree process works in our series of programs, with an emphasis on the
data structures used at various stages.  This can not only help someone who
is trying to learn how to use BSP trees, but will help remind us, because I
personally have a feeling that if I don't write down how this stuff works I
will forget in a couple weeks.  We'll cover the data structures used, and
how the compilation, clipping, collision, ordering, and rendering phases
work.  The purpose of these programs was to increase the complexity of first
person graphics a notch over all of the raycasters, but for simplicity the
engine is basic, as it does not include ceilings or definable Z values. (yet)

DISCLAIMER
This information might be completely wrong.


DATA STRUCTURES USED
 Binary Trees and Sets are the two main structures that are used, and both
are pretty simple.
The world is stored in a set of vertices.  Basically the world is just a big
collection of lines.  They are stored in parameterized form and also include
some attributes, such as color, etc.  Parameterized form making clipping
easier.

 The Binary Tree is a three-tuple.  The root/node/information is a pointer
to a wall in the world.  The other two values are a pointer to the "front"
child and a pointer to the "back" child.  The fundamental thing about these
trees is that all lines in the "front" child are in front of the root line
and all lines in the "back" child are behind the root line.


BSP COMPILATION
 The first step in compiling our BSP tree is to build a source set of lines
that make up the world.  (SUB InsertLine)  Once that is done, we can call
the TreeBuild SUB which operates pretty simply.  It first adds the given
line into a different, output World set, and fills in the root pointer
appropiately.  Then, if the remaining source set is not empty, it is divided
into two sets, those of lines behind the just inserted line, and those of
lines in front of the just inserted line.  (This is done with the SetSplit
SUB and turned out to be the most difficult thing to write.)  Then we fill
in the pointers and recursively call TreeBuild on these new sets until all
lines are gone, and we are done compiling our BSP tree.  To summarize,
we start with a source set, then as the tree is built the source set is
depleted as the World set grows.  When we are done, all we need for the
BSP tree is the tree itself and the World set.

 The process of splitting the set into front and back sets basically
involves rotating all of the lines around so that the line just inserted
into the World is the X axis.  From there it is easier to find out if a
line needs to be split.

 We choose the root line to start with by calculating how many lines each
line in the set splits.  Fewer splits means fewer lines means fewer
calculations and drawing, so that seems to be a good method.  This is done
with the SetNumberOfSplits and SetFindBestRoot routines.

 The best example of BSP tree compilation is the file BSPCOMPL.BAS.



ALL THE STUFF YOU NEED TO DO BEFORE YOU CAN DRAW IN "3D"
 Before we get to the good stuff, we have to do some boring stuff that turns
out to be harder than actually using the trees.  That consists of parsing
input, clipping, doing collisions, and other stuff.  Sequentially the first
thing turns out to be parsing user input.  That's pretty easy to do, but it
leads into collision detection which can be a pain.
 When a player moves, a movement vector is generated.  This vector is passed
to the collision detection routine. (WorldColDetect, which also assumes
access to the current player x and y position)  Collisions are detected
by seeing if the shortest possible distance from the player to the line is
less than a certain distance, for example 5.  This is done by taking a vector
from a wall endpoint to the proposed new position and dotting it with the
wall's normal unit vector.  If we are close enough, than we check to see if
we actually hit the wall by using some parametric algebra.  If we do have a
collision, we have to do some collision repair so that we get that nice
gliding along the walls effect.  This is done by cancelling the portion of
the movement vector aimed at the wall.  To do that, we subtract the
projection of the movement vector onto the wall's normal vector from the
original movement vector.  Then, as our last step in collisions, we push
the player back so their distance remains the constant "arm's length"
distance from the wall.  This process is then repeated until the movement
vector is not changed or the computer crashes.

 Once we have a nice valid collision tested position, we have to translate
the World set into a Viewspace set.  This is done by rotating the set with
the player's coordinates at the origin.  (SUB WorldTranslate)

 Now comes the fun part, clipping, which is marking all the viewspace walls
that we don't need to draw as such.  The idea behind it is simple but it
turned out to be a little bit of a pain to implement.  First of all, once
you have your ViewSpace, all walls with y co-ordinates that are both
negative are behind you, so we mark them are invisible.  Then, we have to
clip the view triangle in X, which is easier if you clip along the lines
y=x and y=-x.  The only hard part about this is lines that get split by
either restriction, but looking at the code should clear things up.
(SUB WorldClipWalls)


WALKING THE TREE
 Once we have our viewspace clipped, we are ready to stop doing operations
on the World set and start using the BSP tree.  What the BSP tree allows us
to do is draw the entire viewspace in front to back order in linear time.
The problem is you might get a lot of overdraw, but it is very fast overdraw
so I guess it's ok.  Ok, to walk the BSP tree, we start at the very top of
the tree.  We then look at the line that the top node points to, and decide
if we are in front of or behind it.  (Hopefully using the same
code/comparison we used to split sets)  If we are in front of the wall, then
we draw the back tree, then the root, then the front tree.  If we are behind
the wall, then we draw the front tree, the root, and then the back tree.
This makes a lot of sense on an intuitive level.  This is demonstrated in
BSPORDER.BAS.  The final element is drawing the walls.


DRAWING THE WALLS
 This is easy to do so there's not much to say, but it is a good idea to
generate your screen points while you are clipping, because you can avoid a
lot of repeated calculations of split lines.  That is how all of our
programs do it.  And that's all there is to writing a BSP tree engine!

MISC
 The one thing that sticks out as being inefficient is doing operations
on the entire world set.  For example, you don't really need to check for
collisions against every wall in the world.  So there is probably a much
better way to pick the walls to operate on.  We'll update the engine when
we figure it out.
