2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 extern float subdivide_size;
30 vec_t microvolume = 1.0;
46 qboolean verboseentities;
50 int block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
55 node_t *block_nodes[10][10];
64 node_t *BlockTree (int xl, int yl, int xh, int yh)
71 if (xl == xh && yl == yh)
73 node = block_nodes[xl+5][yl+5];
75 { // return an empty leaf
77 node->planenum = PLANENUM_LEAF;
78 node->contents = 0; //CONTENTS_SOLID;
84 // create a seperator along the largest axis
87 if (xh - xl > yh - yl)
89 mid = xl + (xh-xl)/2 + 1;
94 node->planenum = FindFloatPlane (normal, dist);
95 node->children[0] = BlockTree ( mid, yl, xh, yh);
96 node->children[1] = BlockTree ( xl, yl, mid-1, yh);
100 mid = yl + (yh-yl)/2 + 1;
105 node->planenum = FindFloatPlane (normal, dist);
106 node->children[0] = BlockTree ( xl, mid, xh, yh);
107 node->children[1] = BlockTree ( xl, yl, xh, mid-1);
119 int brush_start, brush_end;
120 void ProcessBlock_Thread (int blocknum)
128 yblock = block_yl + blocknum / (block_xh-block_xl+1);
129 xblock = block_xl + blocknum % (block_xh-block_xl+1);
131 Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);
133 mins[0] = xblock*1024;
134 mins[1] = yblock*1024;
136 maxs[0] = (xblock+1)*1024;
137 maxs[1] = (yblock+1)*1024;
140 // the makelist and chopbrushes could be cached between the passes...
141 brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
145 node->planenum = PLANENUM_LEAF;
146 node->contents = CONTENTS_SOLID;
147 block_nodes[xblock+5][yblock+5] = node;
152 brushes = ChopBrushes (brushes);
154 tree = BrushBSP (brushes, mins, maxs);
156 block_nodes[xblock+5][yblock+5] = tree->headnode;
165 void ProcessWorldModel (void)
171 xmlNodePtr polyline, leaknode;
174 e = &entities[entity_num];
176 brush_start = e->firstbrush;
177 brush_end = brush_start + e->numbrushes;
181 // perform per-block operations
183 if (block_xh * 1024 > map_maxs[0])
184 block_xh = floor(map_maxs[0]/1024.0);
185 if ( (block_xl+1) * 1024 < map_mins[0])
186 block_xl = floor(map_mins[0]/1024.0);
187 if (block_yh * 1024 > map_maxs[1])
188 block_yh = floor(map_maxs[1]/1024.0);
189 if ( (block_yl+1) * 1024 < map_mins[1])
190 block_yl = floor(map_mins[1]/1024.0);
201 for (optimize = false ; optimize <= true ; optimize++)
203 Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
205 RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
206 !verbose, ProcessBlock_Thread);
209 // build the division tree
210 // oversizing the blocks guarantees that all the boundaries
211 // will also get nodes.
214 Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
217 tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
219 tree->mins[0] = (block_xl)*1024;
220 tree->mins[1] = (block_yl)*1024;
221 tree->mins[2] = map_mins[2] - 8;
223 tree->maxs[0] = (block_xh+1)*1024;
224 tree->maxs[1] = (block_yh+1)*1024;
225 tree->maxs[2] = map_maxs[2] + 8;
228 // perform the global operations
230 MakeTreePortals (tree);
232 if (FloodEntities (tree))
233 FillOutside (tree->headnode);
237 Sys_FPrintf( SYS_NOXML, "**********************\n" );
238 Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
239 Sys_FPrintf( SYS_NOXML, "**********************\n" );
240 polyline = LeakFile( tree );
241 leaknode = xmlNewNode( NULL, "message" );
242 xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
243 xmlAddChild( leaknode, polyline );
244 level[0] = (int) '0' + SYS_ERR;
246 xmlSetProp( leaknode, "level", (char*) &level );
247 xml_SendNode( leaknode );
250 Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
255 Sys_Printf ("**** leaked ****\n");
260 Sys_Printf ("--- MAP LEAKED ---\n");
265 MarkVisibleSides (tree, brush_start, brush_end);
276 WriteGLView (tree, source);
277 MakeFaces (tree->headnode);
278 FixTjuncs (tree->headnode);
281 PruneNodes (tree->headnode);
283 WriteBSP (tree->headnode);
286 WritePortalFile (tree);
297 void ProcessSubModel (void)
305 e = &entities[entity_num];
307 start = e->firstbrush;
308 end = start + e->numbrushes;
310 mins[0] = mins[1] = mins[2] = -4096;
311 maxs[0] = maxs[1] = maxs[2] = 4096;
312 list = MakeBspBrushList (start, end, mins, maxs);
314 list = ChopBrushes (list);
315 tree = BrushBSP (list, mins, maxs);
316 MakeTreePortals (tree);
317 MarkVisibleSides (tree, start, end);
318 MakeFaces (tree->headnode);
319 FixTjuncs (tree->headnode);
320 WriteBSP (tree->headnode);
329 void ProcessModels (void)
333 for (entity_num=0 ; entity_num< num_entities ; entity_num++)
335 if (!entities[entity_num].numbrushes)
338 Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);
341 ProcessWorldModel ();
346 //if (!verboseentities)
347 // verbose = false; // don't bother printing submodels
365 Sys_Printf ("\n----- BSP ----\n\n");
368 start = I_FloatTime ();
371 SetQdirFromPath (mapname);
373 strcpy (source, ExpandArg (mapname));
374 StripExtension (source);
376 // delete portal and line files
377 sprintf (path, "%s.prt", source);
379 sprintf (path, "%s.lin", source);
382 strcpy (name, ExpandArg (mapname));
383 DefaultExtension (name, ".map"); // might be .reg
386 // if onlyents, just grab the entites and resave
392 sprintf (out, "%s.bsp", source);
407 // start from scratch
416 end = I_FloatTime ();
417 total_bsp_time = (int) (end-start);
418 Sys_Printf("\nBSP Time: ");
419 if ( total_bsp_time > 59 )
420 Sys_Printf("%d Minutes ", total_bsp_time/60 );
421 Sys_Printf( "%d Seconds\n", total_bsp_time%60 );