CARLA
MapGenFunctionLibrary.cpp
Go to the documentation of this file.
1 // Copyright (c) 2023 Computer Vision Center (CVC) at the Universitat Autonoma
2 // de Barcelona (UAB).
3 //
4 // This work is licensed under the terms of the MIT license.
5 // For a copy, see <https://opensource.org/licenses/MIT>.
6 
8 
9 // Engine headers
10 #include "AssetRegistry/AssetRegistryModule.h"
11 #include "Materials/MaterialInstance.h"
12 #include "StaticMeshAttributes.h"
13 #include "RenderingThread.h"
14 // Carla C++ headers
15 
16 // Carla plugin headers
17 
18 
19 DEFINE_LOG_CATEGORY(LogCarlaMapGenFunctionLibrary);
20 static const float OSMToCentimetersScaleFactor = 100.0f;
21 
23  const FProceduralCustomMesh& Data,
24  const TArray<FProcMeshTangent>& ParamTangents,
25  UMaterialInstance* MaterialInstance )
26 {
27 
28  int32 VertexCount = Data.Vertices.Num();
29  int32 VertexInstanceCount = Data.Triangles.Num();
30  int32 PolygonCount = Data.Vertices.Num()/3;
31 
32  FMeshDescription MeshDescription;
33  FStaticMeshAttributes AttributeGetter(MeshDescription);
34  AttributeGetter.Register();
35 
36  TPolygonGroupAttributesRef<FName> PolygonGroupNames = AttributeGetter.GetPolygonGroupMaterialSlotNames();
37  TVertexAttributesRef<FVector> VertexPositions = AttributeGetter.GetVertexPositions();
38  TVertexInstanceAttributesRef<FVector> Tangents = AttributeGetter.GetVertexInstanceTangents();
39  TVertexInstanceAttributesRef<float> BinormalSigns = AttributeGetter.GetVertexInstanceBinormalSigns();
40  TVertexInstanceAttributesRef<FVector> Normals = AttributeGetter.GetVertexInstanceNormals();
41  TVertexInstanceAttributesRef<FVector4> Colors = AttributeGetter.GetVertexInstanceColors();
42  TVertexInstanceAttributesRef<FVector2D> UVs = AttributeGetter.GetVertexInstanceUVs();
43 
44  // Calculate the totals for each ProcMesh element type
45  FPolygonGroupID PolygonGroupForSection;
46  MeshDescription.ReserveNewVertices(VertexCount);
47  MeshDescription.ReserveNewVertexInstances(VertexInstanceCount);
48  MeshDescription.ReserveNewPolygons(PolygonCount);
49  MeshDescription.ReserveNewEdges(PolygonCount * 2);
50  UVs.SetNumIndices(4);
51 
52  // Create Materials
53  TMap<UMaterialInterface*, FPolygonGroupID> UniqueMaterials;
54  const int32 NumSections = 1;
55  UniqueMaterials.Reserve(1);
56  FPolygonGroupID NewPolygonGroup = MeshDescription.CreatePolygonGroup();
57 
58  if( MaterialInstance != nullptr ){
59  UMaterialInterface *Material = MaterialInstance;
60  UniqueMaterials.Add(Material, NewPolygonGroup);
61  PolygonGroupNames[NewPolygonGroup] = Material->GetFName();
62  }else{
63  UE_LOG(LogCarla, Error, TEXT("MaterialInstance is nullptr"));
64  }
65  PolygonGroupForSection = NewPolygonGroup;
66 
67 
68 
69  // Create the vertex
70  int32 NumVertex = Data.Vertices.Num();
71  TMap<int32, FVertexID> VertexIndexToVertexID;
72  VertexIndexToVertexID.Reserve(NumVertex);
73  for (int32 VertexIndex = 0; VertexIndex < NumVertex; ++VertexIndex)
74  {
75  const FVector &Vert = Data.Vertices[VertexIndex];
76  const FVertexID VertexID = MeshDescription.CreateVertex();
77  VertexPositions[VertexID] = Vert;
78  VertexIndexToVertexID.Add(VertexIndex, VertexID);
79  }
80 
81  // Create the VertexInstance
82  int32 NumIndices = Data.Triangles.Num();
83  int32 NumTri = NumIndices / 3;
84  TMap<int32, FVertexInstanceID> IndiceIndexToVertexInstanceID;
85  IndiceIndexToVertexInstanceID.Reserve(NumVertex);
86  for (int32 IndiceIndex = 0; IndiceIndex < NumIndices; IndiceIndex++)
87  {
88  const int32 VertexIndex = Data.Triangles[IndiceIndex];
89  const FVertexID VertexID = VertexIndexToVertexID[VertexIndex];
90  const FVertexInstanceID VertexInstanceID =
91  MeshDescription.CreateVertexInstance(VertexID);
92  IndiceIndexToVertexInstanceID.Add(IndiceIndex, VertexInstanceID);
93  Normals[VertexInstanceID] = Data.Normals[VertexIndex];
94 
95  if(ParamTangents.Num() == Data.Vertices.Num())
96  {
97  Tangents[VertexInstanceID] = ParamTangents[VertexIndex].TangentX;
98  BinormalSigns[VertexInstanceID] =
99  ParamTangents[VertexIndex].bFlipTangentY ? -1.f : 1.f;
100  }else{
101 
102  }
103  Colors[VertexInstanceID] = FLinearColor(0,0,0);
104  if(Data.UV0.Num() == Data.Vertices.Num())
105  {
106  UVs.Set(VertexInstanceID, 0, Data.UV0[VertexIndex]);
107  }else{
108  UVs.Set(VertexInstanceID, 0, FVector2D(0,0));
109  }
110  UVs.Set(VertexInstanceID, 1, FVector2D(0,0));
111  UVs.Set(VertexInstanceID, 2, FVector2D(0,0));
112  UVs.Set(VertexInstanceID, 3, FVector2D(0,0));
113  }
114 
115  for (int32 TriIdx = 0; TriIdx < NumTri; TriIdx++)
116  {
117  FVertexID VertexIndexes[3];
118  TArray<FVertexInstanceID> VertexInstanceIDs;
119  VertexInstanceIDs.SetNum(3);
120 
121  for (int32 CornerIndex = 0; CornerIndex < 3; ++CornerIndex)
122  {
123  const int32 IndiceIndex = (TriIdx * 3) + CornerIndex;
124  const int32 VertexIndex = Data.Triangles[IndiceIndex];
125  VertexIndexes[CornerIndex] = VertexIndexToVertexID[VertexIndex];
126  VertexInstanceIDs[CornerIndex] =
127  IndiceIndexToVertexInstanceID[IndiceIndex];
128  }
129 
130  // Insert a polygon into the mesh
131  MeshDescription.CreatePolygon(NewPolygonGroup, VertexInstanceIDs);
132 
133  }
134 
135  return MeshDescription;
136 }
137 
139  const FProceduralCustomMesh& Data,
140  const TArray<FProcMeshTangent>& ParamTangents,
141  UMaterialInstance* MaterialInstance,
142  FString MapName,
143  FString FolderName,
144  FName MeshName)
145 {
146  IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
147 
148  UStaticMesh::FBuildMeshDescriptionsParams Params;
149  Params.bBuildSimpleCollision = true;
150 
151  FString PackageName = "/Game/CustomMaps/" + MapName + "/Static/" + FolderName + "/" + MeshName.ToString();
152 
153  if (!PlatformFile.DirectoryExists(*PackageName))
154  {
155  //PlatformFile.CreateDirectory(*PackageName);
156  }
157 
158 
159  FMeshDescription Description = BuildMeshDescriptionFromData(Data,ParamTangents, MaterialInstance);
160 
161  if (Description.Polygons().Num() > 0)
162  {
163  UPackage* Package = CreatePackage(*PackageName);
164  check(Package);
165  UStaticMesh* Mesh = NewObject<UStaticMesh>( Package, MeshName, RF_Public | RF_Standalone);
166 
167  Mesh->InitResources();
168 
169  Mesh->LightingGuid = FGuid::NewGuid();
170  Mesh->StaticMaterials.Add(FStaticMaterial(MaterialInstance));
171  Mesh->BuildFromMeshDescriptions({ &Description }, Params);
172  Mesh->CreateBodySetup();
173  Mesh->BodySetup->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple;
174  Mesh->BodySetup->CreatePhysicsMeshes();
175  // Build mesh from source
176  Mesh->NeverStream = false;
177  TArray<UObject*> CreatedAssets;
178  CreatedAssets.Add(Mesh);
179 
180  // Notify asset registry of new asset
181  FAssetRegistryModule::AssetCreated(Mesh);
182  //UPackage::SavePackage(Package, Mesh, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *(MeshName.ToString()), GError, nullptr, true, true, SAVE_NoError);
183  Package->MarkPackageDirty();
184  return Mesh;
185  }
186  return nullptr;
187 }
188 
189 FVector2D UMapGenFunctionLibrary::GetTransversemercProjection(float lat, float lon, float lat0, float lon0)
190 {
191  // earth radius in m
192  const float R = 6373000.0f;
193  float latt = FMath::DegreesToRadians(lat);
194  float lonn = FMath::DegreesToRadians(lon - lon0);
195  float latt0 = FMath::DegreesToRadians(lat0);
196  float eps = atan(tan(latt)/cos(lonn));
197  float nab = asinh(sin(lonn)/sqrt(tan(latt)*tan(latt)+cos(lonn)*cos(lonn)));
198  float x = R*nab;
199  float y = R*eps;
200  float eps0 = atan(tan(latt0)/cos(0));
201  float nab0 = asinh(sin(0)/sqrt(tan(latt0)*tan(latt0)+cos(0)*cos(0)));
202  float x0 = R*nab0;
203  float y0 = R*eps0;
204  FVector2D Result = FVector2D(x, -(y - y0)) * OSMToCentimetersScaleFactor;
205 
206  return Result;
207 }
208 
210  //FGenericPlatformProcess::Sleep(seconds);
211 }
212 
214  FlushRenderingCommands(true);
215  FlushPendingDeleteRHIResources_GameThread();
216 }
217 
219  GEngine->PerformGarbageCollectionAndCleanupActors();
220 #if WITH_EDITOR
221  FText TransResetText(FText::FromString("Clean up after Move actors to sublevels"));
222  if ( GEditor->Trans )
223  {
224  GEditor->Trans->Reset(TransResetText);
225  GEditor->Cleanse(true, true, TransResetText);
226  }
227 #endif
228 }
A definition of a Carla Mesh.
static void SetThreadToSleep(float seconds)
static UStaticMesh * CreateMesh(const FProceduralCustomMesh &Data, const TArray< FProcMeshTangent > &ParamTangents, UMaterialInstance *MaterialInstance, FString MapName, FString FolderName, FName MeshName)
TArray< FVector2D > UV0
static FVector2D GetTransversemercProjection(float lat, float lon, float lat0, float lon0)
static T Get(carla::rpc::Response< T > &response)
TArray< FVector > Normals
TArray< FVector > Vertices
static FMeshDescription BuildMeshDescriptionFromData(const FProceduralCustomMesh &Data, const TArray< FProcMeshTangent > &ParamTangents, UMaterialInstance *MaterialInstance)
static const float OSMToCentimetersScaleFactor
DEFINE_LOG_CATEGORY(LogCarlaMapGenFunctionLibrary)
static void FlushRenderingCommandsInBlueprint()