/* ================ BuildFaceTree_r ================ */ void BuildFaceTree_r(node_t * node, bspFace_t * list) { bspFace_t *split; bspFace_t *next; int side; plane_t *plane; bspFace_t *newFace; bspFace_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum; int hintSplit; i = CountFaceList(list); SelectSplitPlaneNum(node, list, &splitPlaneNum, &hintSplit); // if we don't have any more faces, this is a node if(splitPlaneNum == -1) { node->planenum = PLANENUM_LEAF; c_faceLeafs++; return; } // partition the list node->planenum = splitPlaneNum; node->hint = hintSplit; plane = &mapPlanes[splitPlaneNum]; childLists[0] = NULL; childLists[1] = NULL; for(split = list; split; split = next) { next = split->next; if(split->planenum == node->planenum) { FreeBspFace(split); continue; } side = WindingOnPlaneSide(split->w, plane->normal, plane->dist); if(side == SIDE_CROSS) { ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding); if(frontWinding) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->hint = split->hint; childLists[0] = newFace; } if(backWinding) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->hint = split->hint; childLists[1] = newFace; } FreeBspFace(split); } else if(side == SIDE_FRONT) { split->next = childLists[0]; childLists[0] = split; } else if(side == SIDE_BACK) { split->next = childLists[1]; childLists[1] = split; } } // recursively process children for(i = 0; i < 2; i++) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy(node->mins, node->children[i]->mins); VectorCopy(node->maxs, node->children[i]->maxs); } for(i = 0; i < 3; i++) { if(plane->normal[i] == 1) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } for(i = 0; i < 2; i++) { BuildFaceTree_r(node->children[i], childLists[i]); } }
/* ================ BuildFaceTree_r ================ */ void BuildFaceTree_r( node_t *node, bspface_t *list ) { bspface_t *split; bspface_t *next; int side; bspface_t *newFace; bspface_t *childLists[2]; idWinding *frontWinding, *backWinding; int i; int splitPlaneNum; splitPlaneNum = SelectSplitPlaneNum( node, list ); // if we don't have any more faces, this is a node if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; c_faceLeafs++; return; } // partition the list node->planenum = splitPlaneNum; idPlane &plane = dmapGlobals.mapPlanes[ splitPlaneNum ]; childLists[0] = NULL; childLists[1] = NULL; for ( split = list ; split ; split = next ) { next = split->next; if ( split->planenum == node->planenum ) { FreeBspFace( split ); continue; } side = split->w->PlaneSide( plane ); if ( side == SIDE_CROSS ) { split->w->Split( plane, CLIP_EPSILON * 2, &frontWinding, &backWinding ); if ( frontWinding ) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; childLists[0] = newFace; } if ( backWinding ) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; childLists[1] = newFace; } FreeBspFace( split ); } else if ( side == SIDE_FRONT ) { split->next = childLists[0]; childLists[0] = split; } else if ( side == SIDE_BACK ) { split->next = childLists[1]; childLists[1] = split; } } // recursively process children for ( i = 0 ; i < 2 ; i++ ) { node->children[i] = AllocNode(); node->children[i]->parent = node; node->children[i]->bounds = node->bounds; } // split the bounds if we have a nice axial plane for ( i = 0 ; i < 3 ; i++ ) { if ( idMath::Fabs( plane[i] - 1.0 ) < 0.001 ) { node->children[0]->bounds[0][i] = plane.Dist(); node->children[1]->bounds[1][i] = plane.Dist(); break; } } for ( i = 0 ; i < 2 ; i++ ) { BuildFaceTree_r ( node->children[i], childLists[i]); } }
void BuildFaceTree_r( node_t *node, face_t *list ) { face_t *split; face_t *next; int side; plane_t *plane; face_t *newFace; face_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum, compileFlags; /* count faces left */ i = CountFaceList( list ); /* select the best split plane */ SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags ); /* if we don't have any more faces, this is a node */ if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; c_faceLeafs++; return; } /* partition the list */ node->planenum = splitPlaneNum; node->compileFlags = compileFlags; plane = &mapplanes[ splitPlaneNum ]; childLists[0] = NULL; childLists[1] = NULL; for( split = list; split; split = next ) { /* set next */ next = split->next; /* don't split by identical plane */ if( split->planenum == node->planenum ) { FreeBspFace( split ); continue; } /* determine which side the face falls on */ side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); /* switch on side */ if( side == SIDE_CROSS ) { ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding ); if( frontWinding ) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[0] = newFace; } if( backWinding ) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[1] = newFace; } FreeBspFace( split ); } else if ( side == SIDE_FRONT ) { split->next = childLists[0]; childLists[0] = split; } else if ( side == SIDE_BACK ) { split->next = childLists[1]; childLists[1] = split; } } // recursively process children for ( i = 0 ; i < 2 ; i++ ) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy( node->mins, node->children[i]->mins ); VectorCopy( node->maxs, node->children[i]->maxs ); } for ( i = 0 ; i < 3 ; i++ ) { if ( plane->normal[i] == 1 ) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } for ( i = 0 ; i < 2 ; i++ ) { BuildFaceTree_r ( node->children[i], childLists[i]); } }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tree_t *ProcessWorldBrushes(int brush_start, int brush_end) { bspbrush_t *brushes; tree_t *tree; node_t *node; vec3_t mins, maxs; //take the whole world mins[0] = map_mins[0] - 8; mins[1] = map_mins[1] - 8; mins[2] = map_mins[2] - 8; maxs[0] = map_maxs[0] + 8; maxs[1] = map_maxs[1] + 8; maxs[2] = map_maxs[2] + 8; //reset the brush bsp ResetBrushBSP(); // the makelist and chopbrushes could be cached between the passes... //create a list with brushes that are within the given mins/maxs //some brushes will be cut and only the part that falls within the //mins/maxs will be in the bush list brushes = MakeBspBrushList(brush_start, brush_end, mins, maxs); // if (!brushes) { node = AllocNode (); node->planenum = PLANENUM_LEAF; node->contents = CONTENTS_SOLID; tree = Tree_Alloc(); tree->headnode = node; VectorCopy(mins, tree->mins); VectorCopy(maxs, tree->maxs); } //end if else { //Carves any intersecting solid brushes into the minimum number //of non-intersecting brushes. if (!nocsg) { brushes = ChopBrushes(brushes); /* if (create_aas) { brushes = MergeBrushes(brushes); } //end if*/ } //end if //if the conversion is cancelled if (cancelconversion) { FreeBrushList(brushes); return NULL; } //end if //create the actual bsp tree tree = BrushBSP(brushes, mins, maxs); } //end else //return the tree return tree; } //end of the function ProcessWorldBrushes
/* ============ ProcessSubModel ============ */ void ProcessSubModel(int entityNum) { entity_t *e; tree_t *tree; bspBrush_t *b, *bc; node_t *node; e = &entities[entityNum]; e->firstDrawSurf = numMapDrawSurfs; BeginModel(e); PatchMapDrawSurfs(e); // just put all the brushes in an empty leaf // FIXME: patches? node = AllocNode(); node->planenum = PLANENUM_LEAF; for(b = e->brushes; b; b = b->next) { bc = CopyBrush(b); bc->next = node->brushlist; node->brushlist = bc; } tree = AllocTree(); tree->headnode = node; ClipSidesIntoTree(e, tree); // create drawsurfs for triangle models AddTriangleModel(e, qfalse); // subdivide each drawsurf as required by shader tesselation or fog if(!nosubdivide) { SubdivideDrawSurfs(e, tree); } // merge together all common shaders on the same plane and remove // all colinear points, so extra tjunctions won't be generated if(!nomerge) { MergeSides(e, tree); // !@# testing } // add in any vertexes required to fix tjunctions if(!notjunc) { FixTJunctions(e); } // allocate lightmaps for faces and patches AllocateLightmaps(e); // add references to the final drawsurfs in the apropriate clusters FilterDrawsurfsIntoTree(e, tree); EndModel(e, node); FreeTree(tree); }
static orl_return ProcSymbol( orl_symbol_handle symhdl ) /******************************************************/ { orl_symbol_type type; char *name; orl_symbol_value value; orl_sec_handle sechdl; symbol *sym; size_t namelen; sym_flags symop; extnode *newnode; segnode *snode; bool isweak; orl_symbol_handle assocsymhdl; symbol *assocsym; orl_symbol_binding binding; sechdl = ORLSymbolGetSecHandle( symhdl ); snode = FindSegNode( sechdl ); type = ORLSymbolGetType( symhdl ); name = ORLSymbolGetName( symhdl ); if( type & ORL_SYM_TYPE_FILE ) { if( !(CurrMod->modinfo & MOD_GOT_NAME) ) { CurrMod->modinfo |= MOD_GOT_NAME; _LnkFree( CurrMod->name ); CurrMod->name = AddStringStringTable( &PermStrings, name ); } return( ORL_OKAY ); } if( type & ORL_SYM_TYPE_DEBUG ) return( ORL_OKAY ); if( type & (ORL_SYM_TYPE_OBJECT|ORL_SYM_TYPE_FUNCTION) || (type & (ORL_SYM_TYPE_NOTYPE|ORL_SYM_TYPE_UNDEFINED) && name != NULL)) { namelen = strlen( name ); if( namelen == 0 ) { BadObject(); } if( CurrMod->modinfo & MOD_IMPORT_LIB ) { ImpProcSymbol( snode, type, name, namelen ); return( ORL_OKAY ); } newnode = AllocNode( ExtNodes ); newnode->handle = symhdl; binding = ORLSymbolGetBinding( symhdl ); symop = ST_CREATE; if( binding == ORL_SYM_BINDING_LOCAL ) { symop |= ST_STATIC | ST_NONUNIQUE; } if( type & ORL_SYM_TYPE_UNDEFINED && binding != ORL_SYM_BINDING_ALIAS ){ symop |= ST_REFERENCE; } else { symop |= ST_NOALIAS; } sym = SymOp( symop, name, namelen ); CheckIfTocSym( sym ); if( type & ORL_SYM_TYPE_COMMON ) { value = ORLSymbolGetValue( symhdl ); sym = MakeCommunalSym( sym, value, FALSE, TRUE ); } else if( type & ORL_SYM_TYPE_UNDEFINED ) { DefineReference( sym ); isweak = FALSE; switch( binding ) { case ORL_SYM_BINDING_WEAK: isweak = TRUE; case ORL_SYM_BINDING_ALIAS: case ORL_SYM_BINDING_LAZY: assocsymhdl = ORLSymbolGetAssociated( symhdl ); name = ORLSymbolGetName( assocsymhdl ); namelen = strlen(name); if( binding == ORL_SYM_BINDING_ALIAS ) { MakeSymAlias( sym->name, strlen(sym->name), name, namelen ); } else { assocsym = SymOp( ST_CREATE | ST_REFERENCE, name, namelen ); DefineLazyExtdef( sym, assocsym, isweak ); newnode->isweak = TRUE; } } } else { newnode->isdefd = TRUE; value = ORLSymbolGetValue( symhdl ); if( type & ORL_SYM_TYPE_COMMON && type & ORL_SYM_TYPE_OBJECT && sechdl == NULL) { sym = MakeCommunalSym( sym, value, FALSE, TRUE ); } else if( snode != NULL && snode->entry != NULL && snode->entry->iscdat ) { DefineComdatSym( snode, sym, value ); } else { sym->info |= SYM_DEFINED; DefineSymbol( sym, snode, value, 0 ); } } newnode->entry = sym; } else if( type & ORL_SYM_TYPE_SECTION && type & ORL_SYM_CDAT_MASK && snode != NULL && !(snode->info & SEG_DEAD) ) { snode->entry->select = (type & ORL_SYM_CDAT_MASK) >> ORL_SYM_CDAT_SHIFT; }
void BVHTree::BuildNode(BVHNode *node, const objPtr_t *objPtrs, const Aabb *objAabbs, std::vector<objPtr_t> &activeObjIdx) { const int numTris = activeObjIdx.size(); if (numTris <= 0) Error("BuildNode called with no elements in activeObjIndex."); if (numTris == 1) { MakeLeaf(node, objPtrs, activeObjIdx); return; } std::vector<int> splitSides(numTris); Aabb aabb; aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX); aabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX); for (int i=0; i<numTris; i++) { int idx = activeObjIdx[i]; aabb.Update(objAabbs[idx].min); aabb.Update(objAabbs[idx].max); } node->numTris = numTris; node->aabb = aabb; Aabb splitBox = aabb; double splitPos; int splitAxis; int s1count, s2count; int attempt = 0; for (;;) { splitAxis = 0; vector3d boxSize = splitBox.max - splitBox.min; if (boxSize[1] > boxSize[0]) splitAxis = 1; if ((boxSize[2] > boxSize[1]) && (boxSize[2] > boxSize[0])) splitAxis = 2; // split pos in middle of splitBox splitPos = 0.5f * (splitBox.min[splitAxis] + splitBox.max[splitAxis]); s1count = 0, s2count = 0; for (int i=0; i<numTris; i++) { int idx = activeObjIdx[i]; double mid = 0.5 * (objAabbs[idx].min[splitAxis] + objAabbs[idx].max[splitAxis]); if (mid < splitPos) { splitSides[i] = 0; s1count++; } else { splitSides[i] = 1; s2count++; } } if (s1count == numTris) { if (attempt < MAX_SPLITPOS_RETRIES) { // try splitting at average point splitBox.max[splitAxis] = splitPos; attempt++; continue; } else { MakeLeaf(node, objPtrs, activeObjIdx); return; } } else if (s2count == numTris) { if (attempt < MAX_SPLITPOS_RETRIES) { // try splitting at average point splitBox.min[splitAxis] = splitPos; attempt++; continue; } else { MakeLeaf(node, objPtrs, activeObjIdx); return; } } break; } std::vector<int> side[2]; for (int i=0; i<numTris; i++) { side[splitSides[i]].push_back(activeObjIdx[i]); } // recurse! node->triIndicesStart = 0; node->kids[0] = AllocNode(); node->kids[1] = AllocNode(); BuildNode(node->kids[0], objPtrs, objAabbs, side[0]); BuildNode(node->kids[1], objPtrs, objAabbs, side[1]); }
void BuildFaceTree_r(node_t * node, face_t * list) { face_t *split; face_t *next; int side; plane_t *plane; face_t *newFace; face_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum, compileFlags; qboolean isstruct = qfalse; int splits, front, back; /* count faces left */ i = CountFaceList(list); #if defined(DEBUG_SPLITS) Sys_FPrintf(SYS_VRB, "faces left = %d\n", i); #endif /* select the best split plane */ SelectSplitPlaneNum(node, list, &splitPlaneNum, &compileFlags); /* if we don't have any more faces, this is a leaf */ if(splitPlaneNum == -1) { node->planenum = PLANENUM_LEAF; node->has_structural_children = qfalse; c_faceLeafs++; return; } /* partition the list */ node->planenum = splitPlaneNum; node->compileFlags = compileFlags; node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque; plane = &mapplanes[splitPlaneNum]; childLists[0] = NULL; childLists[1] = NULL; splits = front = back = 0; for(split = list; split; split = next) { /* set next */ next = split->next; /* don't split by identical plane */ if(split->planenum == node->planenum) { FreeBspFace(split); continue; } if(!(split->compileFlags & C_DETAIL)) isstruct = 1; /* determine which side the face falls on */ side = WindingOnPlaneSide(split->w, plane->normal, plane->dist); /* switch on side */ if(side == SIDE_CROSS) { splits++; ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding); if(frontWinding) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[0] = newFace; front++; } if(backWinding) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[1] = newFace; back++; } FreeBspFace(split); } else if(side == SIDE_FRONT) { split->next = childLists[0]; childLists[0] = split; front++; } else if(side == SIDE_BACK) { split->next = childLists[1]; childLists[1] = split; back++; } } // recursively process children for(i = 0; i < 2; i++) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy(node->mins, node->children[i]->mins); VectorCopy(node->maxs, node->children[i]->maxs); c_faceNodes++; } for(i = 0; i < 3; i++) { if(plane->normal[i] == 1) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } #if 1 if(drawBSP && drawTree) { drawChildLists[0] = childLists[0]; drawChildLists[1] = childLists[1]; drawSplitNode = node; Draw_Scene(DrawAll); } #endif #if defined(DEBUG_SPLITS) if((node->compileFlags & C_DETAIL) && isstruct) Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf1\n", node->has_structural_children); #endif for(i = 0; i < 2; i++) { BuildFaceTree_r(node->children[i], childLists[i]); node->has_structural_children |= node->children[i]->has_structural_children; } #if defined(DEBUG_SPLITS) if((node->compileFlags & C_DETAIL) && !(node->children[0]->compileFlags & C_DETAIL) && node->children[0]->planenum != PLANENUM_LEAF) Sys_FPrintf(SYS_ERR, "I am detail, my child is structural\n", node->has_structural_children); if((node->compileFlags & C_DETAIL) && isstruct) Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf2\n", node->has_structural_children); #endif }
//=========================================================================== // The incoming brush list will be freed before exiting // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tree_t *BrushBSP(bspbrush_t *brushlist, vec3_t mins, vec3_t maxs) { int i, c_faces, c_nonvisfaces, c_brushes; bspbrush_t *b; node_t *node; tree_t *tree; vec_t volume; // vec3_t point; Log_Print("-------- Brush BSP ---------\n"); tree = Tree_Alloc(); c_faces = 0; c_nonvisfaces = 0; c_brushes = 0; c_totalsides = 0; for (b = brushlist; b; b = b->next) { c_brushes++; volume = BrushVolume(b); if (volume < microvolume) { Log_Print("WARNING: entity %i, brush %i: microbrush\n", b->original->entitynum, b->original->brushnum); } //end if for (i=0 ; i<b->numsides ; i++) { if (b->sides[i].flags & SFL_BEVEL) continue; if (!b->sides[i].winding) continue; if (b->sides[i].texinfo == TEXINFO_NODE) continue; if (b->sides[i].flags & SFL_VISIBLE) { c_faces++; } //end if else { c_nonvisfaces++; //if (create_aas) b->sides[i].texinfo = TEXINFO_NODE; } //end if } //end for c_totalsides += b->numsides; AddPointToBounds (b->mins, tree->mins, tree->maxs); AddPointToBounds (b->maxs, tree->mins, tree->maxs); } //end for Log_Print("%6i brushes\n", c_brushes); Log_Print("%6i visible faces\n", c_faces); Log_Print("%6i nonvisible faces\n", c_nonvisfaces); Log_Print("%6i total sides\n", c_totalsides); c_active_brushes = c_brushes; c_nodememory = 0; c_brushmemory = 0; c_peak_brushmemory = 0; c_nodes = 0; c_nonvis = 0; node = AllocNode (); //volume of first node (head node) node->volume = BrushFromBounds (mins, maxs); // tree->headnode = node; //just get some statistics and the mins/maxs of the node numrecurse = 0; // qprintf("%6d splits", numrecurse); tree->headnode->brushlist = brushlist; BuildTree(tree); //build the bsp tree with the start node from the brushlist // node = BuildTree_r(node, brushlist); //if the conversion is cancelled if (cancelconversion) return tree; qprintf("\n"); Log_Write("%6d splits\r\n", numrecurse); // Log_Print("%6i visible nodes\n", c_nodes/2 - c_nonvis); // Log_Print("%6i nonvis nodes\n", c_nonvis); // Log_Print("%6i leaves\n", (c_nodes+1)/2); // Log_Print("%6i solid leaf nodes\n", c_solidleafnodes); // Log_Print("%6i active brushes\n", c_active_brushes); if (numthreads == 1) { // Log_Print("%6i KB of node memory\n", c_nodememory >> 10); // Log_Print("%6i KB of brush memory\n", c_brushmemory >> 10); // Log_Print("%6i KB of peak brush memory\n", c_peak_brushmemory >> 10); // Log_Print("%6i KB of winding memory\n", WindingMemory() >> 10); // Log_Print("%6i KB of peak winding memory\n", WindingPeakMemory() >> 10); Log_Print("%6i KB of peak total bsp memory\n", c_peak_totalbspmemory >> 10); } //end if
//thread function, gets nodes from the nodelist and processes them void BuildTreeThread(int threadid) { node_t *newnode, *node; side_t *bestside; int i, totalmem; bspbrush_t *brushes; for (node = NextNodeFromList(); node; ) { //if the nodelist isn't empty try to add another thread //if (NodeListSize() > 10) AddThread(BuildTreeThread); //display the number of nodes processed so far if (numthreads == 1) IncreaseNodeCounter(); brushes = node->brushlist; if (numthreads == 1) { totalmem = WindingMemory() + c_nodememory + c_brushmemory; if (totalmem > c_peak_totalbspmemory) { c_peak_totalbspmemory = totalmem; } //end if c_nodes++; } //endif if (drawflag) { DrawBrushList(brushes, node); } //end if if (cancelconversion) { bestside = NULL; } //end if else { // find the best plane to use as a splitter bestside = SelectSplitSide(brushes, node); } //end else //if there's no split side left if (!bestside) { //create a leaf out of the node LeafNode(node, brushes); if (node->contents & CONTENTS_SOLID) c_solidleafnodes++; if (create_aas) { //free up memory!!! FreeBrushList(node->brushlist); node->brushlist = NULL; } //end if //free the node volume brush (it is not used anymore) if (node->volume) { FreeBrush(node->volume); node->volume = NULL; } //end if node = NextNodeFromList(); continue; } //end if // this is a splitplane node node->side = bestside; node->planenum = bestside->planenum & ~1; //always use front facing //allocate children for (i = 0; i < 2; i++) { newnode = AllocNode(); newnode->parent = node; node->children[i] = newnode; } //end for //split the brush list in two for both children SplitBrushList(brushes, node, &node->children[0]->brushlist, &node->children[1]->brushlist); CheckBrushLists(node->children[0]->brushlist, node->children[1]->brushlist); //free the old brush list FreeBrushList(brushes); node->brushlist = NULL; //split the volume brush of the node for the children SplitBrush(node->volume, node->planenum, &node->children[0]->volume, &node->children[1]->volume); if (!node->children[0]->volume || !node->children[1]->volume) { Error("child without volume brush"); } //end if //free the volume brush if (node->volume) { FreeBrush(node->volume); node->volume = NULL; } //end if //add both children to the node list //AddNodeToList(node->children[0]); AddNodeToList(node->children[1]); node = node->children[0]; } //end while RemoveThread(threadid); } //end of the function BuildTreeThread
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
/* PseudoCompileBSP() a stripped down ProcessModels */ void PseudoCompileBSP( qboolean need_tree, const char *BSPFilePath, const char *surfaceFilePath ){ int models; char modelValue[10]; entity_t *entity; face_t *faces; tree_t *tree; node_t *node; brush_t *brush; side_t *side; int i; SetDrawSurfacesBuffer(); mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); numMapDrawSurfs = 0; BeginBSPFile(); models = 1; for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ ) { /* get entity */ entity = &entities[ mapEntityNum ]; if ( entity->brushes == NULL && entity->patches == NULL ) { continue; } if ( mapEntityNum != 0 ) { sprintf( modelValue, "*%d", models++ ); SetKeyValue( entity, "model", modelValue ); } /* process the model */ Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels ); BeginModel(); entity->firstDrawSurf = numMapDrawSurfs; ClearMetaTriangles(); PatchMapDrawSurfs( entity ); if ( mapEntityNum == 0 && need_tree ) { faces = MakeStructuralBSPFaceList( entities[0].brushes ); tree = FaceBSP( faces ); node = tree->headnode; } else { node = AllocNode(); node->planenum = PLANENUM_LEAF; tree = AllocTree(); tree->headnode = node; } /* a minimized ClipSidesIntoTree */ for ( brush = entity->brushes; brush; brush = brush->next ) { /* walk the brush sides */ for ( i = 0; i < brush->numsides; i++ ) { /* get side */ side = &brush->sides[ i ]; if ( side->winding == NULL ) { continue; } /* shader? */ if ( side->shaderInfo == NULL ) { continue; } /* save this winding as a visible surface */ DrawSurfaceForSide( entity, brush, side, side->winding ); } } if ( meta ) { ClassifyEntitySurfaces( entity ); MakeEntityDecals( entity ); MakeEntityMetaTriangles( entity ); SmoothMetaTriangles(); MergeMetaTriangles(); } FilterDrawsurfsIntoTree( entity, tree ); FilterStructuralBrushesIntoTree( entity, tree ); FilterDetailBrushesIntoTree( entity, tree ); EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes ); EndModel( entity, node ); } EndBSPFile( qfalse, BSPFilePath, surfaceFilePath ); }