UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
RuntimeSpatialHashGridHelper.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Algo/Find.h"
5#include "Algo/Transform.h"
6
8
13
14#if WITH_EDITOR
15
20
21#endif
22
27{
28 struct FGrid2D
29 {
33
39
45 inline bool IsValidCoords(const FGridCellCoord2& InCoords) const
46 {
47 if ((InCoords.X >= 0) && (InCoords.X < GridSize) && (InCoords.Y >= 0) && (InCoords.Y < GridSize))
48 {
50 if (ensureMsgf(Index >= 0, TEXT("World Partition reached the current limit of large world coordinates.")))
51 {
52 return true;
53 }
54 }
55 return false;
56 }
57
64 {
65 if (InIndex >= 0 && InIndex <= (GridSize * GridSize))
66 {
68 return GetCellBounds(Coords, OutBounds);
69 }
70
71 return false;
72 }
73
80 {
82 {
86 return true;
87 }
88
89 return false;
90 }
91
98 {
100 FMath::FloorToInt(((InPos.X - Origin.X) / CellSize) + GridSize * 0.5),
101 FMath::FloorToInt(((InPos.Y - Origin.Y) / CellSize) + GridSize * 0.5)
102 );
103
104 return IsValidCoords(OutCoords);
105 }
106
113 {
116 {
117 return false;
118 }
119
121 if ((OutMaxCellCoords.X < 0) || (OutMaxCellCoords.Y < 0))
122 {
123 return false;
124 }
125
130 return true;
131 }
132
138 inline bool GetCellIndex(const FGridCellCoord2& InCoords, uint64& OutIndex) const
139 {
141 {
142 OutIndex = (InCoords.Y * GridSize) + InCoords.X;
143 return true;
144 }
145 return false;
146 }
147
153 inline bool GetCellIndex(const FVector& InPos, uint64& OutIndex) const
154 {
156 FMath::FloorToInt(((InPos.X - Origin.X) / CellSize) + GridSize * 0.5),
157 FMath::FloorToInt(((InPos.Y - Origin.Y) / CellSize) + GridSize * 0.5)
158 );
159
160 return GetCellIndex(Coords, OutIndex);
161 }
162
169 {
172 const FBox2D Bounds2D(FVector2D(InBox.Min), FVector2D(InBox.Max));
173
175 {
176 return (MaxCellCoords.X - MinCellCoords.X + 1) * (MaxCellCoords.Y - MinCellCoords.Y + 1);
177 }
178
179 return 0;
180 }
181
188 {
189 int32 NumCells = 0;
190
193 const FBox2D Bounds2D(FVector2D(InBox.Min), FVector2D(InBox.Max));
194
196 {
197 for (int64 y = MinCellCoords.Y; y <= MaxCellCoords.Y; y++)
198 {
199 for (int64 x = MinCellCoords.X; x <= MaxCellCoords.X; x++)
200 {
201 const FGridCellCoord2 Coord(x, y);
202 // Validate that generated coordinate is valid (in case we reached the 64-bit limit of cell index)
203 if (IsValidCoords(Coord))
204 {
205 if (!InOperation(Coord))
206 {
207 return NumCells;
208 }
209 ++NumCells;
210 }
211 }
212 }
213 }
214
215 return NumCells;
216 }
217
222
229 {
230 int32 NumCells = 0;
231
232 // @todo_ow: rasterize circle instead?
233 const FBox Box(InSphere.Center - FVector(InSphere.W), InSphere.Center + FVector(InSphere.W));
234 const double SquareDistance = InSphere.W * InSphere.W;
235 const FVector2D SphereCenter(InSphere.Center);
236
237 ForEachIntersectingCells(Box, [this, SquareDistance, &SphereCenter, &InOperation, &NumCells](const FGridCellCoord2& Coords)
238 {
239 // No need to check validity of coords as it's already done
240 const bool bCheckIsValidCoords = false;
241 FBox2D CellBounds;
242 GetCellBounds(Coords, CellBounds, bCheckIsValidCoords);
243
245 if ((Delta.X * Delta.X + Delta.Y * Delta.Y) < SquareDistance)
246 {
247 InOperation(Coords);
248 NumCells++;
249 }
250 });
251
252 return NumCells;
253 }
254
261
262 private:
263
264 bool DoesCircleSectorIntersectsCell(const FGridCellCoord2& Coords, const FSphericalSector& InShape) const;
265 };
266
267 struct FGridLevel : public FGrid2D
268 {
269#if WITH_EDITOR
270 struct FGridCellDataChunk
271 {
273 {
274 Algo::TransformIf(InDataLayers, DataLayers, [](const UDataLayerInstance* DataLayer) { return DataLayer->IsRuntime(); }, [](const UDataLayerInstance* DataLayer) { return DataLayer; });
275 DataLayersID = FDataLayersID(DataLayers);
276 ContentBundleID = InContentBundleID;
277 }
278
279 void AddActorSetInstance(const IStreamingGenerationContext::FActorSetInstance* ActorSetInstance) { ActorSetInstances.Add(ActorSetInstance); }
281 bool HasDataLayers() const { return !DataLayers.IsEmpty(); }
282 const TArray<const UDataLayerInstance*>& GetDataLayers() const { return DataLayers; }
283 const FDataLayersID& GetDataLayersID() const { return DataLayersID; }
284 FGuid GetContentBundleID() const { return ContentBundleID; }
285 bool operator==(const FGridCellDataChunk& InGridCellDataChunk) const { return DataLayersID == InGridCellDataChunk.DataLayersID;}
286 friend uint32 GetTypeHash(const FGridCellDataChunk& InGridCellDataChunk) { return GetTypeHash(InGridCellDataChunk.DataLayersID);}
287
288 private:
292 FGuid ContentBundleID;
293 };
294#endif
295
297 {
299 : Coords(InCoords)
300 {}
301
302#if WITH_EDITOR
303 void AddActorSetInstance(const IStreamingGenerationContext::FActorSetInstance* ActorSetInstance)
304 {
306 FGridCellDataChunk& ActorDataChunk = DataChunks.FindOrAddByHash(DataLayersID.GetHash(), FGridCellDataChunk(ActorSetInstance->DataLayers, ActorSetInstance->ContentBundleID));
307 ActorDataChunk.AddActorSetInstance(ActorSetInstance);
308 }
309
311 {
312 return DataChunks;
313 }
314
316 {
317 for (const FGridCellDataChunk& DataChunk : DataChunks)
318 {
319 if (!DataChunk.HasDataLayers())
320 {
321 return &DataChunk;
322 }
323 }
324 return nullptr;
325 }
326#endif
327
329 {
330 return Coords;
331 }
332
333 private:
334 FGridCellCoord Coords;
335#if WITH_EDITOR
336 TSet<FGridCellDataChunk> DataChunks;
337#endif
338 };
339
344
351 {
353
354 uint64 CellIndex;
355 verify(GetCellIndex(InCoords, CellIndex));
356
358 int64* CellIndexMappingPtr = CellsMapping.Find(CellIndex);
360 {
362 }
363 else
364 {
366 CellsMapping.Add(CellIndex, CellIndexMapping);
367 }
368
369 return Cells[CellIndexMapping];
370 }
371
377 inline const FGridCell& GetCell(const FGridCellCoord2& InCoords) const
378 {
380
381 uint64 CellIndex;
382 verify(GetCellIndex(InCoords, CellIndex));
383
384 int64 CellIndexMapping = CellsMapping.FindChecked(CellIndex);
385
387 check(Cell.GetCoords() == FGridCellCoord(InCoords.X, InCoords.Y, Level));
388 return Cell;
389 }
390
394 };
395
396 UE_DEPRECATED(5.4, "Use version with bUseAlignedGridLevels param")
398
399 ENGINE_API FSquare2DGridHelper(const FBox& InWorldBounds, const FVector& InOrigin, int64 InCellSize, bool bUseAlignedGridLevels);
400
401 // Returns the lowest grid level
403
404 // Returns the always loaded (top level) cell
405 inline FGridLevel::FGridCell& GetAlwaysLoadedCell() { return Levels.Last().GetCell(FGridCellCoord2(0,0)); }
406
407 // Returns the always loaded (top level) cell
408 inline const FGridLevel::FGridCell& GetAlwaysLoadedCell() const { return Levels.Last().GetCell(FGridCellCoord2(0,0)); }
409
410 // Returns the cell at the given coord
411 inline const FGridLevel::FGridCell& GetCell(const FGridCellCoord& InCoords) const { return Levels[InCoords.Z].GetCell(FGridCellCoord2(InCoords.X, InCoords.Y)); }
412
419 {
420 if (Levels.IsValidIndex(InCoords.Z))
421 {
422 return Levels[InCoords.Z].GetCellBounds(FGridCellCoord2(InCoords.X, InCoords.Y), OutBounds);
423 }
424 return false;
425 }
426
433 {
434 if (Levels.IsValidIndex(InCoords.Z))
435 {
437 if (GridLevel.IsValidCoords(FGridCellCoord2(InCoords.X, InCoords.Y)))
438 {
443 return true;
444 }
445 }
446 return false;
447 }
448
449 // Runs a function on all cells
451
458
465
472
473public:
478};
479
480#if WITH_EDITOR
481
482FSquare2DGridHelper GetGridHelper(const FBox& WorldBounds, const FVector& GridOrigin, int64 GridCellSize, bool bUseAlignedGridLevels);
484
485UE_DEPRECATED(5.4, "Use version with bUseAlignedGridLevels param")
486FSquare2DGridHelper GetGridHelper(const FBox& WorldBounds, const FVector& GridOrigin, int64 GridCellSize);
487
488UE_DEPRECATED(5.4, "Use version with Settings param")
490#endif // #if WITH_EDITOR
#define check(expr)
Definition AssertionMacros.h:314
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define verify(expr)
Definition AssertionMacros.h:319
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::Math::TVector2< double > FVector2D
Definition MathFwd.h:48
UE::Math::TBox2< double > FBox2D
Definition MathFwd.h:56
FInt64Vector3 FGridCellCoord
Definition WorldPartitionRuntimeSpatialHash.h:18
FInt64Vector2 FGridCellCoord2
Definition WorldPartitionRuntimeSpatialHash.h:19
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition WorldPartitionStreamingSource.h:11
Definition Array.h:670
UE_REWRITE bool IsEmpty() const
Definition Array.h:1133
Definition AssetRegistryState.h:50
Definition UnrealString.h.inl:34
void TransformIf(const InT &Input, OutT &&Output, PredicateT Predicate, TransformT Trans)
Definition Transform.h:47
U16 Index
Definition radfft.cpp:71
Definition Guid.h:109
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
Definition WorldPartitionRuntimeSpatialHash.h:233
Definition WorldPartitionRuntimeSpatialHash.h:37
Definition RuntimeSpatialHashGridHelper.h:29
int32 GetNumIntersectingCells(const FBox &InBox) const
Definition RuntimeSpatialHashGridHelper.h:168
bool GetCellIndex(const FGridCellCoord2 &InCoords, uint64 &OutIndex) const
Definition RuntimeSpatialHashGridHelper.h:138
bool GetCellBounds(int64 InIndex, FBox2D &OutBounds) const
Definition RuntimeSpatialHashGridHelper.h:63
bool GetCellBounds(const FGridCellCoord2 &InCoords, FBox2D &OutBounds, bool bCheckIsValidCoord=true) const
Definition RuntimeSpatialHashGridHelper.h:79
int32 ForEachIntersectingCells(const FBox &InBox, TFunctionRef< void(const FGridCellCoord2 &)> InOperation) const
Definition RuntimeSpatialHashGridHelper.h:218
int32 ForEachIntersectingCellsBreakable(const FBox &InBox, TFunctionRef< bool(const FGridCellCoord2 &)> InOperation) const
Definition RuntimeSpatialHashGridHelper.h:187
bool GetCellIndex(const FVector &InPos, uint64 &OutIndex) const
Definition RuntimeSpatialHashGridHelper.h:153
int32 ForEachIntersectingCells(const FSphere &InSphere, TFunctionRef< void(const FGridCellCoord2 &)> InOperation) const
Definition RuntimeSpatialHashGridHelper.h:228
int64 GridSize
Definition RuntimeSpatialHashGridHelper.h:32
bool GetCellCoords(const FVector2D &InPos, FGridCellCoord2 &OutCoords) const
Definition RuntimeSpatialHashGridHelper.h:97
bool GetCellCoords(const FBox2D &InBounds2D, FGridCellCoord2 &OutMinCellCoords, FGridCellCoord2 &OutMaxCellCoords) const
Definition RuntimeSpatialHashGridHelper.h:112
int64 CellSize
Definition RuntimeSpatialHashGridHelper.h:31
bool IsValidCoords(const FGridCellCoord2 &InCoords) const
Definition RuntimeSpatialHashGridHelper.h:45
FGrid2D(const FVector2D &InOrigin, int64 InCellSize, int64 InGridSize)
Definition RuntimeSpatialHashGridHelper.h:34
FVector2D Origin
Definition RuntimeSpatialHashGridHelper.h:30
Definition RuntimeSpatialHashGridHelper.h:297
FGridCellCoord GetCoords() const
Definition RuntimeSpatialHashGridHelper.h:328
FGridCell(const FGridCellCoord &InCoords)
Definition RuntimeSpatialHashGridHelper.h:298
Definition RuntimeSpatialHashGridHelper.h:268
int32 Level
Definition RuntimeSpatialHashGridHelper.h:391
FGridCell & GetCell(const FGridCellCoord2 &InCoords)
Definition RuntimeSpatialHashGridHelper.h:350
FGridLevel(const FVector2D &InOrigin, int64 InCellSize, int64 InGridSize, int32 InLevel)
Definition RuntimeSpatialHashGridHelper.h:340
TMap< int64, int64 > CellsMapping
Definition RuntimeSpatialHashGridHelper.h:393
const FGridCell & GetCell(const FGridCellCoord2 &InCoords) const
Definition RuntimeSpatialHashGridHelper.h:377
TArray< FGridCell > Cells
Definition RuntimeSpatialHashGridHelper.h:392
Definition RuntimeSpatialHashGridHelper.h:27
const FGridLevel::FGridCell & GetAlwaysLoadedCell() const
Definition RuntimeSpatialHashGridHelper.h:408
TArray< FGridLevel > Levels
Definition RuntimeSpatialHashGridHelper.h:477
ENGINE_API void ForEachCells(TFunctionRef< void(const FSquare2DGridHelper::FGridLevel::FGridCell &)> InOperation) const
Definition RuntimeSpatialHashGridHelper.cpp:98
bool GetCellGlobalCoords(const FGridCellCoord &InCoords, FGridCellCoord &OutGlobalCoords) const
Definition RuntimeSpatialHashGridHelper.h:432
FVector Origin
Definition RuntimeSpatialHashGridHelper.h:475
ENGINE_API int32 ForEachIntersectingCells(const FBox &InBox, TFunctionRef< void(const FGridCellCoord &)> InOperation, int32 InStartLevel=0) const
Definition RuntimeSpatialHashGridHelper.cpp:109
FBox WorldBounds
Definition RuntimeSpatialHashGridHelper.h:474
FGridLevel & GetLowestLevel()
Definition RuntimeSpatialHashGridHelper.h:402
bool GetCellBounds(const FGridCellCoord &InCoords, FBox2D &OutBounds) const
Definition RuntimeSpatialHashGridHelper.h:418
const FGridLevel::FGridCell & GetCell(const FGridCellCoord &InCoords) const
Definition RuntimeSpatialHashGridHelper.h:411
FGridLevel::FGridCell & GetAlwaysLoadedCell()
Definition RuntimeSpatialHashGridHelper.h:405
int64 CellSize
Definition RuntimeSpatialHashGridHelper.h:476
TVector2< T > Max
Definition Box2D.h:39
TVector2< T > Min
Definition Box2D.h:36
Definition IntVector.h:670
Definition IntVector.h:22
static UE_FORCEINLINE_HINT TVector2< double > Min(const TVector2< double > &A, const TVector2< double > &B)
Definition Vector2D.h:959
T Y
Definition Vector2D.h:52
static UE_FORCEINLINE_HINT TVector2< double > Max(const TVector2< double > &A, const TVector2< double > &B)
Definition Vector2D.h:953
T X
Definition Vector2D.h:49