// // Find the best splitting polygon within a pool of polygons, and return its // index (into the PolyList array). // static FPoly *FindBestSplit ( int32 NumPolys, FPoly** PolyList, FBSPOps::EBspOptimization Opt, int32 Balance, int32 InPortalBias ) { check(NumPolys>0); // No need to test if only one poly. if( NumPolys==1 ) return PolyList[0]; FPoly *Poly, *Best=NULL; float Score, BestScore; int32 i, Index, j, Inc; int32 Splits, Front, Back, Coplanar, AllSemiSolids; //PortalBias -- added by Legend on 4/12/2000 float PortalBias = InPortalBias / 100.0f; Balance &= 0xFF; // keep only the low byte to recover "Balance" //UE_LOG(LogBSPOps, Log, TEXT("Balance=%d PortalBias=%f"), Balance, PortalBias ); if (Opt==FBSPOps::BSP_Optimal) Inc = 1; // Test lots of nodes. else if (Opt==FBSPOps::BSP_Good) Inc = FMath::Max(1,NumPolys/20); // Test 20 nodes. else /* BSP_Lame */ Inc = FMath::Max(1,NumPolys/4); // Test 4 nodes. // See if there are any non-semisolid polygons here. for( i=0; i<NumPolys; i++ ) if( !(PolyList[i]->PolyFlags & PF_AddLast) ) break; AllSemiSolids = (i>=NumPolys); // Search through all polygons in the pool and find: // A. The number of splits each poly would make. // B. The number of front and back nodes the polygon would create. // C. Number of coplanars. BestScore = 0; for( i=0; i<NumPolys; i+=Inc ) { Splits = Front = Back = Coplanar = 0; Index = i-1; do { Index++; Poly = PolyList[Index]; } while( Index<(i+Inc) && Index<NumPolys && ( (Poly->PolyFlags & PF_AddLast) && !(Poly->PolyFlags & PF_Portal) ) && !AllSemiSolids ); if( Index>=i+Inc || Index>=NumPolys ) continue; for( j=0; j<NumPolys; j+=Inc ) if( j != Index ) { FPoly *OtherPoly = PolyList[j]; switch( OtherPoly->SplitWithPlaneFast( FPlane( Poly->Vertices[0], Poly->Normal), NULL, NULL ) ) { case SP_Coplanar: Coplanar++; break; case SP_Front: Front++; break; case SP_Back: Back++; break; case SP_Split: // Disfavor splitting polys that are zone portals. if( !(OtherPoly->PolyFlags & PF_Portal) ) Splits++; else Splits += 16; break; } } // added by Legend 1/31/1999 // Score optimization: minimize cuts vs. balance tree (as specified in BSP Rebuilder dialog) Score = ( 100.0 - float(Balance) ) * Splits + float(Balance) * FMath::Abs( Front - Back ); if( Poly->PolyFlags & PF_Portal ) { // PortalBias -- added by Legend on 4/12/2000 // // PortalBias enables level designers to control the effect of Portals on the BSP. // This effect can range from 0.0 (ignore portals), to 1.0 (portals cut everything). // // In builds prior to this (since the 221 build dating back to 1/31/1999) the bias // has been 1.0 causing the portals to cut the BSP in ways that will potentially // degrade level performance, and increase the BSP complexity. // // By setting the bias to a value between 0.3 and 0.7 the positive effects of // the portals are preserved without giving them unreasonable priority in the BSP. // // Portals should be weighted high enough in the BSP to separate major parts of the // level from each other (pushing entire rooms down the branches of the BSP), but // should not be so high that portals cut through adjacent geometry in a way that // increases complexity of the room being (typically, accidentally) cut. // Score -= ( 100.0 - float(Balance) ) * Splits * PortalBias; // ignore PortalBias of the split polys -- bias toward portal selection for cutting planes! } //UE_LOG(LogBSPOps, Log, " %4d: Score = %f (Front = %4d, Back = %4d, Splits = %4d, Flags = %08X)", Index, Score, Front, Back, Splits, Poly->PolyFlags ); //LEC if( Score<BestScore || !Best ) { Best = Poly; BestScore = Score; } } check(Best); return Best; }