CARLA
Loading...
Searching...
No Matches
ObjectRegister.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 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#include "Carla.h"
9#include "Carla/Game/Tagger.h"
11
12#include <util/ue-header-guard-begin.h>
13#include "InstancedFoliageActor.h"
14#include "GameFramework/Character.h"
15#if WITH_EDITOR
16#include "Misc/FileHelper.h"
17#include "Misc/Paths.h"
18#endif // WITH_EDITOR
19#include <util/ue-header-guard-end.h>
20
21namespace crp = carla::rpc;
22
23TArray<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
31 {
32 if(!FilterByTagEnabled || (It.ObjectLabel == TagQueried))
33 {
34 Result.Emplace(It);
35 }
36 }
37
38 return Result;
39}
40
41void UObjectRegister::RegisterObjects(TArray<AActor*> Actors)
42{
43 // Empties the array but doesn't change memory allocations
44 EnvironmentObjects.Reset();
45 // Kept across registrations: a hidden traffic-light box registers no more
46 // (it has no bounds), and its id must still reach its components to show it
47 // again. Only components that are gone are dropped.
48 for (auto It = ObjectIdToComp.CreateIterator(); It; ++It)
49 {
50 if (!It.Value().IsValid())
51 {
52 It.RemoveCurrent();
53 }
54 }
55 // Foliage instance ids count instances from here: from zero on every
56 // registration, an instance keeps its id whenever the objects register
57 // again (a map layer loaded or unloaded), and two servers with the same
58 // levels loaded give it the same one.
60
61 for(AActor* Actor : Actors)
62 {
63
64 FString ClassName = Actor->GetClass()->GetName();
65 // Discard Sky to not break the global ilumination
66 if(ClassName.Equals("BP_Sky_C")) continue;
67
68 ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle>(Actor);
69 if (Vehicle)
70 {
72 continue;
73 }
74
75 ACharacter* Character = Cast<ACharacter>(Actor);
76 if (Character)
77 {
79 continue;
80 }
81
82 ATrafficLightBase* TrafficLight = Cast<ATrafficLightBase>(Actor);
83 if(TrafficLight)
84 {
86 continue;
87 }
88
90
92
94 }
95
96#if WITH_EDITOR
97 // To help debug
98 FString FileContent;
99 FileContent += FString::Printf(TEXT("Num actors %d\n"), Actors.Num());
100 FileContent += FString::Printf(TEXT("Num registered objects %d\n\n"), EnvironmentObjects.Num());
101
102 for(const FEnvironmentObject& Object : EnvironmentObjects)
103 {
104 FileContent += FString::Printf(TEXT("%llu\t"), Object.Id);
105 FileContent += FString::Printf(TEXT("%s\t"), *Object.Name);
106 FileContent += FString::Printf(TEXT("%s\t"), *Object.IdStr);
107 FileContent += FString::Printf(TEXT("%d\n"), static_cast<int32>(Object.Type));
108 }
109
110
111 FString FilePath = FPaths::ProjectSavedDir() + "RegisteredObjects.txt";
112 FFileHelper::SaveStringToFile(
113 FileContent,
114 *FilePath,
115 FFileHelper::EEncodingOptions::AutoDetect,
116 &IFileManager::Get(),
117 EFileWrite::FILEWRITE_Silent);
118
119#endif // WITH_EDITOR
120
121}
122
123void UObjectRegister::EnableEnvironmentObjects(const TSet<uint64>& EnvObjectIds, bool Enable)
124{
125 for(uint64 It : EnvObjectIds)
126 {
127 bool found = false;
128 for(FEnvironmentObject& EnvironmentObject : EnvironmentObjects)
129 {
130 if(It == EnvironmentObject.Id)
131 {
132 EnableEnvironmentObject(EnvironmentObject, Enable);
133 found = true;
134 break;
135 }
136 }
137 if(!found)
138 {
139 UE_LOG(LogCarla, Error, TEXT("EnableEnvironmentObjects id not found %llu"), It);
140 }
141 }
142
143}
144
145TSet<uint64> UObjectRegister::FindEnvironmentObjects(const TSet<uint64>& EnvObjectIds) const
146{
147 TSet<uint64> Found;
148 if (EnvObjectIds.Num() == 0)
149 {
150 return Found;
151 }
152 for (const FEnvironmentObject& EnvironmentObject : EnvironmentObjects)
153 {
154 if (EnvObjectIds.Contains(EnvironmentObject.Id))
155 {
156 Found.Add(EnvironmentObject.Id);
157 }
158 }
159 return Found;
160}
161
163 const TSet<uint64>& EnvObjectIds,
164 const TSet<const AActor*>& Actors) const
165{
166 TSet<uint64> Found;
167 if (EnvObjectIds.Num() == 0)
168 {
169 return Found;
170 }
171 for (const FEnvironmentObject& EnvironmentObject : EnvironmentObjects)
172 {
173 if (EnvObjectIds.Contains(EnvironmentObject.Id) &&
174 EnvironmentObject.Actor.IsValid() &&
175 Actors.Contains(EnvironmentObject.Actor.Get()))
176 {
177 Found.Add(EnvironmentObject.Id);
178 }
179 }
180 return Found;
181}
182
184 AActor* Actor,
187 uint8 Tag)
188{
189 const FString ActorName = Actor->GetName();
190 auto ActorNameAnsichar = StringCast<ANSICHAR>(*ActorName);
191 const char* ActorNameChar = ActorNameAnsichar.Get();
192
193 FEnvironmentObject EnvironmentObject;
194 EnvironmentObject.Transform = Actor->GetActorTransform();
195 EnvironmentObject.Id = CityHash64(ActorNameChar, ActorName.Len());
196 EnvironmentObject.Name = ActorName;
197 EnvironmentObject.Actor = Actor;
198 EnvironmentObject.CanTick = Actor->IsActorTickEnabled();
199 EnvironmentObject.BoundingBox = BoundingBox;
200 EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
201 EnvironmentObject.Type = Type;
202 EnvironmentObjects.Emplace(std::move(EnvironmentObject));
203}
204
212
219
221{
222 check(TrafficLight);
223
224 TArray<FBoundingBox> BBs;
225 TArray<uint8> Tags;
226
228 check(BBs.Num() == Tags.Num());
229
230 const FTransform Transform = TrafficLight->GetTransform();
231 const FString ActorName = TrafficLight->GetName();
232 const bool IsActorTickEnabled = TrafficLight->IsActorTickEnabled();
233
234 for(int i = 0; i < BBs.Num(); i++)
235 {
236 const FBoundingBox& BB = BBs[i];
237 const uint8 Tag = Tags[i];
238
239 crp::CityObjectLabel ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
240
241 const FString TagString = ATagger::GetTagAsString(ObjectLabel);
242 const FString SMName = FString::Printf(TEXT("%s_%s_%d"), *ActorName, *TagString, i);
243
244 FEnvironmentObject EnvironmentObject;
245 EnvironmentObject.Transform = Transform;
246 EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
247 EnvironmentObject.Name = SMName;
248 EnvironmentObject.Actor = TrafficLight;
249 EnvironmentObject.CanTick = IsActorTickEnabled;
250 EnvironmentObject.BoundingBox = BB;
251 EnvironmentObject.Type = EnvironmentObjectType::TrafficLight;
252 EnvironmentObject.ObjectLabel = ObjectLabel;
253 EnvironmentObjects.Emplace(EnvironmentObject);
254
255 // Register components with its ID; it's not the best solution since we are recalculating the BBs
256 // But this is only calculated when the level is loaded
257 TArray<UStaticMeshComponent*> StaticMeshComps;
259 for(const UStaticMeshComponent* Comp : StaticMeshComps)
260 {
261 ObjectIdToComp.AddUnique(EnvironmentObject.Id, Comp);
262 }
263 }
264}
265
267{
268 check(Actor);
269
270 TArray<UInstancedStaticMeshComponent*> ISMComps;
271 Actor->GetComponents<UInstancedStaticMeshComponent>(ISMComps);
272
273 const FString ActorName = Actor->GetName();
274 int InstanceCount = 0;
275 bool IsActorTickEnabled = Actor->IsActorTickEnabled();
276
277 // Foliage actor is a special case, it can appear more than once while traversing the actor list
278 if(Cast<AInstancedFoliageActor>(Actor))
279 {
280 InstanceCount = FoliageActorInstanceCount;
281 }
282
283 for(UInstancedStaticMeshComponent* Comp : ISMComps)
284 {
285 const TArray<FInstancedStaticMeshInstanceData>& PerInstanceSMData = Comp->PerInstanceSMData;
286 const FTransform CompTransform = Comp->GetComponentTransform();
287
288 TArray<FBoundingBox> BoundingBoxes;
290
291 FString CompName = Comp->GetName();
293
294 for(int i = 0; i < PerInstanceSMData.Num(); i++)
295 {
296 const FInstancedStaticMeshInstanceData& It = PerInstanceSMData[i];
297 const FTransform InstanceTransform = FTransform(It.Transform);
298 const FVector InstanceLocation = InstanceTransform.GetLocation();
299
300 // Discard decimal part
301 const int32 X = static_cast<int32>(InstanceLocation.X);
302 const int32 Y = static_cast<int32>(InstanceLocation.Y);
303 const int32 Z = static_cast<int32>(InstanceLocation.Z);
304
305 const FString InstanceName = FString::Printf(TEXT("%s_Inst_%d_%d"), *ActorName, InstanceCount, i);
306 const FString InstanceIdStr = FString::Printf(TEXT("%s_%s_%d_%d_%d_%d"), *ActorName, *CompName, X, Y, Z, InstanceCount);
307 uint64 InstanceId = CityHash64(TCHAR_TO_ANSI(*InstanceIdStr), InstanceIdStr.Len());
308
309 FEnvironmentObject EnvironmentObject;
310 EnvironmentObject.Transform = InstanceTransform * CompTransform;
311 EnvironmentObject.Id = InstanceId;
312 EnvironmentObject.Name = InstanceName;
313 EnvironmentObject.IdStr = InstanceIdStr;
314 EnvironmentObject.Actor = Actor;
315 EnvironmentObject.CanTick = IsActorTickEnabled;
316 if( i < BoundingBoxes.Num())
317 {
318 EnvironmentObject.BoundingBox = BoundingBoxes[i];
319 }
320
321 EnvironmentObject.Type = EnvironmentObjectType::ISMComp;
322 EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tag);
323 EnvironmentObjects.Emplace(EnvironmentObject);
324
325 ObjectIdToComp.AddUnique(InstanceId, Comp);
326 InstanceCount++;
327 }
328 }
329
330 if(Cast<AInstancedFoliageActor>(Actor))
331 {
332 FoliageActorInstanceCount = InstanceCount;
333 }
334}
335
337{
338 check(Actor);
339
340 TArray<UStaticMeshComponent*> StaticMeshComps;
341 Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
342
343 TArray<FBoundingBox> BBs;
344 TArray<uint8> Tags;
346 check(BBs.Num() == Tags.Num());
347
348 const FTransform Transform = Actor->GetTransform();
349 const FString ActorName = Actor->GetName();
350 const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
351
352 for(int i = 0; i < BBs.Num(); i++)
353 {
354 const FString SMName = FString::Printf(TEXT("%s_SM_%d"), *ActorName, i);
355
356 FEnvironmentObject EnvironmentObject;
357 EnvironmentObject.Transform = Transform;
358 EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SMName), SMName.Len());
359 EnvironmentObject.Name = SMName;
360 EnvironmentObject.Actor = Actor;
361 EnvironmentObject.CanTick = IsActorTickEnabled;
362 EnvironmentObject.BoundingBox = BBs[i];
363 EnvironmentObject.Type = EnvironmentObjectType::SMComp;
364 EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
365 EnvironmentObjects.Emplace(EnvironmentObject);
366 }
367}
368
370{
371 check(Actor);
372
373 TArray<USkeletalMeshComponent*> SkeletalMeshComps;
374 Actor->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
375
376 TArray<FBoundingBox> BBs;
377 TArray<uint8> Tags;
378 UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, BBs, Tags);
379 check(BBs.Num() == Tags.Num());
380
381 const FTransform Transform = Actor->GetTransform();
382 const FString ActorName = Actor->GetName();
383 const bool IsActorTickEnabled = Actor->IsActorTickEnabled();
384
385 for(int i = 0; i < BBs.Num(); i++)
386 {
387 const FString SKMName = FString::Printf(TEXT("%s_SKM_%d"), *ActorName, i);
388
389 FEnvironmentObject EnvironmentObject;
390 EnvironmentObject.Transform = Transform;
391 EnvironmentObject.Id = CityHash64(TCHAR_TO_ANSI(*SKMName), SKMName.Len());
392 EnvironmentObject.Name = SKMName;
393 EnvironmentObject.Actor = Actor;
394 EnvironmentObject.CanTick = IsActorTickEnabled;
395 EnvironmentObject.BoundingBox = BBs[i];
396 EnvironmentObject.Type = EnvironmentObjectType::SKMComp;
397 EnvironmentObject.ObjectLabel = static_cast<crp::CityObjectLabel>(Tags[i]);
398 EnvironmentObjects.Emplace(EnvironmentObject);
399
400 }
401
402}
403
405 FEnvironmentObject& EnvironmentObject,
406 bool Enable)
407{
408 switch (EnvironmentObject.Type)
409 {
414 EnableActor(EnvironmentObject, Enable);
415 break;
417 EnableTrafficLight(EnvironmentObject, Enable);
418 break;
420 EnableISMComp(EnvironmentObject, Enable);
421 break;
422 default:
423 check(false);
424 break;
425 }
426
427}
428
429void UObjectRegister::EnableActor(FEnvironmentObject& EnvironmentObject, bool Enable)
430{
431 AActor* Actor = EnvironmentObject.Actor.Get();
432 if (!IsValid(Actor))
433 {
434 return;
435 }
436
437 Actor->SetActorHiddenInGame(!Enable);
438 Actor->SetActorEnableCollision(Enable);
439 if(EnvironmentObject.CanTick)
440 {
441 Actor->SetActorTickEnabled(Enable);
442 }
443}
444
445void UObjectRegister::EnableTrafficLight(FEnvironmentObject& EnvironmentObject, bool Enable)
446{
447 // We need to look for the component(s) that form the EnvironmentObject
448 // i.e.: The light box is composed by various SMComponents, one per light,
449 // we need to enable/disable all of them
450
451 TArray<TWeakObjectPtr<const UStaticMeshComponent>> ObjectComps;
452 ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
453
454 for(const TWeakObjectPtr<const UStaticMeshComponent>& Comp : ObjectComps)
455 {
456 if (!Comp.IsValid())
457 {
458 continue;
459 }
460 UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(Comp.Get());
461 SMComp->SetHiddenInGame(!Enable);
462 ECollisionEnabled::Type CollisionType = Enable ? ECollisionEnabled::Type::QueryAndPhysics : ECollisionEnabled::Type::NoCollision;
463 SMComp->SetCollisionEnabled(CollisionType);
464 }
465
466}
467
468void UObjectRegister::EnableISMComp(FEnvironmentObject& EnvironmentObject, bool Enable)
469{
470 TArray<TWeakObjectPtr<const UStaticMeshComponent>> ObjectComps;
471 TArray<FString> InstanceName;
472 FTransform InstanceTransform = EnvironmentObject.Transform;
473
474 ObjectIdToComp.MultiFind(EnvironmentObject.Id, ObjectComps);
475 if (ObjectComps.Num() == 0 || !ObjectComps[0].IsValid())
476 {
477 return;
478 }
479 EnvironmentObject.Name.ParseIntoArray(InstanceName, TEXT("_"), false);
480
481 int Index = FCString::Atoi(*InstanceName[InstanceName.Num() - 1]);
482
483 if(!Enable)
484 {
485 InstanceTransform.SetTranslation(FVector(1000000.0f));
486 InstanceTransform.SetScale3D(FVector(0.0f));
487 }
488
489 UStaticMeshComponent* SMComp = const_cast<UStaticMeshComponent*>(ObjectComps[0].Get());
490 UInstancedStaticMeshComponent* ISMComp = Cast<UInstancedStaticMeshComponent>(SMComp);
491 if (ISMComp == nullptr)
492 {
493 return;
494 }
495 ISMComp->UpdateInstanceTransform(Index, InstanceTransform, true, true);
496
497}
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
Base class for CARLA wheeled vehicles.
static FString GetTagAsString(crp::CityObjectLabel Tag)
Transform a CityObjectLabel into a string.
Definition Tagger.cpp:269
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
Retrieve the tag of an already tagged component.
Definition Tagger.cpp:213
static void GetBBsOfSkeletalMeshComponents(const TArray< USkeletalMeshComponent * > &SkeletalMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static FBoundingBox GetCharacterBoundingBox(const ACharacter *Character, uint8 InTagQueried=0xFF)
static void GetISMBoundingBox(UInstancedStaticMeshComponent *ISMComp, TArray< FBoundingBox > &OutBoundingBox)
static void GetTrafficLightBoundingBox(const ATrafficLightBase *TrafficLight, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static void GetBBsOfStaticMeshComponents(const TArray< UStaticMeshComponent * > &StaticMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static FBoundingBox GetVehicleBoundingBox(const ACarlaWheeledVehicle *Vehicle, uint8 InTagQueried=0xFF)
static void GetMeshCompsFromActorBoundingBox(const AActor *Actor, const FBoundingBox &InBB, TArray< UStaticMeshComponent * > &OutStaticMeshComps)
void RegisterVehicle(ACarlaWheeledVehicle *Vehicle)
void RegisterSMComponents(AActor *Actor)
TArray< FEnvironmentObject > EnvironmentObjects
void EnableEnvironmentObject(FEnvironmentObject &EnvironmentObject, bool Enable)
TMultiMap< uint64, TWeakObjectPtr< const UStaticMeshComponent > > ObjectIdToComp
void EnableISMComp(FEnvironmentObject &EnvironmentObject, bool Enable)
void EnableEnvironmentObjects(const TSet< uint64 > &EnvObjectIds, bool Enable)
void RegisterTrafficLight(ATrafficLightBase *TrafficLight)
void RegisterEnvironmentObject(AActor *Actor, FBoundingBox &BoundingBox, EnvironmentObjectType Type, uint8 Tag)
void RegisterObjects(TArray< AActor * > Actors)
void RegisterSKMComponents(AActor *Actor)
TSet< uint64 > FindEnvironmentObjectsOf(const TSet< uint64 > &EnvObjectIds, const TSet< const AActor * > &Actors) const
The ids of EnvObjectIds registered now for an actor of Actors.
TArray< FEnvironmentObject > GetEnvironmentObjects(uint8 InTagQueried=0xFF) const
void RegisterCharacter(ACharacter *Character)
void EnableActor(FEnvironmentObject &EnvironmentObject, bool Enable)
void EnableTrafficLight(FEnvironmentObject &EnvironmentObject, bool Enable)
TSet< uint64 > FindEnvironmentObjects(const TSet< uint64 > &EnvObjectIds) const
The ids of EnvObjectIds that are registered now.
void RegisterISMComponents(AActor *Actor)