mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 00:49:29 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
426
tools/quake2/q2map/qbsp.c
Normal file
426
tools/quake2/q2map/qbsp.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
// csg4.c
|
||||
|
||||
#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);
|
||||
|
||||
Sys_FPrintf( SYS_VRB, "############### 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;
|
||||
xmlNodePtr polyline, leaknode;
|
||||
char level[ 2 ];
|
||||
|
||||
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++)
|
||||
{
|
||||
Sys_FPrintf( SYS_VRB, "--------------------------------------------\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.
|
||||
//
|
||||
|
||||
Sys_FPrintf( SYS_VRB, "--------------------------------------------\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
|
||||
{
|
||||
|
||||
Sys_FPrintf( SYS_NOXML, "**********************\n" );
|
||||
Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
|
||||
Sys_FPrintf( SYS_NOXML, "**********************\n" );
|
||||
polyline = LeakFile( tree );
|
||||
leaknode = xmlNewNode( NULL, "message" );
|
||||
xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
|
||||
xmlAddChild( leaknode, polyline );
|
||||
level[0] = (int) '0' + SYS_ERR;
|
||||
level[1] = 0;
|
||||
xmlSetProp( leaknode, "level", (char*) &level );
|
||||
xml_SendNode( leaknode );
|
||||
if( leaktest )
|
||||
{
|
||||
Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
|
||||
exit( 0 );
|
||||
}
|
||||
leaked = true;
|
||||
/*
|
||||
Sys_Printf ("**** leaked ****\n");
|
||||
leaked = true;
|
||||
LeakFile (tree);
|
||||
if (leaktest)
|
||||
{
|
||||
Sys_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;
|
||||
|
||||
Sys_FPrintf( SYS_VRB, "############### 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 BSP_Main ()
|
||||
{
|
||||
double start, end;
|
||||
char path[1024];
|
||||
int total_bsp_time;
|
||||
|
||||
Sys_Printf ("\n----- BSP ----\n\n");
|
||||
|
||||
|
||||
start = I_FloatTime ();
|
||||
|
||||
ThreadSetDefault ();
|
||||
SetQdirFromPath (mapname);
|
||||
|
||||
strcpy (source, ExpandArg (mapname));
|
||||
StripExtension (source);
|
||||
|
||||
// delete portal and line files
|
||||
sprintf (path, "%s.prt", source);
|
||||
remove (path);
|
||||
sprintf (path, "%s.lin", source);
|
||||
remove (path);
|
||||
|
||||
strcpy (name, ExpandArg (mapname));
|
||||
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 ();
|
||||
total_bsp_time = (int) (end-start);
|
||||
Sys_Printf("\nBSP Time: ");
|
||||
if ( total_bsp_time > 59 )
|
||||
Sys_Printf("%d Minutes ", total_bsp_time/60 );
|
||||
Sys_Printf( "%d Seconds\n", total_bsp_time%60 );
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user