CARLA
 
载入中...
搜索中...
未找到
BoundingBoxCalculator.cpp
浏览该文件的文档.
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
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
27namespace 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 {
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 {
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
566template <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
592template <typename Collection>
593static 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
599FBoundingBox UBoundingBoxCalculator::CombineBBs(const TArray<FBoundingBox>& BBsToCombine)
600{
601 return CombineBoundingBoxesGeneric(BBsToCombine);
602}
603
604FBoundingBox 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 ApplyTransformToBB(FBoundingBox InBB, const FTransform &Transform)
static FBoundingBox CombineBoundingBoxesGeneric(Collection &&collection, ExtractAABB &&extract_aabb)
Base class for CARLA wheeled vehicles.
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
Retrieve the tag of an already tagged component.
Definition Tagger.h:52
static void GetBBsOfSkeletalMeshComponents(const TArray< USkeletalMeshComponent * > &SkeletalMeshComps, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static TArray< FBoundingBox > GetBBsOfActor(const AActor *Actor, uint8 InTagQueried=0xFF)
static FBoundingBox GetCharacterBoundingBox(const ACharacter *Character, uint8 InTagQueried=0xFF)
static void GetISMBoundingBox(UInstancedStaticMeshComponent *ISMComp, TArray< FBoundingBox > &OutBoundingBox)
static FBoundingBox GetSkeletalMeshBoundingBox(const USkeletalMesh *SkeletalMesh)
static FBoundingBox GetStaticMeshBoundingBox(const UStaticMesh *StaticMesh)
static void GetTrafficLightBoundingBox(const ATrafficLightBase *TrafficLight, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, uint8 InTagQueried=0xFF)
static FBoundingBox CombineBBs(const TArray< FBoundingBox > &BBsToCombine)
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 CombineBBsOfActor(const AActor *Actor, TArray< FBoundingBox > &OutBB, TArray< uint8 > &OutTag, const float DistanceThreshold=0.0f, uint8 TagToCombine=0xFF)
static FBoundingBox GetActorBoundingBox(const AActor *Actor, uint8 InTagQueried=0xFF)
Compute the bounding box of the given Carla actor.
static void GetMeshCompsFromActorBoundingBox(const AActor *Actor, const FBoundingBox &InBB, TArray< UStaticMeshComponent * > &OutStaticMeshComps)
static FBoundingBox CombineBoxes(const TArray< UBoxComponent * > &BBsToCombine)
static TArray< FBoundingBox > GetBoundingBoxOfActors(const TArray< AActor * > &Actors, uint8 InTagQueried=0xFF)
FVector Origin
Origin of the bounding box relative to its owner.
FVector Extent
Radii extent of the bounding box.