]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/q2map/qbsp.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / q2map / qbsp.c
diff --git a/tools/quake2/q2map/qbsp.c b/tools/quake2/q2map/qbsp.c
new file mode 100644 (file)
index 0000000..84e4570
--- /dev/null
@@ -0,0 +1,426 @@
+/*\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