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);
156 }
157 
159 {
160  check(Character);
162  RegisterEnvironmentObject(Character, BB, EnvironmentObjectType::Character, static_cast<uint8>(crp::CityObjectLabel::Pedestrians));
163 }
164 
166 {
167  check(TrafficLight);
168 
169  TArray<FBoundingBox> BBs;
170  TArray<uint8> Tags;
171 
173  check(BBs.Num() == Tags.Num());
174 
175  const FTransform Transform = TrafficLight->GetTransform();
176  const FString ActorName = TrafficLight->GetName();
177  const bool IsActorTickEnabled = TrafficLight->IsActorTickEnabled();
178 
179  for(int i = 0; i < BBs.Num(); i++)
180  {
181  const FBoundingBox& BB = BBs[i];
182  const uint8 Tag = Tags[i];
183 
184  crp::CityObjectLabel ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
185 
186  const FString TagString = ATagger::GetTagAsString(ObjectLabel);
187  const FString SMName = FString::Printf(TEXT("%s_%s_%d"), *ActorName, *TagString, i);
188 
189  FEnvironmentObject EnvironmentObject;
190  EnvironmentObject.Transform = Transform;
191  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
192  EnvironmentObject.Name = SMName;
193  EnvironmentObject.Actor = TrafficLight;
194  EnvironmentObject.CanTick = IsActorTickEnabled;
195  EnvironmentObject.BoundingBox = BB;
196  EnvironmentObject.Type = EnvironmentObjectType::TrafficLight;
197  EnvironmentObject.ObjectLabel = ObjectLabel;
198  EnvironmentObjects.Emplace(EnvironmentObject);
199 
200  // Register components with its ID; it's not the best solution since we are recalculating the BBs
201  // But this is only calculated when the level is loaded
202  TArray<UStaticMeshComponent*> StaticMeshComps;
203  UBoundingBoxCalculator::GetMeshCompsFromActorBoundingBox(TrafficLight, BB, StaticMeshComps);
204  for(const UStaticMeshComponent* Comp : StaticMeshComps)
205  {
206  ObjectIdToComp.Emplace(EnvironmentObject.Id, Comp);
207  }
208  }
209 }
210 
212 {
213  check(Actor);
214 
215  TArray<UInstancedStaticMeshComponent*> ISMComps;
216  Actor->GetComponents<UInstancedStaticMeshComponent>(ISMComps);
217 
218  const FString ActorName = Actor->GetName();
219  int InstanceCount = 0;
220  bool IsActorTickEnabled = Actor->IsActorTickEnabled();
221 
222  // Foliage actor is a special case, it can appear more than once while traversing the actor list
223  if(Cast<AInstancedFoliageActor>(Actor))
224  {
225  InstanceCount = FoliageActorInstanceCount;
226  }
227 
228  for(UInstancedStaticMeshComponent* Comp : ISMComps)
229  {
230  const TArray<FInstancedStaticMeshInstanceData>& PerInstanceSMData = Comp->PerInstanceSMData;
231  const FTransform CompTransform = Comp->GetComponentTransform();
232 
233  TArray<FBoundingBox> BoundingBoxes;
234  UBoundingBoxCalculator::GetISMBoundingBox(Comp, BoundingBoxes);
235 
236  FString CompName = Comp->GetName();
238 
239  for(int i = 0; i < PerInstanceSMData.Num(); i++)
240  {
241  const FInstancedStaticMeshInstanceData& It = PerInstanceSMData[i];
242  const FTransform InstanceTransform = FTransform(It.Transform);
243  const FVector InstanceLocation = InstanceTransform.GetLocation();
244 
245  // Discard decimal part
246  const int32 X = static_cast<int32>(InstanceLocation.X);
247  const int32 Y = static_cast<int32>(InstanceLocation.Y);
248  const int32 Z = static_cast<int32>(InstanceLocation.Z);
249 
250  const FString InstanceName = FString::Printf(TEXT("%s_Inst_%d_%d"), *ActorName, InstanceCount, i);
251  const FString InstanceIdStr = FString::Printf(TEXT("%s_%s_%d_%d_%d_%d"), *ActorName, *CompName, X, Y, Z, InstanceCount);
252  uint64 InstanceId = CityHash64(TCHAR_TO_ANSI(*InstanceIdStr), InstanceIdStr.Len());
253 
254  FEnvironmentObject EnvironmentObject;
255  EnvironmentObject.Transform = InstanceTransform * CompTransform;
256  EnvironmentObject.Id = InstanceId;
257  EnvironmentObject.Name = InstanceName;
258  EnvironmentObject.IdStr = InstanceIdStr;
259  EnvironmentObject.Actor = Actor;
260  EnvironmentObject.CanTick = IsActorTickEnabled;
261  if( i < BoundingBoxes.Num())
262  {
263  EnvironmentObject.BoundingBox = BoundingBoxes[i];
264  }
265 
266  EnvironmentObject.Type = EnvironmentObjectType::ISMComp;
267  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
268  EnvironmentObjects.Emplace(EnvironmentObject);
269 
270  ObjectIdToComp.Emplace(InstanceId, Comp);
271  InstanceCount++;
272  }
273  }
274 
275  if(Cast<AInstancedFoliageActor>(Actor))
276  {
277  FoliageActorInstanceCount = InstanceCount;
278  }
279 }
280 
282 {
283  check(Actor);
284 
285  TArray<UStaticMeshComponent*> StaticMeshComps;
286  Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
287 
288  TArray<FBoundingBox> BBs;
289  TArray<uint8> Tags;
290  UBoundingBoxCalculator::GetBBsOfStaticMeshComponents(StaticMeshComps, BBs, Tags);
291  check(BBs.Num() == Tags.Num());
292 
293  const FTransform Transform = Actor->GetTransform();
294  const FString ActorName = Actor->GetName();
295  const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
296 
297  for(int i = 0; i < BBs.Num(); i++)
298  {
299  const FString SMName = FString::Printf(TEXT("%s_SM_%d"), *ActorName, i);
300 
301  FEnvironmentObject EnvironmentObject;
302  EnvironmentObject.Transform = Transform;
303  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
304  EnvironmentObject.Name = SMName;
305  EnvironmentObject.Actor = Actor;
306  EnvironmentObject.CanTick = IsActorTickEnabled;
307  EnvironmentObject.BoundingBox = BBs[i];
308  EnvironmentObject.Type = EnvironmentObjectType::SMComp;
309  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
310  EnvironmentObjects.Emplace(EnvironmentObject);
311  }
312 }
313 
315 {
316  check(Actor);
317 
318  TArray<USkeletalMeshComponent*> SkeletalMeshComps;
319  Actor->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
320 
321  TArray<FBoundingBox> BBs;
322  TArray<uint8> Tags;
323  UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, BBs, Tags);
324  check(BBs.Num() == Tags.Num());
325 
326  const FTransform Transform = Actor->GetTransform();
327  const FString ActorName = Actor->GetName();
328  const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
329 
330  for(int i = 0; i < BBs.Num(); i++)
331  {
332  const FString SKMName = FString::Printf(TEXT("%s_SKM_%d"), *ActorName, i);
333 
334  FEnvironmentObject EnvironmentObject;
335  EnvironmentObject.Transform = Transform;
336  EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SKMName), SKMName.Len());
337  EnvironmentObject.Name = SKMName;
338  EnvironmentObject.Actor = Actor;
339  EnvironmentObject.CanTick = IsActorTickEnabled;
340  EnvironmentObject.BoundingBox = BBs[i];
341  EnvironmentObject.Type = EnvironmentObjectType::SKMComp;
342  EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
343  EnvironmentObjects.Emplace(EnvironmentObject);
344 
345  }
346 
347 }
348 
350  FEnvironmentObject& EnvironmentObject,
351  bool Enable)
352 {
353  switch (EnvironmentObject.Type)
354  {
359  EnableActor(EnvironmentObject, Enable);
360  break;
362  EnableTrafficLight(EnvironmentObject, Enable);
363  break;
365  EnableISMComp(EnvironmentObject, Enable);
366  break;
367  default:
368  check(false);
369  break;
370  }
371 
372 }
373 
374 void UObjectRegister::EnableActor(FEnvironmentObject& EnvironmentObject, bool Enable)
375 {
376  AActor* Actor = EnvironmentObject.Actor;
377 
378  Actor->SetActorHiddenInGame(!Enable);
379  Actor->SetActorEnableCollision(Enable);
380  if(EnvironmentObject.CanTick)
381  {
382  Actor->SetActorTickEnabled(Enable);
383  }
384 }
385 
386 void UObjectRegister::EnableTrafficLight(FEnvironmentObject& EnvironmentObject, bool Enable)
387 {
388  // We need to look for the component(s) that form the EnvironmentObject
389  // i.e.: The light box is composed by various SMComponents, one per light,
390  // we need to enable/disable all of them
391 
392  TArray<const UStaticMeshComponent*> ObjectComps;
393  ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
394 
395  for(const UStaticMeshComponent* Comp : ObjectComps)
396  {
397  UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(Comp);
398  SMComp->SetHiddenInGame(!Enable);
399  ECollisionEnabled::Type CollisionType = Enable ? ECollisionEnabled::Type::QueryAndPhysics : ECollisionEnabled::Type::NoCollision;
400  SMComp->SetCollisionEnabled(CollisionType);
401  }
402 
403 }
404 
405 void UObjectRegister::EnableISMComp(FEnvironmentObject& EnvironmentObject, bool Enable)
406 {
407  TArray<const UStaticMeshComponent*> ObjectComps;
408  TArray<FString> InstanceName;
409  FTransform InstanceTransform = EnvironmentObject.Transform;
410 
411  ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
412  EnvironmentObject.Name.ParseIntoArray(InstanceName, TEXT("_"), false);
413 
414  int Index = FCString::Atoi(*InstanceName[InstanceName.Num() - 1]);
415 
416  if(!Enable)
417  {
418  InstanceTransform.SetTranslation(FVector(1000000.0f));
419  InstanceTransform.SetScale3D(FVector(0.0f));
420  }
421 
422  UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(ObjectComps[0]);
423  UInstancedStaticMeshComponent* ISMComp = Cast<UInstancedStaticMeshComponent>(SMComp);
424  bool Result = ISMComp->UpdateInstanceTransform(Index, InstanceTransform, true, true);
425 
426 }
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:226
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