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