]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/q2map/qbsp.c
set eol-style
[xonotic/netradiant.git] / tools / quake2 / q2map / qbsp.c
index 84e4570c870e57cf8377d2fe1cb4b9786d2edcd1..4f1180da8850d7a25c307cfef4ebc5c5412b8acc 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-// csg4.c\r
-\r
-#include "qbsp.h"\r
-\r
-extern float subdivide_size;\r
-\r
-char           source[1024];\r
-char           name[1024];\r
-\r
-vec_t          microvolume = 1.0;\r
-qboolean       noprune;\r
-qboolean       glview;\r
-qboolean       nodetail;\r
-qboolean       fulldetail;\r
-qboolean       onlyents;\r
-qboolean       nomerge;\r
-qboolean       nowater;\r
-qboolean       nofill;\r
-qboolean       nocsg;\r
-qboolean       noweld;\r
-qboolean       noshare;\r
-qboolean       nosubdiv;\r
-qboolean       notjunc;\r
-qboolean       noopt;\r
-qboolean       leaktest;\r
-qboolean       verboseentities;\r
-\r
-char           outbase[32];\r
-\r
-int                    block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;\r
-\r
-int                    entity_num;\r
-\r
-\r
-node_t         *block_nodes[10][10];\r
-\r
-\r
-/*\r
-============\r
-BlockTree\r
-\r
-============\r
-*/\r
-node_t *BlockTree (int xl, int yl, int xh, int yh)\r
-{\r
-       node_t  *node;\r
-       vec3_t  normal;\r
-       float   dist;\r
-       int             mid;\r
-\r
-       if (xl == xh && yl == yh)\r
-       {\r
-               node = block_nodes[xl+5][yl+5];\r
-               if (!node)\r
-               {       // return an empty leaf\r
-                       node = AllocNode ();\r
-                       node->planenum = PLANENUM_LEAF;\r
-                       node->contents = 0; //CONTENTS_SOLID;\r
-                       return node;\r
-               }\r
-               return node;\r
-       }\r
-\r
-       // create a seperator along the largest axis\r
-       node = AllocNode ();\r
-\r
-       if (xh - xl > yh - yl)\r
-       {       // split x axis\r
-               mid = xl + (xh-xl)/2 + 1;\r
-               normal[0] = 1;\r
-               normal[1] = 0;\r
-               normal[2] = 0;\r
-               dist = mid*1024;\r
-               node->planenum = FindFloatPlane (normal, dist);\r
-               node->children[0] = BlockTree ( mid, yl, xh, yh);\r
-               node->children[1] = BlockTree ( xl, yl, mid-1, yh);\r
-       }\r
-       else\r
-       {\r
-               mid = yl + (yh-yl)/2 + 1;\r
-               normal[0] = 0;\r
-               normal[1] = 1;\r
-               normal[2] = 0;\r
-               dist = mid*1024;\r
-               node->planenum = FindFloatPlane (normal, dist);\r
-               node->children[0] = BlockTree ( xl, mid, xh, yh);\r
-               node->children[1] = BlockTree ( xl, yl, xh, mid-1);\r
-       }\r
-\r
-       return node;\r
-}\r
-\r
-/*\r
-============\r
-ProcessBlock_Thread\r
-\r
-============\r
-*/\r
-int                    brush_start, brush_end;\r
-void ProcessBlock_Thread (int blocknum)\r
-{\r
-       int             xblock, yblock;\r
-       vec3_t          mins, maxs;\r
-       bspbrush_t      *brushes;\r
-       tree_t          *tree;\r
-       node_t          *node;\r
-\r
-       yblock = block_yl + blocknum / (block_xh-block_xl+1);\r
-       xblock = block_xl + blocknum % (block_xh-block_xl+1);\r
-\r
-       Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);\r
-\r
-       mins[0] = xblock*1024;\r
-       mins[1] = yblock*1024;\r
-       mins[2] = -4096;\r
-       maxs[0] = (xblock+1)*1024;\r
-       maxs[1] = (yblock+1)*1024;\r
-       maxs[2] = 4096;\r
-\r
-       // the makelist and chopbrushes could be cached between the passes...\r
-       brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);\r
-       if (!brushes)\r
-       {\r
-               node = AllocNode ();\r
-               node->planenum = PLANENUM_LEAF;\r
-               node->contents = CONTENTS_SOLID;\r
-               block_nodes[xblock+5][yblock+5] = node;\r
-               return;\r
-       }\r
-\r
-       if (!nocsg)\r
-               brushes = ChopBrushes (brushes);\r
-\r
-       tree = BrushBSP (brushes, mins, maxs);\r
-\r
-       block_nodes[xblock+5][yblock+5] = tree->headnode;\r
-}\r
-\r
-/*\r
-============\r
-ProcessWorldModel\r
-\r
-============\r
-*/\r
-void ProcessWorldModel (void)\r
-{\r
-       entity_t        *e;\r
-       tree_t          *tree;\r
-       qboolean        leaked;\r
-       qboolean        optimize;\r
-       xmlNodePtr      polyline, leaknode;\r
-  char         level[ 2 ];\r
-\r
-       e = &entities[entity_num];\r
-\r
-       brush_start = e->firstbrush;\r
-       brush_end = brush_start + e->numbrushes;\r
-       leaked = false;\r
-\r
-       //\r
-       // perform per-block operations\r
-       //\r
-       if (block_xh * 1024 > map_maxs[0])\r
-               block_xh = floor(map_maxs[0]/1024.0);\r
-       if ( (block_xl+1) * 1024 < map_mins[0])\r
-               block_xl = floor(map_mins[0]/1024.0);\r
-       if (block_yh * 1024 > map_maxs[1])\r
-               block_yh = floor(map_maxs[1]/1024.0);\r
-       if ( (block_yl+1) * 1024 < map_mins[1])\r
-               block_yl = floor(map_mins[1]/1024.0);\r
-\r
-       if (block_xl <-4)\r
-               block_xl = -4;\r
-       if (block_yl <-4)\r
-               block_yl = -4;\r
-       if (block_xh > 3)\r
-               block_xh = 3;\r
-       if (block_yh > 3)\r
-               block_yh = 3;\r
-\r
-       for (optimize = false ; optimize <= true ; optimize++)\r
-       {\r
-               Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");\r
-\r
-               RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),\r
-                       !verbose, ProcessBlock_Thread);\r
-\r
-               //\r
-               // build the division tree\r
-               // oversizing the blocks guarantees that all the boundaries\r
-               // will also get nodes.\r
-               //\r
-\r
-               Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");\r
-\r
-               tree = AllocTree ();\r
-               tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);\r
-\r
-               tree->mins[0] = (block_xl)*1024;\r
-               tree->mins[1] = (block_yl)*1024;\r
-               tree->mins[2] = map_mins[2] - 8;\r
-\r
-               tree->maxs[0] = (block_xh+1)*1024;\r
-               tree->maxs[1] = (block_yh+1)*1024;\r
-               tree->maxs[2] = map_maxs[2] + 8;\r
-\r
-               //\r
-               // perform the global operations\r
-               //\r
-               MakeTreePortals (tree);\r
-\r
-               if (FloodEntities (tree))\r
-                       FillOutside (tree->headnode);\r
-               else\r
-               {\r
-\r
-      Sys_FPrintf( SYS_NOXML, "**********************\n" );\r
-               Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );\r
-               Sys_FPrintf( SYS_NOXML, "**********************\n" );\r
-               polyline = LeakFile( tree );\r
-               leaknode = xmlNewNode( NULL, "message" );\r
-               xmlNodeSetContent( leaknode, "MAP LEAKED\n" );\r
-               xmlAddChild( leaknode, polyline );\r
-               level[0] = (int) '0' + SYS_ERR;\r
-               level[1] = 0;\r
-               xmlSetProp( leaknode, "level", (char*) &level );\r
-               xml_SendNode( leaknode );\r
-               if( leaktest )\r
-               {\r
-                       Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");\r
-                       exit( 0 );\r
-               }\r
-               leaked = true;\r
-/*\r
-                       Sys_Printf ("**** leaked ****\n");\r
-                       leaked = true;\r
-                       LeakFile (tree);\r
-                       if (leaktest)\r
-                       {\r
-                               Sys_Printf ("--- MAP LEAKED ---\n");\r
-                               exit (0);\r
-                       } */\r
-               }\r
-\r
-               MarkVisibleSides (tree, brush_start, brush_end);\r
-               if (noopt || leaked)\r
-                       break;\r
-               if (!optimize)\r
-               {\r
-                       FreeTree (tree);\r
-               }\r
-       }\r
-\r
-       FloodAreas (tree);\r
-       if (glview)\r
-               WriteGLView (tree, source);\r
-       MakeFaces (tree->headnode);\r
-       FixTjuncs (tree->headnode);\r
-\r
-       if (!noprune)\r
-               PruneNodes (tree->headnode);\r
-\r
-       WriteBSP (tree->headnode);\r
-\r
-       if (!leaked)\r
-               WritePortalFile (tree);\r
-\r
-       FreeTree (tree);\r
-}\r
-\r
-/*\r
-============\r
-ProcessSubModel\r
-\r
-============\r
-*/\r
-void ProcessSubModel (void)\r
-{\r
-       entity_t        *e;\r
-       int                     start, end;\r
-       tree_t          *tree;\r
-       bspbrush_t      *list;\r
-       vec3_t          mins, maxs;\r
-\r
-       e = &entities[entity_num];\r
-\r
-       start = e->firstbrush;\r
-       end = start + e->numbrushes;\r
-\r
-       mins[0] = mins[1] = mins[2] = -4096;\r
-       maxs[0] = maxs[1] = maxs[2] = 4096;\r
-       list = MakeBspBrushList (start, end, mins, maxs);\r
-       if (!nocsg)\r
-               list = ChopBrushes (list);\r
-       tree = BrushBSP (list, mins, maxs);\r
-       MakeTreePortals (tree);\r
-       MarkVisibleSides (tree, start, end);\r
-       MakeFaces (tree->headnode);\r
-       FixTjuncs (tree->headnode);\r
-       WriteBSP (tree->headnode);\r
-       FreeTree (tree);\r
-}\r
-\r
-/*\r
-============\r
-ProcessModels\r
-============\r
-*/\r
-void ProcessModels (void)\r
-{\r
-       BeginBSPFile ();\r
-\r
-       for (entity_num=0 ; entity_num< num_entities ; entity_num++)\r
-       {\r
-               if (!entities[entity_num].numbrushes)\r
-                       continue;\r
-\r
-               Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);\r
-               BeginModel ();\r
-               if (entity_num == 0)\r
-                       ProcessWorldModel ();\r
-               else\r
-                       ProcessSubModel ();\r
-               EndModel ();\r
-\r
-               //if (!verboseentities)\r
-               //      verbose = false;        // don't bother printing submodels\r
-       }\r
-\r
-       EndBSPFile ();\r
-}\r
-\r
-\r
-/*\r
-============\r
-main\r
-============\r
-*/\r
-int BSP_Main ()\r
-{\r
-       double          start, end;\r
-       char            path[1024];\r
-       int             total_bsp_time;\r
-\r
-       Sys_Printf ("\n----- BSP ----\n\n");\r
-\r
-       \r
-       start = I_FloatTime ();\r
-\r
-       ThreadSetDefault ();\r
-       SetQdirFromPath (mapname);\r
-\r
-       strcpy (source, ExpandArg (mapname));\r
-       StripExtension (source);\r
-\r
-       // delete portal and line files\r
-       sprintf (path, "%s.prt", source);\r
-       remove (path);\r
-       sprintf (path, "%s.lin", source);\r
-       remove (path);\r
-\r
-       strcpy (name, ExpandArg (mapname));     \r
-       DefaultExtension (name, ".map");        // might be .reg\r
-\r
-       //\r
-       // if onlyents, just grab the entites and resave\r
-       //\r
-       if (onlyents)\r
-       {\r
-               char out[1024];\r
-\r
-               sprintf (out, "%s.bsp", source);\r
-               LoadBSPFile (out);\r
-               num_entities = 0;\r
-\r
-               LoadMapFile (name);\r
-               SetModelNumbers ();\r
-               SetLightStyles ();\r
-\r
-               UnparseEntities ();\r
-\r
-               WriteBSPFile (out);\r
-       }\r
-       else\r
-       {\r
-               //\r
-               // start from scratch\r
-               //\r
-               LoadMapFile (name);\r
-               SetModelNumbers ();\r
-               SetLightStyles ();\r
-\r
-               ProcessModels ();\r
-       }\r
-\r
-       end = I_FloatTime ();\r
-       total_bsp_time = (int) (end-start);\r
-       Sys_Printf("\nBSP Time: ");\r
-       if ( total_bsp_time > 59 )\r
-               Sys_Printf("%d Minutes ", total_bsp_time/60 );\r
-       Sys_Printf( "%d Seconds\n", total_bsp_time%60 );\r
-\r
-\r
-       return 0;\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// csg4.c
+
+#include "qbsp.h"
+
+extern float subdivide_size;
+
+char           source[1024];
+char           name[1024];
+
+vec_t          microvolume = 1.0;
+qboolean       noprune;
+qboolean       glview;
+qboolean       nodetail;
+qboolean       fulldetail;
+qboolean       onlyents;
+qboolean       nomerge;
+qboolean       nowater;
+qboolean       nofill;
+qboolean       nocsg;
+qboolean       noweld;
+qboolean       noshare;
+qboolean       nosubdiv;
+qboolean       notjunc;
+qboolean       noopt;
+qboolean       leaktest;
+qboolean       verboseentities;
+
+char           outbase[32];
+
+int                    block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
+
+int                    entity_num;
+
+
+node_t         *block_nodes[10][10];
+
+
+/*
+============
+BlockTree
+
+============
+*/
+node_t *BlockTree (int xl, int yl, int xh, int yh)
+{
+       node_t  *node;
+       vec3_t  normal;
+       float   dist;
+       int             mid;
+
+       if (xl == xh && yl == yh)
+       {
+               node = block_nodes[xl+5][yl+5];
+               if (!node)
+               {       // return an empty leaf
+                       node = AllocNode ();
+                       node->planenum = PLANENUM_LEAF;
+                       node->contents = 0; //CONTENTS_SOLID;
+                       return node;
+               }
+               return node;
+       }
+
+       // create a seperator along the largest axis
+       node = AllocNode ();
+
+       if (xh - xl > yh - yl)
+       {       // split x axis
+               mid = xl + (xh-xl)/2 + 1;
+               normal[0] = 1;
+               normal[1] = 0;
+               normal[2] = 0;
+               dist = mid*1024;
+               node->planenum = FindFloatPlane (normal, dist);
+               node->children[0] = BlockTree ( mid, yl, xh, yh);
+               node->children[1] = BlockTree ( xl, yl, mid-1, yh);
+       }
+       else
+       {
+               mid = yl + (yh-yl)/2 + 1;
+               normal[0] = 0;
+               normal[1] = 1;
+               normal[2] = 0;
+               dist = mid*1024;
+               node->planenum = FindFloatPlane (normal, dist);
+               node->children[0] = BlockTree ( xl, mid, xh, yh);
+               node->children[1] = BlockTree ( xl, yl, xh, mid-1);
+       }
+
+       return node;
+}
+
+/*
+============
+ProcessBlock_Thread
+
+============
+*/
+int                    brush_start, brush_end;
+void ProcessBlock_Thread (int blocknum)
+{
+       int             xblock, yblock;
+       vec3_t          mins, maxs;
+       bspbrush_t      *brushes;
+       tree_t          *tree;
+       node_t          *node;
+
+       yblock = block_yl + blocknum / (block_xh-block_xl+1);
+       xblock = block_xl + blocknum % (block_xh-block_xl+1);
+
+       Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);
+
+       mins[0] = xblock*1024;
+       mins[1] = yblock*1024;
+       mins[2] = -4096;
+       maxs[0] = (xblock+1)*1024;
+       maxs[1] = (yblock+1)*1024;
+       maxs[2] = 4096;
+
+       // the makelist and chopbrushes could be cached between the passes...
+       brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
+       if (!brushes)
+       {
+               node = AllocNode ();
+               node->planenum = PLANENUM_LEAF;
+               node->contents = CONTENTS_SOLID;
+               block_nodes[xblock+5][yblock+5] = node;
+               return;
+       }
+
+       if (!nocsg)
+               brushes = ChopBrushes (brushes);
+
+       tree = BrushBSP (brushes, mins, maxs);
+
+       block_nodes[xblock+5][yblock+5] = tree->headnode;
+}
+
+/*
+============
+ProcessWorldModel
+
+============
+*/
+void ProcessWorldModel (void)
+{
+       entity_t        *e;
+       tree_t          *tree;
+       qboolean        leaked;
+       qboolean        optimize;
+       xmlNodePtr      polyline, leaknode;
+  char         level[ 2 ];
+
+       e = &entities[entity_num];
+
+       brush_start = e->firstbrush;
+       brush_end = brush_start + e->numbrushes;
+       leaked = false;
+
+       //
+       // perform per-block operations
+       //
+       if (block_xh * 1024 > map_maxs[0])
+               block_xh = floor(map_maxs[0]/1024.0);
+       if ( (block_xl+1) * 1024 < map_mins[0])
+               block_xl = floor(map_mins[0]/1024.0);
+       if (block_yh * 1024 > map_maxs[1])
+               block_yh = floor(map_maxs[1]/1024.0);
+       if ( (block_yl+1) * 1024 < map_mins[1])
+               block_yl = floor(map_mins[1]/1024.0);
+
+       if (block_xl <-4)
+               block_xl = -4;
+       if (block_yl <-4)
+               block_yl = -4;
+       if (block_xh > 3)
+               block_xh = 3;
+       if (block_yh > 3)
+               block_yh = 3;
+
+       for (optimize = false ; optimize <= true ; optimize++)
+       {
+               Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
+
+               RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
+                       !verbose, ProcessBlock_Thread);
+
+               //
+               // build the division tree
+               // oversizing the blocks guarantees that all the boundaries
+               // will also get nodes.
+               //
+
+               Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
+
+               tree = AllocTree ();
+               tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
+
+               tree->mins[0] = (block_xl)*1024;
+               tree->mins[1] = (block_yl)*1024;
+               tree->mins[2] = map_mins[2] - 8;
+
+               tree->maxs[0] = (block_xh+1)*1024;
+               tree->maxs[1] = (block_yh+1)*1024;
+               tree->maxs[2] = map_maxs[2] + 8;
+
+               //
+               // perform the global operations
+               //
+               MakeTreePortals (tree);
+
+               if (FloodEntities (tree))
+                       FillOutside (tree->headnode);
+               else
+               {
+
+      Sys_FPrintf( SYS_NOXML, "**********************\n" );
+               Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
+               Sys_FPrintf( SYS_NOXML, "**********************\n" );
+               polyline = LeakFile( tree );
+               leaknode = xmlNewNode( NULL, "message" );
+               xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
+               xmlAddChild( leaknode, polyline );
+               level[0] = (int) '0' + SYS_ERR;
+               level[1] = 0;
+               xmlSetProp( leaknode, "level", (char*) &level );
+               xml_SendNode( leaknode );
+               if( leaktest )
+               {
+                       Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
+                       exit( 0 );
+               }
+               leaked = true;
+/*
+                       Sys_Printf ("**** leaked ****\n");
+                       leaked = true;
+                       LeakFile (tree);
+                       if (leaktest)
+                       {
+                               Sys_Printf ("--- MAP LEAKED ---\n");
+                               exit (0);
+                       } */
+               }
+
+               MarkVisibleSides (tree, brush_start, brush_end);
+               if (noopt || leaked)
+                       break;
+               if (!optimize)
+               {
+                       FreeTree (tree);
+               }
+       }
+
+       FloodAreas (tree);
+       if (glview)
+               WriteGLView (tree, source);
+       MakeFaces (tree->headnode);
+       FixTjuncs (tree->headnode);
+
+       if (!noprune)
+               PruneNodes (tree->headnode);
+
+       WriteBSP (tree->headnode);
+
+       if (!leaked)
+               WritePortalFile (tree);
+
+       FreeTree (tree);
+}
+
+/*
+============
+ProcessSubModel
+
+============
+*/
+void ProcessSubModel (void)
+{
+       entity_t        *e;
+       int                     start, end;
+       tree_t          *tree;
+       bspbrush_t      *list;
+       vec3_t          mins, maxs;
+
+       e = &entities[entity_num];
+
+       start = e->firstbrush;
+       end = start + e->numbrushes;
+
+       mins[0] = mins[1] = mins[2] = -4096;
+       maxs[0] = maxs[1] = maxs[2] = 4096;
+       list = MakeBspBrushList (start, end, mins, maxs);
+       if (!nocsg)
+               list = ChopBrushes (list);
+       tree = BrushBSP (list, mins, maxs);
+       MakeTreePortals (tree);
+       MarkVisibleSides (tree, start, end);
+       MakeFaces (tree->headnode);
+       FixTjuncs (tree->headnode);
+       WriteBSP (tree->headnode);
+       FreeTree (tree);
+}
+
+/*
+============
+ProcessModels
+============
+*/
+void ProcessModels (void)
+{
+       BeginBSPFile ();
+
+       for (entity_num=0 ; entity_num< num_entities ; entity_num++)
+       {
+               if (!entities[entity_num].numbrushes)
+                       continue;
+
+               Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);
+               BeginModel ();
+               if (entity_num == 0)
+                       ProcessWorldModel ();
+               else
+                       ProcessSubModel ();
+               EndModel ();
+
+               //if (!verboseentities)
+               //      verbose = false;        // don't bother printing submodels
+       }
+
+       EndBSPFile ();
+}
+
+
+/*
+============
+main
+============
+*/
+int BSP_Main ()
+{
+       double          start, end;
+       char            path[1024];
+       int             total_bsp_time;
+
+       Sys_Printf ("\n----- BSP ----\n\n");
+
+       
+       start = I_FloatTime ();
+
+       ThreadSetDefault ();
+       SetQdirFromPath (mapname);
+
+       strcpy (source, ExpandArg (mapname));
+       StripExtension (source);
+
+       // delete portal and line files
+       sprintf (path, "%s.prt", source);
+       remove (path);
+       sprintf (path, "%s.lin", source);
+       remove (path);
+
+       strcpy (name, ExpandArg (mapname));     
+       DefaultExtension (name, ".map");        // might be .reg
+
+       //
+       // if onlyents, just grab the entites and resave
+       //
+       if (onlyents)
+       {
+               char out[1024];
+
+               sprintf (out, "%s.bsp", source);
+               LoadBSPFile (out);
+               num_entities = 0;
+
+               LoadMapFile (name);
+               SetModelNumbers ();
+               SetLightStyles ();
+
+               UnparseEntities ();
+
+               WriteBSPFile (out);
+       }
+       else
+       {
+               //
+               // start from scratch
+               //
+               LoadMapFile (name);
+               SetModelNumbers ();
+               SetLightStyles ();
+
+               ProcessModels ();
+       }
+
+       end = I_FloatTime ();
+       total_bsp_time = (int) (end-start);
+       Sys_Printf("\nBSP Time: ");
+       if ( total_bsp_time > 59 )
+               Sys_Printf("%d Minutes ", total_bsp_time/60 );
+       Sys_Printf( "%d Seconds\n", total_bsp_time%60 );
+
+
+       return 0;
+}
+