bool FGeomObject::FinalizeSourceData() { if( !GEditorModeTools().IsModeActive(FBuiltinEditorModes::EM_Geometry) ) { return 0; } ABrush* brush = GetActualBrush(); bool Ret = false; double StartTime = FPlatformTime::Seconds(); const double TimeLimit = 10.0; // Remove invalid polygons from the brush for( int32 x = 0 ; x < brush->Brush->Polys->Element.Num() ; ++x ) { FPoly* Poly = &brush->Brush->Polys->Element[x]; if( Poly->Vertices.Num() < 3 ) { brush->Brush->Polys->Element.RemoveAt( x ); x = -1; } } for( int32 p = 0 ; p < brush->Brush->Polys->Element.Num() ; ++p ) { FPoly* Poly = &(brush->Brush->Polys->Element[p]); Poly->iLink = p; int32 SaveNumVertices = Poly->Vertices.Num(); const bool bTimeLimitExpired = TimeLimit < FPlatformTime::Seconds() - StartTime; if( !Poly->IsCoplanar() || !Poly->IsConvex() ) { // If the polygon is no longer coplanar and/or convex, break it up into separate triangles. FPoly WkPoly = *Poly; brush->Brush->Polys->Element.RemoveAt( p ); TArray<FPoly> Polygons; if( !bTimeLimitExpired && WkPoly.Triangulate( brush, Polygons ) > 0 ) { FPoly::OptimizeIntoConvexPolys( brush, Polygons ); for( int32 t = 0 ; t < Polygons.Num() ; ++t ) { brush->Brush->Polys->Element.Add( Polygons[t] ); } } p = -1; Ret = true; } else { int32 FixResult = Poly->Fix(); if( FixResult != SaveNumVertices ) { // If the polygon collapses after running "Fix" against it, it needs to be // removed from the brushes polygon list. if( bTimeLimitExpired || FixResult == 0 ) { brush->Brush->Polys->Element.RemoveAt( p ); } p = -1; Ret = true; } else { // If we get here, the polygon is valid and needs to be kept. Finalize its internals. Poly->Finalize(brush,1); } } } if (TimeLimit < FPlatformTime::Seconds() - StartTime) { UE_LOG(LogEditorGeometry, Error, TEXT("FGeomObject::FinalizeSourceData() failed because it took too long")); } brush->ReregisterAllComponents(); return Ret; }