bsp.h

Go to the documentation of this file.
00001 /*
00002  * bsp.h
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Logical parsing of Quake BSP format streams.
00032  */
00033 
00034 #ifndef WAVEPACKET_QUAKE_BSP_H__
00035 #define WAVEPACKET_QUAKE_BSP_H__
00036 
00037 // includes --------------------------------------------------------------------
00038 #include "bsp-version.h"
00039 
00040 #include "nstream/nstream.h"
00041 
00042 
00043 namespace quake {
00044 
00045 ////////////////////////////////////////////////////////////////////////////////
00046 ///
00047 /// \ingroup quake
00048 /// \defgroup quake_bsp Quake BSP Parsing Library
00049 ///
00050 /// This is a simple library for parsing Quake's BSP file format.
00051 ///
00052 /// A BSP file contains a 3D map (BSP stands for Binary Space Partitioning).
00053 /// Typically the file contains several "lumps", and each lump contains a list
00054 /// of objects.  Example lumps are textures, polygons, vertices, map entities,
00055 /// effects, etc.
00056 ///
00057 /// <b>How to use this parsing library:</b>  The library is designed to handle
00058 /// a wide range of BSP formats.  In general, different vendors (game companies)
00059 /// have slightly different BSP formats.  They'll use different lumps, and maybe
00060 /// even have slightly different objects in lumps with the same name.
00061 ///
00062 /// This library will attempt to determine the vendor that created the BSP
00063 /// based on the BSP header, then allow the caller to iterate over available
00064 /// lumps, and likewise iterate over objects in each lump.  You should write
00065 /// your code to expect some common lumps always (nodes, faces, textures, ...)
00066 /// but treat other vendor-specific lumps as optional.  The more flexible you
00067 /// are, the more likely it is you can handle BSP files from multiple vendors.
00068 ///
00069 /// <b>Warning:</b> do not use the objects defined here (texture_t, face_t,
00070 /// etc.) in your rendering code.  These objects are defined for convenience
00071 /// and safety in parsing, not high-speed rendering.  For instance, they have
00072 /// a high per-object overhead due to vtables.  Just use these objects for
00073 /// parsing, and have your own simple structs to store thousands of vertices,
00074 /// for instance.
00075 ///
00076 /// See these links for references on the BSP format:
00077 ///  - http://www.mralligator.com/q3/
00078 ///  - http://developer.valvesoftware.com/wiki/The_Source_Engine_BSP_File_Format
00079 ///  - http://www.paulsprojects.net/opengl/q3bsp/q3bsp.html
00080 ///  - http://en.wikipedia.org/wiki/BSP_(file_format)
00081 ///
00082 ////////////////////////////////////////////////////////////////////////////////
00083 /*@{*/
00084 
00085 
00086 
00087 /// an object in a lump.  This is a base class from which the actual object
00088 /// structures are subclassed.
00089 struct lump_object_t {
00090         // virtual destructor --------------------------------------------------
00091         virtual ~lump_object_t(void) throw();
00092 
00093         // quake::lump_object_t struct interface methods -----------------------
00094 
00095         /// what sort of lump object is this really?  Can use this information
00096         ///     to perform a dynamic cast to the correct leaf class.
00097         virtual eLumpType getType(void) const throw() { return eLump_Invalid; }
00098 
00099         /// returns the index of this object as stored in its lump
00100         virtual int getIndex(void) const throw() { return index; }
00101 
00102         // data fields
00103         int             index;
00104 };
00105 
00106 
00107 
00108 /// polygon face type
00109 enum eFaceType {
00110         eFace_Polygon           =  1, ///< standard polygon using vertices
00111         eFace_Patch             =  2, ///< bezier patches
00112         eFace_Mesh              =  3, ///< triangle mesh using meshverts
00113         eFace_Billboard         =  4, ///< 2D billboard, location only
00114 
00115         // keep this last!
00116         eFace_Invalid           =  0
00117 };
00118 
00119 
00120 
00121 /// a game entity in the bsp map
00122 struct entity_t : public lump_object_t {
00123         ~entity_t(void) throw();
00124         eLumpType getType(void) const throw() { return eLump_Entities; }
00125 
00126         // data fields
00127         Dictionary      dictionary;     ///< key/value pairs
00128 };
00129 
00130 
00131 
00132 /// a polygon face in the bsp map
00133 struct face_t : public lump_object_t {
00134         ~face_t(void) throw();
00135         eLumpType getType(void) const throw() { return eLump_Faces; }
00136 
00137         // data fields
00138         int32_t         texture;        ///< index to texture path object
00139         int32_t         effect;         ///< index to effect (or -1)
00140         int32_t         type;           ///< face type (eFaceType, above)
00141         int32_t         vertex;         ///< index of first vertex
00142         int32_t         nVertices;      ///< number of vertices
00143         int32_t         meshvert;       ///< index of first mesh vertex
00144         int32_t         nMeshverts;     ///< number of mesh vertices
00145         int32_t         lmIndex;        ///< light map index
00146         int32_t         lmStart[2];     ///< corner of this face's lightmap
00147         int32_t         lmSize[2];      ///< size of this face's lightmap
00148         point3d_t       origin;         ///< origin of lightmap
00149         point3d_t       lmVecs[2];      ///< lightmap s and t vectors
00150         point3d_t       normal;         ///< surface normal
00151         int32_t         size[2];        ///< patch dimensions
00152 };
00153 
00154 
00155 
00156 /// a node in the BSP tree
00157 ///  Note that the indexing scheme is unusual:
00158 ///   - A non-negative index refers to a node
00159 ///   - A negative index is a leaf, -(leaf + 1)
00160 struct node_t : public lump_object_t {
00161         ~node_t(void) throw();
00162         eLumpType getType(void) const throw() { return eLump_Nodes; }
00163 
00164         // data fields
00165         int32_t         plane;          ///< index to plane
00166         int32_t         children[2];    ///< left, right child
00167         int32_t         min[3];         ///< bounding box min xyz coords
00168         int32_t         max[3];         ///< bounding box max xyz coords
00169 };
00170 
00171 
00172 
00173 /// a leaf in the BSP tree
00174 struct leaf_t : public lump_object_t {
00175         ~leaf_t(void) throw();
00176         eLumpType getType(void) const throw() { return eLump_Leafs; }
00177 
00178         // data fields
00179         int32_t         cluster;        ///< cluster index
00180         int32_t         area;           ///< map area (for portals?)
00181         int32_t         min[3];         ///< bounding box min xyz coords
00182         int32_t         max[3];         ///< bounding box max xyz coords
00183         int32_t         leafface;       ///< first leaf face for leaf
00184         int32_t         n_leaffaces;    ///< number of faces
00185         int32_t         leafbrush;      ///< first leaf brush for leaf
00186         int32_t         n_leafbrushes;  ///< number of brushes
00187 };
00188 
00189 
00190 
00191 /// a leaf face in the BSP tree
00192 struct leafface_t : public lump_object_t {
00193         ~leafface_t(void) throw();
00194         eLumpType getType(void) const throw() { return eLump_Leaffaces; }
00195 
00196         // data fields
00197         int32_t         face;           ///< face index
00198 };
00199 
00200 
00201 
00202 /// a mesh vertex
00203 struct meshvert_t : public lump_object_t {
00204         ~meshvert_t(void) throw();
00205         eLumpType getType(void) const throw() { return eLump_Meshverts; }
00206 
00207         // data fields
00208         int32_t         vertex;         ///< vertex index
00209 };
00210 
00211 
00212 
00213 /// a 2D plane in the BSP tree
00214 struct plane_t : public lump_object_t {
00215         ~plane_t(void) throw();
00216         eLumpType getType(void) const throw() { return eLump_Planes; }
00217 
00218         // data fields
00219         point3d_t       n;      ///< plane normal
00220         float           d;      ///< distance from origin along normal
00221 };
00222 
00223 
00224 
00225 /// texture information
00226 struct texture_path_t : public lump_object_t {
00227         ~texture_path_t(void) throw();
00228         eLumpType getType(void) const throw() { return eLump_Textures; }
00229         void dump(void) const throw() {
00230                         DPRINTF("  flag: 0x%08x  content: 0x%08x  path: %s",
00231                             flags, contents, name);
00232                 }
00233 
00234         // data fields
00235         char            name[64];       ///< name
00236         int32_t         flags;
00237         int32_t         contents;
00238 };
00239 
00240 
00241 
00242 /// color struct
00243 /// TODO: centralize this somewhere?  now redundant with glut::color_t
00244 struct color_t {
00245         byte_t          red;
00246         byte_t          green;
00247         byte_t          blue;
00248         byte_t          alpha;
00249 };
00250 
00251 
00252 
00253 /// vertex information
00254 struct vertex_t : public lump_object_t {
00255         ~vertex_t(void) throw();
00256         eLumpType getType(void) const throw() { return eLump_Vertices; }
00257 
00258         // data fields
00259         point3d_t       position;
00260         point3d_t       normal;
00261         float           texcoord[2][2];
00262         color_t         color;
00263 };
00264 
00265 
00266 
00267 /// The 3D space-partitioned map.
00268 ///
00269 /// <b>Warning:</b> this class is NOT threadsafe!  Use only on an isolated
00270 /// thread.
00271 class Bsp {
00272 public:
00273         // constructor, destructor ---------------------------------------------
00274         virtual ~Bsp(void) throw();
00275 
00276         // quake::Bsp class interface methods ----------------------------------
00277         virtual BspVersion getVersion(void) const throw() = 0;
00278         virtual const char * getName(void) const throw() = 0;
00279 
00280         /// returns the list of lump types normally expected in BSP maps for
00281         ///     this vendor.  Sometimes the lumps are empty or missing anyway.
00282         virtual const vec_lump_type_t& getLumps(void) const throw() = 0;
00283 
00284         /// returns 0 if lump does not exist, or if lump exists but is empty.
00285         /// returns -1 if lump exists but contains an unknown number of objects.
00286         virtual int getLumpObjectCount(IN eLumpType type) = 0;
00287 
00288         /// resets lump object iteration to the first of the specified type.
00289         ///     Will silently fail if lump type does not exist.
00290         virtual void startLumpIteration(IN eLumpType type) = 0;
00291 
00292         /// call this to iterate.  Returns NULL at end of iteration.  Returns
00293         ///     NULL immediately if lump does not exist or is empty.
00294         virtual const lump_object_t * getNextLumpObject(void) = 0;
00295 
00296         // static factory methods ----------------------------------------------
00297         static smart_ptr<Bsp> load(IN smart_ptr<nstream::Stream>& stream);
00298 };
00299 
00300 
00301 
00302 };      // quake namespace
00303 
00304 
00305 
00306 #endif  // WAVEPACKET_QUAKE_BSP_H__
00307