/* ================ FaceBSP List will be freed before returning ================ */ tree_t *FaceBSP(bspFace_t * list) { tree_t *tree; bspFace_t *face; int i; int count; Sys_FPrintf(SYS_VRB, "--- FaceBSP ---\n"); tree = AllocTree(); count = 0; for(face = list; face; face = face->next) { count++; for(i = 0; i < face->w->numpoints; i++) { AddPointToBounds(face->w->p[i], tree->mins, tree->maxs); } } Sys_FPrintf(SYS_VRB, "%5i faces\n", count); tree->headnode = AllocNode(); VectorCopy(tree->mins, tree->headnode->mins); VectorCopy(tree->maxs, tree->headnode->maxs); c_faceLeafs = 0; BuildFaceTree_r(tree->headnode, list); Sys_FPrintf(SYS_VRB, "%5i leafs\n", c_faceLeafs); return tree; }
/* ================ FaceBSP List will be freed before returning ================ */ tree_t *FaceBSP(face_t * list, qboolean drawDebug) { tree_t *tree; face_t *face; int i; int count; Sys_FPrintf(SYS_VRB, "--- FaceBSP ---\n"); tree = AllocTree(); count = 0; for(face = list; face != NULL; face = face->next) { count++; for(i = 0; i < face->w->numpoints; i++) { AddPointToBounds(face->w->p[i], tree->mins, tree->maxs); } } Sys_FPrintf(SYS_VRB, "%9d faces\n", count); for(i = 0; i < nummapplanes; i++) { mapplanes[i].counter = 0; } tree->headnode = AllocNode(); VectorCopy(tree->mins, tree->headnode->mins); VectorCopy(tree->maxs, tree->headnode->maxs); c_faceLeafs = 0; c_faceNodes = 1; #if 1 if(drawBSP && drawDebug) { drawTree = tree; } #endif BuildFaceTree_r(tree->headnode, list); Sys_FPrintf(SYS_VRB, "%9d nodes\n", c_faceNodes); Sys_FPrintf(SYS_VRB, "%9d leafs\n", c_faceLeafs); Sys_FPrintf(SYS_VRB, "%9d depth\n", (int)(logf(c_faceNodes) / logf(2))); return tree; }
/* ================ FaceBSP List will be freed before returning ================ */ tree_t *FaceBSP( bspface_t *list ) { tree_t *tree; bspface_t *face; int i; int count; int start, end; start = Sys_Milliseconds(); common->Printf( "--- FaceBSP ---\n" ); tree = AllocTree (); count = 0; tree->bounds.Clear(); for ( face = list ; face ; face = face->next ) { count++; for ( i = 0 ; i < face->w->GetNumPoints() ; i++ ) { tree->bounds.AddPoint( (*face->w)[i].ToVec3() ); } } common->Printf( "%5i faces\n", count ); tree->headnode = AllocNode(); tree->headnode->bounds = tree->bounds; c_faceLeafs = 0; BuildFaceTree_r ( tree->headnode, list ); common->Printf( "%5i leafs\n", c_faceLeafs ); end = Sys_Milliseconds(); common->Printf( "%5.1f seconds faceBsp\n", ( end - start ) / 1000.0 ); return tree; }
/* ================ 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] ); } }
/* ================ 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]); } }
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 }