CARLA
Loading...
Searching...
No Matches
ProceduralBuilding.h
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB). This work is licensed under the terms of the MIT license. For a copy, see <https://opensource.org/licenses/MIT>.
2
3#pragma once
4
5#include <util/ue-header-guard-begin.h>
6#include "CoreMinimal.h"
7#include "GameFramework/Actor.h"
8#include "Components/HierarchicalInstancedStaticMeshComponent.h"
9#include <util/ue-header-guard-end.h>
10
11#include "ProceduralBuilding.generated.h"
12
13
14// TODO: support n-sides building
15
17{
18 TArray<UStaticMesh*>* MainMeshes = nullptr;
19 TArray<TSubclassOf<AActor>>* MainBPs = nullptr;
20 TArray<UStaticMesh*>* CornerMeshes = nullptr;
21 TArray<TSubclassOf<AActor>>* CornerBPs = nullptr;
22 TArray<UStaticMesh*>* AuxiliarMeshes = nullptr;
23 TArray<TSubclassOf<AActor>>* AuxiliarBPs = nullptr;
24};
25
26UCLASS()
27class CARLA_API AProceduralBuilding : public AActor
28{
29 GENERATED_BODY()
30
31public:
32
33 // Sets default values for this actor's properties
35
36 // Looks for the HISMComp on the HISMComps Map that uses the SelectedMesh and returns it.
37 // If doesn't exist its created
38 UFUNCTION(BlueprintCallable, Category="Procedural Building")
39 UHierarchicalInstancedStaticMeshComponent* GetHISMComp(const UStaticMesh* SM);
40
41 UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building")
42 void ConvertOldBP_ToNativeCodeObject(AActor* BP_Building);
43
44 UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building")
45 void HideAllChildren();
46
47 UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion")
48 void SetBaseParameters(
49 const TSet<int>& InDoorsIndexPosition,
50 const TArray<bool>& InUseWallMesh,
51 int InNumFloors,
52 int InLengthX,
53 int InLengthY,
54 bool InCorners,
55 bool InUseFullBlocks);
56
57 UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion")
58 void SetVisibilityParameters(
59 const TArray<bool>& InSideVisibility,
60 const TArray<bool>& InCornerVisibility,
61 bool InRoofVisibility);
62
63 UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion")
64 void SetBaseMeshes(
65 const TArray<UStaticMesh*>& InBaseMeshes,
66 const TArray<TSubclassOf<AActor>>& InBaseBPs,
67 const TArray<UStaticMesh*>& InCornerBaseMeshes,
68 const TArray<TSubclassOf<AActor>>& InCornerBaseBPs,
69 const TArray<UStaticMesh*>& InDoorMeshes,
70 const TArray<TSubclassOf<AActor>>& InDoorBPs);
71
72 UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion")
73 void SetBodyMeshes(
74 const TArray<UStaticMesh*>& InBodyMeshes,
75 const TArray<TSubclassOf<AActor>>& InBodyBPs,
76 const TArray<UStaticMesh*>& InCornerBodyMeshes,
77 const TArray<TSubclassOf<AActor>>& InCornerBodyBPs,
78 const TArray<UStaticMesh*>& InWallMeshes,
79 const TArray<TSubclassOf<AActor>>& InWallBPs);
80
81 UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion")
82 void SetTopMeshes(
83 const TArray<UStaticMesh*>& InTopMeshes,
84 const TArray<TSubclassOf<AActor>>& InTopBPs,
85 const TArray<UStaticMesh*>& InCornerTopMeshes,
86 const TArray<TSubclassOf<AActor>>& InCornerTopBPs,
87 const TArray<UStaticMesh*>& InRoofMeshes,
88 const TArray<TSubclassOf<AActor>>& InRoofBPs);
89
90protected:
91
92 UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building")
93 void CreateBuilding();
94
95 UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building")
96 void Reset();
97
98 UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building")
99 void FixMobility();
100
101 // TODO: AdvancedDisplay
102 // Map containing the pair with the name of the mesh and the component that uses it
103 UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Procedural Building|Debug")
104 TMap<FString, TObjectPtr<UHierarchicalInstancedStaticMeshComponent>> HISMComps;
105
106 // Contains all the ChildActorComps spawned for this Actor
107 UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Procedural Building|Debug")
108 TArray<TObjectPtr<UChildActorComponent>> ChildActorComps;
109
110 UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Procedural Building")
111 TObjectPtr<UStaticMeshComponent> RootSMComp = nullptr;
112
113 /**
114 * Base Parameters
115 */
116
117 // Set to contain the index of the doors that need to be placed on the base floor
118 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ToolTip="Index to indicate where the door is placed"))
119 TSet<int> DoorsIndexPosition;
120
121 // Indicates if the wall has to be filled with the wall-mesh or the body-mesh
122 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ToolTip="True to use wall-mesh instead of body-mesh"))
123 TArray<bool> UseWallMesh;
124
125 // Number of floors for the building, base and roof not included
126 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ClampMin="0", UIMin="0", ToolTip="Number of floors for the building, base and roof not included"))
127 int NumFloors = 0;
128
129 // Number of elements in X Axis
130 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters")
131 int LengthX = 0;
132
133 // Number of elements in Y Axis
134 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters")
135 int LengthY = 0;
136
137 // Enables the corners of the building
138 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters")
139 bool Corners = false;
140
141 // Indicates if the meshes that are used on this buildings fill the whole floor
142 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters")
143 bool UseFullBlocks = false;
144
145 /**
146 * Base Parameters | Visibility
147 */
148
149 // True to render the side of the building. Each index represents the side
150 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility")
151 TArray<bool> SideVisibility;
152
153 // True to render the corner of the building. Each index represents the corner
154 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility")
155 TArray<bool> CornerVisibility;
156
157 // True to render the roof
158 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility")
159 bool RoofVisibility = true;
160
161
162 /**
163 * Meshes
164 */
165
166 /**
167 * Meshes | Base
168 */
169
170 // Pool of meshes to be randomly selected for the base floor
171 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
172 TArray<UStaticMesh*> BaseMeshes;
173
174 // Pool of BPs to be randomly selected for the base floor
175 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
176 TArray<TSubclassOf<AActor>> BaseBPs;
177
178 // Pool of meshes to be randomly selected for doors
179 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
180 TArray<UStaticMesh*> DoorMeshes;
181
182 // Pool of BPs to be randomly selected for doors
183 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
184 TArray<TSubclassOf<AActor>> DoorBPs;
185
186 // Pool of meshes to be randomly selected for the corners of the base floor
187 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
188 TArray<UStaticMesh*> CornerBaseMeshes;
189
190 // Pool of BPs to be randomly selected for the corners of the base floor
191 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base")
192 TArray<TSubclassOf<AActor>> CornerBaseBPs;
193
194 /**
195 * Meshes | Body
196 */
197
198 // Pool of meshes to be randomly selected for the body
199 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
200 TArray<UStaticMesh*> BodyMeshes;
201
202 // Pool of BPs to be randomly selected for the body
203 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
204 TArray<TSubclassOf<AActor>> BodyBPs;
205
206 // Pool of meshes to be randomly selected for the walls of the body
207 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
208 TArray<UStaticMesh*> WallMeshes;
209
210 // Pool of BPs to be randomly selected for the body walls of the body
211 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
212 TArray<TSubclassOf<AActor>> WallBPs;
213
214 // Pool of meshes to be randomly selected for the corners of the body floor
215 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
216 TArray<UStaticMesh*> CornerBodyMeshes;
217
218 // Pool of BPs to be randomly selected for the corners of the body floor
219 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body")
220 TArray<TSubclassOf<AActor>> CornerBodyBPs;
221
222 /**
223 * Meshes | Top
224 */
225
226 // Pool of meshes to be randomly selected for the top
227 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
228 TArray<UStaticMesh*> TopMeshes;
229
230 // Pool of BPs to be randomly selected for the top
231 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
232 TArray<TSubclassOf<AActor>> TopBPs;
233
234 // Pool of meshes to be randomly selected for the corners of the top
235 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
236 TArray<UStaticMesh*> CornerTopMeshes;
237
238 // Pool of BPs to be randomly selected for the corners of the top
239 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
240 TArray<TSubclassOf<AActor>> CornerTopBPs;
241
242 // Pool of meshes to be randomly selected for the roof
243 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
244 TArray<UStaticMesh*> RoofMeshes;
245
246 // Pool of BPs to be randomly selected for the roof
247 UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top")
248 TArray<TSubclassOf<AActor>> RoofBPs;
249
250private:
251
252 void Init();
253
254 void CreateFloor(const FloorMeshCollection& MeshCollection, bool IncludeDoors, bool IncludeWalls);
255
256 void CreateRoof();
257
258 // Creates the side of a floor of the building and returns the maximun height of the side
259 float CreateSide(
260 const FloorMeshCollection& MeshCollection,
261 const TSet<int>& AuxiliarPositions,
262 int SideLength,
263 bool MainVisibility,
264 bool CornerVisbility);
265
266 void CalculateSidesLength();
267
268 // Calculates the doors of DoorsIndexPosition inside the range between [StartIndex, StartIndex + Length)
269 // The set returns the position (index) of the doors relative to the side, ie: [0, Length)
270 TSet<int> CalculateDoorsIndexInSide(int StartIndex, int Length);
271
272 //
273 TSet<int> GenerateWallsIndexPositions(int Length);
274
275 // Check if the main and corner part of the side is visible
276 void CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility);
277
278 // Choose randomly between the Mesh and BP containers, only one option will be returned.
279 void ChooseGeometryToSpawn(
280 const TArray<UStaticMesh*>& InMeshes,
281 const TArray<TSubclassOf<AActor>>& InMainBPs,
282 UStaticMesh** OutMesh,
283 TSubclassOf<AActor>* OutBP);
284
285 // Add one part on the side
286 float AddChunck(
287 const UStaticMesh* SelectedMesh,
288 const TSubclassOf<AActor> SelectedBP,
289 bool Visible,
290 FBox& OutSelectedMeshBounds);
291
292 // Add the Static Mesh on the transform location with the transform orientation
293 void AddMeshToBuilding(const UStaticMesh* SM);
294
295 // Calculate the Bounds for the Static Mesh
296 FVector GetMeshSize(const UStaticMesh* SM);
297
298 void UpdateTransformPositionToNextChunk(const FVector& Box);
299
300 void UpdateTransformPositionToNextSide(const FBox& Box);
301
302 // The lengths of each side of the building. The length of the array is the number of sides
303 // Helper to iterate throught all the sides of the building
304 TArray<int> SidesLength;
305
306 // Transform used to spawn the meshes of the building. It is updated (moved) with each new mesh
307 FTransform CurrentTransform = FTransform::Identity;
308
309 FBox LastSelectedMeshBounds;
310
311};
TArray< UStaticMesh * > * CornerMeshes
TArray< UStaticMesh * > * MainMeshes
TArray< UStaticMesh * > * AuxiliarMeshes
TArray< TSubclassOf< AActor > > * MainBPs
TArray< TSubclassOf< AActor > > * CornerBPs
TArray< TSubclassOf< AActor > > * AuxiliarBPs