home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / utilities / utilsf / graphtext / BSPFAQ < prev    next >
Encoding:
Text File  |  1995-05-12  |  49.3 KB  |  1,168 lines

  1. BSP Tree Frequently Asked Questions (FAQ)
  2.  
  3.     ------------------------------------------------------------------------
  4.  
  5.  
  6. This document is still under construction
  7.  
  8.      This document should not be considered to be in final form by any stretch
  9.      of the imagination. All comments are welcome. I expect to go through
  10.      several iterations of writing and improving, so don't give up on me for a
  11.      few months yet.
  12.  
  13.     ------------------------------------------------------------------------
  14.  
  15.  
  16. Questions
  17.  
  18.   1. About this document
  19.   2. Acknowledgements
  20.   3. How can you contribute?
  21.   4. About the pseudo C++ code
  22.   5. What is a BSP Tree?
  23.   6. How do you build a BSP Tree?
  24.   7. How do you partition a polygon with a plane?
  25.   8. How do you remove hidden surfaces with a BSP Tree?
  26.   9. How do you remove hidden lines with a BSP Tree?
  27.  10. How do you accelerate ray tracing with a BSP Tree?
  28.  11. How do you perform boolean operations on polytopes with a BSP Tree?
  29.  12. How do you perform collision detection with a BSP Tree?
  30.  13. How do you handle dynamic scenes with a BSP Tree?
  31.  14. How do you compute shadows with a BSP Tree?
  32.  15. How do you extract connectivity information from BSP Trees?
  33.  16. How are BSP Trees useful for robot motion planning?
  34.  17. How are BSP Trees used in DOOM?
  35.  18. How can you make a BSP Tree more robust?
  36.  19. How efficient is a BSP Tree?
  37.  20. How can you make a BSP Tree more efficient?
  38.  21. How can you avoid recursion?
  39.  22. What is the history of BSP Trees?
  40.  23. Where can you find sample code?
  41.  24. References
  42.  
  43.     ------------------------------------------------------------------------
  44.  
  45.  
  46. Answers
  47.  
  48.   1. About this document
  49.  
  50.      The purpose of this document is to provide answers to Frequently Asked
  51.      Questions about Binary Space Partitioning (BSP) Trees. This document will
  52.      be posted monthly to comp.graphics.algorithms. It is also available via
  53.      WWW at the URL:
  54.  
  55.           http://www.graphics.cornell.edu/bspfaq/
  56.  
  57.      You can also request that the FAQ be mailed to you in plain text and HTML
  58.      formats by sending e-mail to bsp-faq@graphics.cornell.edu with a subject
  59.      line of "SEND BSP TREE [what]". The "[what]" should be replaced with any
  60.      combination of "TEXT" and "HTML". Respectively, these will return to you a
  61.      plain text version of the FAQ, and an HTML formatted version of the FAQ
  62.      viewable with Mosaic or Netscape.
  63.  
  64.      This document is maintained by Bretton Wade, a graduate student at the
  65.      Cornell University Program of Computer Graphics.
  66.  
  67.      This document, and all its associated parts, are Copyright © 1995, Bretton
  68.      Wade. All rights reserved. Permisson to distribute this collection, in
  69.      part or full, via electronic means (emailed, posted or archived) or
  70.      printed copy are granted providing that no charges are involved,
  71.      reasonable attempt is made to use the most current version, and all
  72.      credits and copyright notices are retained. Requests for other
  73.      distribution rights, including incorporation in commercial products, such
  74.      as books, magazine articles, CD-ROMs, and binary applications should be
  75.      made to bsp-faq@graphics.cornell.edu.
  76.  
  77.      This article is provided as is without any express or implied warranties.
  78.      While every effort has been taken to ensure the accuracy of the
  79.      information contained in this article, the author/maintainer/contributors
  80.      assume(s) no responsibility for errors or omissions, or for damages
  81.      resulting from the use of the information contained herein.
  82.  
  83.      The contents of this article do not necessarily represent the opinions of
  84.      Cornell University or the Program of Computer Graphics.
  85.      --
  86.      Last Update: 04/21/95 15:50:23
  87.  
  88.   2. Acknowledgements
  89.  
  90.      This document would not have been possible without the selfless
  91.      contributions and efforts of many individuals. I would like to take the
  92.      opportunity to thank each one of them. Please be aware that these people
  93.      may not be amenable to recieving e-mail on a random basis. If you have any
  94.      special questions, please contact Bretton Wade (bwade@graphics.cornell.edu
  95.      or bsp-faq@graphics.cornell.edu) before trying to contact anyone else on
  96.      this list. In no particular order:
  97.  
  98.           Bruce Naylor (naylor@research.att.com)
  99.           Richard Lobb (richard@cs.auckland.ac.nz)
  100.           Dani Lischinski (danix@cs.washington.edu)
  101.           Chris Schoeneman (crs@lightscape.com)
  102.           Philip Hubbard (pmh@graphics.cornell.edu)
  103.           Jim Arvo (arvo@graphics.cornell.edu)
  104.           Kevin Ryan (kryan@access.digex.net)
  105.           Joseph Fiore (fiore@cs.buffalo.edu)
  106.           Lukas Rosenthaler (rosenth@foto.chemie.unibas.ch)
  107.           Anson Tsao (ansont@hookup.net)
  108.           Robert Zawarski (zawarski@chaph.usc.edu)
  109.           Ron Capelli (capelli@vnet.ibm.com)
  110.           Eric A. Haines (erich@eye.com)
  111.           Ian CR Mapleson (mapleson@cee.hw.ac.uk)
  112.           Richard Dorman (richard@cs.wits.ac.za)
  113.           Steve Larsen (larsen@sunset.cs.utah.edu)
  114.           Timothy Miller (tsm@cs.brown.edu)
  115.           Ben Trumbore (wbt@graphics.cornell.edu)
  116.           Richard Matthias (richardm@cogs.susx.ac.uk)
  117.           Ken Shoemake (shoemake@graphics.cis.upenn.edu)
  118.           Seth Teller (seth@theory.lcs.mit.edu)
  119.           Peter Shirley (shirley@graphics.cornell.edu)
  120.  
  121.      If I have neglected to mention your name, and you contributed, please let
  122.      me know immediately!
  123.      --
  124.      Last Update: 03/29/95 14:12:10
  125.  
  126.   3. How can you contribute?
  127.  
  128.      Please send all new questions, corrections, suggestions, and contributions
  129.      to bsp-faq@graphics.cornell.edu.
  130.      --
  131.      Last Update: 03/29/95 14:12:10
  132.  
  133.   4. About the pseudo C++ code
  134.  
  135.      Overview
  136.      The general efficiency of C++ makes it a well suited language for
  137.      programming computer graphics. Furthermore, the abstract nature of the
  138.      language allows it to be used effectively as a psuedo code for
  139.      demonstrative purposes. I will use C++ notation for all the examples in
  140.      this document.
  141.  
  142.      In order to provide effective examples, it is necessary to assume that
  143.      certain classes already exist, and can be used without presenting
  144.      excessive details of their operation. Basic classes such as lists and
  145.      arrays fall into this category.
  146.  
  147.      Other classes which will be very useful for examples need to be presented
  148.      here, but the definitions will be generic to allow for freedom of
  149.      interpretation. I assume points and vectors to each be an array of 3 real
  150.      numbers (X, Y, Z).
  151.  
  152.      Planes are represented as an array of 4 real numbers (A, B, C, D). The
  153.      vector (A, B, C) is the normal vector to the plane. Polygons are
  154.      structures composited from an array of points, which are the vertices, and
  155.      a plane.
  156.  
  157.      The overloaded operator for a dot product (inner product, scalar product,
  158.      etc.) of two vectors is the '|' symbol. This has two advantages, the first
  159.      of which is that it can't be confused with the scalar multiplication
  160.      operator. The second is that precedence of C++ operators will usually
  161.      require that dot product operations be parenthesized, which is consistent
  162.      with the linear algebra notation for an inner product.
  163.  
  164.      The code for BSP trees presented here is intended to be educational, and
  165.      may or may not be very efficient. For the sake of clarity, the BSP tree
  166.      itself will not be defined as a class.
  167.      --
  168.      Last Update: 04/30/95 15:45:19
  169.  
  170.   5. What is a BSP Tree?
  171.  
  172.      Overview
  173.      A Binary Space Partitioning (BSP) tree represents a recursive,
  174.      hierarchical partitioning, or subdivision, of n-dimensional space. BSP
  175.      tree construction is a process which takes a subspace and partitions it by
  176.      any hyperplane that intersects the interior of that subspace. The result
  177.      is two new subspaces that can be further partitioned by recursive
  178.      application of the method.
  179.  
  180.      A "hyperplane" in n-dimensional space is an n-1 dimensional object which
  181.      can be used to divide the space into two half-spaces. For example, in
  182.      three dimensional space, the "hyperplane" is a plane. In two dimensional
  183.      space, a line is used.
  184.  
  185.      BSP trees are extremely versatile, because they are powerful sorting and
  186.      classification structures. They have uses ranging from hidden surface
  187.      removal and ray tracing hierarchies to solid modeling and robot motion
  188.      planning.
  189.  
  190.      Example
  191.      An easy way to think about BSP trees is to limit the discussion to two
  192.      dimensions. To simplify the situation, let's say that we will use only
  193.      lines parallel to the X or Y axis, and that we will divide the space
  194.      equally at each node. For example, given a square somewhere in the XY
  195.      plane, we select the first split, and thus the root of the BSP Tree, to
  196.      cut the square in half in the X direction. At each slice, we will choose a
  197.      line of the opposite orientation from the last one, so the second slice
  198.      will divide each of the new pieces in the Y direction. This process will
  199.      continue recursively until we reach a stopping point, and looks like this:
  200.  
  201.      +-----------+      +-----+-----+      +-----+-----+
  202.      |           |      |     |     |      |     |     |
  203.      |           |      |     |     |      |  d  |     |
  204.      |           |      |     |     |      |     |     |
  205.      |     a     |  ->  |  b  X  c  |  ->  +--Y--+  f  |  -> ...
  206.      |           |      |     |     |      |     |     |
  207.      |           |      |     |     |      |  e  |     |
  208.      |           |      |     |     |      |     |     |
  209.      +-----------+      +-----+-----+      +-----+-----+
  210.  
  211.      The resulting BSP tree looks like this at each step:
  212.  
  213.            a                  X                  X           ...
  214.                             -/ \+              -/ \+
  215.                             /   \              /   \
  216.                            b     c            Y     f
  217.                                             -/ \+
  218.                                             /   \
  219.                                            e     d
  220.  
  221.      Other space partitioning structures
  222.      BSP trees are closely related to Quadtrees and Octrees. Quadtrees and
  223.      Octrees are space partitioning trees which recursively divide subspaces
  224.      into four and eight new subspaces, respectively. A BSP Tree can be used to
  225.      simulate both of these structures.
  226.      --
  227.      Last Update: 04/30/95 15:45:19
  228.  
  229.   6. How do you build a BSP Tree?
  230.  
  231.      Overview
  232.      Given a set of polygons in three dimensional space, we want to build a BSP
  233.      tree which contains all of the polygons. For now, we will ignore the
  234.      question of how the resulting tree is going to be used.
  235.  
  236.      The algorithm to build a BSP tree is very simple:
  237.  
  238.        1. Select a partition plane.
  239.        2. Partition the set of polygons with the plane.
  240.        3. Recurse with each of the two new sets.
  241.  
  242.      Choosing the partition plane
  243.      The choice of partition plane depends on how the tree will be used, and
  244.      what sort of efficiency criteria you have for the construction. For some
  245.      purposes, it is appropriate to choose the partition plane from the input
  246.      set of polygons. Other applications may benefit more from axis aligned
  247.      orthogonal partitions.
  248.  
  249.      In any case, you want to evaluate how your choice will affect the results.
  250.      It is desirable to have a balanced tree, where each leaf contains roughly
  251.      the same number of polygons. However, there is some cost in achieving
  252.      this. If a polygon happens to span the partition plane, it will be split
  253.      into two or more pieces. A poor choice of the partition plane can result
  254.      in many such splits, and a marked increase in the number of polygons.
  255.      Usually there will be some trade off between a well balanced tree and a
  256.      large number of splits.
  257.  
  258.      Partitioning polygons
  259.      Partitioning a set of polygons with a plane is done by classifying each
  260.      member of the set with respect to the plane. If a polygon lies entirely to
  261.      one side or the other of the plane, then it is not modified, and is added
  262.      to the partition set for the side that it is on. If a polygon spans the
  263.      plane, it is split into two or more pieces and the resulting parts are
  264.      added to the sets associated with either side as appropriate.
  265.  
  266.      When to stop
  267.      The decision to terminate tree construction is, again, a matter of the
  268.      specific application. Some methods terminate when the number of polygons
  269.      in a leaf node is below a maximum value. Other methods continue until
  270.      every polygon is placed in an internal node. Another criteria is a maximum
  271.      tree depth.
  272.  
  273.      Pseudo C++ code example
  274.      Here is an example of how you might code a BSP tree:
  275.  
  276.      struct  BSP_tree
  277.      {
  278.         plane     partition;
  279.         list      polygons;
  280.         BSP_tree  *front,
  281.                   *back;
  282.      };
  283.  
  284.      This structure definition will be used for all subsequent example code. It
  285.      stores pointers to its children, the partitioning plane for the node, and
  286.      a list of polygons coincident with the partition plane. For this example,
  287.      there will always be at least one polygon in the coincident list: the
  288.      polygon used to determine the partition plane. A constructor method for
  289.      this structure should initialize the child pointers to NULL.
  290.  
  291.      void    Build_BSP_Tree (BSP_tree *tree, list polygons)
  292.      {
  293.         polygon   *root = polygons.Get_From_List ();
  294.         tree->partition = root->Get_Plane ();
  295.         tree->polygons.Add_To_List (root);
  296.         list      front_list,
  297.                   back_list;
  298.         polygon   *poly;
  299.         while ((poly = polygons.Get_From_List ()) != 0)
  300.         {
  301.            int   result = tree->partition.Classify_Polygon (poly);
  302.            switch (result)
  303.            {
  304.               case COINCIDENT:
  305.                  tree->polygons.Add_To_List (poly);
  306.                  break;
  307.               case IN_BACK_OF:
  308.                  backlist.Add_To_List (poly);
  309.                  break;
  310.               case IN_FRONT_OF:
  311.                  frontlist.Add_To_List (poly);
  312.                  break;
  313.               case SPANNING:
  314.                  polygon   *front_piece, *back_piece;
  315.                  Split_Polygon (poly, tree->partition, front_piece, back_piece);
  316.                  backlist.Add_To_List (back_piece);
  317.                  frontlist.Add_To_List (front_piece);
  318.                  break;
  319.            }
  320.         }
  321.         if ( ! front_list.Is_Empty_List ())
  322.         {
  323.            tree->front = new BSP_tree;
  324.            Build_BSP_Tree (tree->front, front_list);
  325.         }
  326.         if ( ! back_list.Is_Empty_List ())
  327.         {
  328.            tree->back = new BSP_tree;
  329.            Build_BSP_Tree (tree->back, back_list);
  330.         }
  331.      }
  332.  
  333.      This routine recursively constructs a BSP tree using the above definition.
  334.      It takes the first polygon from the input list and uses it to partition
  335.      the remainder of the set. The routine then calls itself recursively with
  336.      each of the two partitions. This implementation assumes that all of the
  337.      input polygons are convex.
  338.  
  339.      One obvious improvement to this example is to choose the partitioning
  340.      plane more intelligently. This issue is addressed separately in the
  341.      section, "How can you make a BSP Tree more efficient?".
  342.      --
  343.      Last Update: 05/08/95 13:10:25
  344.  
  345.   7. How do you partition a polygon with a plane?
  346.  
  347.      Overview
  348.      Partitioning a polygon with a plane is a matter of determining which side
  349.      of the plane the polygon is on. This is referred to as a front/back test,
  350.      and is performed by testing each point in the polygon against the plane.
  351.      If all of the points lie to one side of the plane, then the entire polygon
  352.      is on that side and does not need to be split. If some points lie on both
  353.      sides of the plane, then the polygon is split into two or more pieces.
  354.  
  355.      The basic algorithm is to loop across all the edges of the polygon and
  356.      find those for which one vertex is on each side of the partition plane.
  357.      The intersection points of these edges and the plane are computed, and
  358.      those points are used as new vertices for the resulting pieces.
  359.  
  360.      Implementation notes
  361.      Classifying a point with respect to a plane is done by passing the (x, y,
  362.      z) values of the point into the plane equation, Ax + By + Cz + D = 0. The
  363.      result of this operation is the distance from the plane to the point along
  364.      the plane's normal vector. It will be positive if the point is on the side
  365.      of the plane pointed to by the normal vector, negative otherwise. If the
  366.      result is 0, the point is on the plane.
  367.  
  368.      For those not familiar with the plane equation, The values A, B, and C are
  369.      the coordinate values of the normal vector. D can be calculated by
  370.      substituting a point known to be on the plane for x, y, and z.
  371.  
  372.      Convex polygons are generally easier to deal with in BSP tree construction
  373.      than concave ones, because splitting them with a plane always results in
  374.      exactly two convex pieces. Furthermore, the algorithm for splitting convex
  375.      polygons is straightforward and robust. Splitting of concave polygons,
  376.      especially self intersecting ones, is a significant problem in its own
  377.      right.
  378.  
  379.      Pseudo C++ code example
  380.      Here is a very basic function to split a convex polygon with a plane:
  381.  
  382.      void Split_Polygon (polygon *poly, plane *part, polygon *&front, polygon *&back)
  383.      {
  384.         int   count = poly->NumVertices (),
  385.               out_c = 0, in_c = 0;
  386.         point ptA, ptB,
  387.               outpts[MAXPTS],
  388.               inpts[MAXPTS];
  389.         real sideA, sideB;
  390.         ptA = poly->Vertex (count - 1);
  391.         sideA = part->Classify_Point (ptA);
  392.         for (short i = -1; ++i < count;)
  393.         {
  394.            ptB = poly->Vertex (i);
  395.            sideB = part->Classify_Point (ptB);
  396.            if (sideB > 0)
  397.            {
  398.               if (sideA < 0)
  399.               {
  400.                  // compute the intersection point of the line
  401.                  // from point A to point B with the partition
  402.                  // plane. This is a simple ray-plane intersection.
  403.                  vector v = ptB - ptA;
  404.                  real   sect = part->Classify_Point (-ptA) / (part->Normal () | v);
  405.                  outpts[out_c++] = inpts[in_c++] = ptA + (v * sect);
  406.               }
  407.               outpts[out_c++] = ptB;
  408.            }
  409.            else if (sideB < 0)
  410.            {
  411.               if (sideA > 0)
  412.               {
  413.                  // compute the intersection point of the line
  414.                  // from point A to point B with the partition
  415.                  // plane. This is a simple ray-plane intersection.
  416.                  vector v = ptB - ptA;
  417.                  real   sect = part->Classify_Point (-ptA) / (part->Normal () | v);
  418.                  outpts[out_c++] = inpts[in_c++] = ptA + (v * sect);
  419.               }
  420.               inpts[in_c++] = ptB;
  421.            }
  422.            else
  423.               outpts[out_c++] = inpts[in_c++] = ptB;
  424.            ptA = ptB;
  425.            sideA = sideB;
  426.         }
  427.         front = new polygon (outpts, out_c);
  428.         back = new polygon (inpts, in_c);
  429.      }
  430.  
  431.      A simple extension to this code that is good for BSP trees is to combine
  432.      its functionality with the routine to classify a polygon with respect to a
  433.      plane.
  434.  
  435.      Note that this code is not robust, since numerical stability may cause
  436.      errors in the classification of a point. The standard solution is to make
  437.      the plane "thick" by use of an epsilon value.
  438.      --
  439.      Last Update: 05/08/95 13:10:25
  440.  
  441.   8. How do you remove hidden surfaces with a BSP Tree?
  442.  
  443.      Overview
  444.      Probably the most common application of BSP trees is hidden surface
  445.      removal in three dimensions. BSP trees provide an elegant, efficient
  446.      method for sorting polygons via a depth first tree walk. This fact can be
  447.      exploited in a back to front "painter's algorithm" approach to the visible
  448.      surface problem, or a front to back scanline approach.
  449.  
  450.      BSP trees are well suited to interactive display of static (not moving)
  451.      geometry because the tree can be constructed as a preprocess. Then the
  452.      display from any arbitrary viewpoint can be done in linear time. Adding
  453.      dynamic (moving) objects to the scene is discussed in another section of
  454.      this document.
  455.  
  456.      Painter's algorithm
  457.      The idea behind the painter's algorithm is to draw polygons far away from
  458.      the eye first, followed by drawing those that are close to the eye. Hidden
  459.      surfaces will be written over in the image as the surfaces that obscure
  460.      them are drawn. One condition for a successful painter's algorithm is that
  461.      there be a single plane which separates any two objects. This means that
  462.      it might be necessary to split polygons in certain configurations. For
  463.      example, this case can not be drawn correctly with a painter's algorithm:
  464.  
  465.                                +------+
  466.                                |      |
  467.                +---------------|      |--+
  468.                |               |      |  |
  469.                |               |      |  |
  470.                |               |      |  |
  471.                |      +--------|      |--+
  472.                |      |        |      |
  473.             +--|      |--------+      |
  474.             |  |      |               |
  475.             |  |      |               |
  476.             |  |      |               |
  477.             +--|      |---------------+
  478.                |      |
  479.                +------+
  480.  
  481.      One reason that BSP trees are so elegant for the painter's algorithm is
  482.      that the splitting of difficult polygons is an automatic part of tree
  483.      construction. Note that only one of these two polygons needs to be split
  484.      in order to resolve the problem.
  485.  
  486.      To draw the contents of the tree, perform a back to front tree traversal.
  487.      Begin at the root node and classify the eye point with respect to its
  488.      partition plane. Draw the subtree at the far child from the eye, then draw
  489.      the polygons in this node, then draw the near subtree. Repeat this
  490.      procedure recursively for each subtree.
  491.  
  492.      Scanline hidden surface removal
  493.      It is just as easy to traverse the BSP tree in front to back order as it
  494.      is for back to front. We can use this to our advantage in a scanline
  495.      method method by using a write mask which will prevent pixels from being
  496.      written more than once. This will represent significant speedups if a
  497.      complex lighting model is evaluated for each pixel, because the painter's
  498.      algorithm will blindly evaluate the same pixel many times.
  499.  
  500.      The trick to making a scanline approach successful is to have an efficient
  501.      method for masking pixels. One way to do this is to maintain a list of
  502.      pixel spans which have not yet been written to for each scan line. For
  503.      each polygon scan converted, only pixels in the available spans are
  504.      written, and the spans are updated accordingly.
  505.  
  506.      The scan line spans can be represented as binary trees, which are just one
  507.      dimensional BSP trees. This technique can be expanded to a two dimensional
  508.      screen coverage algorithm using a two dimensional BSP tree to represent
  509.      the masked regions. Any convex partitioning scheme, such as a quadtree,
  510.      can be used with similar effect.
  511.  
  512.      Implementation notes
  513.      When building a BSP tree specifically for hidden surface removal, the
  514.      partition planes are usually chosen from the input polygon set. However,
  515.      any arbitrary plane can be used if there are no intersecting or concave
  516.      polygons, as in the example above.
  517.  
  518.      Pseudo C++ code example
  519.      Using the BSP_tree structure defined in the section, "How do you build a
  520.      BSP Tree?", here is a simple example of a back to front tree traversal:
  521.  
  522.      void    Draw_BSP_Tree (BSP_tree *tree, point eye)
  523.      {
  524.         real   result = tree->partition.Classify_Point (eye);
  525.         if (result > 0)
  526.         {
  527.            Draw_BSP_Tree (tree->back, eye);
  528.            tree->polygons.Draw_Polygon_List ();
  529.            Draw_BSP_Tree (tree->front, eye);
  530.         }
  531.         else if (result < 0)
  532.         {
  533.            Draw_BSP_Tree (tree->front, eye);
  534.            tree->polygons.Draw_Polygon_List ();
  535.            Draw_BSP_Tree (tree->back, eye);
  536.         }
  537.         else // result is 0
  538.         {
  539.            // the eye point is on the partition plane...
  540.            Draw_BSP_Tree (tree->front, eye);
  541.            Draw_BSP_Tree (tree->back, eye);
  542.         }
  543.      }
  544.  
  545.      If the eye point is classified as being on the partition plane, the
  546.      drawing order is unclear. This is not a problem if the Draw_Polygon_List
  547.      routine is smart enough to not draw polygons that are not within the
  548.      viewing frustum. The coincident polygon list does not need to be drawn in
  549.      this case, because those polygons will not be visible to the user.
  550.  
  551.      It is possible to substantially improve the quality of this example by
  552.      including the viewing direction vector in the computation. You can
  553.      determine that entire subtrees are behind the viewer by comparing the view
  554.      vector to the partition plane normal vector. This test can also make a
  555.      better decision about tree drawing when the eye point lies on the
  556.      partition plane. It is worth noting that this improvement resembles the
  557.      method for tracing a ray through a BSP tree, which is discussed in another
  558.      section of this document.
  559.  
  560.      Front to back tree traversal is accomplished in exactly the same manner,
  561.      except that the recursive calls to Draw_BSP_Tree occur in reverse order.
  562.      --
  563.      Last Update: 05/08/95 13:10:25
  564.  
  565.   9. How do you remove hidden lines with a BSP Tree?
  566.  
  567.      Overview
  568.  
  569.      --
  570.      Last Update: 04/30/95 15:45:19
  571.  
  572.  10. How do you accelerate ray tracing with a BSP Tree?
  573.  
  574.      Overview
  575.      Ray tracing a BSP tree is very similar to hidden surface removal with a
  576.      BSP tree. The algorithm is a simple forward tree walk, with a few
  577.      additions that apply to ray casting.
  578.  
  579.      MORE TO COME
  580.  
  581.  
  582.      --
  583.      Last Update: 04/30/95 15:45:19
  584.  
  585.  11. How do you perform boolean operations on polytopes with a BSP Tree?
  586.  
  587.      Overview
  588.      There are two major classes of solid modeling methods with BSP trees. For
  589.      both methods, it is useful to introduce the notion of an in/out test.
  590.  
  591.      An in/out test is a different way of talking about the front/back test we
  592.      have been using to classify points with respect to planes. The necessity
  593.      for this shift in thought is evident when considering polytopes instead of
  594.      just polygons. A point can not be merely in front or back of a polytope,
  595.      but inside or outside. Somewhat formally, a point is inside of a polytope
  596.      if it is inside of, or in back of, each hyperplane which composes the
  597.      polytope, otherwise it is outside.
  598.  
  599.      Incremental construction
  600.      Incremental construction of a BSP Tree is the process of inserting convex
  601.      polytopes into the tree one by one. Each polytope has to be processed
  602.      according to the operation desired.
  603.  
  604.      It is useful to examine the construction process in two dimensions.
  605.      Consider the following figure:
  606.  
  607.      A               B
  608.       +-------------+
  609.       |             |
  610.       |             |
  611.       |      E      |        F
  612.       |       +-----+-------+
  613.       |       |     |       |
  614.       |       |     |       |
  615.       |       |     |       |
  616.       +-------+-----+       |
  617.      D        |      C      |
  618.               |             |
  619.               |             |
  620.               +-------------+
  621.              H               G
  622.  
  623.      Two polygons, ABCD, and EFGH, are to be inserted into the tree. We wish to
  624.      find the union of these two polygons. Start by inserting polygon ABCD into
  625.      the tree, choosing the splitting hyperplanes to be coincident with the
  626.      edges. The tree looks like this after insertion of ABCD:
  627.  
  628.                      AB
  629.                    -/  \+
  630.                    /    \
  631.                   /      *
  632.                  BC
  633.                -/  \+
  634.                /    \
  635.               /      *
  636.              CD
  637.            -/  \+
  638.            /    \
  639.           /      *
  640.          DA
  641.        -/  \+
  642.        /    \
  643.       *      *
  644.  
  645.      Now, polygon EFGH is inserted into the tree, one polygon at a time. The
  646.      result looks like this:
  647.  
  648.      A               B
  649.       +-------------+
  650.       |             |
  651.       |             |
  652.       |      E      |J       F
  653.       |       +-----+-------+
  654.       |       |     |       |
  655.       |       |     |       |
  656.       |       |     |       |
  657.       +-------+-----+       |
  658.      D        |L    :C      |
  659.               |     :       |
  660.               |     :       |
  661.               +-----+-------+
  662.              H      K        G
  663.  
  664.                              AB
  665.                            -/  \+
  666.                            /    \
  667.                           /      *
  668.                          BC
  669.                        -/  \+
  670.                        /    \
  671.                       /      \
  672.                      CD       \
  673.                    -/  \+      \
  674.                    /    \       \
  675.                   /      \       \
  676.                  DA       \       \
  677.                -/  \+      \       \
  678.                /    \       \       \
  679.               /      *       \       \
  680.              EJ              KH       \
  681.            -/  \+          -/  \+      \
  682.            /    \          /    \       \
  683.           /      *        /      *       \
  684.          LE              HL              JF
  685.        -/  \+          -/  \+          -/  \+
  686.        /    \          /    \          /    \
  687.       *      *        *      *        FG     *
  688.                                     -/  \+
  689.                                     /    \
  690.                                    /      *
  691.                                   GK
  692.                                 -/  \+
  693.                                 /    \
  694.                                *      *
  695.  
  696.      Notice that when we insert EFGH, we split edges EF and HE along the edges
  697.      of ABCD. this has the effect of dividing these segments into pieces which
  698.      are inside ABCD, and outside ABCD. Segments EJ and LE will not be part of
  699.      the boundary of the union. We could have saved our selves some work by not
  700.      inserting them into the tree at all. For a union operation, you can always
  701.      throw away segments that land in inside nodes. You must be careful about
  702.      this though. What I mean is that any segments which land in inside nodes
  703.      of side the pre-existing tree, not the tree as it is being constructed. EJ
  704.      and LE landed in an inside node of the tree for polygon ABCD, and so can
  705.      be discarded.
  706.  
  707.      Our tree now looks like this:
  708.  
  709.      
  710.      A               B
  711.       +-------------+
  712.       |             |
  713.       |             |
  714.       |             |J       F
  715.       |             +-------+
  716.       |             |       |
  717.       |             |       |
  718.       |             |       |
  719.       +-------+-----+       |
  720.      D        |L    :C      |
  721.               |     :       |
  722.               |     :       |
  723.               +-----+-------+
  724.              H      K        G
  725.  
  726.                              AB
  727.                            -/  \+
  728.                            /    \
  729.                           /      *
  730.                          BC
  731.                        -/  \+
  732.                        /    \
  733.                       /      \
  734.                      CD       \
  735.                    -/  \+      \
  736.                    /    \       \
  737.                   /      \       \
  738.                  DA       \       \
  739.                -/  \+      \       \
  740.                /    \       \       \
  741.               *      *       \       \
  742.                              KH       \
  743.                            -/  \+      \
  744.                            /    \       \
  745.                           /      *       \
  746.                          HL              JF
  747.                        -/  \+          -/  \+
  748.                        /    \          /    \
  749.                       *      *        FG     *
  750.                                     -/  \+
  751.                                     /    \
  752.                                    /      *
  753.                                   GK
  754.                                 -/  \+
  755.                                 /    \
  756.                                *      *
  757.  
  758.      Now, we would like some way to eliminate the segments JC and CL, so that
  759.      we will be left with the boundary segments of the union. Examine the
  760.      segment BC in the tree. What we would like to do is split BC with the
  761.      hyperplane JF. Conveniently, we can do this by pushing the BC segment
  762.      through the node for JF. The resulting segments can be classified with the
  763.      rest of the JF subtree. Notice that the segment BJ lands in an out node,
  764.      and that JC lands in an in node. Remembering that we can discard interior
  765.      nodes, we can eliminate JC. The segment BJ replaces BC in the original
  766.      tree. This process is repeated for segment CD, yielding the segments CL
  767.      and LD. CL is discarded as landing in an interior node, and LD replaces CD
  768.      in the original tree. The result looks like this:
  769.  
  770.      
  771.      A               B
  772.       +-------------+
  773.       |             |
  774.       |             |
  775.       |             |J       F
  776.       |             +-------+
  777.       |                     |
  778.       |                     |
  779.       |        L            |
  780.       +-------+             |
  781.      D        |             |
  782.               |             |
  783.               |             |
  784.               +-----+-------+
  785.              H      K        G
  786.  
  787.                              AB
  788.                            -/  \+
  789.                            /    \
  790.                           /      *
  791.                          BJ
  792.                        -/  \+
  793.                        /    \
  794.                       /      \
  795.                      LD       \
  796.                    -/  \+      \
  797.                    /    \       \
  798.                   /      \       \
  799.                  DA       \       \
  800.                -/  \+      \       \
  801.                /    \       \       \
  802.               *      *       \       \
  803.                              KH       \
  804.                            -/  \+      \
  805.                            /    \       \
  806.                           /      *       \
  807.                          HL              JF
  808.                        -/  \+          -/  \+
  809.                        /    \          /    \
  810.                       *      *        FG     *
  811.                                     -/  \+
  812.                                     /    \
  813.                                    /      *
  814.                                   GK
  815.                                 -/  \+
  816.                                 /    \
  817.                                *      *
  818.  
  819.      As you can see, the result is the union of the polygons ABCD and EFGH.
  820.  
  821.      To perform other boolean operations, the process is similar. For
  822.      intersection, you discard segments which land in exterior nodes instead of
  823.      internal ones. The difference operation is special. It requires that you
  824.      invert the polytope before insertion. For simple objects, this can be
  825.      achieved by scaling with a factor of -1. The insertion process is then
  826.      cinducted as an intersection operation, where segments landing in external
  827.      nodes are discarded.
  828.  
  829.      Tree merging
  830.  
  831.      --
  832.      Last Update: 04/30/95 15:45:20
  833.  
  834.  12. How do you perform collision detection with a BSP Tree?
  835.  
  836.      Overview
  837.      Detecting whether or not a point moving along a line intersects some
  838.      object in space is essentially a ray tracing problem. Detecting whether or
  839.      not two complex objects intersect is something of a tree merging problem.
  840.  
  841.      Typically, motion is computed in a series of Euler steps. This just means
  842.      that the motion is computed at discrete time intervals using some
  843.      description of the speed of motion. For any given point P moving from
  844.      point A with a velocity V, it's location can be computed at time T as P =
  845.      A + (T * V).
  846.  
  847.      Consider the case where T = 1, and we are computing the motion in one
  848.      second steps. To find out if the point P has collided with any part of the
  849.      scene, we will first compute the endpoints of the motion for this time
  850.      step. P1 = A + V, and P2 = A + (2 * V). These two endpoints will be
  851.      classified with respect to the BSP tree. If P1 is outside of all objects,
  852.      and P2 is inside some object, then an intersection has clearly occurred.
  853.      However, if P2 is also outside, we still have to check for a collision in
  854.      between.
  855.  
  856.      Two approaches are possible. The first is commonly used in applications
  857.      like games, where speed is critical, and accuracy is not. This approach is
  858.      to recursively divide the motion segment in half, and check the midpoint
  859.      for containment by some object. Typically, it is good enough to say that
  860.      an intersection occurred, and not be very accurate about where it
  861.      occurred.
  862.  
  863.      The second approach, which is more accurate, but also more time consuming,
  864.      is to treat the motion segment as a ray, and intersect the ray with the
  865.      BSP Tree. This also has the advantage that the motion resulting from the
  866.      impact can be computed more accurately.
  867.      --
  868.      Last Update: 04/30/95 15:45:20
  869.  
  870.  13. How do you handle dynamic scenes with a BSP Tree?
  871.  
  872.      Overview
  873.      So far the discussion of BSP tree structures has been limited to handling
  874.      objects that don't move. However, because the hidden surface removal
  875.      algorithm is so simple and efficient, it would be nice if it could be used
  876.      with dynamic scenes too. Faster animation is the goal for many
  877.      applications, most especially games.
  878.  
  879.      The BSP tree hidden surface removal algorithm can easily be extended to
  880.      allow for dynamic objects. For each frame, start with a BSP tree
  881.      containing all the static objects in the scene, and reinsert the dynamic
  882.      objects. While this is straightforward to implement, it can involve
  883.      substantial computation.
  884.  
  885.      If a dynamic object is separated from each static object by a plane, the
  886.      dynamic object can be represented as a single point regardless of its
  887.      complexity. This can dramatically reduce the computation per frame because
  888.      only one node per dynamic object is inserted into the BSP tree. Compare
  889.      that to one node for every polygon in the object, and the reason for the
  890.      savings is obvious. During tree traversal, each point is expanded into the
  891.      original object.
  892.  
  893.      Implementation notes
  894.      Inserting a point into the BSP tree is very cheap, because there is only
  895.      one front/back test at each node. Points are never split, which explains
  896.      the requirement of separation by a plane. The dynamic object will always
  897.      be drawn completely in front of the static objects behind it.
  898.  
  899.      A dynamic object inserted into the tree as a point can become a child of
  900.      either a static or dynamic node. If the parent is a static node, perform a
  901.      front/back test and insert the new node appropriately. If it is a dynamic
  902.      node, a different front/back test is necessary, because a point doesn't
  903.      partition three dimesnional space. The correct front/back test is to
  904.      simply compare distances to the eye. Once computed, this distance can be
  905.      cached at the node until the frame is drawn.
  906.  
  907.      An alternative when inserting a dynamic node is to construct a plane whose
  908.      normal is the vector from the point to the eye. This plane is used in
  909.      front/back tests just like the partition plane in a static node. The plane
  910.      should be computed lazily and it is not necessary to normalize the vector.
  911.  
  912.      Cleanup at the end of each frame is easy. A static node can never be a
  913.      child of a dynamic node, since all dynamic nodes are inserted after the
  914.      static tree is completed. This implies that all subtrees of dynamic nodes
  915.      can be removed at the same time as the dynamic parent node.
  916.  
  917.      Advanced methods
  918.      Tree merging, "ghosts", real dynamic trees... MORE TO COME
  919.      --
  920.      Last Update: 04/29/95 03:14:22
  921.  
  922.  14. How do you compute shadows with a BSP Tree?
  923.  
  924.      Overview
  925.  
  926.      --
  927.      Last Update: 04/30/95 15:45:20
  928.  
  929.  15. How do you extract connectivity information from BSP Trees?
  930.  
  931.      Overview
  932.  
  933.      --
  934.      Last Update: 04/30/95 15:45:20
  935.  
  936.  16. How are BSP Trees useful for robot motion planning?
  937.  
  938.      Overview
  939.  
  940.      --
  941.      Last Update: 04/30/95 15:45:20
  942.  
  943.  17. How are BSP Trees used in DOOM?
  944.  
  945.      Overview
  946.      Before you can understand how DOOM uses a BSP tree to accelerate its
  947.      rendering process, you have to understand how the world is represented in
  948.      DOOM. When someone creates a DOOM level in a level editor they draw
  949.      linedefs in a 2d space. Yes, that's right, DOOM is only 2d. These linedefs
  950.      (ignoring the special effects linedefs) must be arranged so that they form
  951.      closed polygons. One linedef may be used to form the outline of two
  952.      polygons (in which case it is known as a two-sided linedef) and one
  953.      polygon may be contained within another, but no linedefs may cross. Each
  954.      enclosed area of the world (i.e. polygon) is assigned a floor height,
  955.      ceiling height, floor and ceiling textures, a lower texture and an upper
  956.      texture. The lower texture is visible when a linedef is viewed from a
  957.      direction where the floor is lower in the adjoining area. An equivalent
  958.      thing is true for the upper texture. A set of these enclosed areas that
  959.      all have the same attributes is known as a sector.
  960.  
  961.      When the level is saved by the editor some new information is created
  962.      including the BSP tree for that level. Before the BSP tree can be created,
  963.      all the sectors have to be split into convex polygons known as
  964.      sub-sectors. If you had a sector that was a square area, then that would
  965.      translate exactly into a sub-sector. Whereas if that sector was contained
  966.      inside another larger square sector, the larger one would have to be split
  967.      into four, four sided sub-sectors to make all the sub-sectors convex. When
  968.      more complex sectors are split into sub-sectors the linedefs that bound
  969.      that sector may need to be broken into smaller lengths. These linedef
  970.      sections are called segs.
  971.  
  972.      Given a point on the 2d map, the renderer (which isn't discussed here)
  973.      wants a list of all the segs that are visible from that viewpoint in
  974.      closest first order. Because of the restrictions placed on the DOOM world,
  975.      the renderer can easily tell when the screen has been filled so it can
  976.      stop looking for segs at this time. This is quicker than rendering all the
  977.      segs from back to front and using a method like painters algorithm.
  978.  
  979.      Each node in the BSP tree defines a partition line (this does not have be
  980.      a linedef in the world but usually is) which is the equivalent to the
  981.      partition plane of a 3d BSP tree. It then has left and right pointers
  982.      which are either another node for further sub-division or a leaf, the leaf
  983.      being a sub-sector in DOOM. The BSP tree in DOOM is effectively being used
  984.      to sort whole sub-sectors rather than individual lines front to back. Each
  985.      node also defines an orthogonal bounding box for each side of the
  986.      partition. All segs on a particular side of the partition must be within
  987.      that box. This speeds up the searching process by allowing whole branches
  988.      of the tree to be discarded if that bounding box isn't visible. The test
  989.      for visibility is simply if the bounding box lies wholly or partly within
  990.      the cone defined by the left and right edges of the screen.
  991.  
  992.      During the display update process the BSP tree is searched starting from
  993.      the node containing the sub-sector that the player is currently in. The
  994.      search moves outwards through the tree (searching the other half of the
  995.      current node before moving onto the other half of the parents node). When
  996.      a partition test is performed the branch chosen is the one on the same
  997.      side as the player. This facilitates the front to back searching. Each
  998.      time a leaf is encountered the segs in that sub-sector are passed to the
  999.      renderer. If the renderer has returned that the screen is filled then the
  1000.      process stops, otherwise it continues until the tree has been fully
  1001.      searched (in which case there is an error in the level design).
  1002.  
  1003.      In case you're thinking that it is inefficient to dump a whole sub-sectors
  1004.      worth of segs into the renderer at once, the segs in a sub-sector can be
  1005.      back-face culled very quickly. DOOM stores the angle of linedefs (of which
  1006.      segs are part). When the angle of the players view is calculated this
  1007.      allows segs to be culled in a single instruction! Angles are stored as a
  1008.      16 bit number where 0 is east an 65535 is 1/63336 south of east.
  1009.      --
  1010.      Last Update: 04/30/95 15:45:20
  1011.  
  1012.  18. How can you make a BSP Tree more robust?
  1013.  
  1014.      Overview
  1015.  
  1016.      --
  1017.      Last Update: 04/30/95 15:45:20
  1018.  
  1019.  19. How efficient is a BSP Tree?
  1020.  
  1021.      Space complexity
  1022.      For hidden surface removal and ray tracing accelleration, the upper bound
  1023.      is O(n ^ 2) for n polygons. The expected case is O(n) for most models.
  1024.      MORE LATER
  1025.  
  1026.      Time complexity
  1027.      For hidden surface removal and ray tracing accelleration, the upper bound
  1028.      is O(n ^ 2) for n polygons. The expected case is O(n) for most models.
  1029.      MORE LATER
  1030.      --
  1031.      Last Update: 04/30/95 15:45:20
  1032.  
  1033.  20. How can you make a BSP Tree more efficient?
  1034.  
  1035.      Bounding volumes
  1036.      Bounding spheres are simple to implement, take only a single plane
  1037.      comparison, using the center of the sphere.
  1038.  
  1039.      Tree balancing
  1040.      For hidden surface problem, doesn't affect runtime, assuming that no
  1041.      splitting occurs...
  1042.  
  1043.      Balancing vs. splitting
  1044.      Reference Counting
  1045.      Other Optimizations
  1046.  
  1047.      --
  1048.      Last Update: 03/02/95 23:40:07
  1049.  
  1050.  21. How can you avoid recursion?
  1051.  
  1052.      standard binary tree search/sort techniques apply.
  1053.      --
  1054.      Last Update: 03/02/95 23:40:07
  1055.  
  1056.  22. What is the history of BSP Trees?
  1057.  
  1058.      Overview
  1059.  
  1060.      --
  1061.      Last Update: 04/30/95 15:45:20
  1062.  
  1063.  23. Where can you find sample code?
  1064.  
  1065.      The companion source code to this document is available via FTP at:
  1066.  
  1067.           file://ray.graphics.cornell.edu/pub/bsptree/
  1068.  
  1069.      or, you can also request that the source be mailed to you by sending
  1070.      e-mail to bsp-faq@graphics.cornell.edu with a subject line of "SEND BSP
  1071.      TREE SOURCE". This will return to you a UU encoded copy of the sample C++
  1072.      source code.
  1073.  
  1074.      Pat Fleckenstein and Rob Reay have put together a FAQ on 3D graphics,
  1075.      which includes a blurb on BSP Trees, and an ftp site with some sample
  1076.      code:
  1077.  
  1078.           3D FAQ
  1079.           file://ftp.csh.rit.edu/pub/3dfaq/
  1080.  
  1081.      Other sources for sample BSP Tree code are:
  1082.  
  1083.           file://ftp.idsoftware.com/tonsmore/utils/level_edit/node_builders/
  1084.           file://ftp.princeton.edu/pub/Graphics/GraphicsGems/GemsIII/
  1085.           file://ftp.princeton.edu/pub/Graphics/GraphicsGems/GemsV/
  1086.           file://ftp.cs.brown.edu/pub/sphigs.tar.Z
  1087.  
  1088.      --
  1089.      Last Update: 05/09/95 02:56:49
  1090.  
  1091.  24. References
  1092.  
  1093.  25. Dadoun, N., Kirkpatrick, D., and Walsh, J., The Geometry of Beam Tracing,
  1094.      Proceedings of the ACM Symposium on Computational Geometry, 55--61, jun
  1095.      1985.
  1096.  
  1097.  26. Chin, N., and Feiner, S., Near Real-Time Shadow Generation Using BSP
  1098.      Trees, Computer Graphics (SIGGRAPH '89 Proceedings), 23(3), 99--106, jul
  1099.      1989.
  1100.  
  1101.  27. Chin, N., and Feiner, S., Fast object-precision shadow generation for area
  1102.      light sources using BSP trees, Computer Graphics (1992 Symposium on
  1103.      Interactive 3D Graphics), 25(2), 21--30, mar 1992.
  1104.  
  1105.  28. Chrysanthou, Y., and Slater, M., Computing dynamic changes to BSP trees,
  1106.      Computer Graphics Forum (EUROGRAPHICS '92 Proceedings), 11(3), 321--332,
  1107.      sep 1992.
  1108.  
  1109.  29. Naylor, B., Amanatides, J., and Thibault, W., Merging BSP Trees Yields
  1110.      Polyhedral Set Operations, Computer Graphics (SIGGRAPH '90 Proceedings),
  1111.      24(4), 115--124, aug 1990.
  1112.  
  1113.  30. Chin, N., and Feiner, S., Fast object-precision shadow generation for
  1114.      areal light sources using BSP trees, Computer Graphics (1992 Symposium on
  1115.      Interactive 3D Graphics), 25(2), 21--30, mar 1992.
  1116.  
  1117.  31. Naylor, B., Interactive solid geometry via partitioning trees, Proceedings
  1118.      of Graphics Interface '92, 11--18, may 1992.
  1119.  
  1120.  32. Naylor, B., Partitioning tree image representation and generation from 3D
  1121.      geometric models, Proceedings of Graphics Interface '92, 201--212, may
  1122.      1992.
  1123.  
  1124.  33. Naylor, B., {SCULPT} An Interactive Solid Modeling Tool, Proceedings of
  1125.      Graphics Interface '90, 138--148, may 1990.
  1126.  
  1127.  34. Gordon, D., and Chen, S., Front-to-back display of BSP trees, IEEE
  1128.      Computer Graphics and Applications, 11(5), 79--85, sep 1991.
  1129.  
  1130.  35. Ihm, I., and Naylor, B., Piecewise linear approximations of digitized
  1131.      space curves with applications, Scientific Visualization of Physical
  1132.      Phenomena (Proceedings of CG International '91), 545--569, 1991.
  1133.  
  1134.  36. Vanecek, G., Brep-index: a multidimensional space partitioning tree,
  1135.      Internat. J. Comput. Geom. Appl., 1(3), 243--261, 1991.
  1136.  
  1137.  37. Arvo, J., Linear Time Voxel Walking for Octrees, Ray Tracing News, feb
  1138.      1988.
  1139.  
  1140.  38. Jansen, F., Data Structures for Ray Tracing, Data Structures for Raster
  1141.      Graphics, 57--73, 1986.
  1142.  
  1143.  39. MacDonald, J., and Booth, K., Heuristics for Ray Tracing Using Space
  1144.      Subdivision, Proceedings of Graphics Interface '89, 152--63, jun 1989.
  1145.  
  1146.  40. Naylor, B., and Thibault, W., Application of BSP Trees to Ray Tracing and
  1147.      CSG Evaluation, Tech. Rep. GIT-ICS 86/03, feb 1986.
  1148.  
  1149.  41. Sung, K., and Shirley, P., Ray Tracing with the BSP Tree, Graphics Gems
  1150.      III, 271--274, 1992.
  1151.  
  1152.  42. Fuchs, H., Kedem, Z., and Naylor, B., On Visible Surface Generation by A
  1153.      Priori Tree Structures, Conf. Proc. of SIGGRAPH '80, 14(3), 124--133, jul
  1154.      1980.
  1155.  
  1156.  43. Paterson, M., and Yao, F., Efficient Binary Space Partitions for
  1157.      Hidden-Surface Removal and Solid Modeling, Discrete and Computational
  1158.      Geometry, 5(5), 485--503, 1990.
  1159.  
  1160.  
  1161.      --
  1162.      Last Update: 04/30/95 15:45:20
  1163.  
  1164.     ------------------------------------------------------------------------
  1165.  
  1166. This document was last updated on Sunday, 26-Mar-95 19:22:54 EST
  1167. Bretton Wade (bwade@graphics.cornell.edu)
  1168.