CARLA
 
载入中...
搜索中...
未找到
CityMapMeshHolder.cpp
浏览该文件的文档.
1// Copyright (c) 2017 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 "CityMapMeshHolder.h"
9#include "Engine/StaticMeshActor.h"
10#include "Components/InstancedStaticMeshComponent.h"
11#include "Engine/StaticMesh.h"
12#include <vector>
15#include "Kismet/KismetSystemLibrary.h"
16
17
18// 引入标准库中的类型别名定义,用于将枚举类型ECityMapMeshTag转换为其底层类型
19using tag_size_t = std::underlying_type<ECityMapMeshTag>::type;
20
21// 定义一个常量表达式,获取ECityMapMeshTag枚举类型的标签数量
23
24// =============================================================================
25// -- Construction and update related methods ----------------------------------
26// =============================================================================
27
28// ACityMapMeshHolder类的构造函数,接受一个FObjectInitializer对象用于初始化对象
29ACityMapMeshHolder::ACityMapMeshHolder(const FObjectInitializer& ObjectInitializer)
30 : Super(ObjectInitializer)
31{
32 // 设置该Actor的Tick函数是否可被调用,这里设置为false,表示不需要每帧更新
33 PrimaryActorTick.bCanEverTick = false;
34
35 // 使用传入的ObjectInitializer创建一个默认的场景组件作为根组件
37 ObjectInitializer.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComponent"));
38 // 设置场景组件的移动性为静态,即不可移动
39 SceneRootComponent->SetMobility(EComponentMobility::Static);
40 // 将创建的场景组件设置为Actor的根组件
41 RootComponent = SceneRootComponent;
42
43 // 遍历所有的标签类型,为每个标签类型添加一个静态网格持有者
44 for (tag_size_t i = 0u; i < NUMBER_OF_TAGS; ++i) {
45 // 添加静态网格物体支架。
47 }
48
49}
50
51/*void ACityMapMeshHolder::LayoutDetails(IDetailLayoutBuilder& DetailLayout)
52{
53 // 获取渲染类别细节构建器
54 IDetailCategoryBuilder& DetailCategory = DetailLayout.EditCategory("Rendering");
55 // 在渲染类别中添加一个属性行,属性名为"Generation",显示文本为空字符串
56 IDetailPropertyRow& row = DetailCategory.AddProperty("Generation", TEXT(""));
57
58}*/
59
60// 当该Actor在场景中被构建时调用此函数,会先调用父类的OnConstruction函数
61void ACityMapMeshHolder::OnConstruction(const FTransform &Transform)
62{
63 Super::OnConstruction(Transform);
64
65}
66
67// 在所有组件初始化完成后调用此函数,会先调用父类的PostInitializeComponents函数
69{
70 Super::PostInitializeComponents();
71
72 // 检查当前Actor所在的关卡是否有效且未被标记为待销毁
73 if(IsValid(GetLevel())&&!GetLevel()->IsPendingKill())
74 {
75 // 创建一个数组用于存储附加到该Actor的道路部件Actor
76 TArray<AActor*> roadpieces;
77 // 获取附加到该Actor的所有Actor并存储到roadpieces数组中
78 GetAttachedActors(roadpieces);
79 // 如果没有附加的道路部件Actor
80 if(roadpieces.Num()==0)
81 {
82 // 输出错误日志,提示需要在编辑模式下重新生成道路
83 UE_LOG(LogCarla, Error, TEXT("Please regenerate the road in edit mode for '%s' actor"), *UKismetSystemLibrary::GetDisplayName(this));
84 // 更新地图比例尺
86 // 更新地图
87 UpdateMap();
88 }
89 }
90
91}
92
93// 仅在编辑器环境下编译时生效的函数,当某个属性被编辑修改后调用此函数,会先调用父类的对应函数
94#if WITH_EDITOR
95void ACityMapMeshHolder::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
96{
97 // 如果被修改的属性存在
98 Super::PostEditChangeProperty(PropertyChangedEvent);
99 if (PropertyChangedEvent.Property)
100 {
101 // 删除一些部件(具体实现见DeletePieces函数)
102 DeletePieces();
103 // 更新地图比例尺
105 // 更新地图
106 UpdateMap();
107 }
108}
109#endif // WITH_EDITOR
110
111// =============================================================================
112// -- Other protected methods --------------------------------------------------
113// =============================================================================
114
115// 根据给定的X和Y坐标值,返回一个在地图中的瓦片位置向量
116FVector ACityMapMeshHolder::GetTileLocation(uint32 X, uint32 Y) const
117{
118 // 返回一个以地图比例尺为单位的坐标位置向量,Z坐标固定为0.0f
119 return {X * MapScale, Y * MapScale, 0.0f};
120}
121
122// 设置指定标签对应的静态网格资源
124{
125 // 将指定标签对应的静态网格资源设置为传入的Mesh
126 StaticMeshes[Tag] = Mesh;
127 // 如果传入的Mesh不为空,则将Mesh与对应的标签添加到TagMap映射中
128 if (Mesh != nullptr) {
129 TagMap.Add(Mesh, Tag);
130 }
131}
132
133// 获取指定标签对应的静态网格资源(非const版本)
135{
136 // 返回指定标签对应的静态网格资源
137 return StaticMeshes[Tag];
138}
139
140// 获取指定标签对应的静态网格资源(const版本)
142{
143 // 返回指定标签对应的静态网格资源
144 return StaticMeshes[Tag];
145}
146
147// 根据给定的静态网格资源获取对应的标签
148ECityMapMeshTag ACityMapMeshHolder::GetTag(const UStaticMesh &StaticMesh) const
149{
150 // 在TagMap中查找给定静态网格资源对应的标签指针
151 const ECityMapMeshTag *Tag = TagMap.Find(&StaticMesh);
152 // 如果找到对应的标签指针,则返回该标签,否则返回INVALID标签
153 return (Tag != nullptr ? *Tag : ECityMapMeshTag::INVALID);
154}
155
156// 在指定的瓦片坐标位置添加一个指定标签的实例(仅指定坐标,角度默认)
158{
159 // 调用另一个AddInstance函数,传入根据坐标获取的变换信息
160 AddInstance(Tag, FTransform(GetTileLocation(X, Y)));
161}
162
163// 在指定的瓦片坐标位置添加一个指定标签的实例,并指定角度
164void ACityMapMeshHolder::AddInstance(ECityMapMeshTag Tag, uint32 X, uint32 Y, float Angle)
165{
166 // 根据给定的角度创建一个四元数表示旋转信息
167 const FQuat rotation(FVector(0.0f, 0.0f, 1.0f), Angle);
168 // 根据坐标获取位置信息
169 const FVector location = GetTileLocation(X, Y);
170 // 调用另一个AddInstance函数,传入包含旋转和位置信息的变换对象
171 AddInstance(Tag, FTransform(rotation, location));
172}
173
174// 在指定的变换位置添加一个指定标签的实例
176{
177 // 创建一个Actor生成参数对象,用于指定生成Actor时的一些参数
178 FActorSpawnParameters params;
179 // 设置生成Actor时的碰撞处理方式为总是生成,即使有碰撞也生成
180 params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
181 // 获取变换对象中的位置信息
182 FVector location = Transform.GetLocation();
183 // 获取变换对象中的旋转信息并转换为旋转器类型
184 FRotator rotation = Transform.Rotator();
185 // 在世界中生成一个静态网格Actor,传入类类型、位置、旋转信息和生成参数
186 AStaticMeshActor* StaticMeshActor = Cast<AStaticMeshActor>(GetWorld()->SpawnActor(AStaticMeshActor::StaticClass(),&location,&rotation,params));
187 // 将生成的静态网格Actor附加到当前Actor上,保持相对变换关系
188 StaticMeshActor->AttachToActor(this,FAttachmentTransformRules::KeepRelativeTransform);
189 // 设置静态网格Actor的移动性为静态
190 StaticMeshActor->SetMobility(EComponentMobility::Static);
191 // 获取静态网格Actor的静态网格组件
192 UStaticMeshComponent* staticmeshcomponent = StaticMeshActor->GetStaticMeshComponent();
193 // 设置静态网格组件的移动性为静态
194 staticmeshcomponent->SetMobility(EComponentMobility::Static);
195 // 设置静态网格组件的静态网格资源为指定标签对应的静态网格资源
196 staticmeshcomponent->SetStaticMesh(GetStaticMesh(Tag));
197 // 给生成的静态网格Actor添加一个特定的标签
198 StaticMeshActor->Tags.Add(UCarlaSettings::CARLA_ROAD_TAG);
199 // 启用自动生成细节层次(LOD)功能
200 StaticMeshActor->bEnableAutoLODGeneration = true;
201}
202
203// =============================================================================
204// -- Private methods ----------------------------------------------------------
205// =============================================================================
206
207// 更新地图的函数,这里为空实现,可能在子类中被重写以实现具体的更新逻辑
209
210// 删除一些部件的函数,具体实现如下
212{
213 // 这部分将会被弃用:移除实例化静态网格体组件
214 TArray<UInstancedStaticMeshComponent*> oldcomponents;
215 // 获取当前Actor的所有组件,并将实例化静态网格组件存储到oldcomponents数组中
216 GetComponents(oldcomponents);
217 // 遍历数组,销毁每个实例化静态网格组件
218 for(int32 i=0;i<oldcomponents.Num();i++)
219 {
220 oldcomponents[i]->DestroyComponent();
221 }
222
223 // 创建一个数组用于存储附加到该Actor的道路部件Actor
224 TArray<AActor*> roadpieces;
225 // 获取附加到该Actor的所有Actor并存储到roadpieces数组中
226 GetAttachedActors(roadpieces);
227
228 // 从后往前遍历道路部件Actor数组
229 for(int32 i=roadpieces.Num()-1; i>=0; i--)
230 {
231 // 如果Actor具有特定的道路标签
232 if(roadpieces[i]->ActorHasTag(UCarlaSettings::CARLA_ROAD_TAG))
233 {
234 // 销毁该Actor
235 roadpieces[i]->Destroy();
236 }
237 }
238
239}
240
241// 更新地图比例尺的函数
243{
244 // 获取基础网格标签
246 // 获取对应标签的静态网格资源
247 auto *mesh = GetStaticMesh(Tag);
248 // 如果获取不到对应的静态网格资源
249 if (mesh == nullptr) {
250 // 输出错误日志,提示找不到用于计算瓦片大小的网格资源
251 UE_LOG(
252 LogCarla,
253 Error,
254 TEXT("Cannot find mesh \"%s\" for computing tile size"),
256 // 将地图比例尺设置为1.0f
257 MapScale = 1.0f;
258 } else {
259 // 获取静态网格资源的包围盒大小向量
260 FVector size = mesh->GetBoundingBox().GetSize();
261 // 将地图比例尺设置为静态网格资源包围盒的X轴大小
262 MapScale = size.X;
263 }
264}
265
266
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
static constexpr tag_size_t NUMBER_OF_TAGS
std::underlying_type< ECityMapMeshTag >::type tag_size_t
ECityMapMeshTag
用于标识ProceduralMapGenerator所使用的网格的标签
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
TMap< ECityMapMeshTag, UStaticMesh * > StaticMeshes
virtual void PostInitializeComponents() override
FVector GetTileLocation(uint32 X, uint32 Y) const
void SetStaticMesh(ECityMapMeshTag Tag, UStaticMesh *Mesh)
USceneComponent * SceneRootComponent
TMap< UStaticMesh *, ECityMapMeshTag > TagMap
void AddInstance(ECityMapMeshTag Tag, uint32 X, uint32 Y)
ECityMapMeshTag GetTag(const UStaticMesh &StaticMesh) const
UStaticMesh * GetStaticMesh(ECityMapMeshTag Tag)
ACityMapMeshHolder(const FObjectInitializer &ObjectInitializer)
virtual void OnConstruction(const FTransform &Transform) override
static ECityMapMeshTag FromUInt(uint8 Value)
将 标签转换为无符号整数类型
static constexpr uint8 GetNumberOfTags()
返回标签的数量
static FString ToString(ECityMapMeshTag Tag)
获取一个标签名称作为 FString
static ECityMapMeshTag GetBaseMeshTag()
返回基础网格。基础网格定义了地图缩放的单位图块
static const FName CARLA_ROAD_TAG
CARLA_ROAD 名称用于标记道路网格参与者。