/** * Creates a model from the triangles in a static mesh. */ void CreateModelFromStaticMesh(UModel* Model,AStaticMeshActor* StaticMeshActor) { #if TODO_STATICMESH UStaticMesh* StaticMesh = StaticMeshActor->StaticMeshComponent->StaticMesh; FMatrix ActorToWorld = StaticMeshActor->ActorToWorld().ToMatrixWithScale(); Model->Polys->Element.Empty(); const FStaticMeshTriangle* RawTriangleData = (FStaticMeshTriangle*) StaticMesh->LODModels[0].RawTriangles.Lock(LOCK_READ_ONLY); if(StaticMesh->LODModels[0].RawTriangles.GetElementCount()) { for(int32 TriangleIndex = 0; TriangleIndex < StaticMesh->LODModels[0].RawTriangles.GetElementCount(); TriangleIndex++) { const FStaticMeshTriangle& Triangle = RawTriangleData[TriangleIndex]; FPoly* Polygon = new(Model->Polys->Element) FPoly; Polygon->Init(); Polygon->iLink = Polygon - Model->Polys->Element.GetData(); Polygon->Material = StaticMesh->LODModels[0].Elements[Triangle.MaterialIndex].Material; Polygon->PolyFlags = PF_DefaultFlags; Polygon->SmoothingMask = Triangle.SmoothingMask; new(Polygon->Vertices) FVector(ActorToWorld.TransformPosition(Triangle.Vertices[2])); new(Polygon->Vertices) FVector(ActorToWorld.TransformPosition(Triangle.Vertices[1])); new(Polygon->Vertices) FVector(ActorToWorld.TransformPosition(Triangle.Vertices[0])); Polygon->CalcNormal(1); Polygon->Finalize(NULL,0); FTexCoordsToVectors(Polygon->Vertices[2],FVector(Triangle.UVs[0][0].X * UModel::GetGlobalBSPTexelScale(),Triangle.UVs[0][0].Y * UModel::GetGlobalBSPTexelScale(),1), Polygon->Vertices[1],FVector(Triangle.UVs[1][0].X * UModel::GetGlobalBSPTexelScale(),Triangle.UVs[1][0].Y * UModel::GetGlobalBSPTexelScale(),1), Polygon->Vertices[0],FVector(Triangle.UVs[2][0].X * UModel::GetGlobalBSPTexelScale(),Triangle.UVs[2][0].Y * UModel::GetGlobalBSPTexelScale(),1), &Polygon->Base,&Polygon->TextureU,&Polygon->TextureV); } } StaticMesh->LODModels[0].RawTriangles.Unlock(); Model->Linked = 1; FBSPOps::bspValidateBrush(Model,0,1); Model->BuildBound(); #endif // #if TODO_STATICMESH }
/** * Rotates the specified brush's vertices. */ void FBSPOps::RotateBrushVerts(ABrush* Brush, const FRotator& Rotation, bool bClearComponents) { if(Brush->BrushComponent->Brush && Brush->BrushComponent->Brush->Polys) { for( int32 poly = 0 ; poly < Brush->BrushComponent->Brush->Polys->Element.Num() ; poly++ ) { FPoly* Poly = &(Brush->BrushComponent->Brush->Polys->Element[poly]); // Rotate the vertices. for( int32 vertex = 0 ; vertex < Poly->Vertices.Num() ; vertex++ ) { Poly->Vertices[vertex] = Brush->GetPrePivot() + FRotationMatrix( Rotation ).TransformVector( Poly->Vertices[vertex] - Brush->GetPrePivot() ); } Poly->Base = Brush->GetPrePivot() + FRotationMatrix( Rotation ).TransformVector( Poly->Base - Brush->GetPrePivot() ); // Rotate the texture vectors. Poly->TextureU = FRotationMatrix( Rotation ).TransformVector( Poly->TextureU ); Poly->TextureV = FRotationMatrix( Rotation ).TransformVector( Poly->TextureV ); // Recalc the normal for the poly. Poly->Normal = FVector::ZeroVector; Poly->Finalize(Brush,0); } Brush->BrushComponent->Brush->BuildBound(); if( !Brush->IsStaticBrush() ) { csgPrepMovingBrush( Brush ); } if ( bClearComponents ) { Brush->ReregisterAllComponents(); } } }
FPoly FPoly::BuildAndCutInfiniteFPoly(const FPlane& InPlane, const TArray<FPlane>& InCutPlanes, ABrush* InOwnerBrush) { FPoly PolyMerged = BuildInfiniteFPoly( InPlane ); PolyMerged.Finalize( InOwnerBrush, 1 ); FPoly Front, Back; int32 result; for( int32 p = 0 ; p < InCutPlanes.Num() ; ++p ) { const FPlane* Plane = &InCutPlanes[p]; result = PolyMerged.SplitWithPlane( Plane->GetSafeNormal() * Plane->W, Plane->GetSafeNormal(), &Front, &Back, 1 ); if( result == SP_Split ) { PolyMerged = Back; } } PolyMerged.Reverse(); return PolyMerged; }
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; }
int32 FPoly::Triangulate( ABrush* InOwnerBrush, TArray<FPoly>& OutTriangles ) { #if WITH_EDITOR if( Vertices.Num() < 3 ) { return 0; } FClipSMPolygon Polygon(0); for( int32 v = 0 ; v < Vertices.Num() ; ++v ) { FClipSMVertex vtx; vtx.Pos = Vertices[v]; // Init other data so that VertsAreEqual won't compare garbage vtx.TangentX = FVector::ZeroVector; vtx.TangentY = FVector::ZeroVector; vtx.TangentZ = FVector::ZeroVector; vtx.Color = FColor(0, 0, 0); for( int32 uvIndex=0; uvIndex<ARRAY_COUNT(vtx.UVs); ++uvIndex ) { vtx.UVs[uvIndex] = FVector2D(0.f, 0.f); } Polygon.Vertices.Add( vtx ); } Polygon.FaceNormal = Normal; // Attempt to triangulate this polygon TArray<FClipSMTriangle> Triangles; if( TriangulatePoly( Triangles, Polygon ) ) { // Create a set of FPolys from the triangles OutTriangles.Empty(); FPoly TrianglePoly; for( int32 p = 0 ; p < Triangles.Num() ; ++p ) { FClipSMTriangle* tri = &(Triangles[p]); TrianglePoly.Init(); TrianglePoly.Base = tri->Vertices[0].Pos; TrianglePoly.Vertices.Add( tri->Vertices[0].Pos ); TrianglePoly.Vertices.Add( tri->Vertices[1].Pos ); TrianglePoly.Vertices.Add( tri->Vertices[2].Pos ); if( TrianglePoly.Finalize( InOwnerBrush, 0 ) == 0 ) { OutTriangles.Add( TrianglePoly ); } } } #endif return OutTriangles.Num(); }