CARLA
BoundingBoxCalculator.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"
8 #include "Carla/Game/Tagger.h"
10 
13 #include "Carla/Game/Tagger.h"
15 
17 #include <carla/rpc/ObjectLabel.h>
19 
20 #include "Components/CapsuleComponent.h"
21 #include "GameFramework/Character.h"
22 #include "Components/BoxComponent.h"
23 
24 #include "Rendering/SkeletalMeshRenderData.h"
25 #include "Engine/SkeletalMeshSocket.h"
26 
27 namespace crp = carla::rpc;
28 
30  FBoundingBox InBB,
31  const FTransform& Transform)
32 {
33  auto Scale = Transform.GetScale3D();
34  InBB.Origin *= Scale;
35  InBB.Rotation = Transform.GetRotation().Rotator();
36  InBB.Origin = InBB.Rotation.RotateVector(InBB.Origin) + Transform.GetLocation();
37  InBB.Extent *= Scale;
38  return InBB;
39 }
40 
42 {
43  if (Actor != nullptr)
44  {
45  // Vehicle.
46  auto Vehicle = Cast<ACarlaWheeledVehicle>(Actor);
47  if (Vehicle != nullptr)
48  {
49  FVector Origin = Vehicle->GetVehicleBoundingBoxTransform().GetTranslation();
50  FVector Extent = Vehicle->GetVehicleBoundingBoxExtent();
51  return {Origin, Extent};
52  }
53  // Walker.
54  auto Character = Cast<ACharacter>(Actor);
55  if (Character != nullptr)
56  {
57  auto Capsule = Character->GetCapsuleComponent();
58  if (Capsule != nullptr)
59  {
60  const auto Radius = Capsule->GetScaledCapsuleRadius();
61  const auto HalfHeight = Capsule->GetScaledCapsuleHalfHeight();
62  // Characters have the pivot point centered.
63  FVector Origin = {0.0f, 0.0f, 0.0f};
64  FVector Extent = {Radius, Radius, HalfHeight};
65  return {Origin, Extent};
66  }
67  }
68  // Traffic sign.
69  auto TrafficSign = Cast<ATrafficSignBase>(Actor);
70  if (TrafficSign != nullptr)
71  {
72  // first return a merge of the generated trigger boxes, if any
73  auto TriggerVolumes = TrafficSign->GetTriggerVolumes();
74  if (TriggerVolumes.Num() > 0)
75  {
77  FTransform Transform = Actor->GetActorTransform();
78  Box.Origin = Transform.InverseTransformPosition(Box.Origin);
79  Box.Rotation = Transform.InverseTransformRotation(Box.Rotation.Quaternion()).Rotator();
80  return Box;
81  }
82  // try to return the original bounding box
83  auto TriggerVolume = TrafficSign->GetTriggerVolume();
84  if (TriggerVolume != nullptr)
85  {
86  auto Transform = TriggerVolume->GetRelativeTransform();
87  return
88  {
89  Transform.GetTranslation(),
90  TriggerVolume->GetScaledBoxExtent(),
91  Transform.GetRotation().Rotator()
92  };
93  }
94  else
95  {
96  UE_LOG(LogCarla, Warning, TEXT("Traffic sign missing trigger volume: %s"), *Actor->GetName());
97  return {};
98  }
99  }
100  // Other, by default BB
101  TArray<FBoundingBox> BBs = GetBBsOfActor(Actor);
102  FBoundingBox BB = CombineBBs(BBs);
103  // Conver to local space; GetBBsOfActor return BBs in world space
104  FTransform Transform = Actor->GetActorTransform();
105  BB.Origin = Transform.InverseTransformPosition(BB.Origin);
106  BB.Rotation = Transform.InverseTransformRotation(BB.Rotation.Quaternion()).Rotator();
107  BB.Rotation = Transform.GetRotation().Rotator();
108  return BB;
109 
110  }
111  return {};
112 }
113 
116  uint8 InTagQueried)
117 {
118  check(Vehicle);
119 
120  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
121  bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::Any);
122 
123  UActorComponent *ActorComp = Vehicle->GetComponentByClass(USkeletalMeshComponent::StaticClass());
124  USkeletalMeshComponent* ParentComp = Cast<USkeletalMeshComponent>(ActorComp);
125 
126  // Filter by tag
128  if(FilterByTagEnabled && Tag != TagQueried) return {};
129 
130  USkeletalMesh* SkeletalMesh = ParentComp->SkeletalMesh;
131  FBoundingBox BB = GetSkeletalMeshBoundingBox(SkeletalMesh);
132 
133  if(BB.Extent.IsZero())
134  {
135  UE_LOG(LogCarla, Error, TEXT("%s has no SKM assigned"), *Vehicle->GetName());
136  return {};
137  }
138 
139  // Two wheel vehicle have more than one SKM
140  TArray<USkeletalMeshComponent*> SkeletalMeshComps;
141  Vehicle->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
142 
143  if(SkeletalMeshComps.Num() > 1)
144  {
145  FVector VehicleLocation = Vehicle->GetActorLocation();
146  FRotator VehicleRotation = Vehicle->GetActorRotation();
147  float MaxHeadLocation = TNumericLimits<float>::Lowest();
148  float MaxKneeLocation = TNumericLimits<float>::Lowest();
149  bool SocketFound = false;
150  for(USkeletalMeshComponent* Comp : SkeletalMeshComps)
151  {
152  if(Comp == ParentComp) continue; // ignore vehicle skeleton
153 
154  // Location of sockets are in world space
155  FVector HeadLocation = Comp->GetSocketLocation("crl_Head__C") - VehicleLocation;
156  FVector KneeLocation = Comp->GetSocketLocation("crl_leg__L") - VehicleLocation;
157 
158  HeadLocation = VehicleRotation.UnrotateVector(HeadLocation);
159  KneeLocation = VehicleRotation.UnrotateVector(KneeLocation);
160 
161  MaxHeadLocation = (HeadLocation.Z > MaxHeadLocation) ? HeadLocation.Z : MaxHeadLocation;
162  MaxKneeLocation = (KneeLocation.Y > MaxKneeLocation) ? KneeLocation.Y : MaxKneeLocation;
163 
164  SocketFound = true;
165  }
166 
167  if(SocketFound)
168  {
169  auto Min = BB.Origin - BB.Rotation.RotateVector(BB.Extent);
170  auto Max = BB.Origin + BB.Rotation.RotateVector(BB.Extent);
171  auto Tmp = Min;
172  Min = Min.ComponentMin(Max);
173  Max = Max.ComponentMin(Tmp);
174 
175  MaxHeadLocation += 20.0f; // hack, the bone of the head is at he bottom
176 
177  Max.Y = (MaxKneeLocation > Max.Y) ? MaxKneeLocation : Max.Y;
178  Min.Y = (-MaxKneeLocation < Min.Y) ? MaxKneeLocation : Min.Y;
179  Max.Z = (MaxHeadLocation > Max.Z) ? MaxHeadLocation : Max.Z;
180 
181  BB.Extent = (Max - Min) * 0.5f;
182  BB.Origin = Min + BB.Extent;
183  }
184  }
185 
186  // Component-to-world transform for this component
187  auto& CompToWorldTransform = ParentComp->GetComponentTransform();
188  BB = ApplyTransformToBB(BB, CompToWorldTransform);
189  return BB;
190 }
191 
193  const ACharacter* Character,
194  uint8 InTagQueried)
195 {
196  check(Character);
197 
198  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
199  bool FilterByTag = TagQueried == crp::CityObjectLabel::Any ||
200  TagQueried == crp::CityObjectLabel::Pedestrians;
201 
202  UCapsuleComponent* Capsule = Character->GetCapsuleComponent();
203 
204 
205  if (Capsule && FilterByTag)
206  {
207  const float Radius = Capsule->GetScaledCapsuleRadius();
208  const float HalfHeight = Capsule->GetScaledCapsuleHalfHeight();
210  // Characters have the pivot point centered.
211  BoundingBox.Origin = {0.0f, 0.0f, 0.0f};
212  BoundingBox.Extent = {Radius, Radius, HalfHeight};
213  // Component-to-world transform for this component
214  auto CompToWorldTransform = Capsule->GetComponentTransform();
215  BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform);
216 
217  return BoundingBox;
218  }
219 
220  return {};
221 }
222 
225  TArray<FBoundingBox>& OutBB,
226  TArray<uint8>& OutTag,
227  uint8 InTagQueried)
228 {
229  check(TrafficLight);
230 
231  TArray<FBoundingBox> BBsOfTL;
232  TArray<uint8> TagsOfTL;
233 
234  // This kind of a magic number relying that the lights of a TL are not bigger than 100.
235  // and we are gonna compare against a squared distance
236  const float DistanceThreshold = 100.0f * 100.0f;
237 
238  // The BBs of the TL are calculated per light, so we need to merge the full-box
239  uint8 TLTag = static_cast<uint8>(crp::CityObjectLabel::TrafficLight);
240 
241  CombineBBsOfActor(TrafficLight, BBsOfTL, TagsOfTL, DistanceThreshold, TLTag);
242  check(BBsOfTL.Num() == TagsOfTL.Num());
243 
244  bool FilterByTagEnabled = (InTagQueried != static_cast<uint8>(crp::CityObjectLabel::Any));
245 
246  for(int i = 0; i < BBsOfTL.Num(); i++)
247  {
248  FBoundingBox& BB = BBsOfTL[i];
249  uint8 Tag = TagsOfTL[i];
250 
251  if(FilterByTagEnabled && Tag != InTagQueried) continue;
252 
253  OutBB.Emplace(BB);
254  OutTag.Emplace(Tag);
255  }
256 }
257 
258 // TODO: update to calculate current animation pose
260 {
261  if(!SkeletalMesh)
262  {
263  UE_LOG(LogCarla, Error, TEXT("GetSkeletalMeshBoundingBox no SkeletalMesh"));
264  return {};
265  }
266 
267  // Get Vertex postion information from LOD 0 of the Skeletal Mesh
268  FSkeletalMeshRenderData* SkeletalMeshRenderData = SkeletalMesh->GetResourceForRendering();
269  FSkeletalMeshLODRenderData& LODRenderData = SkeletalMeshRenderData->LODRenderData[0];
270  FStaticMeshVertexBuffers& StaticMeshVertexBuffers = LODRenderData.StaticVertexBuffers;
271  FPositionVertexBuffer& FPositionVertexBuffer = StaticMeshVertexBuffers.PositionVertexBuffer;
272  uint32 NumVertices = FPositionVertexBuffer.GetNumVertices();
273 
274  // Look for Skeletal Mesh bounds (vertex perfect)
275  FVector Max(TNumericLimits<float>::Lowest());
276  FVector Min(TNumericLimits<float>::Max());
277 
278  for(uint32 i = 0; i < NumVertices; i++)
279  {
280  auto Pos = FPositionVertexBuffer.VertexPosition(i);
281  Max = Max.ComponentMax(Pos);
282  Min = Min.ComponentMin(Pos);
283  }
284 
285  auto Extent = (Max - Min) * 0.5f;
286  auto Origin = Min + Extent;
287 
288  return {Origin, Extent};
289 }
290 
292 {
293  if(!StaticMesh)
294  {
295  // UE_LOG(LogCarla, Error, TEXT("GetStaticMeshBoundingBox no StaticMesh"));
296  return {};
297  }
298 
299  FBox Box = StaticMesh->GetBoundingBox();
300  return {Box.GetCenter(), Box.GetExtent()};
301 
302 }
303 
305  UInstancedStaticMeshComponent* ISMComp,
306  TArray<FBoundingBox>& OutBoundingBox)
307 {
308  if(!ISMComp)
309  {
310  UE_LOG(LogCarla, Error, TEXT("GetISMBoundingBox no ISMComp"));
311  return;
312  }
313 
314  const UStaticMesh *Mesh = ISMComp->GetStaticMesh();
315  const FBoundingBox SMBoundingBox = GetStaticMeshBoundingBox(Mesh);
316 
317  if(!Mesh)
318  {
319  UE_LOG(LogCarla, Error, TEXT("%s has no SM assigned to the ISM"), *ISMComp->GetOwner()->GetName());
320  return;
321  }
322 
323  const TArray<FInstancedStaticMeshInstanceData>& PerInstanceSMData = ISMComp->PerInstanceSMData;
324 
325  const FTransform ParentTransform = ISMComp->GetComponentTransform();
326 
327  for(auto& InstSMIData : PerInstanceSMData)
328  {
329  const FTransform Transform = FTransform(InstSMIData.Transform) * ParentTransform;
330  FBoundingBox BoundingBox = ApplyTransformToBB(SMBoundingBox, Transform);
331 
332  OutBoundingBox.Add(BoundingBox);
333  }
334 
335 }
336 
338  const TArray<UStaticMeshComponent*>& StaticMeshComps,
339  TArray<FBoundingBox>& OutBB,
340  TArray<uint8>& OutTag,
341  uint8 InTagQueried)
342 {
343  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
344  bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::Any);
345 
346  for(UStaticMeshComponent* Comp : StaticMeshComps)
347  {
348 
349  bool isCrosswalk = Comp->GetOwner()->GetName().Contains("crosswalk");
350 
351  // Avoid duplication with SMComp and not visible meshes
352  if( (!Comp->IsVisible() && !isCrosswalk) || Cast<UInstancedStaticMeshComponent>(Comp))
353  {
354  continue;
355  }
356 
357  // Filter by tag
359  if(FilterByTagEnabled && Tag != TagQueried) continue;
360 
361  UStaticMesh* StaticMesh = Comp->GetStaticMesh();
363 
364  if(StaticMesh)
365  {
366  // Component-to-world transform for this component
367  const FTransform& CompToWorldTransform = Comp->GetComponentTransform();
368  BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform);
369  OutBB.Emplace(BoundingBox);
370  OutTag.Emplace(static_cast<uint8>(Tag));
371  }
372  }
373 }
374 
376  const TArray<USkeletalMeshComponent*>& SkeletalMeshComps,
377  TArray<FBoundingBox>& OutBB,
378  TArray<uint8>& OutTag,
379  uint8 InTagQueried)
380 {
381  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
382  bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::Any);
383 
384  for(USkeletalMeshComponent* Comp : SkeletalMeshComps)
385  {
386  // Filter by tag
388 
389  if(!Comp->IsVisible() || (FilterByTagEnabled && Tag != TagQueried)) continue;
390 
391  USkeletalMesh* SkeletalMesh = Comp->SkeletalMesh;
393  if(BoundingBox.Extent.IsZero())
394  {
395  UE_LOG(LogCarla, Error, TEXT("%s has no SKM assigned"), *Comp->GetOwner()->GetName());
396  }
397  else
398  {
399  // Component-to-world transform for this component
400  const FTransform& CompToWorldTransform = Comp->GetComponentTransform();
401  BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform);
402  OutBB.Emplace(BoundingBox);
403  OutTag.Emplace(static_cast<uint8>(Tag));
404  }
405  }
406 }
407 
409  const TArray<AActor*>& Actors,
410  uint8 InTagQueried)
411 {
412  TArray<FBoundingBox> Result;
413  for(AActor* Actor : Actors)
414  {
415  TArray<FBoundingBox> BBs = GetBBsOfActor(Actor, InTagQueried);
416  Result.Append(BBs.GetData(), BBs.Num());
417  }
418 
419  return Result;
420 }
421 
423  const AActor* Actor,
424  uint8 InTagQueried)
425 {
426  TArray<FBoundingBox> Result;
427  TArray<uint8> Tags;
428  crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried;
429  bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::Any);
430 
431  FString ClassName = Actor->GetClass()->GetName();
432 
433  // Avoid the BP_Procedural_Building to avoid duplication with their child actors
434  // When improved the BP_Procedural_Building this maybe should be removed
435  // Note: We don't use casting here because the base class is a BP and is easier to do it this way,
436  // than getting the UClass of the BP to cast the actor.
437  if( ClassName.Contains("Procedural_Bulding") ) return Result;
438 
439  // The vehicle's BP has a low-polystatic mesh for collisions, we should avoid it
440  const ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle>(Actor);
441  if (Vehicle)
442  {
443  FBoundingBox BoundingBox = GetVehicleBoundingBox(Vehicle, InTagQueried);
444  if(!BoundingBox.Extent.IsZero())
445  {
446  Result.Add(BoundingBox);
447  }
448  return Result;;
449  }
450 
451  // Pedestrians, we just use the capsule component at the moment.
452  const ACharacter* Character = Cast<ACharacter>(Actor);
453  if (Character)
454  {
455  FBoundingBox BoundingBox = GetCharacterBoundingBox(Character, InTagQueried);
456  if(!BoundingBox.Extent.IsZero())
457  {
458  Result.Add(BoundingBox);
459  }
460  return Result;
461  }
462 
463  // TrafficLight, we need to join all the BB of the lights in one
464  const ATrafficLightBase* TrafficLight = Cast<ATrafficLightBase>(Actor);
465  if(TrafficLight)
466  {
467  GetTrafficLightBoundingBox(TrafficLight, Result, Tags, InTagQueried);
468  return Result;
469  }
470 
471  // Calculate FBoundingBox of ISM
472  TArray<UInstancedStaticMeshComponent *> ISMComps;
473  Actor->GetComponents<UInstancedStaticMeshComponent>(ISMComps);
474  for(UInstancedStaticMeshComponent* Comp: ISMComps)
475  {
476  // Filter by tag
478  if(FilterByTagEnabled && Tag != TagQueried) continue;
479 
480  GetISMBoundingBox(Comp, Result);
481  }
482 
483  // Calculate FBoundingBox of SM
484  TArray<UStaticMeshComponent*> StaticMeshComps;
485  Tags.Reset();
486  Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
487  GetBBsOfStaticMeshComponents(StaticMeshComps, Result, Tags, InTagQueried);
488 
489  // Calculate FBoundingBox of SK_M
490  TArray<USkeletalMeshComponent*> SkeletalMeshComps;
491  Tags.Reset();
492  Actor->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
493  GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, Result, Tags, InTagQueried);
494 
495  return Result;
496 }
497 
499  const AActor* Actor,
500  TArray<FBoundingBox>& OutBB,
501  TArray<uint8>& OutTag,
502  const float DistanceThreshold,
503  uint8 TagToCombine)
504 {
505  check(Actor);
506 
507  TArray<FBoundingBox> BBsOfTL;
508  TArray<uint8> InternalOutTags;
509  TArray<UStaticMeshComponent*> StaticMeshComps;
510  Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
511  GetBBsOfStaticMeshComponents(StaticMeshComps, BBsOfTL, InternalOutTags);
512 
513  bool IgnoreDistanceFilter = (DistanceThreshold <= 0.0f);
514  bool IgnoreTag = (TagToCombine == 0);
515 
516  TSet<int> IndicesDiscarded;
517  for(int i = 0; i < BBsOfTL.Num(); i++)
518  {
519  // Check if the index was used to merge a previous BB
520  if(IndicesDiscarded.Contains(i)) continue;
521 
522  TArray<FBoundingBox> BBsToCombine;
523  FBoundingBox& BB1 = BBsOfTL[i];
524  uint8 Tag1 = InternalOutTags[i];
525 
526  for(int j = i + 1; j < BBsOfTL.Num(); j++)
527  {
528  // Check if the index was used to merge a previous BB
529  if(IndicesDiscarded.Contains(j)) continue;
530 
531  FBoundingBox& BB2 = BBsOfTL[j];
532  uint8 Tag2 = InternalOutTags[j];
533 
534  float Distance = FVector::DistSquared(BB1.Origin, BB2.Origin);
535 
536  // If the BBs are close enough and are from the same type, we merge it
537  if( ((Distance <= DistanceThreshold) || IgnoreDistanceFilter) &&
538  ((Tag1 == Tag2) || IgnoreTag) )
539  {
540  BBsToCombine.Emplace(BB2);
541  IndicesDiscarded.Emplace(j);
542  }
543  }
544  if(BBsToCombine.Num() > 0)
545  {
546  BBsToCombine.Emplace(BB1);
547  IndicesDiscarded.Emplace(i);
548  FBoundingBox MergedBB = CombineBBs(BBsToCombine);
549  MergedBB.Rotation = BB1.Rotation;
550  OutBB.Emplace(MergedBB);
551  OutTag.Emplace(InternalOutTags[i]);
552  }
553  }
554 
555  // Add the BB of the meshes that didn't need to combine
556  for(int i = 0; i < BBsOfTL.Num(); i++)
557  {
558  // Check if the index was used to merge a previous BB
559  if(IndicesDiscarded.Contains(i)) continue;
560  FBoundingBox& BB = BBsOfTL[i];
561  OutBB.Emplace(BB);
562  OutTag.Emplace(InternalOutTags[i]);
563  }
564 }
565 
566 template <typename Collection, typename ExtractAABB>
568  Collection&& collection,
569  ExtractAABB&& extract_aabb)
570 {
571  FVector Max(std::numeric_limits<float>::lowest());
572  FVector Min(std::numeric_limits<float>::max());
573 
574  for (auto& e : collection)
575  {
576  auto BB = extract_aabb(e);
577  auto LocalMax = BB.Origin + BB.Rotation.RotateVector(BB.Extent);
578  auto LocalMin = BB.Origin - BB.Rotation.RotateVector(BB.Extent);
579  auto Tmp = LocalMin;
580  LocalMin = LocalMin.ComponentMin(LocalMax);
581  LocalMax = LocalMax.ComponentMax(Tmp);
582  Max = Max.ComponentMax(LocalMax);
583  Min = Min.ComponentMin(LocalMin);
584  }
585 
586  auto Extent = (Max - Min) * 0.5f;
587  auto Origin = Min + Extent;
588 
589  return { Origin, Extent };
590 }
591 
592 template <typename Collection>
593 static auto CombineBoundingBoxesGeneric(Collection&& collection)
594 {
595  using T = std::remove_reference_t<decltype(collection[0])>;
596  return CombineBoundingBoxesGeneric(std::forward<Collection>(collection), [](T& e) { return e; });
597 }
598 
599 FBoundingBox UBoundingBoxCalculator::CombineBBs(const TArray<FBoundingBox>& BBsToCombine)
600 {
601  return CombineBoundingBoxesGeneric(BBsToCombine);
602 }
603 
604 FBoundingBox UBoundingBoxCalculator::CombineBoxes(const TArray<UBoxComponent *>& BBsToCombine)
605 {
606  return CombineBoundingBoxesGeneric(BBsToCombine, [](UBoxComponent* e)
607  {
608  return FBoundingBox
609  {
610  e->GetComponentLocation(),
611  e->GetScaledBoxExtent(),
612  e->GetComponentRotation()
613  };
614  });
615 }
616 
618  const AActor* Actor,
619  const FBoundingBox& InBB,
620  TArray<UStaticMeshComponent*>& OutStaticMeshComps)
621 {
622  check(Actor);
623 
624 
625  const float DistanceThreshold = 100.0f * 100.0f;
626 
627  TArray<UStaticMeshComponent*> SMComps;
628  Actor->GetComponents<UStaticMeshComponent>(SMComps);
629 
630  for(UStaticMeshComponent* Comp : SMComps)
631  {
632  if(!Comp->IsVisible()) continue;
633 
634  TArray<FBoundingBox> BBs;
635  TArray<uint8> InternalOutTags;
636  GetBBsOfStaticMeshComponents({Comp}, BBs, InternalOutTags);
637 
638  if(BBs.Num() == 0) continue;
639 
640  const FBoundingBox& BB = BBs[0];
641  float Distance = FVector::DistSquared(InBB.Origin, BB.Origin);
642  if(Distance <= DistanceThreshold)
643  {
644  OutStaticMeshComps.Emplace(Comp);
645  }
646  }
647 }
static FBoundingBox CombineBoxes(const TArray< UBoxComponent *> &BBsToCombine)
static void GetBBsOfSkeletalMeshComponents(const TArray< USkeletalMeshComponent *> &SkeletalMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static TArray< FBoundingBox > GetBoundingBoxOfActors(const TArray< AActor *> &Actors, uint8 InTagQueried=0xFF)
static void GetISMBoundingBox(UInstancedStaticMeshComponent *ISMComp, TArray< FBoundingBox > &OutBoundingBox)
static FBoundingBox GetCharacterBoundingBox(const ACharacter *Character, uint8 InTagQueried=0xFF)
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)
static FBoundingBox CombineBoundingBoxesGeneric(Collection &&collection, ExtractAABB &&extract_aabb)
bg::model::box< Point3D > Box
Definition: InMemoryMap.h:52
static void GetTrafficLightBoundingBox(const ATrafficLightBase *TrafficLight, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static void CombineBBsOfActor(const AActor *Actor, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, const float DistanceThreshold=0.0f, uint8 TagToCombine=0xFF)
carla::SharedPtr< cc::Actor > Actor
static TArray< FBoundingBox > GetBBsOfActor(const AActor *Actor, uint8 InTagQueried=0xFF)
FRotator Rotation
Rotation of the bounding box.
static FBoundingBox GetActorBoundingBox(const AActor *Actor, uint8 InTagQueried=0xFF)
Compute the bounding box of the given Carla actor.
static void GetBBsOfStaticMeshComponents(const TArray< UStaticMeshComponent *> &StaticMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static FBoundingBox GetSkeletalMeshBoundingBox(const USkeletalMesh *SkeletalMesh)
static FBoundingBox ApplyTransformToBB(FBoundingBox InBB, const FTransform &Transform)
static FBoundingBox GetStaticMeshBoundingBox(const UStaticMesh *StaticMesh)
FVector Origin
Origin of the bounding box relative to its owner.
static void GetMeshCompsFromActorBoundingBox(const AActor *Actor, const FBoundingBox &InBB, TArray< UStaticMeshComponent *> &OutStaticMeshComps)
static FBoundingBox CombineBBs(const TArray< FBoundingBox > &BBsToCombine)
Base class for CARLA wheeled vehicles.
FVector Extent
Radii extent of the bounding box.
geom::Transform Transform
Definition: rpc/Transform.h:16