Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

brushbsp.c File Reference

#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h"
#include "aas_store.h"
#include "aas_cfg.h"
#include <assert.h>

Include dependency graph for brushbsp.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  cname_s

Defines

#define EDGE_LENGTH   0.2
#define PLANESIDE_EPSILON   0.001

Typedefs

typedef cname_s cname_t

Functions

void AddNodeToQueue (node_t *node)
void AddNodeToStack (node_t *node)
bspbrush_tAllocBrush (int numsides)
node_tAllocNode (void)
void BoundBrush (bspbrush_t *brush)
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, plane_t *p)
tree_tBrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs)
bspbrush_tBrushFromBounds (vec3_t mins, vec3_t maxs)
int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
int BrushOutOfBounds (bspbrush_t *brush, vec3_t mins, vec3_t maxs, float epsilon)
vec_t BrushVolume (bspbrush_t *brush)
void BuildTree (tree_t *tree)
node_tBuildTree_r (node_t *node, bspbrush_t *brushes)
void BuildTreeThread (int threadid)
void CheckBrushLists (bspbrush_t *brushlist1, bspbrush_t *brushlist2)
void CheckPlaneAgainstParents (int pnum, node_t *node)
qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
bspbrush_tCopyBrush (bspbrush_t *brush)
int CountBrushList (bspbrush_t *brushes)
void CreateBrushWindings (bspbrush_t *brush)
void DrawBrushList (bspbrush_t *brush, node_t *node)
void FindBrushInTree (node_t *node, int brushnum)
void FreeBrush (bspbrush_t *brushes)
void FreeBrushList (bspbrush_t *brushes)
void IncreaseNodeCounter (void)
void LeafNode (node_t *node, bspbrush_t *brushes)
node_tNextNodeFromList (void)
int NodeListSize (void)
node_tPointInLeaf (node_t *node, vec3_t point)
void PrintBrush (bspbrush_t *brush)
void PrintContents (int contents)
int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
void ResetBrushBSP (void)
side_tSelectSplitSide (bspbrush_t *brushes, node_t *node)
void SplitBrush (bspbrush_t *brush, int planenum, bspbrush_t **front, bspbrush_t **back)
void SplitBrushList (bspbrush_t *brushes, node_t *node, bspbrush_t **front, bspbrush_t **back)
int TestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits, qboolean *hintsplit, int *epsilonbrush)
qboolean WindingIsHuge (winding_t *w)
qboolean WindingIsTiny (winding_t *w)
void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)

Variables

void(* AddNodeToList )(node_t *node)
int c_active_brushes
int c_brushmemory
int c_nodememory
int c_nodes
int c_nonvis
int c_peak_brushmemory
int c_peak_totalbspmemory
int c_solidleafnodes
int c_totalsides
cname_t contentnames []
node_tfirstnode
node_tlastnode
int nodelistsize
int numrecurse = 0
int numwaiting = 0
int use_nodequeue = 0


Define Documentation

#define EDGE_LENGTH   0.2
 

Definition at line 817 of file brushbsp.c.

#define PLANESIDE_EPSILON   0.001
 

Definition at line 62 of file brushbsp.c.

Referenced by QuickTestBrushToPlanenum(), and TestBrushToPlanenum().


Typedef Documentation

typedef struct cname_s cname_t
 


Function Documentation

void AddNodeToQueue node_t node  ) 
 

Definition at line 1542 of file brushbsp.c.

References firstnode, lastnode, node_s::next, node_t, nodelistsize, ThreadLock(), ThreadSemaphoreIncrease(), and ThreadUnlock().

01543 {
01544     ThreadLock();
01545 
01546     node->next = NULL;
01547     if (lastnode) lastnode->next = node;
01548     else firstnode = node;
01549     lastnode = node;
01550     nodelistsize++;
01551 
01552     ThreadUnlock();
01553     //
01554     ThreadSemaphoreIncrease(1);
01555 } //end of the function AddNodeToQueue

Here is the call graph for this function:

void AddNodeToStack node_t node  ) 
 

Definition at line 1527 of file brushbsp.c.

References firstnode, lastnode, node_s::next, node_t, nodelistsize, ThreadLock(), ThreadSemaphoreIncrease(), and ThreadUnlock().

01528 {
01529     ThreadLock();
01530 
01531     node->next = firstnode;
01532     firstnode = node;
01533     if (!lastnode) lastnode = node;
01534     nodelistsize++;
01535 
01536     ThreadUnlock();
01537     //
01538     ThreadSemaphoreIncrease(1);
01539 } //end of the function AddNodeToStack

Here is the call graph for this function:

bspbrush_t* AllocBrush int  numsides  ) 
 

Definition at line 422 of file brushbsp.c.

00423 {
00424     bspbrush_t  *bb;
00425     int         c;
00426 
00427     c = (int)&(((bspbrush_t *)0)->sides[numsides]);
00428     bb = GetMemory(c);
00429     memset (bb, 0, c);
00430     if (numthreads == 1)
00431     {
00432         c_active_brushes++;
00433         c_brushmemory += MemorySize(bb);
00434         if (c_brushmemory > c_peak_brushmemory)
00435                 c_peak_brushmemory = c_brushmemory;
00436     } //end if
00437     return bb;
00438 } //end of the function AllocBrush

node_t* AllocNode void   ) 
 

Definition at line 404 of file brushbsp.c.

Referenced by BrushBSP(), BuildFaceTree_r(), BuildTree_r(), BuildTreeThread(), FaceBSP(), ProcessSubModel(), and ProcessWorldBrushes().

00405 {
00406     node_t  *node;
00407 
00408     node = GetMemory(sizeof(*node));
00409     memset (node, 0, sizeof(*node));
00410     if (numthreads == 1)
00411     {
00412         c_nodememory += MemorySize(node);
00413     } //end if
00414     return node;
00415 } //end of the function AllocNode

void BoundBrush bspbrush_t brush  ) 
 

Definition at line 237 of file brushbsp.c.

00238 {
00239     int         i, j;
00240     winding_t   *w;
00241 
00242     ClearBounds (brush->mins, brush->maxs);
00243     for (i=0 ; i<brush->numsides ; i++)
00244     {
00245         w = brush->sides[i].winding;
00246         if (!w)
00247             continue;
00248         for (j=0 ; j<w->numpoints ; j++)
00249             AddPointToBounds (w->p[j], brush->mins, brush->maxs);
00250     }
00251 } //end of the function BoundBrush

int BoxOnPlaneSide vec3_t  emins,
vec3_t  emaxs,
plane_t p
 

Definition at line 579 of file brushbsp.c.

00580 {
00581     float   dist1, dist2;
00582     int sides;
00583 
00584     // axial planes are easy
00585     if (p->type < 3)
00586     {
00587         sides = 0;
00588         if (emaxs[p->type] > p->dist+PLANESIDE_EPSILON) sides |= PSIDE_FRONT;
00589         if (emins[p->type] < p->dist-PLANESIDE_EPSILON) sides |= PSIDE_BACK;
00590         return sides;
00591     } //end if
00592     
00593 // general case
00594     switch (p->signbits)
00595     {
00596     case 0:
00597         dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00598         dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00599         break;
00600     case 1:
00601         dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00602         dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00603         break;
00604     case 2:
00605         dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00606         dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00607         break;
00608     case 3:
00609         dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00610         dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00611         break;
00612     case 4:
00613         dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00614         dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00615         break;
00616     case 5:
00617         dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00618         dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00619         break;
00620     case 6:
00621         dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00622         dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00623         break;
00624     case 7:
00625         dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00626         dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00627         break;
00628     default:
00629         dist1 = dist2 = 0;      // shut up compiler
00630 //      assert( 0 );
00631         break;
00632     }
00633 
00634     sides = 0;
00635     if (dist1 - p->dist >= PLANESIDE_EPSILON) sides = PSIDE_FRONT;
00636     if (dist2 - p->dist < PLANESIDE_EPSILON) sides |= PSIDE_BACK;
00637 
00638 //  assert(sides != 0);
00639 
00640     return sides;
00641 }

tree_t* BrushBSP bspbrush_t brushlist,
vec3_t  mins,
vec3_t  maxs
 

Definition at line 1756 of file brushbsp.c.

References AddPointToBounds(), AllocNode(), b, BrushFromBounds(), mapbrush_s::brushnum, BrushVolume(), bspbrush_t, BuildTree(), c_active_brushes, c_brushmemory, c_faces, c_nodememory, c_nodes, c_nonvis, c_peak_brushmemory, c_peak_totalbspmemory, c_totalsides, mapbrush_s::entitynum, side_s::flags, i, Log_Print(), Log_Write(), bspbrush_s::maxs, bspbrush_s::mins, bspbrush_s::next, node_t, numrecurse, bspbrush_s::numsides, numthreads, bspbrush_s::original, qprintf(), bspbrush_s::sides, side_s::texinfo, tree(), Tree_Alloc(), vec_t, node_s::volume, and side_s::winding.

Referenced by ProcessWorldBrushes().

01757 {
01758     int i, c_faces, c_nonvisfaces, c_brushes;
01759     bspbrush_t *b;
01760     node_t *node;
01761     tree_t *tree;
01762     vec_t volume;
01763 //  vec3_t point;
01764 
01765     Log_Print("-------- Brush BSP ---------\n");
01766 
01767     tree = Tree_Alloc();
01768 
01769     c_faces = 0;
01770     c_nonvisfaces = 0;
01771     c_brushes = 0;
01772     c_totalsides = 0;
01773     for (b = brushlist; b; b = b->next)
01774     {
01775         c_brushes++;
01776 
01777         volume = BrushVolume(b);
01778         if (volume < microvolume)
01779         {
01780             Log_Print("WARNING: entity %i, brush %i: microbrush\n",
01781                 b->original->entitynum, b->original->brushnum);
01782         } //end if
01783 
01784         for (i=0 ; i<b->numsides ; i++)
01785         {
01786             if (b->sides[i].flags & SFL_BEVEL)
01787                 continue;
01788             if (!b->sides[i].winding)
01789                 continue;
01790             if (b->sides[i].texinfo == TEXINFO_NODE)
01791                 continue;
01792             if (b->sides[i].flags & SFL_VISIBLE)
01793             {
01794                 c_faces++;
01795             } //end if
01796             else
01797             {
01798                 c_nonvisfaces++;
01799                 //if (create_aas) b->sides[i].texinfo = TEXINFO_NODE;
01800             } //end if
01801         } //end for
01802         c_totalsides += b->numsides;
01803 
01804         AddPointToBounds (b->mins, tree->mins, tree->maxs);
01805         AddPointToBounds (b->maxs, tree->mins, tree->maxs);
01806     } //end for
01807 
01808     Log_Print("%6i brushes\n", c_brushes);
01809     Log_Print("%6i visible faces\n", c_faces);
01810     Log_Print("%6i nonvisible faces\n", c_nonvisfaces);
01811     Log_Print("%6i total sides\n", c_totalsides);
01812 
01813     c_active_brushes = c_brushes;
01814     c_nodememory = 0;
01815     c_brushmemory = 0;
01816     c_peak_brushmemory = 0;
01817 
01818     c_nodes = 0;
01819     c_nonvis = 0;
01820     node = AllocNode ();
01821 
01822     //volume of first node (head node)
01823     node->volume = BrushFromBounds (mins, maxs);
01824     //
01825     tree->headnode = node;
01826     //just get some statistics and the mins/maxs of the node
01827     numrecurse = 0;
01828 //  qprintf("%6d splits", numrecurse);
01829 
01830     tree->headnode->brushlist = brushlist;
01831     BuildTree(tree);
01832 
01833     //build the bsp tree with the start node from the brushlist
01834 //  node = BuildTree_r(node, brushlist);
01835 
01836     //if the conversion is cancelled
01837     if (cancelconversion) return tree;
01838 
01839     qprintf("\n");
01840     Log_Write("%6d splits\r\n", numrecurse);
01841 //  Log_Print("%6i visible nodes\n", c_nodes/2 - c_nonvis);
01842 //  Log_Print("%6i nonvis nodes\n", c_nonvis);
01843 //  Log_Print("%6i leaves\n", (c_nodes+1)/2);
01844 //  Log_Print("%6i solid leaf nodes\n", c_solidleafnodes);
01845 //  Log_Print("%6i active brushes\n", c_active_brushes);
01846     if (numthreads == 1)
01847     {
01848 //      Log_Print("%6i KB of node memory\n", c_nodememory >> 10);
01849 //      Log_Print("%6i KB of brush memory\n", c_brushmemory >> 10);
01850 //      Log_Print("%6i KB of peak brush memory\n", c_peak_brushmemory >> 10);
01851 //      Log_Print("%6i KB of winding memory\n", WindingMemory() >> 10);
01852 //      Log_Print("%6i KB of peak winding memory\n", WindingPeakMemory() >> 10);
01853         Log_Print("%6i KB of peak total bsp memory\n", c_peak_totalbspmemory >> 10);
01854     } //end if
01855 
01856     /*
01857     point[0] = 1485;
01858     point[1] = 956.125;
01859     point[2] = 352.125;
01860     node = PointInLeaf(tree->headnode, point);
01861     if (node->planenum != PLANENUM_LEAF)
01862     {
01863         Log_Print("node not a leaf\n");
01864     } //end if
01865     Log_Print("at %f %f %f:\n", point[0], point[1], point[2]);
01866     PrintContents(node->contents);
01867     Log_Print("node->expansionbboxes = %d\n", node->expansionbboxes);
01868     //*/
01869     return tree;
01870 } //end of the function BrushBSP

Here is the call graph for this function:

bspbrush_t* BrushFromBounds vec3_t  mins,
vec3_t  maxs
 

Definition at line 292 of file brushbsp.c.

00293 {
00294     bspbrush_t *b;
00295     int i;
00296     vec3_t normal;
00297     vec_t dist;
00298 
00299     b = AllocBrush (6);
00300     b->numsides = 6;
00301     for (i=0 ; i<3 ; i++)
00302     {
00303         VectorClear (normal);
00304         normal[i] = 1;
00305         dist = maxs[i];
00306         b->sides[i].planenum = FindFloatPlane (normal, dist);
00307 
00308         normal[i] = -1;
00309         dist = -mins[i];
00310         b->sides[3+i].planenum = FindFloatPlane (normal, dist);
00311     }
00312 
00313     CreateBrushWindings (b);
00314 
00315     return b;
00316 } //end of the function BrushFromBounds

int BrushMostlyOnSide bspbrush_t brush,
plane_t plane
 

Definition at line 1108 of file brushbsp.c.

01109 {
01110     int         i, j;
01111     winding_t   *w;
01112     vec_t       d, max;
01113     int         side;
01114 
01115     max = 0;
01116     side = PSIDE_FRONT;
01117     for (i=0 ; i<brush->numsides ; i++)
01118     {
01119         w = brush->sides[i].winding;
01120         if (!w)
01121             continue;
01122         for (j=0 ; j<w->numpoints ; j++)
01123         {
01124             d = DotProduct (w->p[j], plane->normal) - plane->dist;
01125             if (d > max)
01126             {
01127                 max = d;
01128                 side = PSIDE_FRONT;
01129             }
01130             if (-d > max)
01131             {
01132                 max = -d;
01133                 side = PSIDE_BACK;
01134             }
01135         }
01136     }
01137     return side;
01138 } //end of the function BrushMostlyOnSide

int BrushOutOfBounds bspbrush_t brush,
vec3_t  mins,
vec3_t  maxs,
float  epsilon
 

Definition at line 323 of file brushbsp.c.

References bspbrush_t, i, j, n, winding_t::numpoints, bspbrush_s::numsides, winding_t::p, side_t, bspbrush_s::sides, w, and side_s::winding.

00324 {
00325     int i, j, n;
00326     winding_t *w;
00327     side_t *side;
00328 
00329     for (i = 0; i < brush->numsides; i++)
00330     {
00331         side = &brush->sides[i];
00332         w = side->winding;
00333         for (j = 0; j < w->numpoints; j++)
00334         {
00335             for (n = 0; n < 3; n++)
00336             {
00337                 if (w->p[j][n] < (mins[n] + epsilon) || w->p[j][n] > (maxs[n] - epsilon)) return true;
00338             } //end for
00339         } //end for
00340     } //end for
00341     return false;
00342 } //end of the function BrushOutOfBounds

vec_t BrushVolume bspbrush_t brush  ) 
 

Definition at line 349 of file brushbsp.c.

00350 {
00351     int i;
00352     winding_t *w;
00353     vec3_t corner;
00354     vec_t d, area, volume;
00355     plane_t *plane;
00356 
00357     if (!brush) return 0;
00358 
00359     // grab the first valid point as the corner
00360     w = NULL;
00361     for (i = 0; i < brush->numsides; i++)
00362     {
00363         w = brush->sides[i].winding;
00364         if (w) break;
00365     } //end for
00366     if (!w) return 0;
00367     VectorCopy (w->p[0], corner);
00368 
00369     // make tetrahedrons to all other faces
00370     volume = 0;
00371     for ( ; i < brush->numsides; i++)
00372     {
00373         w = brush->sides[i].winding;
00374         if (!w) continue;
00375         plane = &mapplanes[brush->sides[i].planenum];
00376         d = -(DotProduct (corner, plane->normal) - plane->dist);
00377         area = WindingArea(w);
00378         volume += d * area;
00379     } //end for
00380 
00381     volume /= 3;
00382     return volume;
00383 } //end of the function BrushVolume

void BuildTree tree_t tree  ) 
 

Definition at line 1720 of file brushbsp.c.

References AddNodeToList, AddThread(), BuildTreeThread(), firstnode, i, lastnode, Log_Print(), numthreads, numwaiting, qprintf(), ThreadSetupLock(), ThreadSetupSemaphore(), ThreadShutdownLock(), ThreadShutdownSemaphore(), tree(), and WaitForAllThreadsFinished().

Referenced by BrushBSP().

01721 {
01722     int i;
01723 
01724     firstnode = NULL;
01725     lastnode = NULL;
01726     //use a node queue or node stack
01727     if (use_nodequeue) AddNodeToList = AddNodeToQueue;
01728     else AddNodeToList = AddNodeToStack;
01729     //setup thread locking
01730     ThreadSetupLock();
01731     ThreadSetupSemaphore();
01732     numwaiting = 0;
01733     //
01734     Log_Print("%6d threads max\n", numthreads);
01735     if (use_nodequeue) Log_Print("breadth first bsp building\n");
01736     else Log_Print("depth first bsp building\n");
01737     qprintf("%6d splits", 0);
01738     //add the first node to the list
01739     AddNodeToList(tree->headnode);
01740     //start the threads
01741     for (i = 0; i < numthreads; i++)
01742         AddThread(BuildTreeThread);
01743     //wait for all added threads to be finished
01744     WaitForAllThreadsFinished();
01745     //shutdown the thread locking
01746     ThreadShutdownLock();
01747     ThreadShutdownSemaphore();
01748 } //end of the function BuildTree

Here is the call graph for this function:

node_t* BuildTree_r node_t node,
bspbrush_t brushes
 

Definition at line 1428 of file brushbsp.c.

References AllocNode(), node_s::brushlist, bspbrush_t, c_nodememory, c_nodes, c_peak_totalbspmemory, c_solidleafnodes, node_s::children, node_s::contents, DrawBrushList(), FreeBrush(), FreeBrushList(), i, LeafNode(), newnode(), node_t, numrecurse, numthreads, side_s::planenum, node_s::planenum, qprintf(), SelectSplitSide(), node_s::side, side_t, SplitBrush(), SplitBrushList(), node_s::volume, and WindingMemory().

01429 {
01430     node_t      *newnode;
01431     side_t      *bestside;
01432     int         i, totalmem;
01433     bspbrush_t  *children[2];
01434 
01435     qprintf("\r%6d", numrecurse);
01436     numrecurse++;
01437 
01438     if (numthreads == 1)
01439     {
01440         totalmem = WindingMemory() + c_nodememory + c_brushmemory;
01441         if (totalmem > c_peak_totalbspmemory)
01442             c_peak_totalbspmemory = totalmem;
01443         c_nodes++;
01444     } //endif
01445 
01446     if (drawflag)
01447         DrawBrushList(brushes, node);
01448 
01449     // find the best plane to use as a splitter
01450     bestside = SelectSplitSide (brushes, node);
01451     if (!bestside)
01452     {
01453         // leaf node
01454         node->side = NULL;
01455         node->planenum = -1;
01456         LeafNode(node, brushes);
01457         if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
01458         if (create_aas)
01459         {
01460             //free up memory!!!
01461             FreeBrushList(node->brushlist);
01462             node->brushlist = NULL;
01463             //free the node volume brush
01464             if (node->volume)
01465             {
01466                 FreeBrush(node->volume);
01467                 node->volume = NULL;
01468             } //end if
01469         } //end if
01470         return node;
01471     } //end if
01472 
01473     // this is a splitplane node
01474     node->side = bestside;
01475     node->planenum = bestside->planenum & ~1;   // always use front facing
01476 
01477     //split the brush list in two for both children
01478     SplitBrushList (brushes, node, &children[0], &children[1]);
01479     //free the old brush list
01480     FreeBrushList (brushes);
01481 
01482     // allocate children before recursing
01483     for (i = 0; i < 2; i++)
01484     {
01485         newnode = AllocNode ();
01486         newnode->parent = node;
01487         node->children[i] = newnode;
01488     } //end for
01489 
01490     //split the volume brush of the node for the children
01491     SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
01492         &node->children[1]->volume);
01493 
01494     if (create_aas)
01495     {
01496         //free the volume brush
01497         if (node->volume)
01498         {
01499             FreeBrush(node->volume);
01500             node->volume = NULL;
01501         } //end if
01502     } //end if
01503     // recursively process children
01504     for (i = 0; i < 2; i++)
01505     {
01506         node->children[i] = BuildTree_r(node->children[i], children[i]);
01507     } //end for
01508 
01509     return node;
01510 } //end of the function BuildTree_r

Here is the call graph for this function:

void BuildTreeThread int  threadid  ) 
 

Definition at line 1608 of file brushbsp.c.

References AddNodeToList, AllocNode(), node_s::brushlist, bspbrush_t, c_nodememory, c_nodes, c_peak_totalbspmemory, c_solidleafnodes, CheckBrushLists(), node_s::children, node_s::contents, DrawBrushList(), Error(), FreeBrush(), FreeBrushList(), i, IncreaseNodeCounter(), LeafNode(), newnode(), NextNodeFromList(), node_t, numthreads, side_s::planenum, node_s::planenum, RemoveThread(), SelectSplitSide(), node_s::side, side_t, SplitBrush(), SplitBrushList(), node_s::volume, and WindingMemory().

Referenced by BuildTree().

01609 {
01610     node_t *newnode, *node;
01611     side_t *bestside;
01612     int i, totalmem;
01613     bspbrush_t *brushes;
01614 
01615     for (node = NextNodeFromList(); node; )
01616     {
01617         //if the nodelist isn't empty try to add another thread
01618         //if (NodeListSize() > 10) AddThread(BuildTreeThread);
01619         //display the number of nodes processed so far
01620         if (numthreads == 1)
01621             IncreaseNodeCounter();
01622 
01623         brushes = node->brushlist;
01624 
01625         if (numthreads == 1)
01626         {
01627             totalmem = WindingMemory() + c_nodememory + c_brushmemory;
01628             if (totalmem > c_peak_totalbspmemory)
01629             {
01630                 c_peak_totalbspmemory = totalmem;
01631             } //end if
01632             c_nodes++;
01633         } //endif
01634 
01635         if (drawflag)
01636         {
01637             DrawBrushList(brushes, node);
01638         } //end if
01639 
01640         if (cancelconversion)
01641         {
01642             bestside = NULL;
01643         } //end if
01644         else
01645         {
01646             // find the best plane to use as a splitter
01647             bestside = SelectSplitSide(brushes, node);
01648         } //end else
01649         //if there's no split side left
01650         if (!bestside)
01651         {
01652             //create a leaf out of the node
01653             LeafNode(node, brushes);
01654             if (node->contents & CONTENTS_SOLID) c_solidleafnodes++;
01655             if (create_aas)
01656             {
01657                 //free up memory!!!
01658                 FreeBrushList(node->brushlist);
01659                 node->brushlist = NULL;
01660             } //end if
01661             //free the node volume brush (it is not used anymore)
01662             if (node->volume)
01663             {
01664                 FreeBrush(node->volume);
01665                 node->volume = NULL;
01666             } //end if
01667             node = NextNodeFromList();
01668             continue;
01669         } //end if
01670 
01671         // this is a splitplane node
01672         node->side = bestside;
01673         node->planenum = bestside->planenum & ~1;   //always use front facing
01674 
01675         //allocate children
01676         for (i = 0; i < 2; i++)
01677         {
01678             newnode = AllocNode();
01679             newnode->parent = node;
01680             node->children[i] = newnode;
01681         } //end for
01682 
01683         //split the brush list in two for both children
01684         SplitBrushList(brushes, node, &node->children[0]->brushlist, &node->children[1]->brushlist);
01685 
01686         CheckBrushLists(node->children[0]->brushlist, node->children[1]->brushlist);
01687         //free the old brush list
01688         FreeBrushList(brushes);
01689         node->brushlist = NULL;
01690 
01691         //split the volume brush of the node for the children
01692         SplitBrush(node->volume, node->planenum, &node->children[0]->volume,
01693                                 &node->children[1]->volume);
01694 
01695         if (!node->children[0]->volume || !node->children[1]->volume)
01696         {
01697             Error("child without volume brush");
01698         } //end if
01699 
01700         //free the volume brush
01701         if (node->volume)
01702         {
01703             FreeBrush(node->volume);
01704             node->volume = NULL;
01705         } //end if
01706         //add both children to the node list
01707         //AddNodeToList(node->children[0]);
01708         AddNodeToList(node->children[1]);
01709         node = node->children[0];
01710     } //end while
01711     RemoveThread(threadid);
01712 } //end of the function BuildTreeThread

Here is the call graph for this function:

void CheckBrushLists bspbrush_t brushlist1,
bspbrush_t brushlist2
 

Definition at line 1408 of file brushbsp.c.

References assert, bspbrush_t, and bspbrush_s::next.

Referenced by BuildTreeThread().

01409 {
01410     bspbrush_t *brush1, *brush2;
01411 
01412     for (brush1 = brushlist1; brush1; brush1 = brush1->next)
01413     {
01414         for (brush2 = brushlist2; brush2; brush2 = brush2->next)
01415         {
01416             assert(brush1 != brush2);
01417         } //end for
01418     } //end for
01419 } //end of the function CheckBrushLists

void CheckPlaneAgainstParents int  pnum,
node_t node
 

Definition at line 927 of file brushbsp.c.

References Error(), node_t, p, node_s::parent, and node_s::planenum.

Referenced by SelectSplitSide().

00928 {
00929     node_t  *p;
00930 
00931     for (p = node->parent; p; p = p->parent)
00932     {
00933         if (p->planenum == pnum) Error("Tried parent");
00934     } //end for
00935 } //end of the function CheckPlaneAgainstParants

Here is the call graph for this function:

qboolean CheckPlaneAgainstVolume int  pnum,
node_t node
 

Definition at line 942 of file brushbsp.c.

References bspbrush_t, FreeBrush(), node_t, qboolean, SplitBrush(), and node_s::volume.

Referenced by SelectSplitSide().

00943 {
00944     bspbrush_t  *front, *back;
00945     qboolean    good;
00946 
00947     SplitBrush (node->volume, pnum, &front, &back);
00948 
00949     good = (front && back);
00950 
00951     if (front) FreeBrush (front);
00952     if (back) FreeBrush (back);
00953 
00954     return good;
00955 } //end of the function CheckPlaneAgaintsVolume

Here is the call graph for this function:

bspbrush_t* CopyBrush bspbrush_t brush  ) 
 

Definition at line 484 of file brushbsp.c.

00485 {
00486     bspbrush_t *newbrush;
00487     int         size;
00488     int         i;
00489     
00490     size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
00491 
00492     newbrush = AllocBrush (brush->numsides);
00493     memcpy (newbrush, brush, size);
00494 
00495     for (i=0 ; i<brush->numsides ; i++)
00496     {
00497         if (brush->sides[i].winding)
00498             newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
00499     }
00500 
00501     return newbrush;
00502 } //end of the function CopyBrush

int CountBrushList bspbrush_t brushes  ) 
 

Definition at line 390 of file brushbsp.c.

Referenced by ChopBrushes().

00391 {
00392     int c;
00393 
00394     c = 0;
00395     for ( ; brushes; brushes = brushes->next) c++;
00396     return c;
00397 } //end of the function CountBrushList

void CreateBrushWindings bspbrush_t brush  ) 
 

Definition at line 258 of file brushbsp.c.

00259 {
00260     int         i, j;
00261     winding_t   *w;
00262     side_t      *side;
00263     plane_t     *plane;
00264 
00265     for (i=0 ; i<brush->numsides ; i++)
00266     {
00267         side = &brush->sides[i];
00268         plane = &mapplanes[side->planenum];
00269         w = BaseWindingForPlane (plane->normal, plane->dist);
00270         for (j=0 ; j<brush->numsides && w; j++)
00271         {
00272             if (i == j)
00273                 continue;
00274             if (brush->sides[j].flags & SFL_BEVEL)
00275                 continue;
00276             plane = &mapplanes[brush->sides[j].planenum^1];
00277             ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
00278         }
00279 
00280         side->winding = w;
00281     }
00282 
00283     BoundBrush (brush);
00284 } //end of the function CreateBrushWindings

void DrawBrushList bspbrush_t brush,
node_t node