/** * @brief The incoming list will be freed before exiting */ tree_t *BuildTree (bspbrush_t *brushlist, const vec3_t mins, const vec3_t maxs) { node_t *node; tree_t *tree; vec3_t blmins, blmaxs; Verb_Printf(VERB_EXTRA, "--- BrushBSP ---\n"); tree = AllocTree(); ClearBounds(blmins, blmaxs); BrushlistCalcStats(brushlist, blmins, blmaxs); tree->aabb.add(blmins); tree->aabb.add(blmaxs); c_nodes = 0; c_nonvis = 0; node = AllocNode(); node->volume = BrushFromBounds(mins, maxs); tree->headnode = node; node = BuildTree_r(node, brushlist); Verb_Printf(VERB_EXTRA, "%5i visible nodes\n", c_nodes / 2 - c_nonvis); Verb_Printf(VERB_EXTRA, "%5i nonvis nodes\n", c_nonvis); Verb_Printf(VERB_EXTRA, "%5i leafs\n", (c_nodes + 1) / 2); return tree; }
/* ================ BuildTree_r ================ */ node_t *BuildTree_r (node_t *node, bspbrush_t *brushes) { node_t *newnode; side_t *bestside; int i; bspbrush_t *children[2]; if (numthreads == 1) c_nodes++; if (drawflag) DrawBrushList (brushes, node); // find the best plane to use as a splitter bestside = SelectSplitSide (brushes, node); if (!bestside) { // leaf node node->side = NULL; node->planenum = -1; LeafNode (node, brushes); return node; } // this is a splitplane node node->side = bestside; node->planenum = bestside->planenum & ~1; // always use front facing SplitBrushList (brushes, node, &children[0], &children[1]); FreeBrushList (brushes); // allocate children before recursing for (i=0 ; i<2 ; i++) { newnode = AllocNode (); newnode->parent = node; node->children[i] = newnode; } SplitBrush (node->volume, node->planenum, &node->children[0]->volume, &node->children[1]->volume); // recursively process children for (i=0 ; i<2 ; i++) { node->children[i] = BuildTree_r (node->children[i], children[i]); } return node; }
static node_t *BuildTree_r (node_t *node, bspbrush_t *brushes) { node_t *newnode; side_t *bestside; int i; bspbrush_t *children[2]; if (threadstate.numthreads == 1) c_nodes++; /* find the best plane to use as a splitter */ bestside = SelectSplitSide(brushes, node->volume); if (!bestside) { /* leaf node */ LeafNode(node, brushes); Verb_Printf(VERB_DUMP, "BuildTree_r: Created a leaf node.\n"); return node; } /* make sure the selected plane hasn't been used before. */ CheckPlaneAgainstParents(bestside->planenum, node); Verb_Printf(VERB_DUMP, "BuildTree_r: splitting along plane %i\n", (int)bestside->planenum); /* this is a splitplane node */ node->side = bestside; node->planenum = bestside->planenum & ~1; /* always use front facing */ SplitBrushList(brushes, node->planenum, &children[0], &children[1]); FreeBrushList(brushes); /* allocate children before recursing */ for (i = 0; i < 2; i++) { newnode = AllocNode(); newnode->parent = node; node->children[i] = newnode; } SplitBrush(node->volume, node->planenum, &node->children[0]->volume, &node->children[1]->volume); /* recursively process children */ for (i = 0; i < 2; i++) { node->children[i] = BuildTree_r(node->children[i], children[i]); } return node; }
/* ================= BrushBSP The incoming list will be freed before exiting ================= */ tree_t *BrushBSP (bspbrush_t *brushlist, Vector& mins, Vector& maxs) { node_t *node; bspbrush_t *b; int c_faces, c_nonvisfaces; int c_brushes; tree_t *tree; int i; vec_t volume; qprintf ("--- BrushBSP ---\n"); tree = AllocTree (); c_faces = 0; c_nonvisfaces = 0; c_brushes = 0; for (b=brushlist ; b ; b=b->next) { c_brushes++; volume = BrushVolume (b); if (volume < microvolume) { Warning("Brush %i: WARNING, microbrush\n", b->original->id); } for (i=0 ; i<b->numsides ; i++) { if (b->sides[i].bevel) continue; if (!b->sides[i].winding) continue; if (b->sides[i].texinfo == TEXINFO_NODE) continue; if (b->sides[i].visible) c_faces++; else c_nonvisfaces++; } AddPointToBounds (b->mins, tree->mins, tree->maxs); AddPointToBounds (b->maxs, tree->mins, tree->maxs); } qprintf ("%5i brushes\n", c_brushes); qprintf ("%5i visible faces\n", c_faces); qprintf ("%5i nonvisible faces\n", c_nonvisfaces); c_nodes = 0; c_nonvis = 0; node = AllocNode (); node->volume = BrushFromBounds (mins, maxs); tree->headnode = node; node = BuildTree_r (node, brushlist); qprintf ("%5i visible nodes\n", c_nodes/2 - c_nonvis); qprintf ("%5i nonvis nodes\n", c_nonvis); qprintf ("%5i leafs\n", (c_nodes+1)/2); #if 0 { // debug code static node_t *tnode; Vector p; p[0] = -1469; p[1] = -118; p[2] = 119; tnode = PointInLeaf (tree->headnode, p); Msg("contents: %i\n", tnode->contents); p[0] = 0; } #endif return tree; }
/* * ================= * BrushBSP * * The incoming list will be freed before exiting * ================= */ tree_t *BrushBSP(brush_t *brushlist, vec3_t mins, vec3_t maxs) { node_t *node; brush_t *b; int32_t c_faces, c_nonvisfaces; int32_t c_brushes; tree_t *tree; int32_t i; vec_t volume; Com_Debug(DEBUG_ALL, "--- BrushBSP ---\n"); tree = AllocTree(); c_faces = 0; c_nonvisfaces = 0; c_brushes = 0; for (b = brushlist; b; b = b->next) { c_brushes++; volume = BrushVolume(b); if (volume < microvolume) { Mon_SendSelect(ERROR_WARN, b->original->entity_num, b->original->brush_num, "Microbrush"); } for (i = 0; i < b->num_sides; i++) { if (b->sides[i].bevel) { continue; } if (!b->sides[i].winding) { continue; } if (b->sides[i].texinfo == TEXINFO_NODE) { continue; } if (b->sides[i].visible) { c_faces++; } else { c_nonvisfaces++; } } AddPointToBounds(b->mins, tree->mins, tree->maxs); AddPointToBounds(b->maxs, tree->mins, tree->maxs); } Com_Debug(DEBUG_ALL, "%5i brushes\n", c_brushes); Com_Debug(DEBUG_ALL, "%5i visible faces\n", c_faces); Com_Debug(DEBUG_ALL, "%5i nonvisible faces\n", c_nonvisfaces); SDL_DestroySemaphore(semaphores.vis_nodes); semaphores.vis_nodes = SDL_CreateSemaphore(0); SDL_DestroySemaphore(semaphores.nonvis_nodes); semaphores.nonvis_nodes = SDL_CreateSemaphore(0); node = AllocNode(); node->volume = BrushFromBounds(mins, maxs); tree->head_node = node; node = BuildTree_r(node, brushlist); const uint32_t vis_nodes = SDL_SemValue(semaphores.vis_nodes); const uint32_t nonvis_nodes = SDL_SemValue(semaphores.nonvis_nodes); Com_Debug(DEBUG_ALL, "%5i visible nodes\n", vis_nodes / 2 - nonvis_nodes); Com_Debug(DEBUG_ALL, "%5i nonvis nodes\n", nonvis_nodes); Com_Debug(DEBUG_ALL, "%5i leafs\n", (vis_nodes + 1) / 2); return tree; }
node_t *BuildTree_r( node_t *node, bspbrush_t *brushes ) { node_t *newnode; side_t *bestside; int i, totalmem; bspbrush_t *children[2]; qprintf( "\r%6d", numrecurse ); numrecurse++; if ( numthreads == 1 ) { totalmem = WindingMemory() + c_nodememory + c_brushmemory; if ( totalmem > c_peak_totalbspmemory ) { c_peak_totalbspmemory = totalmem; } c_nodes++; } //endif if ( drawflag ) { DrawBrushList( brushes, node ); } // find the best plane to use as a splitter bestside = SelectSplitSide( brushes, node ); if ( !bestside ) { // leaf node node->side = NULL; node->planenum = -1; LeafNode( node, brushes ); if ( node->contents & CONTENTS_SOLID ) { c_solidleafnodes++; } if ( create_aas ) { //free up memory!!! FreeBrushList( node->brushlist ); node->brushlist = NULL; //free the node volume brush if ( node->volume ) { FreeBrush( node->volume ); node->volume = NULL; } //end if } //end if return node; } //end if // this is a splitplane node node->side = bestside; node->planenum = bestside->planenum & ~1; // always use front facing //split the brush list in two for both children SplitBrushList( brushes, node, &children[0], &children[1] ); //free the old brush list FreeBrushList( brushes ); // allocate children before recursing for ( i = 0; i < 2; i++ ) { newnode = AllocNode(); newnode->parent = node; node->children[i] = newnode; } //end for //split the volume brush of the node for the children SplitBrush( node->volume, node->planenum, &node->children[0]->volume, &node->children[1]->volume ); if ( create_aas ) { //free the volume brush if ( node->volume ) { FreeBrush( node->volume ); node->volume = NULL; } //end if } //end if // recursively process children for ( i = 0; i < 2; i++ ) { node->children[i] = BuildTree_r( node->children[i], children[i] ); } //end for return node; } //end of the function BuildTree_r