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;
48 int block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
53 node_t *block_nodes[10][10];
62 node_t *BlockTree( int xl, int yl, int xh, int yh ){
68 if ( xl == xh && yl == yh ) {
69 node = block_nodes[xl + 5][yl + 5];
70 if ( !node ) { // return an empty leaf
72 node->planenum = PLANENUM_LEAF;
73 node->contents = 0; //CONTENTS_SOLID;
79 // create a seperator along the largest axis
82 if ( xh - xl > yh - yl ) { // split x axis
83 mid = xl + ( xh - xl ) / 2 + 1;
88 node->planenum = FindFloatPlane( normal, dist );
89 node->children[0] = BlockTree( mid, yl, xh, yh );
90 node->children[1] = BlockTree( xl, yl, mid - 1, yh );
94 mid = yl + ( yh - yl ) / 2 + 1;
99 node->planenum = FindFloatPlane( normal, dist );
100 node->children[0] = BlockTree( xl, mid, xh, yh );
101 node->children[1] = BlockTree( xl, yl, xh, mid - 1 );
113 int brush_start, brush_end;
114 void ProcessBlock_Thread( int blocknum ){
121 yblock = block_yl + blocknum / ( block_xh - block_xl + 1 );
122 xblock = block_xl + blocknum % ( block_xh - block_xl + 1 );
124 Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock );
126 mins[0] = xblock * 1024;
127 mins[1] = yblock * 1024;
129 maxs[0] = ( xblock + 1 ) * 1024;
130 maxs[1] = ( yblock + 1 ) * 1024;
133 // the makelist and chopbrushes could be cached between the passes...
134 brushes = MakeBspBrushList( brush_start, brush_end, mins, maxs );
137 node->planenum = PLANENUM_LEAF;
138 node->contents = CONTENTS_SOLID;
139 block_nodes[xblock + 5][yblock + 5] = node;
144 brushes = ChopBrushes( brushes );
147 tree = BrushBSP( brushes, mins, maxs );
149 block_nodes[xblock + 5][yblock + 5] = tree->headnode;
158 void ProcessWorldModel( void ){
163 xmlNodePtr polyline, leaknode;
166 e = &entities[entity_num];
168 brush_start = e->firstbrush;
169 brush_end = brush_start + e->numbrushes;
173 // perform per-block operations
175 if ( block_xh * 1024 > map_maxs[0] ) {
176 block_xh = floor( map_maxs[0] / 1024.0 );
178 if ( ( block_xl + 1 ) * 1024 < map_mins[0] ) {
179 block_xl = floor( map_mins[0] / 1024.0 );
181 if ( block_yh * 1024 > map_maxs[1] ) {
182 block_yh = floor( map_maxs[1] / 1024.0 );
184 if ( ( block_yl + 1 ) * 1024 < map_mins[1] ) {
185 block_yl = floor( map_mins[1] / 1024.0 );
188 if ( block_xl < -4 ) {
191 if ( block_yl < -4 ) {
194 if ( block_xh > 3 ) {
197 if ( block_yh > 3 ) {
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 );
238 Sys_FPrintf( SYS_NOXML, "**********************\n" );
239 Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
240 Sys_FPrintf( SYS_NOXML, "**********************\n" );
241 polyline = LeakFile( tree );
242 leaknode = xmlNewNode( NULL, "message" );
243 xmlNodeAddContent( leaknode, "MAP LEAKED\n" );
244 xmlAddChild( leaknode, polyline );
245 level[0] = (int) '0' + SYS_ERR;
247 xmlSetProp( leaknode, "level", (char*) &level );
248 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 );
266 if ( noopt || leaked ) {
276 WriteGLView( tree, source );
278 MakeFaces( tree->headnode );
279 FixTjuncs( tree->headnode );
282 PruneNodes( tree->headnode );
285 WriteBSP( tree->headnode );
288 WritePortalFile( tree );
300 void ProcessSubModel( void ){
307 e = &entities[entity_num];
309 start = e->firstbrush;
310 end = start + e->numbrushes;
312 mins[0] = mins[1] = mins[2] = -4096;
313 maxs[0] = maxs[1] = maxs[2] = 4096;
314 list = MakeBspBrushList( start, end, mins, maxs );
316 list = ChopBrushes( list );
318 tree = BrushBSP( list, mins, maxs );
319 MakeTreePortals( tree );
320 MarkVisibleSides( tree, start, end );
321 MakeFaces( tree->headnode );
322 FixTjuncs( tree->headnode );
323 WriteBSP( tree->headnode );
332 void ProcessModels( void ){
335 for ( entity_num = 0 ; entity_num < num_entities ; entity_num++ )
337 if ( !entities[entity_num].numbrushes ) {
341 Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels );
343 if ( entity_num == 0 ) {
351 //if (!verboseentities)
352 // verbose = false; // don't bother printing submodels
369 Sys_Printf( "\n----- BSP ----\n\n" );
372 start = I_FloatTime();
375 SetQdirFromPath( mapname );
377 strcpy( source, ExpandArg( mapname ) );
378 StripExtension( source );
380 // delete portal and line files
381 sprintf( path, "%s.prt", source );
383 sprintf( path, "%s.lin", source );
386 strcpy( name, ExpandArg( mapname ) );
387 DefaultExtension( name, ".map" ); // might be .reg
390 // if onlyents, just grab the entites and resave
395 sprintf( out, "%s.bsp", source );
410 // start from scratch
420 total_bsp_time = (int) ( end - start );
421 Sys_Printf( "\nBSP Time: " );
422 if ( total_bsp_time > 59 ) {
423 Sys_Printf( "%d Minutes ", total_bsp_time / 60 );
425 Sys_Printf( "%d Seconds\n", total_bsp_time % 60 );