CARLA
ObjectRegister.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020 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 
7 #include "Carla.h"
9 
10 #include "Carla/Game/Tagger.h"
12 
13 #include "InstancedFoliageActor.h"
14 #include "GameFramework/Character.h"
15 
16 #if WITH_EDITOR
17 #include "FileHelper.h"
18 #include "Paths.h"
19 #endif // WITH_EDITOR
20 
21 namespace crp = carla::rpc;
22 
23 TArray<FEnvironmentObject> UObjectRegister::GetEnvironmentObjects(uint8 InTagQueried) const
24 {
25  TArray<FEnvironmentObject> Result;
26 
27  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
28  bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::Any);
29 
30  for(const FEnvironmentObject& It : EnvironmentObjects)
31  {
32  if(!FilterByTagEnabled || (It.ObjectLabel == TagQueried))
33  {
34  Result.Emplace(It);
35  }
36  }
37 
38  return Result;
39 }
40 
41 void UObjectRegister::RegisterObjects(TArray<AActor*> Actors)
42 {
43  // Empties the array but doesn't change memory allocations
44  EnvironmentObjects.Reset();
45 
46  for(AActor* Actor : Actors)
47  {
48 
49  FString ClassName = Actor->GetClass()->GetName();
50  // Discard Sky to not break the global ilumination
51  if(ClassName.Equals("BP_Sky_C")) continue;
52 
53  ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle>(Actor);
54  if (Vehicle)
55  {
56  RegisterVehicle(Vehicle);
57  continue;
58  }
59 
60  ACharacter* Character = Cast<ACharacter>(Actor);
61  if (Character)
62  {
63  RegisterCharacter(Character);
64  continue;
65  }
66 
67  ATrafficLightBase* TrafficLight = Cast<ATrafficLightBase>(Actor);
68  if(TrafficLight)
69  {
70  RegisterTrafficLight(TrafficLight);
71  continue;
72  }
73 
75 
77 
79  }
80 
81 #if WITH_EDITOR
82  // To help debug
83  FString FileContent;
84  FileContent += FString::Printf(TEXT("Num actors %d\n"), Actors.Num());
85  FileContent += FString::Printf(TEXT("Num registered objects %d\n\n"), EnvironmentObjects.Num());
86 
87  for(const FEnvironmentObject& Object : EnvironmentObjects)
88  {
89  FileContent += FString::Printf(TEXT("%llu\t"), Object.Id);
90  FileContent += FString::Printf(TEXT("%s\t"), *Object.Name);
91  FileContent += FString::Printf(TEXT("%s\t"), *Object.IdStr);
92  FileContent += FString::Printf(TEXT("%d\n"), static_cast<int32>(Object.Type));
93  }
94 
95 
96  FString FilePath = FPaths::ProjectSavedDir() + "RegisteredObjects.txt";
97  FFileHelper::SaveStringToFile(
98  FileContent,
99  *FilePath,
100  FFileHelper::EEncodingOptions::AutoDetect,
102  EFileWrite::FILEWRITE_Silent);
103 
104 #endif // WITH_EDITOR
105 
106 }
107 
108 void UObjectRegister::EnableEnvironmentObjects(const TSet<uint64>& EnvObjectIds, bool Enable)
109 {
110  for(uint64 It : EnvObjectIds)
111  {
112  bool found = false;
113  for(FEnvironmentObject& EnvironmentObject : EnvironmentObjects)
114  {
115  if(It == EnvironmentObject.Id)
116  {
117  EnableEnvironmentObject(EnvironmentObject, Enable);
118  found = true;
119  break;
120  }
121  }
122  if(!found)
123  {
124  UE_LOG(LogCarla, Error, TEXT("EnableEnvironmentObjects id not found %llu"), It);
125  }
126  }
127 
128 }
129 
131  AActor* Actor,
134  uint8 Tag)
135 {
136  const FString ActorName = Actor->GetName();
137  const char* ActorNameChar = TCHAR_TO_ANSI(*ActorName);
138 
139  FEnvironmentObject EnvironmentObject;
140  EnvironmentObject.Transform = Actor->GetActorTransform();
141  EnvironmentObject.Id = CityHash64(ActorNameChar, ActorName.Len());
142  EnvironmentObject.Name = ActorName;
143  EnvironmentObject.Actor = Actor;
144  EnvironmentObject.CanTick = Actor->IsActorTickEnabled();
145  EnvironmentObject.BoundingBox = BoundingBox;
146  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
147  EnvironmentObject.Type = Type;
148  EnvironmentObjects.Emplace(std::move(EnvironmentObject));
149 }
150 
152 {
153  check(Vehicle);
155  auto Tag = ATagger::GetTagOfTaggedComponent(*Vehicle->GetMesh());
156  RegisterEnvironmentObject(Vehicle, BB, EnvironmentObjectType::Vehicle, static_cast<uint8>(Tag));
157 }
158 
160 {
161  check(Character);
163  RegisterEnvironmentObject(Character, BB, EnvironmentObjectType::Character, static_cast<uint8>(crp::CityObjectLabel::Pedestrians));
164 }
165 
167 {
168  check(TrafficLight);
169 
170  TArray<FBoundingBox> BBs;
171  TArray<uint8> Tags;
172 
174  check(BBs.Num() == Tags.Num());
175 
176  const FTransform Transform = TrafficLight->GetTransform();
177  const FString ActorName = TrafficLight->GetName();
178  const bool IsActorTickEnabled = TrafficLight->IsActorTickEnabled();
179 
180  for(int i = 0; i < BBs.Num(); i++)
181  {
182  const FBoundingBox& BB = BBs[i];
183  const uint8 Tag = Tags[i];
184 
185  crp::CityObjectLabel ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
186 
187  const FString TagString = ATagger::GetTagAsString(ObjectLabel);
188  const FString SMName = FString::Printf(TEXT("%s_%s_%d"), *ActorName, *TagString, i);
189 
190  FEnvironmentObject EnvironmentObject;
191  EnvironmentObject.Transform = Transform;
192  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
193  EnvironmentObject.Name = SMName;
194  EnvironmentObject.Actor = TrafficLight;
195  EnvironmentObject.CanTick = IsActorTickEnabled;
196  EnvironmentObject.BoundingBox = BB;
197  EnvironmentObject.Type = EnvironmentObjectType::TrafficLight;
198  EnvironmentObject.ObjectLabel = ObjectLabel;
199  EnvironmentObjects.Emplace(EnvironmentObject);
200 
201  // Register components with its ID; it's not the best solution since we are recalculating the BBs
202  // But this is only calculated when the level is loaded
203  TArray<UStaticMeshComponent*> StaticMeshComps;
204  UBoundingBoxCalculator::GetMeshCompsFromActorBoundingBox(TrafficLight, BB, StaticMeshComps);
205  for(const UStaticMeshComponent* Comp : StaticMeshComps)
206  {
207  ObjectIdToComp.Emplace(EnvironmentObject.Id, Comp);
208  }
209  }
210 }
211 
213 {
214  check(Actor);
215 
216  TArray<UInstancedStaticMeshComponent*> ISMComps;
217  Actor->GetComponents<UInstancedStaticMeshComponent>(ISMComps);
218 
219  const FString ActorName = Actor->GetName();
220  int InstanceCount = 0;
221  bool IsActorTickEnabled = Actor->IsActorTickEnabled();
222 
223  // Foliage actor is a special case, it can appear more than once while traversing the actor list
224  if(Cast<AInstancedFoliageActor>(Actor))
225  {
226  InstanceCount = FoliageActorInstanceCount;
227  }
228 
229  for(UInstancedStaticMeshComponent* Comp : ISMComps)
230  {
231  const TArray<FInstancedStaticMeshInstanceData>& PerInstanceSMData = Comp->PerInstanceSMData;
232  const FTransform CompTransform = Comp->GetComponentTransform();
233 
234  TArray<FBoundingBox> BoundingBoxes;
235  UBoundingBoxCalculator::GetISMBoundingBox(Comp, BoundingBoxes);
236 
237  FString CompName = Comp->GetName();
239 
240  for(int i = 0; i < PerInstanceSMData.Num(); i++)
241  {
242  const FInstancedStaticMeshInstanceData& It = PerInstanceSMData[i];
243  const FTransform InstanceTransform = FTransform(It.Transform);
244  const FVector InstanceLocation = InstanceTransform.GetLocation();
245 
246  // Discard decimal part
247  const int32 X = static_cast<int32>(InstanceLocation.X);
248  const int32 Y = static_cast<int32>(InstanceLocation.Y);
249  const int32 Z = static_cast<int32>(InstanceLocation.Z);
250 
251  const FString InstanceName = FString::Printf(TEXT("%s_Inst_%d_%d"), *ActorName, InstanceCount, i);
252  const FString InstanceIdStr = FString::Printf(TEXT("%s_%s_%d_%d_%d_%d"), *ActorName, *CompName, X, Y, Z, InstanceCount);
253  uint64 InstanceId = CityHash64(TCHAR_TO_ANSI(*InstanceIdStr), InstanceIdStr.Len());
254 
255  FEnvironmentObject EnvironmentObject;
256  EnvironmentObject.Transform = InstanceTransform * CompTransform;
257  EnvironmentObject.Id = InstanceId;
258  EnvironmentObject.Name = InstanceName;
259  EnvironmentObject.IdStr = InstanceIdStr;
260  EnvironmentObject.Actor = Actor;
261  EnvironmentObject.CanTick = IsActorTickEnabled;
262  if( i < BoundingBoxes.Num())
263  {
264  EnvironmentObject.BoundingBox = BoundingBoxes[i];
265  }
266 
267  EnvironmentObject.Type = EnvironmentObjectType::ISMComp;
268  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
269  EnvironmentObjects.Emplace(EnvironmentObject);
270 
271  ObjectIdToComp.Emplace(InstanceId, Comp);
272  InstanceCount++;
273  }
274  }
275 
276  if(Cast<AInstancedFoliageActor>(Actor))
277  {
278  FoliageActorInstanceCount = InstanceCount;
279  }
280 }
281 
283 {
284  check(Actor);
285 
286  TArray<UStaticMeshComponent*> StaticMeshComps;
287  Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
288 
289  TArray<FBoundingBox> BBs;
290  TArray<uint8> Tags;
291  UBoundingBoxCalculator::GetBBsOfStaticMeshComponents(StaticMeshComps, BBs, Tags);
292  check(BBs.Num() == Tags.Num());
293 
294  const FTransform Transform = Actor->GetTransform();
295  const FString ActorName = Actor->GetName();
296  const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
297 
298  for(int i = 0; i < BBs.Num(); i++)
299  {
300  const FString SMName = FString::Printf(TEXT("%s_SM_%d"), *ActorName, i);
301 
302  FEnvironmentObject EnvironmentObject;
303  EnvironmentObject.Transform = Transform;
304  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
305  EnvironmentObject.Name = SMName;
306  EnvironmentObject.Actor = Actor;
307  EnvironmentObject.CanTick = IsActorTickEnabled;
308  EnvironmentObject.BoundingBox = BBs[i];
309  EnvironmentObject.Type = EnvironmentObjectType::SMComp;
310  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
311  EnvironmentObjects.Emplace(EnvironmentObject);
312  }
313 }
314 
316 {
317  check(Actor);
318 
319  TArray<USkeletalMeshComponent*> SkeletalMeshComps;
320  Actor->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
321 
322  TArray<FBoundingBox> BBs;
323  TArray<uint8> Tags;
324  UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, BBs, Tags);
325  check(BBs.Num() == Tags.Num());
326 
327  const FTransform Transform = Actor->GetTransform();
328  const FString ActorName = Actor->GetName();
329  const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
330 
331  for(int i = 0; i < BBs.Num(); i++)
332  {
333  const FString SKMName = FString::Printf(TEXT("%s_SKM_%d"), *ActorName, i);
334 
335  FEnvironmentObject EnvironmentObject;
336  EnvironmentObject.Transform = Transform;
337  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SKMName), SKMName.Len());
338  EnvironmentObject.Name = SKMName;
339  EnvironmentObject.Actor = Actor;
340  EnvironmentObject.CanTick = IsActorTickEnabled;
341  EnvironmentObject.BoundingBox = BBs[i];
342  EnvironmentObject.Type = EnvironmentObjectType::SKMComp;
343  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
344  EnvironmentObjects.Emplace(EnvironmentObject);
345 
346  }
347 
348 }
349 
351  FEnvironmentObject& EnvironmentObject,
352  bool Enable)
353 {
354  switch (EnvironmentObject.Type)
355  {
360  EnableActor(EnvironmentObject, Enable);
361  break;
363  EnableTrafficLight(EnvironmentObject, Enable);
364  break;
366  EnableISMComp(EnvironmentObject, Enable);
367  break;
368  default:
369  check(false);
370  break;
371  }
372 
373 }
374 
375 void UObjectRegister::EnableActor(FEnvironmentObject& EnvironmentObject, bool Enable)
376 {
377  AActor* Actor = EnvironmentObject.Actor;
378 
379  Actor->SetActorHiddenInGame(!Enable);
380  Actor->SetActorEnableCollision(Enable);
381  if(EnvironmentObject.CanTick)
382  {
383  Actor->SetActorTickEnabled(Enable);
384  }
385 }
386 
387 void UObjectRegister::EnableTrafficLight(FEnvironmentObject& EnvironmentObject, bool Enable)
388 {
389  // We need to look for the component(s) that form the EnvironmentObject
390  // i.e.: The light box is composed by various SMComponents, one per light,
391  // we need to enable/disable all of them
392 
393  TArray<const UStaticMeshComponent*> ObjectComps;
394  ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
395 
396  for(const UStaticMeshComponent* Comp : ObjectComps)
397  {
398  UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(Comp);
399  SMComp->SetHiddenInGame(!Enable);
400  ECollisionEnabled::Type CollisionType = Enable ? ECollisionEnabled::Type::QueryAndPhysics : ECollisionEnabled::Type::NoCollision;
401  SMComp->SetCollisionEnabled(CollisionType);
402  }
403 
404 }
405 
406 void UObjectRegister::EnableISMComp(FEnvironmentObject& EnvironmentObject, bool Enable)
407 {
408  TArray<const UStaticMeshComponent*> ObjectComps;
409  TArray<FString> InstanceName;
410  FTransform InstanceTransform = EnvironmentObject.Transform;
411 
412  ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
413  EnvironmentObject.Name.ParseIntoArray(InstanceName, TEXT("_"), false);
414 
415  int Index = FCString::Atoi(*InstanceName[InstanceName.Num() - 1]);
416 
417  if(!Enable)
418  {
419  InstanceTransform.SetTranslation(FVector(1000000.0f));
420  InstanceTransform.SetScale3D(FVector(0.0f));
421  }
422 
423  UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(ObjectComps[0]);
424  UInstancedStaticMeshComponent* ISMComp = Cast<UInstancedStaticMeshComponent>(SMComp);
425  bool Result = ISMComp->UpdateInstanceTransform(Index, InstanceTransform, true, true);
426 
427 }
static void GetBBsOfSkeletalMeshComponents(const TArray< USkeletalMeshComponent *> &SkeletalMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
void RegisterVehicle(ACarlaWheeledVehicle *Vehicle)
TArray< FEnvironmentObject > GetEnvironmentObjects(uint8 InTagQueried=0xFF) const
static void GetISMBoundingBox(UInstancedStaticMeshComponent *ISMComp, TArray< FBoundingBox > &OutBoundingBox)
void RegisterEnvironmentObject(AActor *Actor, FBoundingBox &BoundingBox, EnvironmentObjectType Type, uint8 Tag)
void EnableTrafficLight(FEnvironmentObject &EnvironmentObject, bool Enable)
static FBoundingBox GetCharacterBoundingBox(const ACharacter *Character, uint8 InTagQueried=0xFF)
void EnableISMComp(FEnvironmentObject &EnvironmentObject, bool Enable)
void EnableActor(FEnvironmentObject &EnvironmentObject, bool Enable)
void RegisterCharacter(ACharacter *Character)
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
Retrieve the tag of an already tagged component.
Definition: Tagger.h:52
static FBoundingBox GetVehicleBoundingBox(const ACarlaWheeledVehicle *Vehicle, uint8 InTagQueried=0xFF)
void EnableEnvironmentObjects(const TSet< uint64 > &EnvObjectIds, bool Enable)
static T Get(carla::rpc::Response< T > &response)
static void GetTrafficLightBoundingBox(const ATrafficLightBase *TrafficLight, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
void RegisterTrafficLight(ATrafficLightBase *TrafficLight)
carla::SharedPtr< cc::Actor > Actor
void RegisterISMComponents(AActor *Actor)
void RegisterSMComponents(AActor *Actor)
static FString GetTagAsString(crp::CityObjectLabel Tag)
Retrieve the tags of an already tagged actor.
Definition: Tagger.cpp:250
TArray< FEnvironmentObject > EnvironmentObjects
static void GetBBsOfStaticMeshComponents(const TArray< UStaticMeshComponent *> &StaticMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
void RegisterSKMComponents(AActor *Actor)
void EnableEnvironmentObject(FEnvironmentObject &EnvironmentObject, bool Enable)
TMultiMap< uint64, const UStaticMeshComponent * > ObjectIdToComp
void RegisterObjects(TArray< AActor *> Actors)
static void GetMeshCompsFromActorBoundingBox(const AActor *Actor, const FBoundingBox &InBB, TArray< UStaticMeshComponent *> &OutStaticMeshComps)
int FoliageActorInstanceCount
Base class for CARLA wheeled vehicles.
geom::Transform Transform
Definition: rpc/Transform.h:16