--- /dev/null
+/*\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