31 const TArray<FProcMeshTangent>& ParamTangents,
32 UMaterialInstance* MaterialInstance )
35 int32 VertexCount = Data.
Vertices.Num();
36 int32 VertexInstanceCount = Data.
Triangles.Num();
37 int32 PolygonCount = Data.
Vertices.Num()/3;
39 FMeshDescription MeshDescription;
40 FStaticMeshAttributes AttributeGetter(MeshDescription);
41 AttributeGetter.Register();
43 auto PolygonGroupNames = AttributeGetter.GetPolygonGroupMaterialSlotNames();
44 auto VertexPositions = AttributeGetter.GetVertexPositions();
45 auto Tangents = AttributeGetter.GetVertexInstanceTangents();
46 auto BinormalSigns = AttributeGetter.GetVertexInstanceBinormalSigns();
47 auto Normals = AttributeGetter.GetVertexInstanceNormals();
48 auto Colors = AttributeGetter.GetVertexInstanceColors();
49 auto UVs = AttributeGetter.GetVertexInstanceUVs();
52 FPolygonGroupID PolygonGroupForSection;
53 MeshDescription.ReserveNewVertices(VertexCount);
54 MeshDescription.ReserveNewVertexInstances(VertexInstanceCount);
55 MeshDescription.ReserveNewPolygons(PolygonCount);
56 MeshDescription.ReserveNewEdges(PolygonCount * 2);
57 UVs.SetNumChannels(4);
60 TMap<UMaterialInterface*, FPolygonGroupID> UniqueMaterials;
61 const int32 NumSections = 1;
62 UniqueMaterials.Reserve(1);
63 FPolygonGroupID NewPolygonGroup = MeshDescription.CreatePolygonGroup();
65 if( MaterialInstance !=
nullptr ){
66 UMaterialInterface *Material = MaterialInstance;
67 UniqueMaterials.Add(Material, NewPolygonGroup);
68 PolygonGroupNames[NewPolygonGroup] = Material->GetFName();
70 UE_LOG(LogCarla, Error, TEXT(
"MaterialInstance is nullptr"));
72 PolygonGroupForSection = NewPolygonGroup;
77 int32 NumVertex = Data.
Vertices.Num();
78 TMap<int32, FVertexID> VertexIndexToVertexID;
79 VertexIndexToVertexID.Reserve(NumVertex);
80 for (int32 VertexIndex = 0; VertexIndex < NumVertex; ++VertexIndex)
82 auto &Vert = Data.
Vertices[VertexIndex];
83 auto VertexID = MeshDescription.CreateVertex();
84 VertexPositions[VertexID] = FVector3f(Vert);
85 VertexIndexToVertexID.Add(VertexIndex, VertexID);
90 int32 NumTri = NumIndices / 3;
91 TMap<int32, FVertexInstanceID> IndiceIndexToVertexInstanceID;
92 IndiceIndexToVertexInstanceID.Reserve(NumVertex);
93 for (int32 IndiceIndex = 0; IndiceIndex < NumIndices; IndiceIndex++)
95 const int32 VertexIndex = Data.
Triangles[IndiceIndex];
96 const FVertexID VertexID = VertexIndexToVertexID[VertexIndex];
97 const FVertexInstanceID VertexInstanceID =
98 MeshDescription.CreateVertexInstance(VertexID);
99 IndiceIndexToVertexInstanceID.Add(IndiceIndex, VertexInstanceID);
100 Normals[VertexInstanceID] = FVector3f(Data.
Normals[VertexIndex]);
102 if(ParamTangents.Num() == Data.
Vertices.Num())
104 Tangents[VertexInstanceID] = FVector3f(ParamTangents[VertexIndex].TangentX);
105 BinormalSigns[VertexInstanceID] =
106 ParamTangents[VertexIndex].bFlipTangentY ? -1.f : 1.f;
110 Colors[VertexInstanceID] = FLinearColor(0,0,0);
113 UVs.Set(VertexInstanceID, 0, FVector2f(Data.
UV0[VertexIndex]));
115 UVs.Set(VertexInstanceID, 0, FVector2f(0,0));
117 UVs.Set(VertexInstanceID, 1, FVector2f(0,0));
118 UVs.Set(VertexInstanceID, 2, FVector2f(0,0));
119 UVs.Set(VertexInstanceID, 3, FVector2f(0,0));
122 for (int32 TriIdx = 0; TriIdx < NumTri; TriIdx++)
124 FVertexID VertexIndexes[3];
125 TArray<FVertexInstanceID> VertexInstanceIDs;
126 VertexInstanceIDs.SetNum(3);
128 for (int32 CornerIndex = 0; CornerIndex < 3; ++CornerIndex)
130 const int32 IndiceIndex = (TriIdx * 3) + CornerIndex;
131 const int32 VertexIndex = Data.
Triangles[IndiceIndex];
132 VertexIndexes[CornerIndex] = VertexIndexToVertexID[VertexIndex];
133 VertexInstanceIDs[CornerIndex] =
134 IndiceIndexToVertexInstanceID[IndiceIndex];
138 MeshDescription.CreatePolygon(NewPolygonGroup, VertexInstanceIDs);
142 return MeshDescription;
147 const TArray<FProcMeshTangent>& ParamTangents,
148 UMaterialInstance* MaterialInstance,
153 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
155 UStaticMesh::FBuildMeshDescriptionsParams Params;
156 Params.bBuildSimpleCollision =
true;
158 FString PackageName =
"/Game/CustomMaps/" + MapName +
"/Static/" + FolderName +
"/" + MeshName.ToString();
160 if (!PlatformFile.DirectoryExists(*PackageName))
168 if (Description.Polygons().Num() > 0)
170 UPackage* Package = CreatePackage(*PackageName);
172 UStaticMesh* Mesh = NewObject<UStaticMesh>( Package, MeshName, RF_Public | RF_Standalone);
174 Mesh->InitResources();
175 Mesh->SetLightingGuid(FGuid::NewGuid());
176 Mesh->GetStaticMaterials().Add(FStaticMaterial(MaterialInstance));
177 Mesh->BuildFromMeshDescriptions({ &Description }, Params);
178 Mesh->CreateBodySetup();
179 Mesh->GetBodySetup()->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple;
180 Mesh->GetBodySetup()->CreatePhysicsMeshes();
182 Mesh->NeverStream =
false;
183 TArray<UObject*> CreatedAssets;
184 CreatedAssets.Add(Mesh);
187 FAssetRegistryModule::AssetCreated(Mesh);
208 Package->MarkPackageDirty();
262 TArray<AInstancedStaticMeshActor*> Result;
263 TArray<AActor*> FoundActors;
264 UGameplayStatics::GetAllActorsOfClass(World, AStaticMeshActor::StaticClass(), FoundActors);
265 TMap<UStaticMesh*, TArray<AStaticMeshActor*>> ActorsToCheckIfReplacedMap;
266 for(
AActor* CurrentActor : FoundActors )
268 AStaticMeshActor* CurrentStaticMeshActor = Cast<AStaticMeshActor>(CurrentActor);
269 UStaticMeshComponent* CurrentStaticMeshComponent = CurrentStaticMeshActor->GetStaticMeshComponent();
270 UStaticMesh* CurrentStaticMesh = CurrentStaticMeshComponent->GetStaticMesh();
271 if( Filter.IsEmpty() || Filter.Contains(CurrentStaticMesh) )
273 TArray<AStaticMeshActor*>& Instances = ActorsToCheckIfReplacedMap.FindOrAdd(CurrentStaticMesh);
274 Instances.Add(CurrentStaticMeshActor);
278 for(
auto CurrentPair : ActorsToCheckIfReplacedMap)
281 if(CurrentPair.Value.Num() > MinNumOfInstancesToBeChanged)
283 TArray<FTransform> TransformsToBeInstanced;
284 for( AStaticMeshActor* SMActor : CurrentPair.Value )
286 TransformsToBeInstanced.Add(SMActor->GetActorTransform());
291 if(InstancedStaticMeshActor)
295 Result.Add(InstancedStaticMeshActor);
305 TArray<AActor*> FoundActors;
306 TArray<AStaticMeshActor*> Result;
307 UGameplayStatics::GetAllActorsOfClass(World, AInstancedStaticMeshActor::StaticClass(), FoundActors);
308 for(
AActor* CurrentActor : FoundActors )
311 if(InstancedStaticMeshActor)
314 if( Filter.IsEmpty() || Filter.Contains(CurrentStaticMesh))
317 for( FInstancedStaticMeshInstanceData CurrentInstanceData : Instances )
319 AStaticMeshActor* StaticMeshActor = World->SpawnActor<AStaticMeshActor>();
320 StaticMeshActor->GetStaticMeshComponent()->SetStaticMesh(CurrentStaticMesh);
321 StaticMeshActor->SetActorTransform(FTransform(CurrentInstanceData.Transform));
322 Result.Add(StaticMeshActor);
324 InstancedStaticMeshActor->Destroy();
337 UE_LOG(LogCarlaMapGenFunctionLibrary, Warning, TEXT(
"Invalid TargetActor in AddInstancedStaticMeshComponentToActor"));
340 if (!TargetActor->GetRootComponent())
342 USceneComponent* NewRoot = NewObject<USceneComponent>(TargetActor, TEXT(
"GeneratedRootComponent"));
343 TargetActor->SetRootComponent(NewRoot);
344 NewRoot->RegisterComponent();
346 UInstancedStaticMeshComponent* ISMComponent = NewObject<UInstancedStaticMeshComponent>(TargetActor);
349 UE_LOG(LogCarlaMapGenFunctionLibrary, Error, TEXT(
"Could not create UInstancedStaticMeshComponent"));
352 ISMComponent->SetupAttachment(TargetActor->GetRootComponent());
353 ISMComponent->RegisterComponent();
354 TargetActor->AddInstanceComponent(ISMComponent);
434 TArray<FVector>& Vertices,
435 const TArray<int32>& Indices,
438 float SmoothingFactor
441 const int32 NumVertices = Vertices.Num();
444 TMap<int32, TSet<int32>> VertexNeighbors;
445 const int32 NumTriangles = Indices.Num() / 3;
447 for (int32 i = 0; i < NumTriangles; ++i)
449 int32 I0 = Indices[i * 3 + 0];
450 int32 I1 = Indices[i * 3 + 1];
451 int32 I2 = Indices[i * 3 + 2];
453 VertexNeighbors.FindOrAdd(I0).Add(I1);
454 VertexNeighbors.FindOrAdd(I0).Add(I2);
456 VertexNeighbors.FindOrAdd(I1).Add(I0);
457 VertexNeighbors.FindOrAdd(I1).Add(I2);
459 VertexNeighbors.FindOrAdd(I2).Add(I0);
460 VertexNeighbors.FindOrAdd(I2).Add(I1);
464 for (int32 Iter = 0; Iter < NumIterations; ++Iter)
466 TArray<FVector> NewVertices = Vertices;
467 for (int32 i = 0; i < NumVertices; ++i)
470 TQueue<TPair<int32, int32>> Queue;
472 Queue.Enqueue(TPair<int32, int32>(i, 0));
473 TArray<int32> CollectedNeighbors;
475 while (!Queue.IsEmpty())
477 TPair<int32, int32> Current;
478 Queue.Dequeue(Current);
479 int32 CurrentIndex = Current.Key;
480 int32 CurrentDepth = Current.Value;
482 if (CurrentDepth >= Depth)
484 const TSet<int32>* Neighbors = VertexNeighbors.Find(CurrentIndex);
485 if (!Neighbors)
continue;
487 for (int32 NeighborIndex : *Neighbors)
489 if (!Visited.Contains(NeighborIndex))
491 Visited.Add(NeighborIndex);
492 CollectedNeighbors.Add(NeighborIndex);
493 Queue.Enqueue(TPair<int32, int32>(NeighborIndex, CurrentDepth + 1));
498 if (CollectedNeighbors.Num() > 0)
500 FVector Average = FVector::ZeroVector;
501 for (int32 NeighborIdx : CollectedNeighbors)
503 Average += Vertices[NeighborIdx];
505 Average /= CollectedNeighbors.Num();
506 NewVertices[i] = FMath::Lerp(Vertices[i], Average, SmoothingFactor);
509 Vertices = NewVertices;
515 int ix = FMath::FloorToInt(X);
516 int iy = FMath::FloorToInt(Y);
523 for (
int m = -1; m <= 2; ++m)
525 for (
int n = -1; n <= 2; ++n)
527 uint16 val =
GetPixelG16(Pixels, Width, Height, ix + n, iy + m);
528 patch[m + 1][n + 1] = val / 65535.0f;
533 for (
int i = 0; i < 4; ++i)
535 col[i] =
CubicHermite(patch[i][0], patch[i][1], patch[i][2], patch[i][3], fx);
538 float result =
CubicHermite(col[0], col[1], col[2], col[3], fy);
539 return FMath::Clamp(result, 0.0f, 1.0f);