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)// 如果Actor不为空
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 // 角色的枢轴点在胶囊体的中心
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 // 首先返回合并的触发框(如果有的话)
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 //尝试返回原始的边界框
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 // 其他情况,默认使用边界框
101 TArray<FBoundingBox> BBs = GetBBsOfActor(Actor);
102 FBoundingBox BB = CombineBBs(BBs);
103 // 转换为局部空间;GetBBsOfActor返回的是世界空间的边界框
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 //根据标签进行过滤
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 //两轮车辆有多个SkeletalMesh
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 // 获取Socket的世界空间位置
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; // 修改头部位置,假设头部骨骼位于底部
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 // 计算组件到世界空间的变换
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 // 角色的枢轴点位于中心
211 BoundingBox.Origin = {0.0f, 0.0f, 0.0f};
212 BoundingBox.Extent = {Radius, Radius, HalfHeight};
213 // 计算组件到世界空间的变换
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 // 这种“魔法数字”的使用是基于假设信号灯的数量不会超过 100。
235 // 这里通过平方距离来进行比较
236 const float DistanceThreshold = 100.0f * 100.0f;
237
238 //计算每个交通信号灯的边界框,因此需要合并成一个总的边界框
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: 更新为计算当前动画姿势的边界框
260{
261 if(!SkeletalMesh)
262 {
263 UE_LOG(LogCarla, Error, TEXT("GetSkeletalMeshBoundingBox no SkeletalMesh"));
264 return {};
265 }
266
267 // 获取Skeletal Mesh的LOD 0(细节级别0)渲染数据中的顶点位置数据
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 //查找Skeletal Mesh的边界框(完美顶点)
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 // 避免与静态网格组件(SMComp)重复,并且排除不可见的网格
352 if( (!Comp->IsVisible() && !isCrosswalk) || Cast<UInstancedStaticMeshComponent>(Comp))
353 {
354 continue;
355 }
356
357 //根据标签进行过滤
359 if(FilterByTagEnabled && Tag != TagQueried) continue;
360
361 UStaticMesh* StaticMesh = Comp->GetStaticMesh();
363
364 if(StaticMesh)
365 {
366 // 获取该组件的世界坐标变换矩阵
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 // 将该组件的局部变换应用到世界坐标系的变换
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 // 避免处理BP_Procedural_Building类的Actor,以避免与其子Actor重复
434 //当改进BP_Procedural_Building时,这个检查可能应该移除
435 //注意:这里没有使用类型转换,因为基类是蓝图(BP),这种方式更简单,不需要通过获取UClass来进行类型转换。
436 if( ClassName.Contains("Procedural_Bulding") ) return Result;
437
438 // 车辆的蓝图使用了低多边形静态网格进行碰撞检测,我们应该避免处理它
439 const ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle>(Actor);
440 if (Vehicle)
441 {
443 if(!BoundingBox.Extent.IsZero())
444 {
445 Result.Add(BoundingBox);
446 }
447 return Result;;
448 }
449
450 // 行人,我们目前仅使用胶囊组件
451 const ACharacter* Character = Cast<ACharacter>(Actor);
452 if (Character)
453 {
455 if(!BoundingBox.Extent.IsZero())
456 {
457 Result.Add(BoundingBox);
458 }
459 return Result;
460 }
461
462 // 对于交通信号灯,我们需要将所有信号灯的边界框合并为一个
463 const ATrafficLightBase* TrafficLight = Cast<ATrafficLightBase>(Actor);
464 if(TrafficLight)
465 {
466 GetTrafficLightBoundingBox(TrafficLight, Result, Tags, InTagQueried);
467 return Result;
468 }
469
470 // 计算实例化静态网格组件(ISM)的边界框
471 TArray<UInstancedStaticMeshComponent *> ISMComps;
472 Actor->GetComponents<UInstancedStaticMeshComponent>(ISMComps);
473 for(UInstancedStaticMeshComponent* Comp: ISMComps)
474 {
475 // 通过标签过滤
477 if(FilterByTagEnabled && Tag != TagQueried) continue;
478
479 GetISMBoundingBox(Comp, Result);
480 }
481
482 // 计算静态网格组件(SM)的边界框
483 TArray<UStaticMeshComponent*> StaticMeshComps;
484 Tags.Reset();
485 Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
486 GetBBsOfStaticMeshComponents(StaticMeshComps, Result, Tags, InTagQueried);
487
488 //计算骨骼网格组件(SK_M)的边界框
489 TArray<USkeletalMeshComponent*> SkeletalMeshComps;
490 Tags.Reset();
491 Actor->GetComponents<USkeletalMeshComponent>(SkeletalMeshComps);
492 GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, Result, Tags, InTagQueried);
493
494 return Result;
495}
496
498 const AActor* Actor,
499 TArray<FBoundingBox>& OutBB,
500 TArray<uint8>& OutTag,
501 const float DistanceThreshold,
502 uint8 TagToCombine)
503{
504 check(Actor);
505
506 TArray<FBoundingBox> BBsOfTL;
507 TArray<uint8> InternalOutTags;
508 TArray<UStaticMeshComponent*> StaticMeshComps;
509 Actor->GetComponents<UStaticMeshComponent>(StaticMeshComps);
510 GetBBsOfStaticMeshComponents(StaticMeshComps, BBsOfTL, InternalOutTags);
511
512 bool IgnoreDistanceFilter = (DistanceThreshold <= 0.0f);
513 bool IgnoreTag = (TagToCombine == 0);
514
515 TSet<int> IndicesDiscarded;
516 for(int i = 0; i < BBsOfTL.Num(); i++)
517 {
518 // 检查该索引是否已用于合并之前的边界框
519 if(IndicesDiscarded.Contains(i)) continue;
520
521 TArray<FBoundingBox> BBsToCombine;
522 FBoundingBox& BB1 = BBsOfTL[i];
523 uint8 Tag1 = InternalOutTags[i];
524
525 for(int j = i + 1; j < BBsOfTL.Num(); j++)
526 {
527 // 检查该索引是否已用于合并之前的边界框
528 if(IndicesDiscarded.Contains(j)) continue;
529
530 FBoundingBox& BB2 = BBsOfTL[j];
531 uint8 Tag2 = InternalOutTags[j];
532
533 float Distance = FVector::DistSquared(BB1.Origin, BB2.Origin);
534
535 //如果两个边界框足够接近并且属于同一类型,则合并
536 if( ((Distance <= DistanceThreshold) || IgnoreDistanceFilter) &&
537 ((Tag1 == Tag2) || IgnoreTag) )
538 {
539 BBsToCombine.Emplace(BB2);
540 IndicesDiscarded.Emplace(j);
541 }
542 }
543 if(BBsToCombine.Num() > 0)
544 {
545 BBsToCombine.Emplace(BB1);
546 IndicesDiscarded.Emplace(i);
547 FBoundingBox MergedBB = CombineBBs(BBsToCombine);
548 MergedBB.Rotation = BB1.Rotation;
549 OutBB.Emplace(MergedBB);
550 OutTag.Emplace(InternalOutTags[i]);
551 }
552 }
553
554 // 添加不需要合并的网格的边界框
555 for(int i = 0; i < BBsOfTL.Num(); i++)
556 {
557 //检查该索引是否已用于合并之前的边界框
558 if(IndicesDiscarded.Contains(i)) continue;
559 FBoundingBox& BB = BBsOfTL[i];
560 OutBB.Emplace(BB);
561 OutTag.Emplace(InternalOutTags[i]);
562 }
563}
564
565template <typename Collection, typename ExtractAABB>
567 Collection&& collection,
568 ExtractAABB&& extract_aabb)
569{
570 FVector Max(std::numeric_limits<float>::lowest());
571 FVector Min(std::numeric_limits<float>::max());
572
573 for (auto& e : collection)
574 {
575 auto BB = extract_aabb(e);
576 auto LocalMax = BB.Origin + BB.Rotation.RotateVector(BB.Extent);
577 auto LocalMin = BB.Origin - BB.Rotation.RotateVector(BB.Extent);
578 auto Tmp = LocalMin;
579 LocalMin = LocalMin.ComponentMin(LocalMax);
580 LocalMax = LocalMax.ComponentMax(Tmp);
581 Max = Max.ComponentMax(LocalMax);
582 Min = Min.ComponentMin(LocalMin);
583 }
584
585 auto Extent = (Max - Min) * 0.5f;
586 auto Origin = Min + Extent;
587
588 return { Origin, Extent };
589}
590
591template <typename Collection>
592static auto CombineBoundingBoxesGeneric(Collection&& collection)
593{
594 using T = std::remove_reference_t<decltype(collection[0])>;
595 return CombineBoundingBoxesGeneric(std::forward<Collection>(collection), [](T& e) { return e; });
596}
597
598FBoundingBox UBoundingBoxCalculator::CombineBBs(const TArray<FBoundingBox>& BBsToCombine)
599{
600 return CombineBoundingBoxesGeneric(BBsToCombine);
601}
602
603FBoundingBox UBoundingBoxCalculator::CombineBoxes(const TArray<UBoxComponent *>& BBsToCombine)
604{
605 return CombineBoundingBoxesGeneric(BBsToCombine, [](UBoxComponent* e)
606 {
607 return FBoundingBox
608 {
609 e->GetComponentLocation(),
610 e->GetScaledBoxExtent(),
611 e->GetComponentRotation()
612 };
613 });
614}
615
617 const AActor* Actor,
618 const FBoundingBox& InBB,
619 TArray<UStaticMeshComponent*>& OutStaticMeshComps)
620{
621 check(Actor);
622
623
624 const float DistanceThreshold = 100.0f * 100.0f;
625
626 TArray<UStaticMeshComponent*> SMComps;
627 Actor->GetComponents<UStaticMeshComponent>(SMComps);
628
629 for(UStaticMeshComponent* Comp : SMComps)
630 {
631 if(!Comp->IsVisible()) continue;
632
633 TArray<FBoundingBox> BBs;
634 TArray<uint8> InternalOutTags;
635 GetBBsOfStaticMeshComponents({Comp}, BBs, InternalOutTags);
636
637 if(BBs.Num() == 0) continue;
638
639 const FBoundingBox& BB = BBs[0];
640 float Distance = FVector::DistSquared(InBB.Origin, BB.Origin);
641 if(Distance <= DistanceThreshold)
642 {
643 OutStaticMeshComps.Emplace(Comp);
644 }
645 }
646}
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
TMap< IdType, AActor * > Actors
static FBoundingBox ApplyTransformToBB(FBoundingBox InBB, const FTransform &Transform)
static FBoundingBox CombineBoundingBoxesGeneric(Collection &&collection, ExtractAABB &&extract_aabb)
TSharedPtr< const FActorInfo > carla::rpc::ActorState UWorld Actor
Base class for CARLA wheeled vehicles.
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &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)
计算给定 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
边界框相对于其所有者的原点