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