]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/extra/bsp/qbsp3/qbsp3.c
Merge remote-tracking branch 'ttimo/master'
[xonotic/netradiant.git] / tools / quake2 / extra / bsp / qbsp3 / qbsp3.c
diff --git a/tools/quake2/extra/bsp/qbsp3/qbsp3.c b/tools/quake2/extra/bsp/qbsp3/qbsp3.c
new file mode 100644 (file)
index 0000000..1cc5b90
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+===========================================================================
+Copyright (C) 1997-2006 Id Software, Inc.
+
+This file is part of Quake 2 Tools source code.
+
+Quake 2 Tools source code 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.
+
+Quake 2 Tools source code 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 Quake 2 Tools source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#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);
+
+       qprintf ("############### 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;
+
+       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++)
+       {
+               qprintf ("--------------------------------------------\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.
+               //
+
+               qprintf ("--------------------------------------------\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
+               {
+                       printf ("**** leaked ****\n");
+                       leaked = true;
+                       LeakFile (tree);
+                       if (leaktest)
+                       {
+                               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;
+
+               qprintf ("############### 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 main (int argc, char **argv)
+{
+       int             i;
+       double          start, end;
+       char            path[1024];
+
+       printf ("---- qbsp3 ----\n");
+
+       for (i=1 ; i<argc ; i++)
+       {
+               if (!strcmp(argv[i],"-threads"))
+               {
+                       numthreads = atoi (argv[i+1]);
+                       i++;
+               }
+               else if (!strcmp(argv[i],"-glview"))
+               {
+                       glview = true;
+               }
+               else if (!strcmp(argv[i], "-v"))
+               {
+                       printf ("verbose = true\n");
+                       verbose = true;
+               }
+               else if (!strcmp(argv[i], "-draw"))
+               {
+                       printf ("drawflag = true\n");
+                       drawflag = true;
+               }
+               else if (!strcmp(argv[i], "-noweld"))
+               {
+                       printf ("noweld = true\n");
+                       noweld = true;
+               }
+               else if (!strcmp(argv[i], "-nocsg"))
+               {
+                       printf ("nocsg = true\n");
+                       nocsg = true;
+               }
+               else if (!strcmp(argv[i], "-noshare"))
+               {
+                       printf ("noshare = true\n");
+                       noshare = true;
+               }
+               else if (!strcmp(argv[i], "-notjunc"))
+               {
+                       printf ("notjunc = true\n");
+                       notjunc = true;
+               }
+               else if (!strcmp(argv[i], "-nowater"))
+               {
+                       printf ("nowater = true\n");
+                       nowater = true;
+               }
+               else if (!strcmp(argv[i], "-noopt"))
+               {
+                       printf ("noopt = true\n");
+                       noopt = true;
+               }
+               else if (!strcmp(argv[i], "-noprune"))
+               {
+                       printf ("noprune = true\n");
+                       noprune = true;
+               }
+               else if (!strcmp(argv[i], "-nofill"))
+               {
+                       printf ("nofill = true\n");
+                       nofill = true;
+               }
+               else if (!strcmp(argv[i], "-nomerge"))
+               {
+                       printf ("nomerge = true\n");
+                       nomerge = true;
+               }
+               else if (!strcmp(argv[i], "-nosubdiv"))
+               {
+                       printf ("nosubdiv = true\n");
+                       nosubdiv = true;
+               }
+               else if (!strcmp(argv[i], "-nodetail"))
+               {
+                       printf ("nodetail = true\n");
+                       nodetail = true;
+               }
+               else if (!strcmp(argv[i], "-fulldetail"))
+               {
+                       printf ("fulldetail = true\n");
+                       fulldetail = true;
+               }
+               else if (!strcmp(argv[i], "-onlyents"))
+               {
+                       printf ("onlyents = true\n");
+                       onlyents = true;
+               }
+               else if (!strcmp(argv[i], "-micro"))
+               {
+                       microvolume = atof(argv[i+1]);
+                       printf ("microvolume = %f\n", microvolume);
+                       i++;
+               }
+               else if (!strcmp(argv[i], "-leaktest"))
+               {
+                       printf ("leaktest = true\n");
+                       leaktest = true;
+               }
+               else if (!strcmp(argv[i], "-verboseentities"))
+               {
+                       printf ("verboseentities = true\n");
+                       verboseentities = true;
+               }
+               else if (!strcmp(argv[i], "-chop"))
+               {
+                       subdivide_size = atof(argv[i+1]);
+                       printf ("subdivide_size = %f\n", subdivide_size);
+                       i++;
+               }
+               else if (!strcmp(argv[i], "-block"))
+               {
+                       block_xl = block_xh = atoi(argv[i+1]);
+                       block_yl = block_yh = atoi(argv[i+2]);
+                       printf ("block: %i,%i\n", block_xl, block_yl);
+                       i+=2;
+               }
+               else if (!strcmp(argv[i], "-blocks"))
+               {
+                       block_xl = atoi(argv[i+1]);
+                       block_yl = atoi(argv[i+2]);
+                       block_xh = atoi(argv[i+3]);
+                       block_yh = atoi(argv[i+4]);
+                       printf ("blocks: %i,%i to %i,%i\n", 
+                               block_xl, block_yl, block_xh, block_yh);
+                       i+=4;
+               }
+               else if (!strcmp (argv[i],"-tmpout"))
+               {
+                       strcpy (outbase, "/tmp");
+               }
+               else if (argv[i][0] == '-')
+                       Error ("Unknown option \"%s\"", argv[i]);
+               else
+                       break;
+       }
+
+       if (i != argc - 1)
+               Error ("usage: qbsp3 [options] mapfile");
+
+       start = I_FloatTime ();
+
+       ThreadSetDefault ();
+numthreads = 1;                // multiple threads aren't helping...
+       SetQdirFromPath (argv[i]);
+
+       strcpy (source, ExpandArg (argv[i]));
+       StripExtension (source);
+
+       // delete portal and line files
+       sprintf (path, "%s.prt", source);
+       remove (path);
+       sprintf (path, "%s.lin", source);
+       remove (path);
+
+       strcpy (name, ExpandArg (argv[i]));     
+       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 ();
+       printf ("%5.0f seconds elapsed\n", end-start);
+
+       return 0;
+}
+