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