BspLib
 
INTRODUCTION
 
BspLib is a C++ class library from which a BSP compiler for 3-D objects can be built very easily. It consists of a class hierarchy for handling three-dimensional objects, together with various processing functions, the most important of which is BSP compilation. An I/O class hierarchy is provided for importing and exporting 3-D data. Aside from proprietary formats BspLib is capable of reading VRML V1.0 data files. A slightly modified version of Silicon Graphics' QvLib is employed for parsing the VRML V1.0 file format. Apart from the included version of QvLib, BspLib is completely self-contained, i.e., only the standard C++ run-time library (no STL needed!) need be linked to be able to use all functions. This, for example, means that VRML primitives (spheres, boxes, cones, cylinders) have to be tessellated on-the-fly prior to BSP compilation, in order to convert them to b-reps that can be BSP compiled. Since BspLib is able to create BSP trees for entire VRML scene graphs this also means that all transformations and modifications demanded by the scene graph have to be applied to achieve correct spatial relationships between contained objects, without which BSP compilation is not possible. Normally, all this would only be done when rendering the scene, since OpenGL supports exactly those operations very easily. That is, primitives would be submitted to OpenGL in implicit (non-polygonal) form and transformations would be done on-the-fly through OpenGL's matrix stack. Since one goal of BspLib was to make it possible to build a purely command-line BSP compiler without any additional libraries, potentially running on a large variety of platforms (which only need to support C++), OpenGL could not be used to alleviate the problem of supporting an entire VRML scene graph. So, in contrast to many VRML viewers, some basic OpenGL functionality had to be duplicated within BspLib.
 
CONTENTS
 
The BspLib documentation consists of the following sections: 

1. GENERAL STRUCTURE 
2. CLASS HIERARCHIES 
3. INPUT/OUTPUT CLASS HIERARCHY 
4. GEOMETRY CLASSES 
5. BSP TREE TYPES 
6. PROCESSING FUNCTIONS 
7. A MINIMAL BSP COMPILER

 

 
1. GENERAL STRUCTURE
 
BspLib consists of a collection of C++ classes. All of BspLib's classes are contained in the BspLib namespace (this may be turned off via a preprocessor macro and subsequent recompilation, though). With only very few exceptions, each class's interface is contained in its own header file (class-name.h). If a class contains non-inline functions, its implementation is contained in a single separate C++ file (class-name.cpp). Some global definitions and declarations are contained in BspLibDefs.h, which is included by every header of BspLib. All in all, BspLib is comprised of 56 classes and two class templates. Additionally, in order to be able to read VRML V1.0 files, a slightly modified version of Silicon Graphics' QvLib must be linked. 

All interface classes of BspLib (that is, all classes normally used by the user) using dynamic storage are separated into handle and representation classes. The handle class is what the application programmer actually uses. Basically, a handle class is just a pointer to the representation class. Every time a handle is instanced, the reference count contained in the representation is incremented. Dynamic storage will only be freed when this count reaches zero. This scheme allows for efficient copying of objects containing large amounts of dynamically allocated data (without provoking storage maintenance problems, or mandating deep-copy of objects). A representation class for a handle class Test is named TestRep. The representation class should never be used directly, in order to allow for correct reference-counting and avoid problems with handling of dynamic storage! 

Another important concept in BspLib is the so-called chunk. A chunk (implemented via templates Chunk<> and ChunkRep<>) basically is just an array that expands itself if too few indexes are available, performs index validation, and so on. Primitives in BspLib are most of the time either stored in singly linked lists or in such chunks. For example, a 3-D object contains chunks for vertices, faces, textures, mappings, and a list for polygons. The basic array nature of a chunk notwithstanding it is dynamic storage referenced via a pointer, can be copied very easily (using reference-counting to avoid deep-copy, see preceding paragraph) and provides data abstraction, since the implementation is hidden from the user. 

Note that BspLib uses RTTI (run-time type information), so this feature must be supported and enabled in order to compile and use BspLib.

 

 
2. CLASS HIERARCHIES
 
Most classes in BspLib belong to one of two distinct class hierarchies. First, there is a class hierarchy encompassing all geometrical classes. This includes very low-level primitives like vertices and vectors (e.g., class Vertex3 and class Vector3), and linesegments (class LineSeg2, class LineSeg3), primitives of intermediate complexity like polygons (class Polygon), and very powerful aggregate classes like class BspObject, which represents an entire geometrical object and utilizes many of the more primitive classes in order to be able to store and manipulate them. This collection of classes is no strict hierarchy. In fact, most of these classes may be bound to other classes at run-time via pointers but are not related through inheritance. The second class hierarchy where virtually all classes are related through inheritance is the I/O class hierarchy. These classes are responsible for parsing input data files, creating the scene graph, and writing the current scene graph to output data files of various formats. An input data file can be read and parsed by simply instancing class InputData3D, for example. Finally, since BspLib uses Silicon Graphics' QvLib to parse VRML V1.0 files there is also a number of classes with the 'Qv' prefix to the class name, comprising QvLib.
 

 
3. INPUT/OUTPUT CLASS HIERARCHY
 
In order to be able to import and export three-dimensional data BspLib contains a hierarchy of I/O classes. These classes are used for all input and output purposes. The application programmer basically just needs to instance InputData3D and OutputData3D objects to read and write object data. These will be explained in detail below. 

BspLib's I/O hierarchy currently supports input and output of the proprietary AOD and BSP formats, as well as VRML V1.0 input (VRML output is not available). 

The following figure shows the entire I/O class hierarchy of BspLib, arrows denote inheritance: 

   

 I/O Class Hierarchy
 

In the following we describe each of these I/O classes briefly (the only two classes important for an application programmer using BspLib are InputData3D and OutputData3D): 

  • SystemIO

  • This is the base class for all I/O classes (and also all other classes needing host system-services, e.g., message output). It encapsulates host system-dependent code and provides basic facilities like file access, error message output, and the like. 
     
  • IOData3D

  • This is the base class for all classes related to file I/O. 

  • InputData3D

  • This class encapsulates all input functionality. It provides an abstract input interface to the application programmer. The user can instance an InputData3D object, passing the input file's name and an object of class BspObjectList to the constructor. The input file will then be read and parsed automatically, the input format is directly determined from the specified file itself. The passed in BspObjectList will then contain 3-D object representations for all data contained in the input file. That is, after correctly instancing an InputData3D object, the resulting BspObjectList is ready to be used for geometrical processing, rendering, and so on. InputData3D will instance AodInput, BspInput, and VrmlFile objects, according to the detected input format. If automatic format detection is not desired these classes may be used directly. 

  • OutputData3D

  • This class encapsulates all output functionality. It provides an abstract output interface to the application programmer. The user can instance an OutputData3D object, passing the output file's name and an object of class BspObjectList to the constructor. Everything described by the passed in BspObjectList will then be written to the output file upon destruction of the OutputData3D object, the output format being determined by the file name's extension. Alternatively, an InputData3D object may be provided to the constructor, along with the desired output format. The input file name with an accordingly altered file name extension will then be used as output file. OutputData3D will instance AodOutput and BspOutput objects, according to the desired output format. If this semi-automatic output format detection is not desired these classes may be used directly. 
     
  • VrmlFile

  • A VrmlFile object is used to read and parse VRML V1.0 files. This class employs Silicon Graphics' QvLib for parsing. An object of class BRep is used to interface QvLib to BspLib. BRep is capable of tessellating VRML primitives and converting VRML shape nodes to BspLib 3-D objects. This class will also apply necessary transformations and other conversions (e.g., texture transformations via VRML's Texture2Transform node, material application, and so on) to facilitate BspLib's further operation on the VRML scene graph. 
     
  • SingleFormat
  • SingleInput
  • SingleOutput

  • SingleFormat contains everything AOD and BSP files have in common. SingleInput provides input functionality for the common part of AOD and BSP files. SingleOutput provides output functionality for the common part of AOD and BSP files. 
     
  • AodFormat
  • AodInput
  • AodOutput

  • These classes contain everything that the AOD format supports in addition to the common format (SingleFormat). 
     
  • BspFormat
  • BspInput
  • BspOutput

  • These classes contain everything that the BSP format supports in addition to the common format (SingleFormat). 
     
  • ObjectAodFormat

  • Inherits 3-D object properties from BspObject and file format properties from AodFormat. The result is an object that is able to write 3-D information in AOD format. 
     
  • ObjectBspFormat

  • Inherits 3-D object properties from BspObject and file format properties from BspFormat. The result is an object that is able to write 3-D information in BSP format.
An example for how to use the InputData3D and OutputData3D classes may be found in the chapter on a minimal BSP compiler.
 

 
4. GEOMETRY CLASSES
 
A large part of BspLib is responsible for representing geometrical entities. Normally, input data is read from any of the input formats supported by the I/O class hierarchy and 3-D representations are created during parsing. As soon as the geometrical representation has been created it can be used for rendering, for instance. Rendering has to be done by the application using BspLib, though. The library itself provides no such functionality, it only represents three-dimensional data and provides various geometry processing functions that can be invoked to operate on objects. The most important object processing function provided by BspLib is, of course, BSP compilation. 

The most important graphical entity in BspLib is the BspObject (class BspObject) which describes a single b-rep object, its material properties, and - if already compiled - its BSP tree. In order to be able to operate on many objects at once, BspObjects can be part of a BspObjectList (class BspObjectList). Normally, a BspObjectList is used to represent the entire scene. Processing functions can be invoked for such a list and BspLib will process all objects contained in it in the same way. Thus, the entire scene can be operated upon (for example, BSP compiled) very easily. 

The following figure shows what a scene consisting of multiple objects could look like on the data-structure level: 
 

BspObjectList and PolygonList
 

The most important member of each BspObject is a PolygonList, which essentially is the object's boundary representation. For a description of a BspObject and all its fields see class BspObject. (Remember that all interface objects in BspLib are separated into handle and representation classes. Thus, the actual lists are of classes BSPObjectListRep and PolygonListRep, respectively, although the user uses class BSPObjectList and class PolygonList.) 

Here is a list of all other major geometry-related classes provided/used by BspLib: 

4.1 Geometry class descriptions

4.1.1 class BspObject

This is the single most powerful class in BspLib. It represents a graphical object in its entirety. Thus, it necessarily contains all the geometrical data associated with such an object. A BspObject is comprised of the following parts: 
  • List of vertices (chunk of class Vertex3)

  • An object's vertices are triplets specifying the vertex's x, y, and z coordinates. (Well, actually there is also a w component, but this is normally not used for ordinary vertices.) 
     
  • List of polygons (class PolygonList)

  • A polygon is comprised of a list of vertexindexes. These index into the vertexlist and specify the polygon's vertices as seen from their front-side in clockwise order. The polygonlist contains all polygons prior to BSP compilation in no specific order. During BSP compilation the original polygonlist is dissolved. Afterwards, polygons can only be accessed through the BSP tree. Every BSP node has one or more polygons attached to it. (There may also be BSP nodes with no attached polygons at all, these are separator planes only.) 
     
  • List of faces (chunk of class Face)

  • In contrast to polygons, faces primarily specify surface properties, say, in terms of material and color (there may be color information not already included in the material). A face is comprised of one to many polygons. Originally, faces and polygons have a one to one correspondence. During BSP compilation, however, polygons have to be split. Split polygons retain their original properties apart from geometry, that is, they still belong to the same face afterwards. This also holds for face normals, which, of course, stay the same when polygons get split. Hence, normals are also associated with faces instead of with every polygon. 
     
  • List of textures (chunk of class Texture)

  • This list specifies all textures that may be used by this object. This specification is only done in terms of texture properties, texture coordinates are not involved here! 
     
  • List of mappings (chunk of class Mapping)

  • This list specifies correspondences for texture mapping. This is normally only used during parsing, correspondences will be converted to affine mappings and be contained directly in the faces of the object later on. 
     
  • Linked bsp tree (class BSPTree)

  • If a BSP tree has been compiled for this object, it is contained in this field. Such a BSP tree is dynamically linked. 
     
  • Flat bsp tree (class BSPTreeFlat)

  • In addition to a dynamically linked BSP tree there may be a flat (array) version of it. This is usually used immediately after parsing, because it's easier to parse the tree line by line into an array and build the dynamic version afterwards. 
     
  • Attached transformation (class Transform3)

  • A general transformation matrix may be attached. As long as this transformation is only attached, it has not been applied yet. In order to actually transform the object and alter vertex coordinates accordingly, BspObject::ApplyTransformation() must be invoked. 
     
  • Object name

  • Every BspObject may have a name assigned to it. 
     
  • Pointer to next BspObject in list

  • This field points to the next node in the list of BspObjects.

4.1.2 class BspObjectList

Represents a list of BspObjects. Since every BspObject includes a next field, the actual list is internal to the BspObjects themselves. A BspObjectList is primarily used as a standard interface to the entire list, to invoke processing functions for all BspObjects contained in the list, and for list handling in general, e.g., copying with reference counting. BspObjectList is the most important class for an application programmer using BspLib, since it is normally used to represent the entire scene. Objects in a scene are usually nodes of a BspObjectList in no particular order. The most important member function of a BspObjectList is BspObjectList::ProcessObjects(). This function is invoked with an integer parameter which is interpreted as a bit field. That is, every bit controls a specific processing function. BspObjectList::ProcessObjects() scans the entire list and invokes the corresponding processing functions for each node. 

4.1.3 class BoundingBox

A BoundingBox can be attached to each BSP tree node, encompassing all polygons of this node and its children. Therefore it can be used for viewing frustum culling, for instance. Every BoundingBox is axial and specified via its minimum and maximum extents in all three coordinate axes. BoundingBoxes can be merged and a spatial partitioning can be created, yielding a BSP tree of BoundingBoxes (objects). This can be used to separate objects cleanly as long as possible without splitting any polygons. BoundingBoxes that cannot be separated will be merged. 

4.1.4 class BSPNode

This class defines a single node of a BSP tree. Each node may contain polygons lying in the same plane (the node's plane) and may have front-, and back-subtrees (pointers to other BSPNodes). 

Each BSPNode consists of the following fields: 
 
 

field name description
nodeid id of this node
polygon pointer to list of contained front-facing polygons
backpolygon pointer to list of contained back-facing polygons
fronttree pointer to front-subtree
backtree pointer to back-subtree
plane optional plane specification via normal and distance
boundingbox optional bounding box via minimum and maximum
 

So, each node actually contains two lists of polygons. The first list contains polygons lying in the same plane as the splitter (the first element of the front-facing list) and also facing in the same direction as the splitter. The second list contains polygons facing in the opposite direction (and also lying in the same plane, of course). Simple nodes with only one polygon (i.e, no coplanar polygons) have a front-facing list of just one polygon (the splitter itself) and no back-facing list at all (i.e., the field is NULL). 
Note that the node id allocation is sort of shared between real tree nodes and nodes of polygon lists. That is, each polygon in one of these lists except the splitter has also a unique node id. Node ids of polygon nodes don't occur as node ids of tree nodes. This is done in order to make unique identification possible when storing the entire tree to a file. Each pointer is then replaced by the id of the node pointed to. And because not only other BSP (sub)trees can be pointed to, but also ordinary polygons, unique ids have to be allocated for those nodes too. We said this is true except for the splitter, since the splitter has exactly the same id as the BSP tree node it belongs to. Within BspLib polygon node ids are actually not stored anywhere, because they can be inferred from tree node ids at any time. 

4.1.5 class BSPNodeFlat

This class is nearly identical to class BSPNode, but instead of pointers the links to subtrees consist of array-indexes. In this way the entire BSP tree can be contained in a single array, following links is just stepping to another array index. 

4.1.6 class BspTree

This class encapsulates the root of a BSP tree (which is of class BSPNode). The actual tree consists of BSPNodes, though. 

4.1.7 class BspTreeFlat

This class provides an interface to a BSP tree contained in an array. The array will be dynamically allocated and maintained by an object of this class. 

4.1.8 class Face

A Face is used to describe face properties that are defined over an entire plane. First of all, this is the plane equation. A face also describes material properties (color, shading type), texture, and texture parameterization specified via an affine mapping. Every face has a unique id, all polygons that belong to this face (are part of this face and are contained in this face's plane) refer to this id. 

4.1.9 class Lineseg2, class Lineseg3

These are simple classes describing line segments. A member function for "point on line segment"-test is available. This is used to test polygon edges for contained vertices, for instance. 

4.1.10 class Mapping

A mapping is used to specify arbitrary texture coordinates for all vertices of a face. If the face is non-planar it will be split into planar parts and this mapping will be used to derive affine parameterizations for each of these planes. From then on, only affine mappings (class TriMapping) will be used. 

4.1.11 class Material

This class can be used to specify a face's material properties in OpenGL style. That is, it describes a material via ambient color, diffuse color, specular color, emissive color, shininess, and transparency. A material object can be attached to a face in order to describe its material properties. 

4.1.12 class ObjectBSPNode

An ObjectBSPNode is the basic building block for BSP trees separating objects in their entirety. Each such node corresponds either to a separating plane, or contains an entire object referenced via its bounding box. This class is tightly coupled to class BoundingBox, since the latter provides a member function to partition space containing bounding boxes and return an ObjectBSPNode as root of the resulting tree. 

4.1.13 class ObjectBSPTree

This class encapsulates an object BSP tree consisting of ObjectBSPNodes. Basically it is just a pointer to the root node together with a few interface member functions, testing the tree against NULL, for instance. 

4.1.14 class Plane

A plane in three-space is defined by a normal vector and its distance to the origin along this normal vector. A Plane provides member functions to determine if a point lies in its positive or negative halfspace, or is contained in the plane itself. 

4.1.15 class Polygon

This is a very important class within BspLib. Polygons basically consist of a list of vertex-indexes listed in clock-wise order. A Polygon also contains a pointer to the next polygon in a list, so a polygon is always a node of such a (singly-linked) list. Each polygon has a unique id and contains the id of the face it belongs to. Polygons lying in the same plane may be part of the same face. A Polygon contains the entire functionality needed to compile a polygon BSP tree. That is, the Polygon::PartitionSpace() member function may be used to compile a BSP tree containing all polygons of this list (this polygon and the list pointed to by the next-field). Note that this BSP compilation function should only be used by BspLib itself, BSP compilation functionality for the user is presented through other, much more abstract and powerful, interfaces. 

4.1.16 class PolygonList

A PolygonList is primarily only a wrapper around a list of Polygons. It encapsulates the list's head polygon, provides centralized access to the entire list and list maintenance functions.. 

4.1.17 class Texture

This class describes a texture in terms of its texture name, file name, and geometry (width and height). If the specified texture's format is recognized (which currently is only the case for 3DF files) its geometry and texel format (e.g., ARGB4444) will be retrieved from the texture header. 

4.1.18 class Transform2, class Transform3

These classes provide the ability to perform homogeneous transformations in two and three dimensions, respectively. The elementary transformations rotation, scale, and translation are supported. Transformations can be concatenated, both in natural and reversed order. 

4.1.19 class TriMapping

All texture-map parameterization in BspLib is done with affine mappings. To specify such a (two-dimensional) mapping three point-correspondences are used. These are stored in TriMapping objects. The use of point-correspondences instead of directly specifying the mapping is useful to avoid problems with singularities. Collinear vertices need only be detected as soon as the actual mapping is calculated.  

4.1.20 class Vector2, class Vector3

The vector classes describe homogeneous vectors, that is, they contain an additional w coordinate and therefore consist of (x,y,w) and (x,y,z,w), respectively. A number of overloaded operators and member functions are provided for vector calculations, e.g., dot product, cross product, vector addition, and the like. Vectors are derived from vertices, since they are only vertices augmented by these operations. Vectors can be normalized, homogenized, tested for vanishing length, and so on. 

4.1.21 class Vertex2, class Vertex3

Vertices describe points in projective space, i.e., homogeneous coordinates are used. Since vertices are just points, calculations are only possible in conjunction with vectors. A vector can be added to a vertex to translate this vertex, for instance. 

4.1.22 class VIndx

This class describes a single vertex-index and is normally only used by Polygons as part of the list of vertex-indexes defining the polygon. A VIndx also contains the link field necessary for this purpose. 
 

 
5. BSP TREE TYPES
 
BspLib employs two distinct types of BSP trees, each with its own set of classes. The first type is a BSP tree containing polygons (class BSPTree). The second type contains whole objects that are referenced via their bounding boxes (class ObjectBSPTree). We are now going to have a look at these two different types of BSP trees. 

5.1 Polygon BSP trees

Polygon BSP trees are used to describe a single object defined by its boundary representation. A node may contain one or more polygons, or it may be a separator node only. Separator-only nodes are used to partition space into two halfspaces without an actual polygon lying in the separator plane. If at least one polygon is attached to the BSP node, the separator plane need not be defined explicitly (by an attached Plane), since the plane can always be derived from the polygon itself. BspLib creates separator-only nodes only when merging objects contained in an object BSP tree into a single polygon BSP tree. During this process all ObjectBSPNodes become BSPNodes with no polygons attached to them but specifying a separator plane. All BSP trees attached to the contained BSPObjects become subtrees with all nodes containing polygons. This creates a unified BSP tree describing a single object that is identical to the union of all objects contained in the original ObjectBSPTree. 

The structure of a polygon BSP tree in BspLib can be seen in the following figure: 
 

Polygon BSP tree

(Remember that all interface objects in BspLib are separated into handle and representation classes. Thus, the actual tree is of class BSPTreeRep, although the user uses class BSPTree.) 

An overview of all the fields comprising a BSPNode may be found at the description of class BSPNode. This class description also describes how lists of polygons may be attached to each BSPNode. 

5.2 Object BSP trees

Object BSP trees can be used to partition space containing objects as a whole. That is, no polygons will be split at all, since objects are only considered in their entirety. During the creation of such a BSP tree BspLib tries to separate the bounding boxes of the contained objects with separator planes. If this is not possible for any two given objects of a scene, these objects will be merged and considered as a single object from then on. Actually, BSP compilation proceeds like follows: The scene is described by a list of objects in arbitrary order (class BspObjectList). First, this list of objects is used to create a list of bounding boxes, each bounding box containing a pointer to each of these objects. A BoundingBox has the capability to partition space via the BoundingBox::PartitionSpace() member function (see also class BoundingBox). This function is used to create an object BSP tree containing bounding boxes. This object BSP tree contains objects that are not BSP compiled themselves yet (although the spatial relationship between objects as a whole is already described by the object BSP tree). In order to use BspLib's capability to process a list of objects identically, an auxiliary data structure is created for the object BSP tree: A list of all the objects contained in the tree (note that, since objects might have been merged, this list need not be identical to the original BspObjectList!) is built using ObjectBSPTree::CreateObjectList(). This resulting BspObjectList is used to compile a polygon BSP tree for each of the contained objects (via BspObjectList::ProcessObjects()). At this stage we have two different types of BSP trees: One object BSP tree for the entire scene, and many polygon BSP trees for the objects contained in the scene. The object BSP tree can be used to access all of these trees! The tree can now either be used directly (by distinguishing between single objects and the entire scene), or, alternatively, a single, unified BSP tree can be created for the entire scene. This unified BSP tree can be compiled by using the BspObjectList::MergeObjectBSPTree() member function, yielding a BspObjectList containing a single BspObject with a single BspTree. 

The structure of an object BSP tree in BspLib can be seen in the following figure: 
 

 Object BSP Tree

(Remember that all interface objects in BspLib are separated into handle and representation classes. Thus, the actual tree is of class ObjectBSPTreeRep, although the user uses class ObjectBSPTree.) 

This figure shows an object BSP tree containing two objects that are separated with a single separator plane. The tree itself references objects' bounding boxes which in turn reference the objects themselves. Such an object BSP tree containing multiple objects may be used to create a single object and BSP tree that is the union of all contained objects and BSP trees. This can be achieved by using the ObjectBSPTree::CreateMergedBSPTree() member function. (If the resulting BspObject should be the sole object contained in a BspObjectList the BspObjectList::MergeObjectBSPTree() member function may be used, as described in the preceding paragraph.)

 

 
6. PROCESSING FUNCTIONS
 
BspLib exports most of its object processing functionality via a single member function: BspObjectList::ProcessObjects(). This function takes a single int parameter where each bit determines whether a specific processing function should be applied. The specified functions are applied to each of the BspObjects contained in the BspObjectList. If more than one function should be applied the corresponding flags can simply be OR'ed together. 

Valid object processing flags are: 

Note that these flags are listed in the order in which they will be applied to an object. That is, if (CHECK_PLANES | BUILD_BSP | CHECK_EDGES) is specified, planes will be checked prior to BSP compilation, whereas edges will be checked after BSP compilation! 

6.1 Object processing flags

6.1.1 APPLY_TRANSFORMATIONS

If this flag is specified, the transformation attached to each BspObject is applied to all vertices. The transformation will be set to an identity mapping afterwards. This function is often necessary prior to other processing, since many geometrical properties might not be correct if a transformation is applied after their calculation. For example, if bounding boxes are calculated before an arbitrary transformation is applied they will be invalid afterwards, because the transformation does not transform the bounding box information accordingly. 

6.1.2 CALC_PLANE_NORMALS

If this flag is specified, explicit plane normals (actually, the entire plane equation) are calculated for all polygons if this has not already been done. Plane information must be valid prior to BSP compilation! 

6.1.3 BUILD_FROM_FLAT

Using this flag, a dynamically linked BSP tree can be built from a flat BSP tree contained in a BspObject. This can be used if a flat BSP tree has been read from an input file, for instance.  

6.1.4 CHECK_PLANES

This function should be performed prior to BSP compilation, since it checks all polygons for planarity. If some polygons are non-planar they will be split into several different polygons. 

6.1.5 BUILD_BSP

This is the most important processing function! If this flag is specified a BSP tree will be compiled for each of the BspObjects contained in the BspObjectList. 

6.1.6 BUILD_BSP_WITH_CHECKS

This flag is identical to specifying CHECK_PLANES, BUILD_BSP, CHECK_VERTICES, and CHECK_EDGES separately. 

6.1.7 CHECK_VERTICES

This can be used to check for multiple vertices. Vertices that are exactly the same (that is, contained within the same epsilon-volume) are only reported, not removed! 

6.1.8 CALC_BOUNDING_BOXES

Normally, explicit bounding box information is not calculated for BSP tree nodes. If this flag is specified bounding boxes will be calculated for all nodes, however. This also implies that bounding box information will be written to the output file. 

6.1.9 CALC_SEPARATOR_PLANES

Normally, explicit plane information is not calculated for ordinary BSP tree nodes (that is, nodes that are not separator planes only). If this flag is specified explicit plane information will be calculated for all nodes, however. This also implies that explicit plane information for each node will be written to the output file. 

6.1.10 CHECK_EDGES

This function checks all polygon edges for contained vertices. If any vertices are lying exactly on an edge they will be inserted into the vertex-index list of the corresponding polygons. This is useful to create trace-vertices. These are vertices contained in an edge for the sole purpose of eliminating pixel-dropouts in the presence of t-junctions. 

6.1.11 DISPLAY_STATS

This flag can be used to display some statistical information about objects after BSP compilation. It is only useful if BspLib's message output is rooted to a text-display or a log-file. 
 

 
7. A MINIMAL BSP COMPILER
 
In this section we are going to show you how a minimal BSP compiler can be built using BspLib. The resulting "program" will read a file called test.wrl, compile the contained scene, and write the resulting output to test.bsp. 

First, let's state that we want to use BspLib's classes without prefixing them with BspLib:: every time: 

using namespace BspLib; 

As first real action, we have to create an (initially empty) object of class BspObjectList, which will contain our entire input scene: 

BspObjectList testscene; 

Next, we have to create an object of class InputData3D, which reads and parses our input file, and builds a scene representation in memory (that is, it fills our testscene object), all during its construction: 

InputData3D inputdata( testscene, "test.wrl" ); 

Now, if everything went alright (if not, BspLib will already have exited with an appropriate error message; to avoid this, error response must be overridden/configured) the entire scene specified within the VRML file is in memory, contained in BspLib's 3-D data structures. Given this, we are going to perform some functions to get ready for BSP compilation: 

testscene.ProcessObjects( BspObjectList::CALC_PLANE_NORMALS ); 
testscene.ProcessObjects( BspObjectList::CHECK_PLANES ); 

This is necessary to ensure plane information (plane normal and distance to origin) is available for every polygon and all polygons are indeed planar. (These two function calls could be combined into one by OR'ing the two flags together, avoiding the overhead of scanning the BspObjectList twice.) 

Next, we will compile an object BSP tree for all objects contained in the scene (see Object BSP trees and class ObjectBSPTree): 

ObjectBSPTree objbsptree; 
testscene.PrepareObjectBSPTree( objbsptree ); 

Now, we get to something really interesting: BSP compilation! A polygon BSP tree will be compiled for each object (see Polygon BSP trees): 

testscene.ProcessObjects( BspObjectList::BUILD_BSP_WITH_CHECKS ); 

At this stage, the object BSP tree is valid and contains polygon BSP trees for each of the objects. We, however, want a unified BSP tree in order to be able to write a single object to the output file: 

testscene.MergeObjectBSPTree( objbsptree ); 

Well, we are nearly finished! Let's quickly write our (only) object to the output file using an object of class OutputData3D: 

OutputData3D outputdata( inputdata, IOData3D::BSP_FORMAT_1_1 ); 

That's it! The output file will be written when our outputdata object goes out of scope (and therefore its destructor is invoked). 

Note that, since we have used BspLib's default options we didn't have to configure them. Note also that all that object BSP tree stuff is only necessary since a VRML file may contain multiple objects. If we would have read an AOD file, or a VRML file containing only one object, we could have shortened this process even more!

 


back to main page.
BspLib documentation copyright (c) by Markus Hadwiger, 1998. ALL RIGHTS RESERVED.